aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Application/ConfigurationLoader.cs4
-rw-r--r--OpenSim/Region/Application/OpenSim.cs56
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs1
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs57
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs74
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs39
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs9
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs18
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs18
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs68
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs27
-rw-r--r--OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs93
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs16
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs63
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs88
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs15
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs2
-rwxr-xr-xOpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs335
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs20
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs91
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs221
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs4
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs40
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs41
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs25
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintConeTwist.cs54
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintSlider.cs55
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintSpring.cs103
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs43
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs31
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs494
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSParam.cs25
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs21
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs91
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs94
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs71
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs399
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs238
58 files changed, 2616 insertions, 653 deletions
diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs
index bc7ecb7..010ae5a 100644
--- a/OpenSim/Region/Application/ConfigurationLoader.cs
+++ b/OpenSim/Region/Application/ConfigurationLoader.cs
@@ -203,10 +203,10 @@ namespace OpenSim
203 m_config.Source.Merge(envConfigSource); 203 m_config.Source.Merge(envConfigSource);
204 } 204 }
205 205
206 ReadConfigSettings();
207
208 m_config.Source.ExpandKeyValues(); 206 m_config.Source.ExpandKeyValues();
209 207
208 ReadConfigSettings();
209
210 return m_config; 210 return m_config;
211 } 211 }
212 212
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index a18a6fe..20f6af5 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -237,27 +237,33 @@ namespace OpenSim
237 237
238 m_console.Commands.AddCommand("General", false, "change region", 238 m_console.Commands.AddCommand("General", false, "change region",
239 "change region <region name>", 239 "change region <region name>",
240 "Change current console region", ChangeSelectedRegion); 240 "Change current console region",
241 ChangeSelectedRegion);
241 242
242 m_console.Commands.AddCommand("Archiving", false, "save xml", 243 m_console.Commands.AddCommand("Archiving", false, "save xml",
243 "save xml", 244 "save xml",
244 "Save a region's data in XML format", SaveXml); 245 "Save a region's data in XML format",
246 SaveXml);
245 247
246 m_console.Commands.AddCommand("Archiving", false, "save xml2", 248 m_console.Commands.AddCommand("Archiving", false, "save xml2",
247 "save xml2", 249 "save xml2",
248 "Save a region's data in XML2 format", SaveXml2); 250 "Save a region's data in XML2 format",
251 SaveXml2);
249 252
250 m_console.Commands.AddCommand("Archiving", false, "load xml", 253 m_console.Commands.AddCommand("Archiving", false, "load xml",
251 "load xml [-newIDs [<x> <y> <z>]]", 254 "load xml [-newIDs [<x> <y> <z>]]",
252 "Load a region's data from XML format", LoadXml); 255 "Load a region's data from XML format",
256 LoadXml);
253 257
254 m_console.Commands.AddCommand("Archiving", false, "load xml2", 258 m_console.Commands.AddCommand("Archiving", false, "load xml2",
255 "load xml2", 259 "load xml2",
256 "Load a region's data from XML2 format", LoadXml2); 260 "Load a region's data from XML2 format",
261 LoadXml2);
257 262
258 m_console.Commands.AddCommand("Archiving", false, "save prims xml2", 263 m_console.Commands.AddCommand("Archiving", false, "save prims xml2",
259 "save prims xml2 [<prim name> <file name>]", 264 "save prims xml2 [<prim name> <file name>]",
260 "Save named prim to XML2", SavePrimsXml2); 265 "Save named prim to XML2",
266 SavePrimsXml2);
261 267
262 m_console.Commands.AddCommand("Archiving", false, "load oar", 268 m_console.Commands.AddCommand("Archiving", false, "load oar",
263 "load oar [--merge] [--skip-assets] [<OAR path>]", 269 "load oar [--merge] [--skip-assets] [<OAR path>]",
@@ -287,7 +293,8 @@ namespace OpenSim
287 293
288 m_console.Commands.AddCommand("Objects", false, "edit scale", 294 m_console.Commands.AddCommand("Objects", false, "edit scale",
289 "edit scale <name> <x> <y> <z>", 295 "edit scale <name> <x> <y> <z>",
290 "Change the scale of a named prim", HandleEditScale); 296 "Change the scale of a named prim",
297 HandleEditScale);
291 298
292 m_console.Commands.AddCommand("Users", false, "kick user", 299 m_console.Commands.AddCommand("Users", false, "kick user",
293 "kick user <first> <last> [--force] [message]", 300 "kick user <first> <last> [--force] [message]",
@@ -305,31 +312,38 @@ namespace OpenSim
305 312
306 m_console.Commands.AddCommand("Comms", false, "show connections", 313 m_console.Commands.AddCommand("Comms", false, "show connections",
307 "show connections", 314 "show connections",
308 "Show connection data", HandleShow); 315 "Show connection data",
316 HandleShow);
309 317
310 m_console.Commands.AddCommand("Comms", false, "show circuits", 318 m_console.Commands.AddCommand("Comms", false, "show circuits",
311 "show circuits", 319 "show circuits",
312 "Show agent circuit data", HandleShow); 320 "Show agent circuit data",
321 HandleShow);
313 322
314 m_console.Commands.AddCommand("Comms", false, "show pending-objects", 323 m_console.Commands.AddCommand("Comms", false, "show pending-objects",
315 "show pending-objects", 324 "show pending-objects",
316 "Show # of objects on the pending queues of all scene viewers", HandleShow); 325 "Show # of objects on the pending queues of all scene viewers",
326 HandleShow);
317 327
318 m_console.Commands.AddCommand("General", false, "show modules", 328 m_console.Commands.AddCommand("General", false, "show modules",
319 "show modules", 329 "show modules",
320 "Show module data", HandleShow); 330 "Show module data",
331 HandleShow);
321 332
322 m_console.Commands.AddCommand("Regions", false, "show regions", 333 m_console.Commands.AddCommand("Regions", false, "show regions",
323 "show regions", 334 "show regions",
324 "Show region data", HandleShow); 335 "Show region data",
336 HandleShow);
325 337
326 m_console.Commands.AddCommand("Regions", false, "show ratings", 338 m_console.Commands.AddCommand("Regions", false, "show ratings",
327 "show ratings", 339 "show ratings",
328 "Show rating data", HandleShow); 340 "Show rating data",
341 HandleShow);
329 342
330 m_console.Commands.AddCommand("Objects", false, "backup", 343 m_console.Commands.AddCommand("Objects", false, "backup",
331 "backup", 344 "backup",
332 "Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.", RunCommand); 345 "Persist currently unsaved object changes immediately instead of waiting for the normal persistence call.",
346 RunCommand);
333 347
334 m_console.Commands.AddCommand("Regions", false, "create region", 348 m_console.Commands.AddCommand("Regions", false, "create region",
335 "create region [\"region name\"] <region_file.ini>", 349 "create region [\"region name\"] <region_file.ini>",
@@ -342,19 +356,23 @@ namespace OpenSim
342 356
343 m_console.Commands.AddCommand("Regions", false, "restart", 357 m_console.Commands.AddCommand("Regions", false, "restart",
344 "restart", 358 "restart",
345 "Restart all sims in this instance", RunCommand); 359 "Restart all sims in this instance",
360 RunCommand);
346 361
347 m_console.Commands.AddCommand("General", false, "command-script", 362 m_console.Commands.AddCommand("General", false, "command-script",
348 "command-script <script>", 363 "command-script <script>",
349 "Run a command script from file", RunCommand); 364 "Run a command script from file",
365 RunCommand);
350 366
351 m_console.Commands.AddCommand("Regions", false, "remove-region", 367 m_console.Commands.AddCommand("Regions", false, "remove-region",
352 "remove-region <name>", 368 "remove-region <name>",
353 "Remove a region from this simulator", RunCommand); 369 "Remove a region from this simulator",
370 RunCommand);
354 371
355 m_console.Commands.AddCommand("Regions", false, "delete-region", 372 m_console.Commands.AddCommand("Regions", false, "delete-region",
356 "delete-region <name>", 373 "delete-region <name>",
357 "Delete a region from disk", RunCommand); 374 "Delete a region from disk",
375 RunCommand);
358 } 376 }
359 377
360 protected override void ShutdownSpecific() 378 protected override void ShutdownSpecific()
@@ -434,7 +452,7 @@ namespace OpenSim
434 else 452 else
435 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); 453 presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n");
436 454
437 presence.Scene.IncomingCloseAgent(presence.UUID, force); 455 presence.Scene.CloseAgent(presence.UUID, force);
438 break; 456 break;
439 } 457 }
440 } 458 }
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index b3b0b8a..9e24bce 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -96,7 +96,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
96 UUID spId = TestHelpers.ParseTail(0x1); 96 UUID spId = TestHelpers.ParseTail(0x1);
97 97
98 SceneHelpers.AddScenePresence(m_scene, spId); 98 SceneHelpers.AddScenePresence(m_scene, spId);
99 m_scene.IncomingCloseAgent(spId, false); 99 m_scene.CloseAgent(spId, false);
100 100
101 // TODO: Add more assertions for the other aspects of event queues 101 // TODO: Add more assertions for the other aspects of event queues
102 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); 102 Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0));
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
index 92805e2..94f8bc1 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs
@@ -155,6 +155,7 @@ namespace OpenSim.Region.ClientStack.Linden
155 Quaternion rotation = Quaternion.Identity; 155 Quaternion rotation = Quaternion.Identity;
156 Vector3 scale = Vector3.Zero; 156 Vector3 scale = Vector3.Zero;
157 int state = 0; 157 int state = 0;
158 int lastattach = 0;
158 159
159 if (r.Type != OSDType.Map) // not a proper req 160 if (r.Type != OSDType.Map) // not a proper req
160 return responsedata; 161 return responsedata;
@@ -224,6 +225,7 @@ namespace OpenSim.Region.ClientStack.Linden
224 225
225 ray_target_id = ObjMap["RayTargetId"].AsUUID(); 226 ray_target_id = ObjMap["RayTargetId"].AsUUID();
226 state = ObjMap["State"].AsInteger(); 227 state = ObjMap["State"].AsInteger();
228 lastattach = ObjMap["LastAttachPoint"].AsInteger();
227 try 229 try
228 { 230 {
229 ray_end = ((OSDArray)ObjMap["RayEnd"]).AsVector3(); 231 ray_end = ((OSDArray)ObjMap["RayEnd"]).AsVector3();
@@ -290,6 +292,7 @@ namespace OpenSim.Region.ClientStack.Linden
290 292
291 //session_id = rm["session_id"].AsUUID(); 293 //session_id = rm["session_id"].AsUUID();
292 state = rm["state"].AsInteger(); 294 state = rm["state"].AsInteger();
295 lastattach = rm["last_attach_point"].AsInteger();
293 try 296 try
294 { 297 {
295 ray_end = ((OSDArray)rm["ray_end"]).AsVector3(); 298 ray_end = ((OSDArray)rm["ray_end"]).AsVector3();
@@ -331,6 +334,7 @@ namespace OpenSim.Region.ClientStack.Linden
331 pbs.ProfileEnd = (ushort)profile_end; 334 pbs.ProfileEnd = (ushort)profile_end;
332 pbs.Scale = scale; 335 pbs.Scale = scale;
333 pbs.State = (byte)state; 336 pbs.State = (byte)state;
337 pbs.LastAttachPoint = (byte)lastattach;
334 338
335 SceneObjectGroup obj = null; ; 339 SceneObjectGroup obj = null; ;
336 340
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
index 55a503e..769fe28 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs
@@ -277,6 +277,7 @@ namespace OpenSim.Region.ClientStack.Linden
277 pbs.ProfileEnd = (ushort) obj.ProfileEnd; 277 pbs.ProfileEnd = (ushort) obj.ProfileEnd;
278 pbs.Scale = obj.Scale; 278 pbs.Scale = obj.Scale;
279 pbs.State = (byte) 0; 279 pbs.State = (byte) 0;
280 pbs.LastAttachPoint = (byte) 0;
280 SceneObjectPart prim = new SceneObjectPart(); 281 SceneObjectPart prim = new SceneObjectPart();
281 prim.UUID = UUID.Random(); 282 prim.UUID = UUID.Random();
282 prim.CreatorID = AgentId; 283 prim.CreatorID = AgentId;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index f816ad3..6fc35cd 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -116,7 +116,7 @@ namespace OpenSim.Region.ClientStack.Linden
116 m_scene.EventManager.OnRegisterCaps -= RegisterCaps; 116 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
117 117
118 foreach (Thread t in m_workerThreads) 118 foreach (Thread t in m_workerThreads)
119 Watchdog.AbortThread(t.ManagedThreadId); 119 Watchdog.AbortThread(t.ManagedThreadId);
120 120
121 m_scene = null; 121 m_scene = null;
122 } 122 }
@@ -298,36 +298,49 @@ namespace OpenSim.Region.ClientStack.Linden
298 requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null); 298 requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
299 299
300 lock (responses) 300 lock (responses)
301 responses[requestID] = response; 301 responses[requestID] = response;
302 } 302 }
303 } 303 }
304 304
305 private void RegisterCaps(UUID agentID, Caps caps) 305 private void RegisterCaps(UUID agentID, Caps caps)
306 { 306 {
307 if (m_fetchInventoryDescendents2Url == "") 307 RegisterFetchDescendentsCap(agentID, caps, "FetchInventoryDescendents2", m_fetchInventoryDescendents2Url);
308 }
309
310 private void RegisterFetchDescendentsCap(UUID agentID, Caps caps, string capName, string url)
311 {
312 string capUrl;
313
314 // disable the cap clause
315 if (url == "")
316 {
308 return; 317 return;
318 }
319 // handled by the simulator
320 else if (url == "localhost")
321 {
322 capUrl = "/CAPS/" + UUID.Random() + "/";
309 323
310 // Register this as a poll service 324 // Register this as a poll service
311 PollServiceInventoryEventArgs args 325 PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(m_scene, capUrl, agentID);
312 = new PollServiceInventoryEventArgs(m_scene, "/CAPS/" + UUID.Random() + "/", agentID); 326 args.Type = PollServiceEventArgs.EventType.Inventory;
313 args.Type = PollServiceEventArgs.EventType.Inventory;
314 327
315 caps.RegisterPollHandler("FetchInventoryDescendents2", args); 328 caps.RegisterPollHandler(capName, args);
329 }
330 // external handler
331 else
332 {
333 capUrl = url;
334 IExternalCapsModule handler = m_scene.RequestModuleInterface<IExternalCapsModule>();
335 if (handler != null)
336 handler.RegisterExternalUserCapsHandler(agentID,caps,capName,capUrl);
337 else
338 caps.RegisterHandler(capName, capUrl);
339 }
316 340
317// MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); 341 // m_log.DebugFormat(
318// 342 // "[FETCH INVENTORY DESCENDENTS2 MODULE]: Registered capability {0} at {1} in region {2} for {3}",
319// string hostName = m_scene.RegionInfo.ExternalHostName; 343 // capName, capUrl, m_scene.RegionInfo.RegionName, agentID);
320// uint port = (MainServer.Instance == null) ? 0 : MainServer.Instance.Port;
321// string protocol = "http";
322//
323// if (MainServer.Instance.UseSSL)
324// {
325// hostName = MainServer.Instance.SSLCommonName;
326// port = MainServer.Instance.SSLPort;
327// protocol = "https";
328// }
329//
330// caps.RegisterHandler("FetchInventoryDescendents2", String.Format("{0}://{1}:{2}{3}", protocol, hostName, port, capUrl));
331 } 344 }
332 345
333// private void DeregisterCaps(UUID agentID, Caps caps) 346// private void DeregisterCaps(UUID agentID, Caps caps)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 36edd0b..51cc2bf 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -783,7 +783,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
783 783
784 public virtual void Start() 784 public virtual void Start()
785 { 785 {
786 m_scene.AddNewClient(this, PresenceType.User); 786 m_scene.AddNewAgent(this, PresenceType.User);
787 787
788 RefreshGroupMembership(); 788 RefreshGroupMembership();
789 } 789 }
@@ -12548,6 +12548,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12548 12548
12549 shape.PCode = addPacket.ObjectData.PCode; 12549 shape.PCode = addPacket.ObjectData.PCode;
12550 shape.State = addPacket.ObjectData.State; 12550 shape.State = addPacket.ObjectData.State;
12551 shape.LastAttachPoint = addPacket.ObjectData.State;
12551 shape.PathBegin = addPacket.ObjectData.PathBegin; 12552 shape.PathBegin = addPacket.ObjectData.PathBegin;
12552 shape.PathEnd = addPacket.ObjectData.PathEnd; 12553 shape.PathEnd = addPacket.ObjectData.PathEnd;
12553 shape.PathScaleX = addPacket.ObjectData.PathScaleX; 12554 shape.PathScaleX = addPacket.ObjectData.PathScaleX;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index ad3f715..01981dd 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -1764,32 +1764,76 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1764 endPoint = (IPEndPoint)array[0]; 1764 endPoint = (IPEndPoint)array[0];
1765 CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1]; 1765 CompleteAgentMovementPacket packet = (CompleteAgentMovementPacket)array[1];
1766 1766
1767 m_log.DebugFormat(
1768 "[LLUDPSERVER]: Handling CompleteAgentMovement request from {0} in {1}", endPoint, m_scene.Name);
1769
1767 // Determine which agent this packet came from 1770 // Determine which agent this packet came from
1768 int count = 20; 1771 // We need to wait here because in when using the OpenSimulator V2 teleport protocol to travel to a destination
1769 bool ready = false; 1772 // simulator with no existing child presence, the viewer (at least LL 3.3.4) will send UseCircuitCode
1770 while (!ready && count-- > 0) 1773 // and then CompleteAgentMovement immediately without waiting for an ack. As we are now handling these
1774 // packets asynchronously, we need to account for this thread proceeding more quickly than the
1775 // UseCircuitCode thread.
1776 int count = 40;
1777 while (count-- > 0)
1771 { 1778 {
1772 if (m_scene.TryGetClient(endPoint, out client) && client.IsActive && client.SceneAgent != null) 1779 if (m_scene.TryGetClient(endPoint, out client))
1773 { 1780 {
1774 LLClientView llClientView = (LLClientView)client; 1781 if (!client.IsActive)
1775 LLUDPClient udpClient = llClientView.UDPClient; 1782 {
1776 if (udpClient != null && udpClient.IsConnected) 1783 // This check exists to catch a condition where the client has been closed by another thread
1777 ready = true; 1784 // but has not yet been removed from the client manager (and possibly a new connection has
1785 // not yet been established).
1786 m_log.DebugFormat(
1787 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active yet. Waiting.",
1788 endPoint, client.Name, m_scene.Name);
1789 }
1790 else if (client.SceneAgent == null)
1791 {
1792 // This check exists to catch a condition where the new client has been added to the client
1793 // manager but the SceneAgent has not yet been set in Scene.AddNewAgent(). If we are too
1794 // eager, then the new ScenePresence may not have registered a listener for this messsage
1795 // before we try to process it.
1796 // XXX: A better long term fix may be to add the SceneAgent before the client is added to
1797 // the client manager
1798 m_log.DebugFormat(
1799 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client SceneAgent not set yet. Waiting.",
1800 endPoint, client.Name, m_scene.Name);
1801 }
1778 else 1802 else
1779 { 1803 {
1780 m_log.Debug("[LLUDPSERVER]: Received a CompleteMovementIntoRegion in " + m_scene.RegionInfo.RegionName + " (not ready yet)"); 1804 break;
1781 Thread.Sleep(200);
1782 } 1805 }
1783 } 1806 }
1784 else 1807 else
1785 { 1808 {
1786 m_log.Debug("[LLUDPSERVER]: Received a CompleteMovementIntoRegion in " + m_scene.RegionInfo.RegionName + " (not ready yet)"); 1809 m_log.DebugFormat(
1787 Thread.Sleep(200); 1810 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} in {1} but no client exists yet. Waiting.",
1811 endPoint, m_scene.Name);
1788 } 1812 }
1813
1814 Thread.Sleep(200);
1789 } 1815 }
1790 1816
1791 if (client == null) 1817 if (client == null)
1818 {
1819 m_log.DebugFormat(
1820 "[LLUDPSERVER]: No client found for CompleteAgentMovement from {0} in {1} after wait. Dropping.",
1821 endPoint, m_scene.Name);
1822
1823 return;
1824 }
1825 else if (!client.IsActive || client.SceneAgent == null)
1826 {
1827 // This check exists to catch a condition where the client has been closed by another thread
1828 // but has not yet been removed from the client manager.
1829 // The packet could be simply ignored but it is useful to know if this condition occurred for other debugging
1830 // purposes.
1831 m_log.DebugFormat(
1832 "[LLUDPSERVER]: Received a CompleteAgentMovement from {0} for {1} in {2} but client is not active after wait. Dropping.",
1833 endPoint, client.Name, m_scene.Name);
1834
1792 return; 1835 return;
1836 }
1793 1837
1794 IncomingPacket incomingPacket1; 1838 IncomingPacket incomingPacket1;
1795 1839
@@ -1810,7 +1854,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1810 catch (Exception e) 1854 catch (Exception e)
1811 { 1855 {
1812 m_log.ErrorFormat( 1856 m_log.ErrorFormat(
1813 "[LLUDPSERVER]: CompleteMovementIntoRegion handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", 1857 "[LLUDPSERVER]: CompleteAgentMovement handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}",
1814 endPoint != null ? endPoint.ToString() : "n/a", 1858 endPoint != null ? endPoint.ToString() : "n/a",
1815 client != null ? client.Name : "unknown", 1859 client != null ? client.Name : "unknown",
1816 client != null ? client.AgentId.ToString() : "unknown", 1860 client != null ? client.AgentId.ToString() : "unknown",
@@ -1921,7 +1965,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1921 client.Kick("Simulator logged you out due to connection timeout."); 1965 client.Kick("Simulator logged you out due to connection timeout.");
1922 } 1966 }
1923 1967
1924 m_scene.IncomingCloseAgent(client.AgentId, true); 1968 m_scene.CloseAgent(client.AgentId, true);
1925 } 1969 }
1926 1970
1927 private void IncomingPacketHandler() 1971 private void IncomingPacketHandler()
@@ -2264,7 +2308,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2264 if (!client.IsLoggingOut) 2308 if (!client.IsLoggingOut)
2265 { 2309 {
2266 client.IsLoggingOut = true; 2310 client.IsLoggingOut = true;
2267 m_scene.IncomingCloseAgent(client.AgentId, false); 2311 m_scene.CloseAgent(client.AgentId, false);
2268 } 2312 }
2269 } 2313 }
2270 } 2314 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 48c5b37..881e768 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -291,7 +291,16 @@ namespace OpenMetaverse
291 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort); 291 m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort);
292 } 292 }
293 } 293 }
294 catch (ObjectDisposedException) { } 294 catch (ObjectDisposedException e)
295 {
296 m_log.Error(
297 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
298 }
299 catch (Exception e)
300 {
301 m_log.Error(
302 string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e);
303 }
295 } 304 }
296 } 305 }
297 306
@@ -308,12 +317,12 @@ namespace OpenMetaverse
308 if (m_asyncPacketHandling) 317 if (m_asyncPacketHandling)
309 AsyncBeginReceive(); 318 AsyncBeginReceive();
310 319
311 // get the buffer that was created in AsyncBeginReceive
312 // this is the received data
313 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
314
315 try 320 try
316 { 321 {
322 // get the buffer that was created in AsyncBeginReceive
323 // this is the received data
324 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
325
317 int startTick = Util.EnvironmentTickCount(); 326 int startTick = Util.EnvironmentTickCount();
318 327
319 // get the length of data actually read from the socket, store it with the 328 // get the length of data actually read from the socket, store it with the
@@ -341,8 +350,24 @@ namespace OpenMetaverse
341 m_currentReceiveTimeSamples++; 350 m_currentReceiveTimeSamples++;
342 } 351 }
343 } 352 }
344 catch (SocketException) { } 353 catch (SocketException se)
345 catch (ObjectDisposedException) { } 354 {
355 m_log.Error(
356 string.Format(
357 "[UDPBASE]: Error processing UDP end receive {0}, socket error code {1}. Exception ",
358 UdpReceives, se.ErrorCode),
359 se);
360 }
361 catch (ObjectDisposedException e)
362 {
363 m_log.Error(
364 string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e);
365 }
366 catch (Exception e)
367 {
368 m_log.Error(
369 string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e);
370 }
346 finally 371 finally
347 { 372 {
348// if (UsePools) 373// if (UsePools)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
index 119a677..e2178e5 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/MockScene.cs
@@ -52,17 +52,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
52 public override void Update(int frames) {} 52 public override void Update(int frames) {}
53 public override void LoadWorldMap() {} 53 public override void LoadWorldMap() {}
54 54
55 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 55 public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type)
56 { 56 {
57 client.OnObjectName += RecordObjectNameCall; 57 client.OnObjectName += RecordObjectNameCall;
58 58
59 // FIXME 59 // FIXME
60 return null; 60 return null;
61 } 61 }
62 62
63 public override void RemoveClient(UUID agentID, bool someReason) {} 63 public override bool CloseAgent(UUID agentID, bool force) { return true; }
64// public override void CloseAllAgents(uint circuitcode) {} 64
65 public override bool CheckClient(UUID clientId, IPEndPoint endPoint) { return true; } 65 public override bool CheckClient(UUID clientId, IPEndPoint endPoint) { return true; }
66
66 public override void OtherRegionUp(GridRegion otherRegion) { } 67 public override void OtherRegionUp(GridRegion otherRegion) { }
67 68
68 public override bool TryGetScenePresence(UUID uuid, out ScenePresence sp) { sp = null; return false; } 69 public override bool TryGetScenePresence(UUID uuid, out ScenePresence sp) { sp = null; return false; }
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 95cc6b7..81a7278 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -482,13 +482,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
482 attachPos = Vector3.Zero; 482 attachPos = Vector3.Zero;
483 } 483 }
484 484
485 // AttachmentPt 0 (default) means the client chose to 'wear' the attachment. 485 // if the attachment point is the same as previous, make sure we get the saved
486 // position info.
487 if (attachmentPt != 0 && attachmentPt == group.RootPart.Shape.LastAttachPoint)
488 {
489 attachPos = group.RootPart.AttachedPos;
490 }
491
492 // AttachmentPt 0 means the client chose to 'wear' the attachment.
486 if (attachmentPt == (uint)AttachmentPoint.Default) 493 if (attachmentPt == (uint)AttachmentPoint.Default)
487 { 494 {
488 // Check object for stored attachment point 495 // Check object for stored attachment point
489 attachmentPt = group.AttachmentPoint; 496 attachmentPt = group.AttachmentPoint;
490 } 497 }
491 498
499 // if we didn't find an attach point, look for where it was last attached
500 if (attachmentPt == 0)
501 {
502 attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint;
503 attachPos = group.RootPart.AttachedPos;
504 group.HasGroupChanged = true;
505 }
506
492 // if we still didn't find a suitable attachment point....... 507 // if we still didn't find a suitable attachment point.......
493 if (attachmentPt == 0) 508 if (attachmentPt == 0)
494 { 509 {
@@ -684,6 +699,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
684 so.ClearPartAttachmentData(); 699 so.ClearPartAttachmentData();
685 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive,false); 700 rootPart.ApplyPhysics(rootPart.GetEffectiveObjectFlags(), rootPart.VolumeDetectActive,false);
686 so.HasGroupChanged = true; 701 so.HasGroupChanged = true;
702 so.RootPart.Shape.LastAttachPoint = (byte)so.AttachmentPoint;
687 rootPart.Rezzed = DateTime.Now; 703 rootPart.Rezzed = DateTime.Now;
688 rootPart.RemFlag(PrimFlags.TemporaryOnRez); 704 rootPart.RemFlag(PrimFlags.TemporaryOnRez);
689 so.AttachToBackup(); 705 so.AttachToBackup();
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 62acd78..f023e77 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -719,7 +719,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
719 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; 719 SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
720 720
721 m_numberOfAttachEventsFired = 0; 721 m_numberOfAttachEventsFired = 0;
722 scene.IncomingCloseAgent(presence.UUID, false); 722 scene.CloseAgent(presence.UUID, false);
723 723
724 // Check that we can't retrieve this attachment from the scene. 724 // Check that we can't retrieve this attachment from the scene.
725 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); 725 Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);
diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
index 6b14fa6..adb838c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs
@@ -276,7 +276,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods
276 if (sp.IsChildAgent) 276 if (sp.IsChildAgent)
277 return; 277 return;
278 sp.ControllingClient.Kick(reason); 278 sp.ControllingClient.Kick(reason);
279 sp.Scene.IncomingCloseAgent(sp.UUID, true); 279 sp.Scene.CloseAgent(sp.UUID, true);
280 } 280 }
281 281
282 private void OnIncomingInstantMessage(GridInstantMessage msg) 282 private void OnIncomingInstantMessage(GridInstantMessage msg)
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index e285f21..03aaaac 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -149,8 +149,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
149 private void OnInstantMessage(IClientAPI client, GridInstantMessage im) 149 private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
150 { 150 {
151// m_log.DebugFormat( 151// m_log.DebugFormat(
152// "[INVENTORY TRANSFER]: {0} IM type received from {1}", 152// "[INVENTORY TRANSFER]: {0} IM type received from client {1}. From={2} ({3}), To={4}",
153// (InstantMessageDialog)im.dialog, client.Name); 153// (InstantMessageDialog)im.dialog, client.Name,
154// im.fromAgentID, im.fromAgentName, im.toAgentID);
154 155
155 Scene scene = FindClientScene(client.AgentId); 156 Scene scene = FindClientScene(client.AgentId);
156 157
@@ -467,9 +468,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
467 /// <summary> 468 /// <summary>
468 /// 469 ///
469 /// </summary> 470 /// </summary>
470 /// <param name="msg"></param> 471 /// <param name="im"></param>
471 private void OnGridInstantMessage(GridInstantMessage im) 472 private void OnGridInstantMessage(GridInstantMessage im)
472 { 473 {
474 // Check if it's a type of message that we should handle
475 if (!((im.dialog == (byte) InstantMessageDialog.InventoryOffered)
476 || (im.dialog == (byte) InstantMessageDialog.InventoryAccepted)
477 || (im.dialog == (byte) InstantMessageDialog.InventoryDeclined)
478 || (im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined)))
479 return;
480
481 m_log.DebugFormat(
482 "[INVENTORY TRANSFER]: {0} IM type received from grid. From={1} ({2}), To={3}",
483 (InstantMessageDialog)im.dialog, im.fromAgentID, im.fromAgentName, im.toAgentID);
484
473 // Check if this is ours to handle 485 // Check if this is ours to handle
474 // 486 //
475 Scene scene = FindClientScene(new UUID(im.toAgentID)); 487 Scene scene = FindClientScene(new UUID(im.toAgentID));
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
index 0c64f19..c517a30 100644
--- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs
@@ -165,7 +165,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure
165 (uint)presence.AbsolutePosition.Y, 165 (uint)presence.AbsolutePosition.Y,
166 (uint)presence.AbsolutePosition.Z + 2); 166 (uint)presence.AbsolutePosition.Z + 2);
167 167
168 m_log.DebugFormat("TP invite with message {0}, type {1}", message, lureType); 168 m_log.DebugFormat("[LURE MODULE]: TP invite with message {0}, type {1}", message, lureType);
169 169
170 GridInstantMessage m; 170 GridInstantMessage m;
171 171
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index ed14c12..ef5239a 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -56,6 +56,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
56 public const int DefaultMaxTransferDistance = 4095; 56 public const int DefaultMaxTransferDistance = 4095;
57 public const bool WaitForAgentArrivedAtDestinationDefault = true; 57 public const bool WaitForAgentArrivedAtDestinationDefault = true;
58 58
59 public string OutgoingTransferVersionName { get; set; }
60
61 /// <summary>
62 /// Determine the maximum entity transfer version we will use for teleports.
63 /// </summary>
64 public float MaxOutgoingTransferVersion { get; set; }
65
59 /// <summary> 66 /// <summary>
60 /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer. 67 /// The maximum distance, in standard region units (256m) that an agent is allowed to transfer.
61 /// </summary> 68 /// </summary>
@@ -151,9 +158,39 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
151 /// <param name="source"></param> 158 /// <param name="source"></param>
152 protected virtual void InitialiseCommon(IConfigSource source) 159 protected virtual void InitialiseCommon(IConfigSource source)
153 { 160 {
161 string transferVersionName = "SIMULATION";
162 float maxTransferVersion = 0.2f;
163
154 IConfig transferConfig = source.Configs["EntityTransfer"]; 164 IConfig transferConfig = source.Configs["EntityTransfer"];
155 if (transferConfig != null) 165 if (transferConfig != null)
156 { 166 {
167 string rawVersion
168 = transferConfig.GetString(
169 "MaxOutgoingTransferVersion",
170 string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
171
172 string[] rawVersionComponents = rawVersion.Split(new char[] { '/' });
173
174 bool versionValid = false;
175
176 if (rawVersionComponents.Length >= 2)
177 versionValid = float.TryParse(rawVersionComponents[1], out maxTransferVersion);
178
179 if (!versionValid)
180 {
181 m_log.ErrorFormat(
182 "[ENTITY TRANSFER MODULE]: MaxOutgoingTransferVersion {0} is invalid, using {1}",
183 rawVersion, string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
184 }
185 else
186 {
187 transferVersionName = rawVersionComponents[0];
188
189 m_log.InfoFormat(
190 "[ENTITY TRANSFER MODULE]: MaxOutgoingTransferVersion set to {0}",
191 string.Format("{0}/{1}", transferVersionName, maxTransferVersion));
192 }
193
157 DisableInterRegionTeleportCancellation 194 DisableInterRegionTeleportCancellation
158 = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false); 195 = transferConfig.GetBoolean("DisableInterRegionTeleportCancellation", false);
159 196
@@ -167,6 +204,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
167 MaxTransferDistance = DefaultMaxTransferDistance; 204 MaxTransferDistance = DefaultMaxTransferDistance;
168 } 205 }
169 206
207 OutgoingTransferVersionName = transferVersionName;
208 MaxOutgoingTransferVersion = maxTransferVersion;
209
170 m_entityTransferStateMachine = new EntityTransferStateMachine(this); 210 m_entityTransferStateMachine = new EntityTransferStateMachine(this);
171 211
172 m_Enabled = true; 212 m_Enabled = true;
@@ -522,6 +562,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
522 /// </returns> 562 /// </returns>
523 private bool IsWithinMaxTeleportDistance(RegionInfo sourceRegion, GridRegion destRegion) 563 private bool IsWithinMaxTeleportDistance(RegionInfo sourceRegion, GridRegion destRegion)
524 { 564 {
565 if(MaxTransferDistance == 0)
566 return true;
567
525// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY); 568// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Source co-ords are x={0} y={1}", curRegionX, curRegionY);
526// 569//
527// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}", 570// m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Final dest is x={0} y={1} {2}@{3}",
@@ -623,7 +666,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
623 if (!sp.ValidateAttachments()) 666 if (!sp.ValidateAttachments())
624 m_log.DebugFormat( 667 m_log.DebugFormat(
625 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.", 668 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
626 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName); 669 sp.Name, sp.Scene.Name, finalDestination.RegionName);
627 670
628 string reason; 671 string reason;
629 string version; 672 string version;
@@ -634,7 +677,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
634 677
635 m_log.DebugFormat( 678 m_log.DebugFormat(
636 "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}", 679 "[ENTITY TRANSFER MODULE]: {0} was stopped from teleporting from {1} to {2} because {3}",
637 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName, reason); 680 sp.Name, sp.Scene.Name, finalDestination.RegionName, reason);
638 681
639 return; 682 return;
640 } 683 }
@@ -644,7 +687,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
644 // as server attempts. 687 // as server attempts.
645 m_interRegionTeleportAttempts.Value++; 688 m_interRegionTeleportAttempts.Value++;
646 689
647 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); 690 m_log.DebugFormat(
691 "[ENTITY TRANSFER MODULE]: {0} max transfer version is {1}/{2}, {3} max version is {4}",
692 sp.Scene.Name, OutgoingTransferVersionName, MaxOutgoingTransferVersion, finalDestination.RegionName, version);
648 693
649 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from 694 // Fixing a bug where teleporting while sitting results in the avatar ending up removed from
650 // both regions 695 // both regions
@@ -691,7 +736,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
691 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); 736 agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath();
692 } 737 }
693 738
694 if (version.Equals("SIMULATION/0.2")) 739 // We're going to fallback to V1 if the destination gives us anything smaller than 0.2 or we're forcing
740 // use of the earlier protocol
741 float versionNumber = 0.1f;
742 string[] versionComponents = version.Split(new char[] { '/' });
743 if (versionComponents.Length >= 2)
744 float.TryParse(versionComponents[1], out versionNumber);
745
746 if (versionNumber == 0.2f && MaxOutgoingTransferVersion >= versionNumber)
695 TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason); 747 TransferAgent_V2(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
696 else 748 else
697 TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason); 749 TransferAgent_V1(sp, agentCircuit, reg, finalDestination, endPoint, teleportFlags, oldRegionX, newRegionX, oldRegionY, newRegionY, version, out reason);
@@ -925,7 +977,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
925 977
926 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 978 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
927 { 979 {
928 if (!sp.Scene.IncomingPreCloseAgent(sp)) 980 if (!sp.Scene.IncomingPreCloseClient(sp))
929 return; 981 return;
930 982
931 // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before 983 // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before
@@ -936,7 +988,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
936 // an agent cannot teleport back to this region if it has teleported away. 988 // an agent cannot teleport back to this region if it has teleported away.
937 Thread.Sleep(2000); 989 Thread.Sleep(2000);
938 990
939 sp.Scene.IncomingCloseAgent(sp.UUID, false); 991 sp.Scene.CloseAgent(sp.UUID, false);
940 } 992 }
941 else 993 else
942 { 994 {
@@ -1090,7 +1142,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1090 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 1142 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1091 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 1143 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
1092 { 1144 {
1093 if (!sp.Scene.IncomingPreCloseAgent(sp)) 1145 if (!sp.Scene.IncomingPreCloseClient(sp))
1094 return; 1146 return;
1095 1147
1096 // RED ALERT!!!! 1148 // RED ALERT!!!!
@@ -1107,7 +1159,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1107 m_log.DebugFormat( 1159 m_log.DebugFormat(
1108 "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name); 1160 "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name);
1109 1161
1110 sp.Scene.IncomingCloseAgent(sp.UUID, false); 1162 sp.Scene.CloseAgent(sp.UUID, false);
1111 } 1163 }
1112 else 1164 else
1113 { 1165 {
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
index 1cf1884..74b834a 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs
@@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
181 if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) 181 if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI"))
182 { 182 {
183 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); 183 string url = aCircuit.ServiceURLs["AssetServerURI"].ToString();
184 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachement {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url); 184 m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachment {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url);
185 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>(); 185 Dictionary<UUID, AssetType> ids = new Dictionary<UUID, AssetType>();
186 HGUuidGatherer uuidGatherer = new HGUuidGatherer(Scene.AssetService, url); 186 HGUuidGatherer uuidGatherer = new HGUuidGatherer(Scene.AssetService, url);
187 uuidGatherer.GatherAssetUuids(so, ids); 187 uuidGatherer.GatherAssetUuids(so, ids);
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index 89bb037..3feeb13 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -906,6 +906,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
906 m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3"); 906 m_log.Debug("[INVENTORY ACCESS MODULE]: Object has UUID.Zero! Position 3");
907 } 907 }
908 908
909 // if this was previously an attachment and is now being rezzed,
910 // save the old attachment info.
911 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
912 {
913 group.RootPart.AttachedPos = group.AbsolutePosition;
914 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
915 }
916
909 foreach (SceneObjectPart part in group.Parts) 917 foreach (SceneObjectPart part in group.Parts)
910 { 918 {
911 // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset. 919 // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset.
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index 8c983e6..d3926cc 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -178,17 +178,20 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
178 m_ServiceThrottle.Enqueue("name", uuid.ToString(), delegate 178 m_ServiceThrottle.Enqueue("name", uuid.ToString(), delegate
179 { 179 {
180 //m_log.DebugFormat("[YYY]: Name request {0}", uuid); 180 //m_log.DebugFormat("[YYY]: Name request {0}", uuid);
181 bool foundRealName = TryGetUserNames(uuid, names);
182
183 if (names.Length == 2)
184 {
185 if (!foundRealName)
186 m_log.DebugFormat("[USER MANAGEMENT MODULE]: Sending {0} {1} for {2} to {3} since no bound name found", names[0], names[1], uuid, client.Name);
187 181
182 // As least upto September 2013, clients permanently cache UUID -> Name bindings. Some clients
183 // appear to clear this when the user asks it to clear the cache, but others may not.
184 //
185 // So to avoid clients
186 // (particularly Hypergrid clients) permanently binding "Unknown User" to a given UUID, we will
187 // instead drop the request entirely.
188 if (TryGetUserNames(uuid, names))
188 client.SendNameReply(uuid, names[0], names[1]); 189 client.SendNameReply(uuid, names[0], names[1]);
189 } 190// else
191// m_log.DebugFormat(
192// "[USER MANAGEMENT MODULE]: No bound name for {0} found, ignoring request from {1}",
193// uuid, client.Name);
190 }); 194 });
191
192 } 195 }
193 } 196 }
194 197
@@ -391,7 +394,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
391 } 394 }
392 395
393 names[0] = "Unknown"; 396 names[0] = "Unknown";
394 names[1] = "UserUMMTGUN8"; 397 names[1] = "UserUMMTGUN9";
395 398
396 return false; 399 return false;
397 } 400 }
@@ -539,7 +542,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
539 AddUser(uuid, homeURL + ";" + first + " " + last); 542 AddUser(uuid, homeURL + ";" + first + " " + last);
540 } 543 }
541 544
542 public void AddUser (UUID id, string creatorData) 545 public void AddUser(UUID id, string creatorData)
543 { 546 {
544 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData); 547 //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData);
545 548
@@ -599,6 +602,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
599 user.LastName = "@unknown"; 602 user.LastName = "@unknown";
600 } 603 }
601 } 604 }
605
602 if (parts.Length >= 2) 606 if (parts.Length >= 2)
603 user.FirstName = parts[1].Replace(' ', '.'); 607 user.FirstName = parts[1].Replace(' ', '.');
604 } 608 }
@@ -611,7 +615,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
611 user.FirstName = "Unknown"; 615 user.FirstName = "Unknown";
612 user.LastName = "UserUMMAU4"; 616 user.LastName = "UserUMMAU4";
613 } 617 }
614 618
615 AddUserInternal(user); 619 AddUserInternal(user);
616 } 620 }
617 } 621 }
@@ -639,6 +643,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
639 643
640 protected void Init() 644 protected void Init()
641 { 645 {
646 AddUser(UUID.Zero, "Unknown", "User");
642 RegisterConsoleCmds(); 647 RegisterConsoleCmds();
643 } 648 }
644 649
diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
index f196973..8946b5c 100644
--- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs
@@ -129,7 +129,7 @@ namespace OpenSim.Region.CoreModules.Hypergrid
129 b.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's 129 b.Access = 254; // means 'simulator is offline'. We need this because the viewer ignores 255's
130 } 130 }
131 131
132 m_log.DebugFormat("[HG MAP]: Reseting {0} blocks", mapBlocks.Count); 132 m_log.DebugFormat("[HG MAP]: Resetting {0} blocks", mapBlocks.Count);
133 sp.ControllingClient.SendMapBlock(mapBlocks, 0); 133 sp.ControllingClient.SendMapBlock(mapBlocks, 0);
134 m_SeenMapBlocks.Remove(clientID); 134 m_SeenMapBlocks.Remove(clientID);
135 } 135 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
index a9aa73c..3be80eb 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs
@@ -94,7 +94,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
94 throw new Exception(string.Format("Invalid ConnectorProtocolVersion {0}", ServiceVersion)); 94 throw new Exception(string.Format("Invalid ConnectorProtocolVersion {0}", ServiceVersion));
95 95
96 m_log.InfoFormat( 96 m_log.InfoFormat(
97 "[LOCAL SIMULATION CONNECTOR]: Initialzied with connector protocol version {0}", ServiceVersion); 97 "[LOCAL SIMULATION CONNECTOR]: Initialized with connector protocol version {0}", ServiceVersion);
98 } 98 }
99 } 99 }
100 100
@@ -235,7 +235,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
235// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", 235// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
236// destination.RegionName, destination.RegionID); 236// destination.RegionName, destination.RegionID);
237 237
238 return m_scenes[destination.RegionID].IncomingChildAgentDataUpdate(cAgentData); 238 return m_scenes[destination.RegionID].IncomingUpdateChildAgent(cAgentData);
239 } 239 }
240 240
241// m_log.DebugFormat( 241// m_log.DebugFormat(
@@ -245,7 +245,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
245 return false; 245 return false;
246 } 246 }
247 247
248 public bool UpdateAgent(GridRegion destination, AgentPosition cAgentData) 248 public bool UpdateAgent(GridRegion destination, AgentPosition agentPosition)
249 { 249 {
250 if (destination == null) 250 if (destination == null)
251 return false; 251 return false;
@@ -257,7 +257,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
257 foreach (Scene s in m_scenes.Values) 257 foreach (Scene s in m_scenes.Values)
258 { 258 {
259// m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate"); 259// m_log.Debug("[LOCAL COMMS]: Found region to send ChildAgentUpdate");
260 s.IncomingChildAgentDataUpdate(cAgentData); 260 s.IncomingUpdateChildAgent(agentPosition);
261 } 261 }
262 262
263 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate"); 263 //m_log.Debug("[LOCAL COMMS]: region not found for ChildAgentUpdate");
@@ -311,7 +311,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
311// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", 311// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
312// s.RegionInfo.RegionName, destination.RegionHandle); 312// s.RegionInfo.RegionName, destination.RegionHandle);
313 313
314 m_scenes[destination.RegionID].IncomingCloseAgent(id, false, auth_token); 314 m_scenes[destination.RegionID].CloseAgent(id, false, auth_token);
315 return true; 315 return true;
316 } 316 }
317 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); 317 //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent");
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 1808fdd..487aa09 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -572,7 +572,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
572 if (!Scene.TeleportClientHome(user, s.ControllingClient)) 572 if (!Scene.TeleportClientHome(user, s.ControllingClient))
573 { 573 {
574 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out."); 574 s.ControllingClient.Kick("Your access to the region was revoked and TP home failed - you have been logged out.");
575 Scene.IncomingCloseAgent(s.UUID, false); 575 Scene.CloseAgent(s.UUID, false);
576 } 576 }
577 } 577 }
578 } 578 }
@@ -807,7 +807,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
807 if (!Scene.TeleportClientHome(prey, s.ControllingClient)) 807 if (!Scene.TeleportClientHome(prey, s.ControllingClient))
808 { 808 {
809 s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); 809 s.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
810 Scene.IncomingCloseAgent(s.UUID, false); 810 Scene.CloseAgent(s.UUID, false);
811 } 811 }
812 } 812 }
813 } 813 }
@@ -830,7 +830,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
830 if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient)) 830 if (!Scene.TeleportClientHome(p.UUID, p.ControllingClient))
831 { 831 {
832 p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out."); 832 p.ControllingClient.Kick("You were teleported home by the region owner, but the TP failed - you have been logged out.");
833 Scene.IncomingCloseAgent(p.UUID, false); 833 Scene.CloseAgent(p.UUID, false);
834 } 834 }
835 } 835 }
836 } 836 }
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 6e8eb91..7f06e82 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -148,7 +148,7 @@ namespace OpenSim.Region.Framework.Scenes
148 /// Triggered when a new presence is added to the scene 148 /// Triggered when a new presence is added to the scene
149 /// </summary> 149 /// </summary>
150 /// <remarks> 150 /// <remarks>
151 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both 151 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both
152 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> 152 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
153 /// </remarks> 153 /// </remarks>
154 public event OnNewPresenceDelegate OnNewPresence; 154 public event OnNewPresenceDelegate OnNewPresence;
@@ -159,7 +159,7 @@ namespace OpenSim.Region.Framework.Scenes
159 /// Triggered when a presence is removed from the scene 159 /// Triggered when a presence is removed from the scene
160 /// </summary> 160 /// </summary>
161 /// <remarks> 161 /// <remarks>
162 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both 162 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/> which is used by both
163 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see> 163 /// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
164 /// 164 ///
165 /// Triggered under per-agent lock. So if you want to perform any long-running operations, please 165 /// Triggered under per-agent lock. So if you want to perform any long-running operations, please
@@ -1107,7 +1107,7 @@ namespace OpenSim.Region.Framework.Scenes
1107 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/> 1107 /// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/>
1108 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/> 1108 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/>
1109 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/> 1109 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/>
1110 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> 1110 /// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewAgent"/>
1111 /// </remarks> 1111 /// </remarks>
1112 public event MoneyTransferEvent OnMoneyTransfer; 1112 public event MoneyTransferEvent OnMoneyTransfer;
1113 1113
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 4337b5a..659bde9 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -507,6 +507,9 @@ namespace OpenSim.Region.Framework.Scenes
507 // This MAY be problematic, if it is, another solution 507 // This MAY be problematic, if it is, another solution
508 // needs to be found. If inventory item flags are updated 508 // needs to be found. If inventory item flags are updated
509 // the viewer's notion of the item needs to be refreshed. 509 // the viewer's notion of the item needs to be refreshed.
510 //
511 // In other situations we cannot send out a bulk update here, since this will cause editing of clothing to start
512 // failing frequently. Possibly this is a race with a separate transaction that uploads the asset.
510 if (sendUpdate) 513 if (sendUpdate)
511 remoteClient.SendBulkUpdateInventory(item); 514 remoteClient.SendBulkUpdateInventory(item);
512 } 515 }
@@ -2393,6 +2396,13 @@ namespace OpenSim.Region.Framework.Scenes
2393 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2396 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2394 } 2397 }
2395 2398
2399
2400 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2401 {
2402 group.RootPart.AttachedPos = group.AbsolutePosition;
2403 group.RootPart.Shape.LastAttachPoint = (byte)group.AttachmentPoint;
2404 }
2405
2396 group.FromPartID = sourcePart.UUID; 2406 group.FromPartID = sourcePart.UUID;
2397 AddNewSceneObject(group, true, pos, rot, vel); 2407 AddNewSceneObject(group, true, pos, rot, vel);
2398 2408
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index d6d2df4..21036d8 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -751,6 +751,7 @@ namespace OpenSim.Region.Framework.Scenes
751 m_config = config; 751 m_config = config;
752 MinFrameTime = 0.089f; 752 MinFrameTime = 0.089f;
753 MinMaintenanceTime = 1; 753 MinMaintenanceTime = 1;
754 SeeIntoRegion = true;
754 755
755 Random random = new Random(); 756 Random random = new Random();
756 757
@@ -863,6 +864,7 @@ namespace OpenSim.Region.Framework.Scenes
863 //Animation states 864 //Animation states
864 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 865 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
865 866
867 SeeIntoRegion = startupConfig.GetBoolean("see_into_region", SeeIntoRegion);
866 868
867 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); 869 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
868 870
@@ -1338,7 +1340,7 @@ namespace OpenSim.Region.Framework.Scenes
1338 Thread.Sleep(500); 1340 Thread.Sleep(500);
1339 1341
1340 // Stop all client threads. 1342 // Stop all client threads.
1341 ForEachScenePresence(delegate(ScenePresence avatar) { IncomingCloseAgent(avatar.UUID, false); }); 1343 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); });
1342 1344
1343 m_log.Debug("[SCENE]: TriggerSceneShuttingDown"); 1345 m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
1344 EventManager.TriggerSceneShuttingDown(this); 1346 EventManager.TriggerSceneShuttingDown(this);
@@ -2953,7 +2955,7 @@ namespace OpenSim.Region.Framework.Scenes
2953 2955
2954 #region Add/Remove Avatar Methods 2956 #region Add/Remove Avatar Methods
2955 2957
2956 public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) 2958 public override ISceneAgent AddNewAgent(IClientAPI client, PresenceType type)
2957 { 2959 {
2958 ScenePresence sp; 2960 ScenePresence sp;
2959 bool vialogin; 2961 bool vialogin;
@@ -2961,7 +2963,7 @@ namespace OpenSim.Region.Framework.Scenes
2961 2963
2962 // Validation occurs in LLUDPServer 2964 // Validation occurs in LLUDPServer
2963 // 2965 //
2964 // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with 2966 // XXX: A race condition exists here where two simultaneous calls to AddNewAgent can interfere with
2965 // each other. In practice, this does not currently occur in the code. 2967 // each other. In practice, this does not currently occur in the code.
2966 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); 2968 AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode);
2967 2969
@@ -2969,9 +2971,9 @@ namespace OpenSim.Region.Framework.Scenes
2969 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point 2971 // and a simultaneous one that removes it (as can happen if the client is closed at a particular point
2970 // whilst connecting). 2972 // whilst connecting).
2971 // 2973 //
2972 // It would be easier to lock across all NewUserConnection(), AddNewClient() and 2974 // It would be easier to lock across all NewUserConnection(), AddNewAgent() and
2973 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service 2975 // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service
2974 // response in some module listening to AddNewClient()) from holding up unrelated agent calls. 2976 // response in some module listening to AddNewAgent()) from holding up unrelated agent calls.
2975 // 2977 //
2976 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all 2978 // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all
2977 // AddNewClient() operations (though not other ops). 2979 // AddNewClient() operations (though not other ops).
@@ -2988,7 +2990,7 @@ namespace OpenSim.Region.Framework.Scenes
2988 2990
2989 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this 2991 // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this
2990 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause 2992 // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause
2991 // other problems, and possible the code calling AddNewClient() should ensure that no client is already 2993 // other problems, and possibly the code calling AddNewAgent() should ensure that no client is already
2992 // connected. 2994 // connected.
2993 if (sp == null) 2995 if (sp == null)
2994 { 2996 {
@@ -3021,6 +3023,9 @@ namespace OpenSim.Region.Framework.Scenes
3021 3023
3022 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the 3024 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
3023 // client is for a root or child agent. 3025 // client is for a root or child agent.
3026 // XXX: This may be better set for a new client before that client is added to the client manager.
3027 // But need to know what happens in the case where a ScenePresence is already present (and if this
3028 // actually occurs).
3024 client.SceneAgent = sp; 3029 client.SceneAgent = sp;
3025 3030
3026 // This is currently also being done earlier in NewUserConnection for real users to see if this 3031 // This is currently also being done earlier in NewUserConnection for real users to see if this
@@ -3130,7 +3135,7 @@ namespace OpenSim.Region.Framework.Scenes
3130 { 3135 {
3131 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3136 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
3132 3137
3133 IncomingCloseAgent(sp.UUID, false); 3138 CloseAgent(sp.UUID, false);
3134 } 3139 }
3135 3140
3136 // BANG! SLASH! 3141 // BANG! SLASH!
@@ -3554,7 +3559,7 @@ namespace OpenSim.Region.Framework.Scenes
3554 /// <param name='closeChildAgents'> 3559 /// <param name='closeChildAgents'>
3555 /// Close the neighbour child agents associated with this client. 3560 /// Close the neighbour child agents associated with this client.
3556 /// </param> 3561 /// </param>
3557 public override void RemoveClient(UUID agentID, bool closeChildAgents) 3562 public void RemoveClient(UUID agentID, bool closeChildAgents)
3558 { 3563 {
3559 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3564 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
3560 3565
@@ -3940,7 +3945,7 @@ namespace OpenSim.Region.Framework.Scenes
3940 sp.Name, sp.UUID, RegionInfo.RegionName); 3945 sp.Name, sp.UUID, RegionInfo.RegionName);
3941 3946
3942 if (sp.ControllingClient != null) 3947 if (sp.ControllingClient != null)
3943 IncomingCloseAgent(sp.UUID, true); 3948 CloseAgent(sp.UUID, true);
3944 3949
3945 sp = null; 3950 sp = null;
3946 } 3951 }
@@ -4024,19 +4029,6 @@ namespace OpenSim.Region.Framework.Scenes
4024 // Let the SP know how we got here. This has a lot of interesting 4029 // Let the SP know how we got here. This has a lot of interesting
4025 // uses down the line. 4030 // uses down the line.
4026 sp.TeleportFlags = (TPFlags)teleportFlags; 4031 sp.TeleportFlags = (TPFlags)teleportFlags;
4027
4028 // We must carry out a further authorization check if there's an
4029 // attempt to make a child agent into a root agent, since SeeIntoRegion may have allowed a child
4030 // agent to login to a region where a full avatar would not be allowed.
4031 //
4032 // We determine whether this is a CreateAgent for a future non-child agent by inspecting
4033 // TeleportFlags, which will be default for a child connection. This relies on input from the source
4034 // region.
4035 if (sp.TeleportFlags != TPFlags.Default)
4036 {
4037 if (!AuthorizeUser(acd, false, out reason))
4038 return false;
4039 }
4040 4032
4041 if (sp.IsChildAgent) 4033 if (sp.IsChildAgent)
4042 { 4034 {
@@ -4469,7 +4461,7 @@ namespace OpenSim.Region.Framework.Scenes
4469 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent. 4461 /// <param name="cAgentData">Agent that contains all of the relevant things about an agent.
4470 /// Appearance, animations, position, etc.</param> 4462 /// Appearance, animations, position, etc.</param>
4471 /// <returns>true if we handled it.</returns> 4463 /// <returns>true if we handled it.</returns>
4472 public virtual bool IncomingChildAgentDataUpdate(AgentData cAgentData) 4464 public virtual bool IncomingUpdateChildAgent(AgentData cAgentData)
4473 { 4465 {
4474 m_log.DebugFormat( 4466 m_log.DebugFormat(
4475 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4467 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
@@ -4487,7 +4479,7 @@ namespace OpenSim.Region.Framework.Scenes
4487 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4479 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
4488 if (nearestParcel == null) 4480 if (nearestParcel == null)
4489 { 4481 {
4490 m_log.DebugFormat( 4482 m_log.InfoFormat(
4491 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel", 4483 "[SCENE]: Denying root agent entry to {0} in {1}: no allowed parcel",
4492 cAgentData.AgentID, RegionInfo.RegionName); 4484 cAgentData.AgentID, RegionInfo.RegionName);
4493 4485
@@ -4497,7 +4489,7 @@ namespace OpenSim.Region.Framework.Scenes
4497 // We have to wait until the viewer contacts this region 4489 // We have to wait until the viewer contacts this region
4498 // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol) 4490 // after receiving the EnableSimulator HTTP Event Queue message (for the v1 teleport protocol)
4499 // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send 4491 // or TeleportFinish (for the v2 teleport protocol). This triggers the viewer to send
4500 // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. 4492 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
4501 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID); 4493 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4502 4494
4503 if (sp != null) 4495 if (sp != null)
@@ -4512,7 +4504,7 @@ namespace OpenSim.Region.Framework.Scenes
4512 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID)); 4504 sp.UUID, sp.ControllingClient.SessionId, cAgentData.SessionID));
4513 } 4505 }
4514 4506
4515 sp.ChildAgentDataUpdate(cAgentData); 4507 sp.UpdateChildAgent(cAgentData);
4516 4508
4517 int ntimes = 20; 4509 int ntimes = 20;
4518 if (cAgentData.SenderWantsToWaitForRoot) 4510 if (cAgentData.SenderWantsToWaitForRoot)
@@ -4520,9 +4512,14 @@ namespace OpenSim.Region.Framework.Scenes
4520 while (sp.IsChildAgent && ntimes-- > 0) 4512 while (sp.IsChildAgent && ntimes-- > 0)
4521 Thread.Sleep(1000); 4513 Thread.Sleep(1000);
4522 4514
4523 m_log.DebugFormat( 4515 if (sp.IsChildAgent)
4524 "[SCENE]: Found presence {0} {1} {2} in {3} after {4} waits", 4516 m_log.WarnFormat(
4525 sp.Name, sp.UUID, sp.IsChildAgent ? "child" : "root", Name, 20 - ntimes); 4517 "[SCENE]: Found presence {0} {1} unexpectedly still child in {2}",
4518 sp.Name, sp.UUID, Name);
4519 else
4520 m_log.InfoFormat(
4521 "[SCENE]: Found presence {0} {1} as root in {2} after {3} waits",
4522 sp.Name, sp.UUID, Name, 20 - ntimes);
4526 4523
4527 if (sp.IsChildAgent) 4524 if (sp.IsChildAgent)
4528 return false; 4525 return false;
@@ -4540,7 +4537,7 @@ namespace OpenSim.Region.Framework.Scenes
4540 /// </summary> 4537 /// </summary>
4541 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param> 4538 /// <param name="cAgentData">AgentPosition that contains agent positional data so we can know what to send</param>
4542 /// <returns>true if we handled it.</returns> 4539 /// <returns>true if we handled it.</returns>
4543 public virtual bool IncomingChildAgentDataUpdate(AgentPosition cAgentData) 4540 public virtual bool IncomingUpdateChildAgent(AgentPosition cAgentData)
4544 { 4541 {
4545 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName); 4542 //m_log.Debug(" XXX Scene IncomingChildAgentDataUpdate POSITION in " + RegionInfo.RegionName);
4546 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID); 4543 ScenePresence childAgentUpdate = GetScenePresence(cAgentData.AgentID);
@@ -4560,7 +4557,7 @@ namespace OpenSim.Region.Framework.Scenes
4560 uint tRegionX = RegionInfo.RegionLocX; 4557 uint tRegionX = RegionInfo.RegionLocX;
4561 uint tRegionY = RegionInfo.RegionLocY; 4558 uint tRegionY = RegionInfo.RegionLocY;
4562 //Send Data to ScenePresence 4559 //Send Data to ScenePresence
4563 childAgentUpdate.ChildAgentDataUpdate(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY); 4560 childAgentUpdate.UpdateChildAgent(cAgentData, tRegionX, tRegionY, rRegionX, rRegionY);
4564 // Not Implemented: 4561 // Not Implemented:
4565 //TODO: Do we need to pass the message on to one of our neighbors? 4562 //TODO: Do we need to pass the message on to one of our neighbors?
4566 } 4563 }
@@ -4610,7 +4607,7 @@ namespace OpenSim.Region.Framework.Scenes
4610 /// <param name="force"></param> 4607 /// <param name="force"></param>
4611 /// <param name="auth_token"></param> 4608 /// <param name="auth_token"></param>
4612 /// <returns></returns> 4609 /// <returns></returns>
4613 public bool IncomingCloseAgent(UUID agentID, bool force, string auth_token) 4610 public bool CloseAgent(UUID agentID, bool force, string auth_token)
4614 { 4611 {
4615 //m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token); 4612 //m_log.DebugFormat("[SCENE]: Processing incoming close agent {0} in region {1} with auth_token {2}", agentID, RegionInfo.RegionName, auth_token);
4616 4613
@@ -4628,7 +4625,7 @@ namespace OpenSim.Region.Framework.Scenes
4628 4625
4629 if (acd.SessionID.ToString() == auth_token) 4626 if (acd.SessionID.ToString() == auth_token)
4630 { 4627 {
4631 return IncomingCloseAgent(agentID, force); 4628 return CloseAgent(agentID, force);
4632 } 4629 }
4633 else 4630 else
4634 { 4631 {
@@ -4640,27 +4637,27 @@ namespace OpenSim.Region.Framework.Scenes
4640 return false; 4637 return false;
4641 } 4638 }
4642 4639
4643 public bool IncomingCloseAgent(UUID agentID) 4640// public bool IncomingCloseAgent(UUID agentID)
4644 { 4641// {
4645 return IncomingCloseAgent(agentID, false); 4642// return IncomingCloseAgent(agentID, false);
4646 } 4643// }
4647 4644
4648 public bool IncomingCloseChildAgent(UUID agentID) 4645// public bool IncomingCloseChildAgent(UUID agentID)
4649 { 4646// {
4650 return IncomingCloseAgent(agentID, true); 4647// return IncomingCloseAgent(agentID, true);
4651 } 4648// }
4652 4649
4653 /// <summary> 4650 /// <summary>
4654 /// Tell a single agent to prepare to close. 4651 /// Tell a single client to prepare to close.
4655 /// </summary> 4652 /// </summary>
4656 /// <remarks> 4653 /// <remarks>
4657 /// This should only be called if we may close the agent but there will be some delay in so doing. Meant for 4654 /// This should only be called if we may close the client but there will be some delay in so doing. Meant for
4658 /// internal use - other callers should almost certainly called IncomingCloseAgent(). 4655 /// internal use - other callers should almost certainly called CloseClient().
4659 /// </remarks> 4656 /// </remarks>
4660 /// <param name="sp"></param> 4657 /// <param name="sp"></param>
4661 /// <returns>true if pre-close state notification was successful. false if the agent 4658 /// <returns>true if pre-close state notification was successful. false if the agent
4662 /// was not in a state where it could transition to pre-close.</returns> 4659 /// was not in a state where it could transition to pre-close.</returns>
4663 public bool IncomingPreCloseAgent(ScenePresence sp) 4660 public bool IncomingPreCloseClient(ScenePresence sp)
4664 { 4661 {
4665 lock (m_removeClientLock) 4662 lock (m_removeClientLock)
4666 { 4663 {
@@ -4702,7 +4699,7 @@ namespace OpenSim.Region.Framework.Scenes
4702 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to 4699 /// Force the agent to close even if it might be in the middle of some other operation. You do not want to
4703 /// force unless you are absolutely sure that the agent is dead and a normal close is not working. 4700 /// force unless you are absolutely sure that the agent is dead and a normal close is not working.
4704 /// </param> 4701 /// </param>
4705 public bool IncomingCloseAgent(UUID agentID, bool force) 4702 public override bool CloseAgent(UUID agentID, bool force)
4706 { 4703 {
4707 ScenePresence sp; 4704 ScenePresence sp;
4708 4705
@@ -4713,7 +4710,7 @@ namespace OpenSim.Region.Framework.Scenes
4713 if (sp == null) 4710 if (sp == null)
4714 { 4711 {
4715 m_log.DebugFormat( 4712 m_log.DebugFormat(
4716 "[SCENE]: Called IncomingCloseAgent() with agent ID {0} but no such presence is in {1}", 4713 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
4717 agentID, Name); 4714 agentID, Name);
4718 4715
4719 return false; 4716 return false;
@@ -4722,7 +4719,7 @@ namespace OpenSim.Region.Framework.Scenes
4722 if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove) 4719 if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
4723 { 4720 {
4724 m_log.DebugFormat( 4721 m_log.DebugFormat(
4725 "[SCENE]: Called IncomingCloseAgent() for {0} in {1} but presence is already in state {2}", 4722 "[SCENE]: Called CloseClient() for {0} in {1} but presence is already in state {2}",
4726 sp.Name, Name, sp.LifecycleState); 4723 sp.Name, Name, sp.LifecycleState);
4727 4724
4728 return false; 4725 return false;
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 1dac676..9354a88 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -217,21 +217,9 @@ namespace OpenSim.Region.Framework.Scenes
217 217
218 #region Add/Remove Agent/Avatar 218 #region Add/Remove Agent/Avatar
219 219
220 public abstract ISceneAgent AddNewClient(IClientAPI client, PresenceType type); 220 public abstract ISceneAgent AddNewAgent(IClientAPI client, PresenceType type);
221 221
222 /// <summary> 222 public abstract bool CloseAgent(UUID agentID, bool force);
223 /// Remove the given client from the scene.
224 /// </summary>
225 /// <remarks>
226 /// Only clientstack code should call this directly. All other code should call IncomingCloseAgent() instead
227 /// to properly operate the state machine and avoid race conditions with other close requests (such as directly
228 /// from viewers).
229 /// </remarks>
230 /// <param name='agentID'>ID of agent to close</param>
231 /// <param name='closeChildAgents'>
232 /// Close the neighbour child agents associated with this client.
233 /// </param>
234 public abstract void RemoveClient(UUID agentID, bool closeChildAgents);
235 223
236 public bool TryGetScenePresence(UUID agentID, out object scenePresence) 224 public bool TryGetScenePresence(UUID agentID, out object scenePresence)
237 { 225 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index cf03d7c..66b42a1 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -2960,6 +2960,26 @@ namespace OpenSim.Region.Framework.Scenes
2960 //ParentGroup.RootPart.m_groupPosition = newpos; 2960 //ParentGroup.RootPart.m_groupPosition = newpos;
2961 } 2961 }
2962 2962
2963 if (pa != null && ParentID != 0 && ParentGroup != null)
2964 {
2965 // Special case where a child object is requesting property updates.
2966 // This happens when linksets are modified to use flexible links rather than
2967 // the default links.
2968 // The simulator code presumes that child parts are only modified by scripts
2969 // so the logic for changing position/rotation/etc does not take into
2970 // account the physical object actually moving.
2971 // This code updates the offset position and rotation of the child and then
2972 // lets the update code push the update to the viewer.
2973 // Since physics engines do not normally generate this event for linkset children,
2974 // this code will not be active unless you have a specially configured
2975 // physics engine.
2976 Quaternion invRootRotation = Quaternion.Normalize(Quaternion.Inverse(ParentGroup.RootPart.RotationOffset));
2977 m_offsetPosition = pa.Position - m_groupPosition;
2978 RotationOffset = pa.Orientation * invRootRotation;
2979 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}",
2980 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset);
2981 }
2982
2963 ScheduleTerseUpdate(); 2983 ScheduleTerseUpdate();
2964 } 2984 }
2965 2985
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 183d8d1..9f330fd 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -320,7 +320,21 @@ namespace OpenSim.Region.Framework.Scenes
320 /// </summary> 320 /// </summary>
321 private string m_callbackURI; 321 private string m_callbackURI;
322 322
323 public UUID m_originRegionID; 323 /// <summary>
324 /// Records the region from which this presence originated, if not from login.
325 /// </summary>
326 /// <remarks>
327 /// Also acts as a signal in the teleport V2 process to release UpdateAgent after a viewer has triggered
328 /// CompleteMovement and made the previous child agent a root agent.
329 /// </remarks>
330 private UUID m_originRegionID;
331
332 /// <summary>
333 /// This object is used as a lock before accessing m_originRegionID to make sure that every thread is seeing
334 /// the very latest value and not using some cached version. Cannot make m_originRegionID itself volatite as
335 /// it is a value type.
336 /// </summary>
337 private object m_originRegionIDAccessLock = new object();
324 338
325 /// <summary> 339 /// <summary>
326 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent 340 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
@@ -975,11 +989,11 @@ namespace OpenSim.Region.Framework.Scenes
975 /// This method is on the critical path for transferring an avatar from one region to another. Delay here 989 /// This method is on the critical path for transferring an avatar from one region to another. Delay here
976 /// delays that crossing. 990 /// delays that crossing.
977 /// </summary> 991 /// </summary>
978 public void MakeRootAgent(Vector3 pos, bool isFlying) 992 private void MakeRootAgent(Vector3 pos, bool isFlying)
979 { 993 {
980 m_log.InfoFormat( 994// m_log.InfoFormat(
981 "[SCENE]: Upgrading child to root agent for {0} in {1}", 995// "[SCENE]: Upgrading child to root agent for {0} in {1}",
982 Name, m_scene.RegionInfo.RegionName); 996// Name, m_scene.RegionInfo.RegionName);
983 997
984 if (ParentUUID != UUID.Zero) 998 if (ParentUUID != UUID.Zero)
985 { 999 {
@@ -1545,15 +1559,26 @@ namespace OpenSim.Region.Framework.Scenes
1545 1559
1546 private bool WaitForUpdateAgent(IClientAPI client) 1560 private bool WaitForUpdateAgent(IClientAPI client)
1547 { 1561 {
1548 // Before UpdateAgent, m_originRegionID is UUID.Zero; after, it's non-Zero 1562 // Before the source region executes UpdateAgent
1563 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination,
1564 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
1565 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
1549 int count = 50; 1566 int count = 50;
1550 while (m_originRegionID.Equals(UUID.Zero) && count-- > 0) 1567 UUID originID;
1568
1569 lock (m_originRegionIDAccessLock)
1570 originID = m_originRegionID;
1571
1572 while (originID.Equals(UUID.Zero) && count-- > 0)
1551 { 1573 {
1574 lock (m_originRegionIDAccessLock)
1575 originID = m_originRegionID;
1576
1552 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name); 1577 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
1553 Thread.Sleep(200); 1578 Thread.Sleep(200);
1554 } 1579 }
1555 1580
1556 if (m_originRegionID.Equals(UUID.Zero)) 1581 if (originID.Equals(UUID.Zero))
1557 { 1582 {
1558 // Movement into region will fail 1583 // Movement into region will fail
1559 m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name); 1584 m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
@@ -1576,9 +1601,9 @@ namespace OpenSim.Region.Framework.Scenes
1576 { 1601 {
1577// DateTime startTime = DateTime.Now; 1602// DateTime startTime = DateTime.Now;
1578 1603
1579 m_log.DebugFormat( 1604 m_log.InfoFormat(
1580 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", 1605 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1581 client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); 1606 client.Name, Scene.Name, AbsolutePosition);
1582 1607
1583 // Make sure it's not a login agent. We don't want to wait for updates during login 1608 // Make sure it's not a login agent. We don't want to wait for updates during login
1584 if (PresenceType != PresenceType.Npc && (m_teleportFlags & TeleportFlags.ViaLogin) == 0) 1609 if (PresenceType != PresenceType.Npc && (m_teleportFlags & TeleportFlags.ViaLogin) == 0)
@@ -1633,7 +1658,12 @@ namespace OpenSim.Region.Framework.Scenes
1633 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", 1658 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1634 client.Name, client.AgentId, m_callbackURI); 1659 client.Name, client.AgentId, m_callbackURI);
1635 1660
1636 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); 1661 UUID originID;
1662
1663 lock (m_originRegionIDAccessLock)
1664 originID = m_originRegionID;
1665
1666 Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
1637 m_callbackURI = null; 1667 m_callbackURI = null;
1638 } 1668 }
1639// else 1669// else
@@ -3089,7 +3119,7 @@ namespace OpenSim.Region.Framework.Scenes
3089 // If we are using the the cached appearance then send it out to everyone 3119 // If we are using the the cached appearance then send it out to everyone
3090 if (cachedappearance) 3120 if (cachedappearance)
3091 { 3121 {
3092 m_log.DebugFormat("[SCENE PRESENCE]: baked textures are in the cache for {0}", Name); 3122 m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name);
3093 3123
3094 // If the avatars baked textures are all in the cache, then we have a 3124 // If the avatars baked textures are all in the cache, then we have a
3095 // complete appearance... send it out, if not, then we'll send it when 3125 // complete appearance... send it out, if not, then we'll send it when
@@ -3553,7 +3583,7 @@ namespace OpenSim.Region.Framework.Scenes
3553 3583
3554 #region Child Agent Updates 3584 #region Child Agent Updates
3555 3585
3556 public void ChildAgentDataUpdate(AgentData cAgentData) 3586 public void UpdateChildAgent(AgentData cAgentData)
3557 { 3587 {
3558// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName); 3588// m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
3559 if (!IsChildAgent) 3589 if (!IsChildAgent)
@@ -3563,15 +3593,17 @@ namespace OpenSim.Region.Framework.Scenes
3563 } 3593 }
3564 3594
3565 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 3595 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
3596
3566 private void RaiseUpdateThrottles() 3597 private void RaiseUpdateThrottles()
3567 { 3598 {
3568 m_scene.EventManager.TriggerThrottleUpdate(this); 3599 m_scene.EventManager.TriggerThrottleUpdate(this);
3569 } 3600 }
3601
3570 /// <summary> 3602 /// <summary>
3571 /// This updates important decision making data about a child agent 3603 /// This updates important decision making data about a child agent
3572 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region 3604 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
3573 /// </summary> 3605 /// </summary>
3574 public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY) 3606 public void UpdateChildAgent(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
3575 { 3607 {
3576 if (!IsChildAgent) 3608 if (!IsChildAgent)
3577 return; 3609 return;
@@ -3679,7 +3711,8 @@ namespace OpenSim.Region.Framework.Scenes
3679 3711
3680 private void CopyFrom(AgentData cAgent) 3712 private void CopyFrom(AgentData cAgent)
3681 { 3713 {
3682 m_originRegionID = cAgent.RegionID; 3714 lock (m_originRegionIDAccessLock)
3715 m_originRegionID = cAgent.RegionID;
3683 3716
3684 m_callbackURI = cAgent.CallbackURI; 3717 m_callbackURI = cAgent.CallbackURI;
3685// m_log.DebugFormat( 3718// m_log.DebugFormat(
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 68918d3..bc51b32 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -365,6 +365,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
365 m_SOPXmlProcessors.Add("CollisionSound", ProcessCollisionSound); 365 m_SOPXmlProcessors.Add("CollisionSound", ProcessCollisionSound);
366 m_SOPXmlProcessors.Add("CollisionSoundVolume", ProcessCollisionSoundVolume); 366 m_SOPXmlProcessors.Add("CollisionSoundVolume", ProcessCollisionSoundVolume);
367 m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl); 367 m_SOPXmlProcessors.Add("MediaUrl", ProcessMediaUrl);
368 m_SOPXmlProcessors.Add("AttachedPos", ProcessAttachedPos);
368 m_SOPXmlProcessors.Add("DynAttrs", ProcessDynAttrs); 369 m_SOPXmlProcessors.Add("DynAttrs", ProcessDynAttrs);
369 m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation); 370 m_SOPXmlProcessors.Add("TextureAnimation", ProcessTextureAnimation);
370 m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem); 371 m_SOPXmlProcessors.Add("ParticleSystem", ProcessParticleSystem);
@@ -443,6 +444,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
443 m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd); 444 m_ShapeXmlProcessors.Add("ProfileEnd", ProcessShpProfileEnd);
444 m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow); 445 m_ShapeXmlProcessors.Add("ProfileHollow", ProcessShpProfileHollow);
445 m_ShapeXmlProcessors.Add("Scale", ProcessShpScale); 446 m_ShapeXmlProcessors.Add("Scale", ProcessShpScale);
447 m_ShapeXmlProcessors.Add("LastAttachPoint", ProcessShpLastAttach);
446 m_ShapeXmlProcessors.Add("State", ProcessShpState); 448 m_ShapeXmlProcessors.Add("State", ProcessShpState);
447 m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape); 449 m_ShapeXmlProcessors.Add("ProfileShape", ProcessShpProfileShape);
448 m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape); 450 m_ShapeXmlProcessors.Add("HollowShape", ProcessShpHollowShape);
@@ -798,6 +800,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
798 obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty); 800 obj.MediaUrl = reader.ReadElementContentAsString("MediaUrl", String.Empty);
799 } 801 }
800 802
803 private static void ProcessAttachedPos(SceneObjectPart obj, XmlTextReader reader)
804 {
805 obj.AttachedPos = Util.ReadVector(reader, "AttachedPos");
806 }
807
801 private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader) 808 private static void ProcessDynAttrs(SceneObjectPart obj, XmlTextReader reader)
802 { 809 {
803 obj.DynAttrs.ReadXml(reader); 810 obj.DynAttrs.ReadXml(reader);
@@ -1099,6 +1106,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1099 shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty); 1106 shp.State = (byte)reader.ReadElementContentAsInt("State", String.Empty);
1100 } 1107 }
1101 1108
1109 private static void ProcessShpLastAttach(PrimitiveBaseShape shp, XmlTextReader reader)
1110 {
1111 shp.LastAttachPoint = (byte)reader.ReadElementContentAsInt("LastAttachPoint", String.Empty);
1112 }
1113
1102 private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader) 1114 private static void ProcessShpProfileShape(PrimitiveBaseShape shp, XmlTextReader reader)
1103 { 1115 {
1104 shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape"); 1116 shp.ProfileShape = Util.ReadEnum<ProfileShape>(reader, "ProfileShape");
@@ -1345,6 +1357,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1345 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); 1357 writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString());
1346 if (sop.MediaUrl != null) 1358 if (sop.MediaUrl != null)
1347 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); 1359 writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString());
1360 WriteVector(writer, "AttachedPos", sop.AttachedPos);
1348 1361
1349 if (sop.DynAttrs.CountNamespaces > 0) 1362 if (sop.DynAttrs.CountNamespaces > 0)
1350 { 1363 {
@@ -1539,6 +1552,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1539 writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString()); 1552 writer.WriteElementString("ProfileEnd", shp.ProfileEnd.ToString());
1540 writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString()); 1553 writer.WriteElementString("ProfileHollow", shp.ProfileHollow.ToString());
1541 writer.WriteElementString("State", shp.State.ToString()); 1554 writer.WriteElementString("State", shp.State.ToString());
1555 writer.WriteElementString("LastAttachPoint", shp.LastAttachPoint.ToString());
1542 1556
1543 WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options); 1557 WriteFlags(writer, "ProfileShape", shp.ProfileShape.ToString(), options);
1544 WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options); 1558 WriteFlags(writer, "HollowShape", shp.HollowShape.ToString(), options);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index bbe34d2..d1aeaee 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -146,7 +146,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
146 } 146 }
147 147
148 [Test] 148 [Test]
149 public void TestCloseAgent() 149 public void TestCloseClient()
150 { 150 {
151 TestHelpers.InMethod(); 151 TestHelpers.InMethod();
152// TestHelpers.EnableLogging(); 152// TestHelpers.EnableLogging();
@@ -154,7 +154,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
154 TestScene scene = new SceneHelpers().SetupScene(); 154 TestScene scene = new SceneHelpers().SetupScene();
155 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 155 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
156 156
157 scene.IncomingCloseAgent(sp.UUID, false); 157 scene.CloseAgent(sp.UUID, false);
158 158
159 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); 159 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
160 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); 160 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null);
@@ -200,7 +200,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
200 // *** This is the second stage, where the client established a child agent/scene presence using the 200 // *** This is the second stage, where the client established a child agent/scene presence using the
201 // circuit code given to the scene in stage 1 *** 201 // circuit code given to the scene in stage 1 ***
202 TestClient client = new TestClient(acd, scene); 202 TestClient client = new TestClient(acd, scene);
203 scene.AddNewClient(client, PresenceType.User); 203 scene.AddNewAgent(client, PresenceType.User);
204 204
205 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null); 205 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null);
206 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); 206 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
@@ -279,7 +279,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
279// string reason; 279// string reason;
280// scene.NewUserConnection(agent, (uint)TeleportFlags.ViaLogin, out reason); 280// scene.NewUserConnection(agent, (uint)TeleportFlags.ViaLogin, out reason);
281// testclient = new TestClient(agent, scene); 281// testclient = new TestClient(agent, scene);
282// scene.AddNewClient(testclient); 282// scene.AddNewAgent(testclient);
283// 283//
284// ScenePresence presence = scene.GetScenePresence(agent1); 284// ScenePresence presence = scene.GetScenePresence(agent1);
285// 285//
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
index 4ae7a8e..9fa0a71 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
@@ -79,8 +79,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
79 79
80 // TODO: Need to add tests for other ICapabiltiesModule methods. 80 // TODO: Need to add tests for other ICapabiltiesModule methods.
81 81
82 scene.IncomingCloseAgent(sp.UUID, false); 82// scene.IncomingCloseAgent(sp.UUID, false);
83 //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null); 83// //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
84 scene.CloseAgent(sp.UUID, false);
85// Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
84 86
85 // TODO: Need to add tests for other ICapabiltiesModule methods. 87 // TODO: Need to add tests for other ICapabiltiesModule methods.
86 } 88 }
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
index 12a778b..b806a97 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
@@ -38,6 +38,7 @@ using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.CoreModules.Framework; 38using OpenSim.Region.CoreModules.Framework;
39using OpenSim.Region.CoreModules.Framework.EntityTransfer; 39using OpenSim.Region.CoreModules.Framework.EntityTransfer;
40using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; 40using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
41using OpenSim.Region.CoreModules.World.Permissions;
41using OpenSim.Tests.Common; 42using OpenSim.Tests.Common;
42using OpenSim.Tests.Common.Mock; 43using OpenSim.Tests.Common.Mock;
43 44
@@ -159,5 +160,90 @@ namespace OpenSim.Region.Framework.Scenes.Tests
159 Assert.That(agentMovementCompleteReceived, Is.EqualTo(1)); 160 Assert.That(agentMovementCompleteReceived, Is.EqualTo(1));
160 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False); 161 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.False);
161 } 162 }
163
164 /// <summary>
165 /// Test a cross attempt where the user can see into the neighbour but does not have permission to become
166 /// root there.
167 /// </summary>
168 [Test]
169 public void TestCrossOnSameSimulatorNoRootDestPerm()
170 {
171 TestHelpers.InMethod();
172// TestHelpers.EnableLogging();
173
174 UUID userId = TestHelpers.ParseTail(0x1);
175
176 EntityTransferModule etmA = new EntityTransferModule();
177 EntityTransferModule etmB = new EntityTransferModule();
178 LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
179
180 IConfigSource config = new IniConfigSource();
181 IConfig modulesConfig = config.AddConfig("Modules");
182 modulesConfig.Set("EntityTransferModule", etmA.Name);
183 modulesConfig.Set("SimulationServices", lscm.Name);
184
185 SceneHelpers sh = new SceneHelpers();
186 TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
187 TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1000, 999);
188
189 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
190 SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA);
191
192 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
193 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
194 // IsAdministrator if no permissions module is present is true.
195// SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new PermissionsModule(), etmB);
196
197 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
198 TestClient tc = new TestClient(acd, sceneA);
199 List<TestClient> destinationTestClients = new List<TestClient>();
200 EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients);
201
202 // Make sure sceneB will not accept this avatar.
203 sceneB.RegionInfo.EstateSettings.PublicAccess = false;
204
205 ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd);
206 originalSp.AbsolutePosition = new Vector3(128, 32, 10);
207
208 AgentUpdateArgs moveArgs = new AgentUpdateArgs();
209 //moveArgs.BodyRotation = Quaternion.CreateFromEulers(Vector3.Zero);
210 moveArgs.BodyRotation = Quaternion.CreateFromEulers(new Vector3(0, 0, (float)-(Math.PI / 2)));
211 moveArgs.ControlFlags = (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS;
212 moveArgs.SessionID = acd.SessionID;
213
214 originalSp.HandleAgentUpdate(originalSp.ControllingClient, moveArgs);
215
216 sceneA.Update(1);
217
218// Console.WriteLine("Second pos {0}", originalSp.AbsolutePosition);
219
220 // FIXME: This is a sufficient number of updates to for the presence to reach the northern border.
221 // But really we want to do this in a more robust way.
222 for (int i = 0; i < 100; i++)
223 {
224 sceneA.Update(1);
225// Console.WriteLine("Pos {0}", originalSp.AbsolutePosition);
226 }
227
228 // sceneA agent should still be root
229 ScenePresence spAfterCrossSceneA = sceneA.GetScenePresence(originalSp.UUID);
230 Assert.That(spAfterCrossSceneA.IsChildAgent, Is.False);
231
232 ScenePresence spAfterCrossSceneB = sceneB.GetScenePresence(originalSp.UUID);
233
234 // sceneB agent should also still be root
235 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
236
237 // sceneB should ignore unauthorized attempt to upgrade agent to root
238 TestClient sceneBTc = ((TestClient)spAfterCrossSceneB.ControllingClient);
239
240 int agentMovementCompleteReceived = 0;
241 sceneBTc.OnReceivedMoveAgentIntoRegion += (ri, pos, look) => agentMovementCompleteReceived++;
242
243 sceneBTc.CompleteMovement();
244
245 Assert.That(agentMovementCompleteReceived, Is.EqualTo(0));
246 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
247 }
162 } 248 }
163} \ No newline at end of file 249}
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index e60a025..84e410f 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -168,7 +168,20 @@ namespace OpenSim.Region.Framework.Scenes
168 // If the prim is a sculpt then preserve this information too 168 // If the prim is a sculpt then preserve this information too
169 if (part.Shape.SculptTexture != UUID.Zero) 169 if (part.Shape.SculptTexture != UUID.Zero)
170 assetUuids[part.Shape.SculptTexture] = AssetType.Texture; 170 assetUuids[part.Shape.SculptTexture] = AssetType.Texture;
171 171
172 if (part.Shape.ProjectionTextureUUID != UUID.Zero)
173 assetUuids[part.Shape.ProjectionTextureUUID] = AssetType.Texture;
174
175 if (part.CollisionSound != UUID.Zero)
176 assetUuids[part.CollisionSound] = AssetType.Sound;
177
178 if (part.ParticleSystem.Length > 0)
179 {
180 Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0);
181 if (ps.Texture != UUID.Zero)
182 assetUuids[ps.Texture] = AssetType.Texture;
183 }
184
172 TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); 185 TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone();
173 186
174 // Now analyze this prim's inventory items to preserve all the uuids that they reference 187 // Now analyze this prim's inventory items to preserve all the uuids that they reference
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index a96c8b4..373ed41 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -908,7 +908,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
908 908
909 public void Start() 909 public void Start()
910 { 910 {
911 m_scene.AddNewClient(this, PresenceType.User); 911 m_scene.AddNewAgent(this, PresenceType.User);
912 912
913 // Mimicking LLClientView which gets always set appearance from client. 913 // Mimicking LLClientView which gets always set appearance from client.
914 AvatarAppearance appearance; 914 AvatarAppearance appearance;
diff --git a/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs b/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs
index d1d318c..9daf9d7 100755
--- a/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs
@@ -29,12 +29,14 @@ using System.Collections.Generic;
29using System.Linq; 29using System.Linq;
30using System.Reflection; 30using System.Reflection;
31using System.Text; 31using System.Text;
32using System.Threading;
32 33
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Region.CoreModules; 35using OpenSim.Region.CoreModules;
35using OpenSim.Region.Framework; 36using OpenSim.Region.Framework;
36using OpenSim.Region.Framework.Interfaces; 37using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Region.Physics.Manager;
38 40
39using Mono.Addins; 41using Mono.Addins;
40using Nini.Config; 42using Nini.Config;
@@ -60,6 +62,10 @@ public class ExtendedPhysics : INonSharedRegionModule
60 // Per prim functions. See BSPrim. 62 // Per prim functions. See BSPrim.
61 public const string PhysFunctGetLinksetType = "BulletSim.GetLinksetType"; 63 public const string PhysFunctGetLinksetType = "BulletSim.GetLinksetType";
62 public const string PhysFunctSetLinksetType = "BulletSim.SetLinksetType"; 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";
63 69
64 // ============================================================= 70 // =============================================================
65 71
@@ -155,7 +161,7 @@ public class ExtendedPhysics : INonSharedRegionModule
155 } 161 }
156 162
157 [ScriptConstant] 163 [ScriptConstant]
158 public static int PHYS_CENTER_OF_MASS = 1 << 0; 164 public const int PHYS_CENTER_OF_MASS = 1 << 0;
159 165
160 [ScriptInvocation] 166 [ScriptInvocation]
161 public string physGetEngineType(UUID hostID, UUID scriptID) 167 public string physGetEngineType(UUID hostID, UUID scriptID)
@@ -171,11 +177,11 @@ public class ExtendedPhysics : INonSharedRegionModule
171 } 177 }
172 178
173 [ScriptConstant] 179 [ScriptConstant]
174 public static int PHYS_LINKSET_TYPE_CONSTRAINT = 0; 180 public const int PHYS_LINKSET_TYPE_CONSTRAINT = 0;
175 [ScriptConstant] 181 [ScriptConstant]
176 public static int PHYS_LINKSET_TYPE_COMPOUND = 1; 182 public const int PHYS_LINKSET_TYPE_COMPOUND = 1;
177 [ScriptConstant] 183 [ScriptConstant]
178 public static int PHYS_LINKSET_TYPE_MANUAL = 2; 184 public const int PHYS_LINKSET_TYPE_MANUAL = 2;
179 185
180 [ScriptInvocation] 186 [ScriptInvocation]
181 public int physSetLinksetType(UUID hostID, UUID scriptID, int linksetType) 187 public int physSetLinksetType(UUID hostID, UUID scriptID, int linksetType)
@@ -195,10 +201,38 @@ public class ExtendedPhysics : INonSharedRegionModule
195 201
196 if (rootPart != null) 202 if (rootPart != null)
197 { 203 {
198 Physics.Manager.PhysicsActor rootPhysActor = rootPart.PhysActor; 204 PhysicsActor rootPhysActor = rootPart.PhysActor;
199 if (rootPhysActor != null) 205 if (rootPhysActor != null)
200 { 206 {
201 ret = (int)rootPhysActor.Extension(PhysFunctSetLinksetType, linksetType); 207 if (rootPhysActor.IsPhysical)
208 {
209 // Change a physical linkset by making non-physical, waiting for one heartbeat so all
210 // the prim and linkset state is updated, changing the type and making the
211 // linkset physical again.
212 containingGroup.ScriptSetPhysicsStatus(false);
213 Thread.Sleep(150); // longer than one heartbeat tick
214
215 // A kludge for the moment.
216 // Since compound linksets move the children but don't generate position updates to the
217 // simulator, it is possible for compound linkset children to have out-of-sync simulator
218 // and physical positions. The following causes the simulator to push the real child positions
219 // down into the physics engine to get everything synced.
220 containingGroup.UpdateGroupPosition(containingGroup.AbsolutePosition);
221 containingGroup.UpdateGroupRotationR(containingGroup.GroupRotation);
222
223 object[] parms2 = { rootPhysActor, null, linksetType };
224 ret = MakeIntError(rootPhysActor.Extension(PhysFunctSetLinksetType, parms2));
225 Thread.Sleep(150); // longer than one heartbeat tick
226
227 containingGroup.ScriptSetPhysicsStatus(true);
228 }
229 else
230 {
231 // Non-physical linksets don't have a physical instantiation so there is no state to
232 // worry about being updated.
233 object[] parms2 = { rootPhysActor, null, linksetType };
234 ret = MakeIntError(rootPhysActor.Extension(PhysFunctSetLinksetType, parms2));
235 }
202 } 236 }
203 else 237 else
204 { 238 {
@@ -223,7 +257,6 @@ public class ExtendedPhysics : INonSharedRegionModule
223 public int physGetLinksetType(UUID hostID, UUID scriptID) 257 public int physGetLinksetType(UUID hostID, UUID scriptID)
224 { 258 {
225 int ret = -1; 259 int ret = -1;
226
227 if (!Enabled) return ret; 260 if (!Enabled) return ret;
228 261
229 // The part that is requesting the change. 262 // The part that is requesting the change.
@@ -237,10 +270,11 @@ public class ExtendedPhysics : INonSharedRegionModule
237 270
238 if (rootPart != null) 271 if (rootPart != null)
239 { 272 {
240 Physics.Manager.PhysicsActor rootPhysActor = rootPart.PhysActor; 273 PhysicsActor rootPhysActor = rootPart.PhysActor;
241 if (rootPhysActor != null) 274 if (rootPhysActor != null)
242 { 275 {
243 ret = (int)rootPhysActor.Extension(PhysFunctGetLinksetType); 276 object[] parms2 = { rootPhysActor, null };
277 ret = MakeIntError(rootPhysActor.Extension(PhysFunctGetLinksetType, parms2));
244 } 278 }
245 else 279 else
246 { 280 {
@@ -260,5 +294,288 @@ public class ExtendedPhysics : INonSharedRegionModule
260 } 294 }
261 return ret; 295 return ret;
262 } 296 }
297
298 [ScriptConstant]
299 public const int PHYS_LINK_TYPE_FIXED = 1234;
300 [ScriptConstant]
301 public const int PHYS_LINK_TYPE_HINGE = 4;
302 [ScriptConstant]
303 public const int PHYS_LINK_TYPE_SPRING = 9;
304 [ScriptConstant]
305 public const int PHYS_LINK_TYPE_6DOF = 6;
306 [ScriptConstant]
307 public const int PHYS_LINK_TYPE_SLIDER = 7;
308
309 // physChangeLinkType(integer linkNum, integer typeCode)
310 [ScriptInvocation]
311 public int physChangeLinkType(UUID hostID, UUID scriptID, int linkNum, int typeCode)
312 {
313 int ret = -1;
314 if (!Enabled) return ret;
315
316 PhysicsActor rootPhysActor;
317 PhysicsActor childPhysActor;
318
319 if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
320 {
321 object[] parms2 = { rootPhysActor, childPhysActor, typeCode };
322 ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkType, parms2));
323 }
324
325 return ret;
326 }
327
328 // physGetLinkType(integer linkNum)
329 [ScriptInvocation]
330 public int physGetLinkType(UUID hostID, UUID scriptID, int linkNum)
331 {
332 int ret = -1;
333 if (!Enabled) return ret;
334
335 PhysicsActor rootPhysActor;
336 PhysicsActor childPhysActor;
337
338 if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
339 {
340 object[] parms2 = { rootPhysActor, childPhysActor };
341 ret = MakeIntError(rootPhysActor.Extension(PhysFunctGetLinkType, parms2));
342 }
343
344 return ret;
345 }
346
347 // physChangeLinkFixed(integer linkNum)
348 // Change the link between the root and the linkNum into a fixed, static physical connection.
349 [ScriptInvocation]
350 public int physChangeLinkFixed(UUID hostID, UUID scriptID, int linkNum)
351 {
352 int ret = -1;
353 if (!Enabled) return ret;
354
355 PhysicsActor rootPhysActor;
356 PhysicsActor childPhysActor;
357
358 if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
359 {
360 object[] parms2 = { rootPhysActor, childPhysActor , PHYS_LINK_TYPE_FIXED };
361 ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkType, parms2));
362 }
363
364 return ret;
365 }
366
367 // Code for specifying params.
368 // The choice if 14400 is arbitrary and only serves to catch parameter code misuse.
369 public const int PHYS_PARAM_MIN = 14401;
370
371 [ScriptConstant]
372 public const int PHYS_PARAM_FRAMEINA_LOC = 14401;
373 [ScriptConstant]
374 public const int PHYS_PARAM_FRAMEINA_ROT = 14402;
375 [ScriptConstant]
376 public const int PHYS_PARAM_FRAMEINB_LOC = 14403;
377 [ScriptConstant]
378 public const int PHYS_PARAM_FRAMEINB_ROT = 14404;
379 [ScriptConstant]
380 public const int PHYS_PARAM_LINEAR_LIMIT_LOW = 14405;
381 [ScriptConstant]
382 public const int PHYS_PARAM_LINEAR_LIMIT_HIGH = 14406;
383 [ScriptConstant]
384 public const int PHYS_PARAM_ANGULAR_LIMIT_LOW = 14407;
385 [ScriptConstant]
386 public const int PHYS_PARAM_ANGULAR_LIMIT_HIGH = 14408;
387 [ScriptConstant]
388 public const int PHYS_PARAM_USE_FRAME_OFFSET = 14409;
389 [ScriptConstant]
390 public const int PHYS_PARAM_ENABLE_TRANSMOTOR = 14410;
391 [ScriptConstant]
392 public const int PHYS_PARAM_TRANSMOTOR_MAXVEL = 14411;
393 [ScriptConstant]
394 public const int PHYS_PARAM_TRANSMOTOR_MAXFORCE = 14412;
395 [ScriptConstant]
396 public const int PHYS_PARAM_CFM = 14413;
397 [ScriptConstant]
398 public const int PHYS_PARAM_ERP = 14414;
399 [ScriptConstant]
400 public const int PHYS_PARAM_SOLVER_ITERATIONS = 14415;
401 [ScriptConstant]
402 public const int PHYS_PARAM_SPRING_AXIS_ENABLE = 14416;
403 [ScriptConstant]
404 public const int PHYS_PARAM_SPRING_DAMPING = 14417;
405 [ScriptConstant]
406 public const int PHYS_PARAM_SPRING_STIFFNESS = 14418;
407 [ScriptConstant]
408 public const int PHYS_PARAM_LINK_TYPE = 14419;
409 [ScriptConstant]
410 public const int PHYS_PARAM_USE_LINEAR_FRAMEA = 14420;
411 [ScriptConstant]
412 public const int PHYS_PARAM_SPRING_EQUILIBRIUM_POINT = 14421;
413
414 public const int PHYS_PARAM_MAX = 14421;
415
416 // Used when specifying a parameter that has settings for the three linear and three angular axis
417 [ScriptConstant]
418 public const int PHYS_AXIS_ALL = -1;
419 [ScriptConstant]
420 public const int PHYS_AXIS_LINEAR_ALL = -2;
421 [ScriptConstant]
422 public const int PHYS_AXIS_ANGULAR_ALL = -3;
423 [ScriptConstant]
424 public const int PHYS_AXIS_LINEAR_X = 0;
425 [ScriptConstant]
426 public const int PHYS_AXIS_LINEAR_Y = 1;
427 [ScriptConstant]
428 public const int PHYS_AXIS_LINEAR_Z = 2;
429 [ScriptConstant]
430 public const int PHYS_AXIS_ANGULAR_X = 3;
431 [ScriptConstant]
432 public const int PHYS_AXIS_ANGULAR_Y = 4;
433 [ScriptConstant]
434 public const int PHYS_AXIS_ANGULAR_Z = 5;
435
436 // physChangeLinkParams(integer linkNum, [ PHYS_PARAM_*, value, PHYS_PARAM_*, value, ...])
437 [ScriptInvocation]
438 public int physChangeLinkParams(UUID hostID, UUID scriptID, int linkNum, object[] parms)
439 {
440 int ret = -1;
441 if (!Enabled) return ret;
442
443 PhysicsActor rootPhysActor;
444 PhysicsActor childPhysActor;
445
446 if (GetRootAndChildPhysActors(hostID, linkNum, out rootPhysActor, out childPhysActor))
447 {
448 object[] parms2 = AddToBeginningOfArray(rootPhysActor, childPhysActor, parms);
449 ret = MakeIntError(rootPhysActor.Extension(PhysFunctChangeLinkParams, parms2));
450 }
451
452 return ret;
453 }
454
455 private bool GetRootPhysActor(UUID hostID, out PhysicsActor rootPhysActor)
456 {
457 SceneObjectGroup containingGroup;
458 SceneObjectPart rootPart;
459 return GetRootPhysActor(hostID, out containingGroup, out rootPart, out rootPhysActor);
460 }
461
462 private bool GetRootPhysActor(UUID hostID, out SceneObjectGroup containingGroup, out SceneObjectPart rootPart, out PhysicsActor rootPhysActor)
463 {
464 bool ret = false;
465 rootPhysActor = null;
466 containingGroup = null;
467 rootPart = null;
468
469 SceneObjectPart requestingPart;
470
471 requestingPart = BaseScene.GetSceneObjectPart(hostID);
472 if (requestingPart != null)
473 {
474 // The type is is always on the root of a linkset.
475 containingGroup = requestingPart.ParentGroup;
476 if (containingGroup != null && !containingGroup.IsDeleted)
477 {
478 rootPart = containingGroup.RootPart;
479 if (rootPart != null)
480 {
481 rootPhysActor = rootPart.PhysActor;
482 if (rootPhysActor != null)
483 {
484 ret = true;
485 }
486 else
487 {
488 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not have a physics actor. rootName={1}, hostID={2}",
489 LogHeader, rootPart.Name, hostID);
490 }
491 }
492 else
493 {
494 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not exist. RequestingPartName={1}, hostID={2}",
495 LogHeader, requestingPart.Name, hostID);
496 }
497 }
498 else
499 {
500 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Containing group missing or deleted. hostID={1}", LogHeader, hostID);
501 }
502 }
503 else
504 {
505 m_log.WarnFormat("{0} GetRootAndChildPhysActors: cannot find script object in scene. hostID={1}", LogHeader, hostID);
506 }
507
508 return ret;
509 }
510
511 // Find the root and child PhysActors based on the linkNum.
512 // Return 'true' if both are found and returned.
513 private bool GetRootAndChildPhysActors(UUID hostID, int linkNum, out PhysicsActor rootPhysActor, out PhysicsActor childPhysActor)
514 {
515 bool ret = false;
516 rootPhysActor = null;
517 childPhysActor = null;
518
519 SceneObjectGroup containingGroup;
520 SceneObjectPart rootPart;
521
522 if (GetRootPhysActor(hostID, out containingGroup, out rootPart, out rootPhysActor))
523 {
524 SceneObjectPart linkPart = containingGroup.GetLinkNumPart(linkNum);
525 if (linkPart != null)
526 {
527 childPhysActor = linkPart.PhysActor;
528 if (childPhysActor != null)
529 {
530 ret = true;
531 }
532 else
533 {
534 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Link part has no physical actor. rootName={1}, hostID={2}, linknum={3}",
535 LogHeader, rootPart.Name, hostID, linkNum);
536 }
537 }
538 else
539 {
540 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Could not find linknum part. rootName={1}, hostID={2}, linknum={3}",
541 LogHeader, rootPart.Name, hostID, linkNum);
542 }
543 }
544 else
545 {
546 m_log.WarnFormat("{0} GetRootAndChildPhysActors: Root part does not have a physics actor. rootName={1}, hostID={2}",
547 LogHeader, rootPart.Name, hostID);
548 }
549
550 return ret;
551 }
552
553 // Return an array of objects with the passed object as the first object of a new array
554 private object[] AddToBeginningOfArray(object firstOne, object secondOne, object[] prevArray)
555 {
556 object[] newArray = new object[2 + prevArray.Length];
557 newArray[0] = firstOne;
558 newArray[1] = secondOne;
559 prevArray.CopyTo(newArray, 2);
560 return newArray;
561 }
562
563 // Extension() returns an object. Convert that object into the integer error we expect to return.
564 private int MakeIntError(object extensionRet)
565 {
566 int ret = -1;
567 if (extensionRet != null)
568 {
569 try
570 {
571 ret = (int)extensionRet;
572 }
573 catch
574 {
575 ret = -1;
576 }
577 }
578 return ret;
579 }
263} 580}
264} 581}
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 78fe096..9ec4740 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -176,7 +176,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
176 lock (m_avatars) 176 lock (m_avatars)
177 { 177 {
178 scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd); 178 scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
179 scene.AddNewClient(npcAvatar, PresenceType.Npc); 179 scene.AddNewAgent(npcAvatar, PresenceType.Npc);
180 180
181 ScenePresence sp; 181 ScenePresence sp;
182 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp)) 182 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
@@ -207,8 +207,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC
207 if (scene.TryGetScenePresence(agentID, out sp)) 207 if (scene.TryGetScenePresence(agentID, out sp))
208 { 208 {
209// m_log.DebugFormat( 209// m_log.DebugFormat(
210// "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}", 210// "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
211// sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget); 211// sp.Name, pos, scene.RegionInfo.RegionName,
212// noFly, landAtTarget);
212 213
213 sp.MoveToTarget(pos, noFly, landAtTarget); 214 sp.MoveToTarget(pos, noFly, landAtTarget);
214 sp.SetAlwaysRun = running; 215 sp.SetAlwaysRun = running;
@@ -285,9 +286,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
285 ScenePresence sp; 286 ScenePresence sp;
286 if (scene.TryGetScenePresence(agentID, out sp)) 287 if (scene.TryGetScenePresence(agentID, out sp))
287 { 288 {
288 sp.HandleAgentRequestSit(m_avatars[agentID], agentID, 289 sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero);
289 partID, Vector3.Zero);
290 //sp.HandleAgentSit(m_avatars[agentID], agentID);
291 290
292 return true; 291 return true;
293 } 292 }
@@ -378,11 +377,14 @@ namespace OpenSim.Region.OptionalModules.World.NPC
378 agentID, av.Name); 377 agentID, av.Name);
379 */ 378 */
380 379
381 scene.IncomingCloseAgent(agentID, false); 380 scene.CloseAgent(agentID, false);
382// scene.RemoveClient(agentID, false); 381
383 m_avatars.Remove(agentID); 382 m_avatars.Remove(agentID);
384 383
385// m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}", agentID, av.Name); 384 /*
385 m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}",
386 agentID, av.Name);
387 */
386 return true; 388 return true;
387 } 389 }
388 } 390 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
index 12a0c17..3bd81d4 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIUnman.cs
@@ -596,6 +596,60 @@ public override bool SetBreakingImpulseThreshold(BulletConstraint constrain, flo
596 return BSAPICPP.SetBreakingImpulseThreshold2(constrainu.ptr, threshold); 596 return BSAPICPP.SetBreakingImpulseThreshold2(constrainu.ptr, threshold);
597} 597}
598 598
599public override bool HingeSetLimits(BulletConstraint constrain, float low, float high, float softness, float bias, float relaxation)
600{
601 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
602 return BSAPICPP.HingeSetLimits2(constrainu.ptr, low, high, softness, bias, relaxation);
603}
604
605public override bool SpringEnable(BulletConstraint constrain, int index, float numericTrueFalse)
606{
607 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
608 return BSAPICPP.ConstraintSpringEnable2(constrainu.ptr, index, numericTrueFalse);
609}
610
611public override bool SpringSetEquilibriumPoint(BulletConstraint constrain, int index, float equilibriumPoint)
612{
613 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
614 return BSAPICPP.ConstraintSpringSetEquilibriumPoint2(constrainu.ptr, index, equilibriumPoint);
615}
616
617public override bool SpringSetStiffness(BulletConstraint constrain, int index, float stiffnesss)
618{
619 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
620 return BSAPICPP.ConstraintSpringSetStiffness2(constrainu.ptr, index, stiffnesss);
621}
622
623public override bool SpringSetDamping(BulletConstraint constrain, int index, float damping)
624{
625 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
626 return BSAPICPP.ConstraintSpringSetDamping2(constrainu.ptr, index, damping);
627}
628
629public override bool SliderSetLimits(BulletConstraint constrain, int lowerUpper, int linAng, float val)
630{
631 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
632 return BSAPICPP.SliderSetLimits2(constrainu.ptr, lowerUpper, linAng, val);
633}
634
635public override bool SliderSet(BulletConstraint constrain, int softRestDamp, int dirLimOrtho, int linAng, float val)
636{
637 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
638 return BSAPICPP.SliderSet2(constrainu.ptr, softRestDamp, dirLimOrtho, linAng, val);
639}
640
641public override bool SliderMotorEnable(BulletConstraint constrain, int linAng, float numericTrueFalse)
642{
643 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
644 return BSAPICPP.SliderMotorEnable2(constrainu.ptr, linAng, numericTrueFalse);
645}
646
647public override bool SliderMotor(BulletConstraint constrain, int forceVel, int linAng, float val)
648{
649 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
650 return BSAPICPP.SliderMotor2(constrainu.ptr, forceVel, linAng, val);
651}
652
599public override bool CalculateTransforms(BulletConstraint constrain) 653public override bool CalculateTransforms(BulletConstraint constrain)
600{ 654{
601 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman; 655 BulletConstraintUnman constrainu = constrain as BulletConstraintUnman;
@@ -671,6 +725,13 @@ public override bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj)
671 return BSAPICPP.RemoveObjectFromWorld2(worldu.ptr, bodyu.ptr); 725 return BSAPICPP.RemoveObjectFromWorld2(worldu.ptr, bodyu.ptr);
672} 726}
673 727
728public override bool ClearCollisionProxyCache(BulletWorld world, BulletBody obj)
729{
730 BulletWorldUnman worldu = world as BulletWorldUnman;
731 BulletBodyUnman bodyu = obj as BulletBodyUnman;
732 return BSAPICPP.ClearCollisionProxyCache2(worldu.ptr, bodyu.ptr);
733}
734
674public override bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects) 735public override bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects)
675{ 736{
676 BulletWorldUnman worldu = world as BulletWorldUnman; 737 BulletWorldUnman worldu = world as BulletWorldUnman;
@@ -1601,6 +1662,33 @@ public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enabl
1601public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold); 1662public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold);
1602 1663
1603[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1664[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1665public static extern bool HingeSetLimits2(IntPtr constrain, float low, float high, float softness, float bias, float relaxation);
1666
1667[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1668public static extern bool ConstraintSpringEnable2(IntPtr constrain, int index, float numericTrueFalse);
1669
1670[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1671public static extern bool ConstraintSpringSetEquilibriumPoint2(IntPtr constrain, int index, float equilibriumPoint);
1672
1673[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1674public static extern bool ConstraintSpringSetStiffness2(IntPtr constrain, int index, float stiffness);
1675
1676[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1677public static extern bool ConstraintSpringSetDamping2(IntPtr constrain, int index, float damping);
1678
1679[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1680public static extern bool SliderSetLimits2(IntPtr constrain, int lowerUpper, int linAng, float val);
1681
1682[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1683public static extern bool SliderSet2(IntPtr constrain, int softRestDamp, int dirLimOrtho, int linAng, float val);
1684
1685[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1686public static extern bool SliderMotorEnable2(IntPtr constrain, int linAng, float numericTrueFalse);
1687
1688[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1689public static extern bool SliderMotor2(IntPtr constrain, int forceVel, int linAng, float val);
1690
1691[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1604public static extern bool CalculateTransforms2(IntPtr constrain); 1692public static extern bool CalculateTransforms2(IntPtr constrain);
1605 1693
1606[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1694[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -1632,6 +1720,9 @@ public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
1632public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj); 1720public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
1633 1721
1634[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1722[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1723public static extern bool ClearCollisionProxyCache2(IntPtr world, IntPtr obj);
1724
1725[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1635public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects); 1726public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects);
1636 1727
1637[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1728[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
index 2a820be..17ebed2 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSAPIXNA.cs
@@ -169,6 +169,19 @@ private sealed class BulletConstraintXNA : BulletConstraint
169 return true; 169 return true;
170 } 170 }
171 171
172 public override bool ClearCollisionProxyCache(BulletWorld pWorld, BulletBody pBody)
173 {
174 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
175 RigidBody body = ((BulletBodyXNA)pBody).rigidBody;
176 CollisionObject collisionObject = ((BulletBodyXNA)pBody).body;
177 if (body != null && collisionObject != null && collisionObject.GetBroadphaseHandle() != null)
178 {
179 world.RemoveCollisionObject(collisionObject);
180 world.AddCollisionObject(collisionObject);
181 }
182 return true;
183 }
184
172 public override bool AddConstraintToWorld(BulletWorld pWorld, BulletConstraint pConstraint, bool pDisableCollisionsBetweenLinkedObjects) 185 public override bool AddConstraintToWorld(BulletWorld pWorld, BulletConstraint pConstraint, bool pDisableCollisionsBetweenLinkedObjects)
173 { 186 {
174 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world; 187 DiscreteDynamicsWorld world = (pWorld as BulletWorldXNA).world;
@@ -752,6 +765,214 @@ private sealed class BulletConstraintXNA : BulletConstraint
752 constraint.SetBreakingImpulseThreshold(threshold); 765 constraint.SetBreakingImpulseThreshold(threshold);
753 return true; 766 return true;
754 } 767 }
768 public override bool HingeSetLimits(BulletConstraint pConstraint, float low, float high, float softness, float bias, float relaxation)
769 {
770 HingeConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as HingeConstraint;
771 if (softness == HINGE_NOT_SPECIFIED)
772 constraint.SetLimit(low, high);
773 else
774 constraint.SetLimit(low, high, softness, bias, relaxation);
775 return true;
776 }
777 public override bool SpringEnable(BulletConstraint pConstraint, int index, float numericTrueFalse)
778 {
779 Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
780 constraint.EnableSpring(index, (numericTrueFalse == 0f ? false : true));
781 return true;
782 }
783
784 public override bool SpringSetEquilibriumPoint(BulletConstraint pConstraint, int index, float equilibriumPoint)
785 {
786 Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
787 if (index == SPRING_NOT_SPECIFIED)
788 {
789 constraint.SetEquilibriumPoint();
790 }
791 else
792 {
793 if (equilibriumPoint == SPRING_NOT_SPECIFIED)
794 constraint.SetEquilibriumPoint(index);
795 else
796 constraint.SetEquilibriumPoint(index, equilibriumPoint);
797 }
798 return true;
799 }
800
801 public override bool SpringSetStiffness(BulletConstraint pConstraint, int index, float stiffness)
802 {
803 Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
804 constraint.SetStiffness(index, stiffness);
805 return true;
806 }
807
808 public override bool SpringSetDamping(BulletConstraint pConstraint, int index, float damping)
809 {
810 Generic6DofSpringConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as Generic6DofSpringConstraint;
811 constraint.SetDamping(index, damping);
812 return true;
813 }
814
815 public override bool SliderSetLimits(BulletConstraint pConstraint, int lowerUpper, int linAng, float val)
816 {
817 SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
818 switch (lowerUpper)
819 {
820 case SLIDER_LOWER_LIMIT:
821 switch (linAng)
822 {
823 case SLIDER_LINEAR:
824 constraint.SetLowerLinLimit(val);
825 break;
826 case SLIDER_ANGULAR:
827 constraint.SetLowerAngLimit(val);
828 break;
829 }
830 break;
831 case SLIDER_UPPER_LIMIT:
832 switch (linAng)
833 {
834 case SLIDER_LINEAR:
835 constraint.SetUpperLinLimit(val);
836 break;
837 case SLIDER_ANGULAR:
838 constraint.SetUpperAngLimit(val);
839 break;
840 }
841 break;
842 }
843 return true;
844 }
845 public override bool SliderSet(BulletConstraint pConstraint, int softRestDamp, int dirLimOrtho, int linAng, float val)
846 {
847 SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
848 switch (softRestDamp)
849 {
850 case SLIDER_SET_SOFTNESS:
851 switch (dirLimOrtho)
852 {
853 case SLIDER_SET_DIRECTION:
854 switch (linAng)
855 {
856 case SLIDER_LINEAR: constraint.SetSoftnessDirLin(val); break;
857 case SLIDER_ANGULAR: constraint.SetSoftnessDirAng(val); break;
858 }
859 break;
860 case SLIDER_SET_LIMIT:
861 switch (linAng)
862 {
863 case SLIDER_LINEAR: constraint.SetSoftnessLimLin(val); break;
864 case SLIDER_ANGULAR: constraint.SetSoftnessLimAng(val); break;
865 }
866 break;
867 case SLIDER_SET_ORTHO:
868 switch (linAng)
869 {
870 case SLIDER_LINEAR: constraint.SetSoftnessOrthoLin(val); break;
871 case SLIDER_ANGULAR: constraint.SetSoftnessOrthoAng(val); break;
872 }
873 break;
874 }
875 break;
876 case SLIDER_SET_RESTITUTION:
877 switch (dirLimOrtho)
878 {
879 case SLIDER_SET_DIRECTION:
880 switch (linAng)
881 {
882 case SLIDER_LINEAR: constraint.SetRestitutionDirLin(val); break;
883 case SLIDER_ANGULAR: constraint.SetRestitutionDirAng(val); break;
884 }
885 break;
886 case SLIDER_SET_LIMIT:
887 switch (linAng)
888 {
889 case SLIDER_LINEAR: constraint.SetRestitutionLimLin(val); break;
890 case SLIDER_ANGULAR: constraint.SetRestitutionLimAng(val); break;
891 }
892 break;
893 case SLIDER_SET_ORTHO:
894 switch (linAng)
895 {
896 case SLIDER_LINEAR: constraint.SetRestitutionOrthoLin(val); break;
897 case SLIDER_ANGULAR: constraint.SetRestitutionOrthoAng(val); break;
898 }
899 break;
900 }
901 break;
902 case SLIDER_SET_DAMPING:
903 switch (dirLimOrtho)
904 {
905 case SLIDER_SET_DIRECTION:
906 switch (linAng)
907 {
908 case SLIDER_LINEAR: constraint.SetDampingDirLin(val); break;
909 case SLIDER_ANGULAR: constraint.SetDampingDirAng(val); break;
910 }
911 break;
912 case SLIDER_SET_LIMIT:
913 switch (linAng)
914 {
915 case SLIDER_LINEAR: constraint.SetDampingLimLin(val); break;
916 case SLIDER_ANGULAR: constraint.SetDampingLimAng(val); break;
917 }
918 break;
919 case SLIDER_SET_ORTHO:
920 switch (linAng)
921 {
922 case SLIDER_LINEAR: constraint.SetDampingOrthoLin(val); break;
923 case SLIDER_ANGULAR: constraint.SetDampingOrthoAng(val); break;
924 }
925 break;
926 }
927 break;
928 }
929 return true;
930 }
931 public override bool SliderMotorEnable(BulletConstraint pConstraint, int linAng, float numericTrueFalse)
932 {
933 SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
934 switch (linAng)
935 {
936 case SLIDER_LINEAR:
937 constraint.SetPoweredLinMotor(numericTrueFalse == 0.0 ? false : true);
938 break;
939 case SLIDER_ANGULAR:
940 constraint.SetPoweredAngMotor(numericTrueFalse == 0.0 ? false : true);
941 break;
942 }
943 return true;
944 }
945 public override bool SliderMotor(BulletConstraint pConstraint, int forceVel, int linAng, float val)
946 {
947 SliderConstraint constraint = (pConstraint as BulletConstraintXNA).constrain as SliderConstraint;
948 switch (forceVel)
949 {
950 case SLIDER_MOTOR_VELOCITY:
951 switch (linAng)
952 {
953 case SLIDER_LINEAR:
954 constraint.SetTargetLinMotorVelocity(val);
955 break;
956 case SLIDER_ANGULAR:
957 constraint.SetTargetAngMotorVelocity(val);
958 break;
959 }
960 break;
961 case SLIDER_MAX_MOTOR_FORCE:
962 switch (linAng)
963 {
964 case SLIDER_LINEAR:
965 constraint.SetMaxLinMotorForce(val);
966 break;
967 case SLIDER_ANGULAR:
968 constraint.SetMaxAngMotorForce(val);
969 break;
970 }
971 break;
972 }
973 return true;
974 }
975
755 //BulletSimAPI.SetAngularDamping(Prim.PhysBody.ptr, angularDamping); 976 //BulletSimAPI.SetAngularDamping(Prim.PhysBody.ptr, angularDamping);
756 public override void SetAngularDamping(BulletBody pBody, float angularDamping) 977 public override void SetAngularDamping(BulletBody pBody, float angularDamping)
757 { 978 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
index 68bc1b9..1bcf879 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSActorAvatarMove.cs
@@ -105,7 +105,7 @@ public class BSActorAvatarMove : BSActor
105 // into the movement motor. 105 // into the movement motor.
106 public void SetVelocityAndTarget(OMV.Vector3 vel, OMV.Vector3 targ, bool inTaintTime) 106 public void SetVelocityAndTarget(OMV.Vector3 vel, OMV.Vector3 targ, bool inTaintTime)
107 { 107 {
108 m_physicsScene.TaintedObject(inTaintTime, "BSActorAvatarMove.setVelocityAndTarget", delegate() 108 m_physicsScene.TaintedObject(inTaintTime, m_controllingPrim.LocalID, "BSActorAvatarMove.setVelocityAndTarget", delegate()
109 { 109 {
110 if (m_velocityMotor != null) 110 if (m_velocityMotor != null)
111 { 111 {
@@ -128,6 +128,7 @@ public class BSActorAvatarMove : BSActor
128 BSMotor.Infinite, // decay time scale 128 BSMotor.Infinite, // decay time scale
129 1f // efficiency 129 1f // efficiency
130 ); 130 );
131 m_velocityMotor.ErrorZeroThreshold = BSParam.AvatarStopZeroThreshold;
131 // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. 132 // _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.
132 SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */); 133 SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity, true /* inTaintTime */);
133 134
@@ -278,6 +279,7 @@ public class BSActorAvatarMove : BSActor
278 if (m_controllingPrim.IsStationary) 279 if (m_controllingPrim.IsStationary)
279 { 280 {
280 entprop.Position = m_controllingPrim.RawPosition; 281 entprop.Position = m_controllingPrim.RawPosition;
282 entprop.Velocity = OMV.Vector3.Zero;
281 m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation); 283 m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation);
282 } 284 }
283 285
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
index 6cdc112..f7dd158 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
@@ -43,7 +43,9 @@ public enum ConstraintType : int
43 SLIDER_CONSTRAINT_TYPE, 43 SLIDER_CONSTRAINT_TYPE,
44 CONTACT_CONSTRAINT_TYPE, 44 CONTACT_CONSTRAINT_TYPE,
45 D6_SPRING_CONSTRAINT_TYPE, 45 D6_SPRING_CONSTRAINT_TYPE,
46 MAX_CONSTRAINT_TYPE 46 MAX_CONSTRAINT_TYPE, // last type defined by Bullet
47 //
48 FIXED_CONSTRAINT_TYPE = 1234 // BulletSim constraint that is fixed and unmoving
47} 49}
48 50
49// =============================================================================== 51// ===============================================================================
@@ -290,7 +292,7 @@ public enum ConstraintParamAxis : int
290 AXIS_ANGULAR_X, 292 AXIS_ANGULAR_X,
291 AXIS_ANGULAR_Y, 293 AXIS_ANGULAR_Y,
292 AXIS_ANGULAR_Z, 294 AXIS_ANGULAR_Z,
293 AXIS_LINEAR_ALL = 20, // these last three added by BulletSim so we don't have to do zillions of calls 295 AXIS_LINEAR_ALL = 20, // added by BulletSim so we don't have to do zillions of calls
294 AXIS_ANGULAR_ALL, 296 AXIS_ANGULAR_ALL,
295 AXIS_ALL 297 AXIS_ALL
296}; 298};
@@ -441,6 +443,38 @@ public abstract bool TranslationalLimitMotor(BulletConstraint constrain, float e
441 443
442public abstract bool SetBreakingImpulseThreshold(BulletConstraint constrain, float threshold); 444public abstract bool SetBreakingImpulseThreshold(BulletConstraint constrain, float threshold);
443 445
446public const int HINGE_NOT_SPECIFIED = -1;
447public abstract bool HingeSetLimits(BulletConstraint constrain, float low, float high, float softness, float bias, float relaxation);
448
449public abstract bool SpringEnable(BulletConstraint constrain, int index, float numericTrueFalse);
450
451public const int SPRING_NOT_SPECIFIED = -1;
452public abstract bool SpringSetEquilibriumPoint(BulletConstraint constrain, int index, float equilibriumPoint);
453
454public abstract bool SpringSetStiffness(BulletConstraint constrain, int index, float stiffnesss);
455
456public abstract bool SpringSetDamping(BulletConstraint constrain, int index, float damping);
457
458public const int SLIDER_LOWER_LIMIT = 0;
459public const int SLIDER_UPPER_LIMIT = 1;
460public const int SLIDER_LINEAR = 2;
461public const int SLIDER_ANGULAR = 3;
462public abstract bool SliderSetLimits(BulletConstraint constrain, int lowerUpper, int linAng, float val);
463
464public const int SLIDER_SET_SOFTNESS = 4;
465public const int SLIDER_SET_RESTITUTION = 5;
466public const int SLIDER_SET_DAMPING = 6;
467public const int SLIDER_SET_DIRECTION = 7;
468public const int SLIDER_SET_LIMIT = 8;
469public const int SLIDER_SET_ORTHO = 9;
470public abstract bool SliderSet(BulletConstraint constrain, int softRestDamp, int dirLimOrtho, int linAng, float val);
471
472public abstract bool SliderMotorEnable(BulletConstraint constrain, int linAng, float numericTrueFalse);
473
474public const int SLIDER_MOTOR_VELOCITY = 10;
475public const int SLIDER_MAX_MOTOR_FORCE = 11;
476public abstract bool SliderMotor(BulletConstraint constrain, int forceVel, int linAng, float val);
477
444public abstract bool CalculateTransforms(BulletConstraint constrain); 478public abstract bool CalculateTransforms(BulletConstraint constrain);
445 479
446public abstract bool SetConstraintParam(BulletConstraint constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis); 480public abstract bool SetConstraintParam(BulletConstraint constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
@@ -464,6 +498,8 @@ public abstract bool AddObjectToWorld(BulletWorld world, BulletBody obj);
464 498
465public abstract bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj); 499public abstract bool RemoveObjectFromWorld(BulletWorld world, BulletBody obj);
466 500
501public abstract bool ClearCollisionProxyCache(BulletWorld world, BulletBody obj);
502
467public abstract bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects); 503public abstract bool AddConstraintToWorld(BulletWorld world, BulletConstraint constrain, bool disableCollisionsBetweenLinkedObjects);
468 504
469public abstract bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain); 505public abstract bool RemoveConstraintFromWorld(BulletWorld world, BulletConstraint constrain);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 291dfcd..fc18960 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -93,7 +93,7 @@ public sealed class BSCharacter : BSPhysObject
93 LocalID, _size, Scale, Density, _avatarVolume, RawMass, pos); 93 LocalID, _size, Scale, Density, _avatarVolume, RawMass, pos);
94 94
95 // do actual creation in taint time 95 // do actual creation in taint time
96 PhysScene.TaintedObject("BSCharacter.create", delegate() 96 PhysScene.TaintedObject(LocalID, "BSCharacter.create", delegate()
97 { 97 {
98 DetailLog("{0},BSCharacter.create,taint", LocalID); 98 DetailLog("{0},BSCharacter.create,taint", LocalID);
99 // New body and shape into PhysBody and PhysShape 99 // New body and shape into PhysBody and PhysShape
@@ -121,7 +121,7 @@ public sealed class BSCharacter : BSPhysObject
121 base.Destroy(); 121 base.Destroy();
122 122
123 DetailLog("{0},BSCharacter.Destroy", LocalID); 123 DetailLog("{0},BSCharacter.Destroy", LocalID);
124 PhysScene.TaintedObject("BSCharacter.destroy", delegate() 124 PhysScene.TaintedObject(LocalID, "BSCharacter.destroy", delegate()
125 { 125 {
126 PhysScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */); 126 PhysScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */);
127 PhysBody.Clear(); 127 PhysBody.Clear();
@@ -209,7 +209,7 @@ public sealed class BSCharacter : BSPhysObject
209 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}", 209 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
210 LocalID, _size, Scale, Density, _avatarVolume, RawMass); 210 LocalID, _size, Scale, Density, _avatarVolume, RawMass);
211 211
212 PhysScene.TaintedObject("BSCharacter.setSize", delegate() 212 PhysScene.TaintedObject(LocalID, "BSCharacter.setSize", delegate()
213 { 213 {
214 if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape) 214 if (PhysBody.HasPhysicalBody && PhysShape.physShapeInfo.HasPhysicalShape)
215 { 215 {
@@ -257,7 +257,7 @@ public sealed class BSCharacter : BSPhysObject
257 _rotationalVelocity = OMV.Vector3.Zero; 257 _rotationalVelocity = OMV.Vector3.Zero;
258 258
259 // Zero some other properties directly into the physics engine 259 // Zero some other properties directly into the physics engine
260 PhysScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() 260 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.ZeroMotion", delegate()
261 { 261 {
262 if (PhysBody.HasPhysicalBody) 262 if (PhysBody.HasPhysicalBody)
263 PhysScene.PE.ClearAllForces(PhysBody); 263 PhysScene.PE.ClearAllForces(PhysBody);
@@ -267,7 +267,7 @@ public sealed class BSCharacter : BSPhysObject
267 { 267 {
268 _rotationalVelocity = OMV.Vector3.Zero; 268 _rotationalVelocity = OMV.Vector3.Zero;
269 269
270 PhysScene.TaintedObject(inTaintTime, "BSCharacter.ZeroMotion", delegate() 270 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.ZeroMotion", delegate()
271 { 271 {
272 if (PhysBody.HasPhysicalBody) 272 if (PhysBody.HasPhysicalBody)
273 { 273 {
@@ -291,7 +291,7 @@ public sealed class BSCharacter : BSPhysObject
291 set { 291 set {
292 RawPosition = value; 292 RawPosition = value;
293 293
294 PhysScene.TaintedObject("BSCharacter.setPosition", delegate() 294 PhysScene.TaintedObject(LocalID, "BSCharacter.setPosition", delegate()
295 { 295 {
296 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation); 296 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
297 PositionSanityCheck(); 297 PositionSanityCheck();
@@ -363,7 +363,7 @@ public sealed class BSCharacter : BSPhysObject
363 { 363 {
364 // The new position value must be pushed into the physics engine but we can't 364 // The new position value must be pushed into the physics engine but we can't
365 // just assign to "Position" because of potential call loops. 365 // just assign to "Position" because of potential call loops.
366 PhysScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() 366 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.PositionSanityCheck", delegate()
367 { 367 {
368 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation); 368 DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
369 ForcePosition = RawPosition; 369 ForcePosition = RawPosition;
@@ -390,7 +390,7 @@ public sealed class BSCharacter : BSPhysObject
390 set { 390 set {
391 RawForce = value; 391 RawForce = value;
392 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); 392 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
393 PhysScene.TaintedObject("BSCharacter.SetForce", delegate() 393 PhysScene.TaintedObject(LocalID, "BSCharacter.SetForce", delegate()
394 { 394 {
395 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce); 395 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, RawForce);
396 if (PhysBody.HasPhysicalBody) 396 if (PhysBody.HasPhysicalBody)
@@ -438,7 +438,7 @@ public sealed class BSCharacter : BSPhysObject
438 set { 438 set {
439 RawVelocity = value; 439 RawVelocity = value;
440 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity); 440 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, RawVelocity);
441 PhysScene.TaintedObject("BSCharacter.setVelocity", delegate() 441 PhysScene.TaintedObject(LocalID, "BSCharacter.setVelocity", delegate()
442 { 442 {
443 if (m_moveActor != null) 443 if (m_moveActor != null)
444 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */); 444 m_moveActor.SetVelocityAndTarget(RawVelocity, RawVelocity, true /* inTaintTime */);
@@ -480,7 +480,7 @@ public sealed class BSCharacter : BSPhysObject
480 if (RawOrientation != value) 480 if (RawOrientation != value)
481 { 481 {
482 RawOrientation = value; 482 RawOrientation = value;
483 PhysScene.TaintedObject("BSCharacter.setOrientation", delegate() 483 PhysScene.TaintedObject(LocalID, "BSCharacter.setOrientation", delegate()
484 { 484 {
485 // Bullet assumes we know what we are doing when forcing orientation 485 // Bullet assumes we know what we are doing when forcing orientation
486 // so it lets us go against all the rules and just compensates for them later. 486 // so it lets us go against all the rules and just compensates for them later.
@@ -560,7 +560,7 @@ public sealed class BSCharacter : BSPhysObject
560 public override bool FloatOnWater { 560 public override bool FloatOnWater {
561 set { 561 set {
562 _floatOnWater = value; 562 _floatOnWater = value;
563 PhysScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() 563 PhysScene.TaintedObject(LocalID, "BSCharacter.setFloatOnWater", delegate()
564 { 564 {
565 if (PhysBody.HasPhysicalBody) 565 if (PhysBody.HasPhysicalBody)
566 { 566 {
@@ -588,7 +588,7 @@ public sealed class BSCharacter : BSPhysObject
588 public override float Buoyancy { 588 public override float Buoyancy {
589 get { return _buoyancy; } 589 get { return _buoyancy; }
590 set { _buoyancy = value; 590 set { _buoyancy = value;
591 PhysScene.TaintedObject("BSCharacter.setBuoyancy", delegate() 591 PhysScene.TaintedObject(LocalID, "BSCharacter.setBuoyancy", delegate()
592 { 592 {
593 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 593 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
594 ForceBuoyancy = _buoyancy; 594 ForceBuoyancy = _buoyancy;
@@ -633,7 +633,7 @@ public sealed class BSCharacter : BSPhysObject
633 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude); 633 OMV.Vector3 addForce = Util.ClampV(force, BSParam.MaxAddForceMagnitude);
634 // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce); 634 // DetailLog("{0},BSCharacter.addForce,call,force={1}", LocalID, addForce);
635 635
636 PhysScene.TaintedObject(inTaintTime, "BSCharacter.AddForce", delegate() 636 PhysScene.TaintedObject(inTaintTime, LocalID, "BSCharacter.AddForce", delegate()
637 { 637 {
638 // Bullet adds this central force to the total force for this tick 638 // Bullet adds this central force to the total force for this tick
639 // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce); 639 // DetailLog("{0},BSCharacter.addForce,taint,force={1}", LocalID, addForce);
@@ -676,18 +676,20 @@ public sealed class BSCharacter : BSPhysObject
676 float heightAdjust = BSParam.AvatarHeightMidFudge; 676 float heightAdjust = BSParam.AvatarHeightMidFudge;
677 if (BSParam.AvatarHeightLowFudge != 0f || BSParam.AvatarHeightHighFudge != 0f) 677 if (BSParam.AvatarHeightLowFudge != 0f || BSParam.AvatarHeightHighFudge != 0f)
678 { 678 {
679 // An avatar is between 1.61 and 2.12 meters. Midpoint is 1.87m. 679 const float AVATAR_LOW = 1.1f;
680 // The "times 4" relies on the fact that the difference from the midpoint to the extremes is exactly 0.25 680 const float AVATAR_MID = 1.775f; // 1.87f
681 float midHeightOffset = size.Z - 1.87f; 681 const float AVATAR_HI = 2.45f;
682 // An avatar is between 1.1 and 2.45 meters. Midpoint is 1.775m.
683 float midHeightOffset = size.Z - AVATAR_MID;
682 if (midHeightOffset < 0f) 684 if (midHeightOffset < 0f)
683 { 685 {
684 // Small avatar. Add the adjustment based on the distance from midheight 686 // Small avatar. Add the adjustment based on the distance from midheight
685 heightAdjust += -1f * midHeightOffset * 4f * BSParam.AvatarHeightLowFudge; 687 heightAdjust += ((-1f * midHeightOffset) / (AVATAR_MID - AVATAR_LOW)) * BSParam.AvatarHeightLowFudge;
686 } 688 }
687 else 689 else
688 { 690 {
689 // Large avatar. Add the adjustment based on the distance from midheight 691 // Large avatar. Add the adjustment based on the distance from midheight
690 heightAdjust += midHeightOffset * 4f * BSParam.AvatarHeightHighFudge; 692 heightAdjust += ((midHeightOffset) / (AVATAR_HI - AVATAR_MID)) * BSParam.AvatarHeightHighFudge;
691 } 693 }
692 } 694 }
693 // The total scale height is the central cylindar plus the caps on the two ends. 695 // The total scale height is the central cylindar plus the caps on the two ends.
@@ -698,6 +700,9 @@ public sealed class BSCharacter : BSPhysObject
698 if (newScale.Z < 0) 700 if (newScale.Z < 0)
699 newScale.Z = 0.1f; 701 newScale.Z = 0.1f;
700 702
703 DetailLog("{0},BSCharacter.ComputerAvatarScale,size={1},lowF={2},midF={3},hiF={4},adj={5},newScale={6}",
704 LocalID, size, BSParam.AvatarHeightLowFudge, BSParam.AvatarHeightMidFudge, BSParam.AvatarHeightHighFudge, heightAdjust, newScale);
705
701 return newScale; 706 return newScale;
702 } 707 }
703 708
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index 42b5c49..b47e9a8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -64,7 +64,7 @@ public abstract class BSConstraint : IDisposable
64 { 64 {
65 bool success = PhysicsScene.PE.DestroyConstraint(m_world, m_constraint); 65 bool success = PhysicsScene.PE.DestroyConstraint(m_world, m_constraint);
66 m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", 66 m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}",
67 BSScene.DetailLogZero, 67 m_body1.ID,
68 m_body1.ID, m_body1.AddrString, 68 m_body1.ID, m_body1.AddrString,
69 m_body2.ID, m_body2.AddrString, 69 m_body2.ID, m_body2.AddrString,
70 success); 70 success);
@@ -77,7 +77,10 @@ public abstract class BSConstraint : IDisposable
77 { 77 {
78 bool ret = false; 78 bool ret = false;
79 if (m_enabled) 79 if (m_enabled)
80 {
81 m_world.physicsScene.DetailLog("{0},BSConstraint.SetLinearLimits,taint,low={1},high={2}", m_body1.ID, low, high);
80 ret = PhysicsScene.PE.SetLinearLimits(m_constraint, low, high); 82 ret = PhysicsScene.PE.SetLinearLimits(m_constraint, low, high);
83 }
81 return ret; 84 return ret;
82 } 85 }
83 86
@@ -86,6 +89,7 @@ public abstract class BSConstraint : IDisposable
86 bool ret = false; 89 bool ret = false;
87 if (m_enabled) 90 if (m_enabled)
88 { 91 {
92 m_world.physicsScene.DetailLog("{0},BSConstraint.SetAngularLimits,taint,low={1},high={2}", m_body1.ID, low, high);
89 ret = PhysicsScene.PE.SetAngularLimits(m_constraint, low, high); 93 ret = PhysicsScene.PE.SetAngularLimits(m_constraint, low, high);
90 } 94 }
91 return ret; 95 return ret;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
index d0949f5..7fcb75c 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs
@@ -32,12 +32,19 @@ using OpenMetaverse;
32namespace OpenSim.Region.Physics.BulletSPlugin 32namespace OpenSim.Region.Physics.BulletSPlugin
33{ 33{
34 34
35public sealed class BSConstraint6Dof : BSConstraint 35public class BSConstraint6Dof : BSConstraint
36{ 36{
37 private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; 37 private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]";
38 38
39 public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } 39 public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } }
40 40
41 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2) :base(world)
42 {
43 m_body1 = obj1;
44 m_body2 = obj2;
45 m_enabled = false;
46 }
47
41 // Create a btGeneric6DofConstraint 48 // Create a btGeneric6DofConstraint
42 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2, 49 public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
43 Vector3 frame1, Quaternion frame1rot, 50 Vector3 frame1, Quaternion frame1rot,
@@ -52,9 +59,11 @@ public sealed class BSConstraint6Dof : BSConstraint
52 frame2, frame2rot, 59 frame2, frame2rot,
53 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies); 60 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
54 m_enabled = true; 61 m_enabled = true;
55 world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", 62 PhysicsScene.DetailLog("{0},BS6DofConstraint,create,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
56 BSScene.DetailLogZero, world.worldID, 63 m_body1.ID, world.worldID,
57 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString); 64 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
65 PhysicsScene.DetailLog("{0},BS6DofConstraint,create, f1Loc={1},f1Rot={2},f2Loc={3},f2Rot={4},usefA={5},disCol={6}",
66 m_body1.ID, frame1, frame1rot, frame2, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
58 } 67 }
59 68
60 // 6 Dof constraint based on a midpoint between the two constrained bodies 69 // 6 Dof constraint based on a midpoint between the two constrained bodies
@@ -79,9 +88,11 @@ public sealed class BSConstraint6Dof : BSConstraint
79 m_constraint = PhysicsScene.PE.Create6DofConstraintToPoint(m_world, m_body1, m_body2, 88 m_constraint = PhysicsScene.PE.Create6DofConstraintToPoint(m_world, m_body1, m_body2,
80 joinPoint, 89 joinPoint,
81 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies); 90 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
91
82 PhysicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", 92 PhysicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}",
83 BSScene.DetailLogZero, world.worldID, m_constraint.AddrString, 93 m_body1.ID, world.worldID, m_constraint.AddrString,
84 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString); 94 obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
95
85 if (!m_constraint.HasPhysicalConstraint) 96 if (!m_constraint.HasPhysicalConstraint)
86 { 97 {
87 world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", 98 world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}",
@@ -106,8 +117,10 @@ public sealed class BSConstraint6Dof : BSConstraint
106 frameInBloc, frameInBrot, 117 frameInBloc, frameInBrot,
107 useLinearReferenceFrameB, disableCollisionsBetweenLinkedBodies); 118 useLinearReferenceFrameB, disableCollisionsBetweenLinkedBodies);
108 m_enabled = true; 119 m_enabled = true;
109 world.physicsScene.DetailLog("{0},BS6DofConstraint,createFixed,wID={1},rID={2},rBody={3}", 120 PhysicsScene.DetailLog("{0},BS6DofConstraint,createFixed,wID={1},rID={2},rBody={3}",
110 BSScene.DetailLogZero, world.worldID, obj1.ID, obj1.AddrString); 121 m_body1.ID, world.worldID, obj1.ID, obj1.AddrString);
122 PhysicsScene.DetailLog("{0},BS6DofConstraint,createFixed, fBLoc={1},fBRot={2},usefA={3},disCol={4}",
123 m_body1.ID, frameInBloc, frameInBrot, useLinearReferenceFrameB, disableCollisionsBetweenLinkedBodies);
111 } 124 }
112 125
113 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) 126 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintConeTwist.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintConeTwist.cs
new file mode 100755
index 0000000..7a76a9a
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintConeTwist.cs
@@ -0,0 +1,54 @@
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.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public sealed class BSConstraintConeTwist : BSConstraint
36{
37 public override ConstraintType Type { get { return ConstraintType.CONETWIST_CONSTRAINT_TYPE; } }
38
39 public BSConstraintConeTwist(BulletWorld world, BulletBody obj1, BulletBody obj2,
40 Vector3 frameInAloc, Quaternion frameInArot,
41 Vector3 frameInBloc, Quaternion frameInBrot,
42 bool disableCollisionsBetweenLinkedBodies)
43 : base(world)
44 {
45 m_body1 = obj1;
46 m_body2 = obj2;
47 m_constraint = PhysicsScene.PE.CreateConeTwistConstraint(world, obj1, obj2,
48 frameInAloc, frameInArot, frameInBloc, frameInBrot,
49 disableCollisionsBetweenLinkedBodies);
50 m_enabled = true;
51 }
52}
53
54}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSlider.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSlider.cs
new file mode 100755
index 0000000..37cfa07
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSlider.cs
@@ -0,0 +1,55 @@
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.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public sealed class BSConstraintSlider : BSConstraint
36{
37 public override ConstraintType Type { get { return ConstraintType.SLIDER_CONSTRAINT_TYPE; } }
38
39 public BSConstraintSlider(BulletWorld world, BulletBody obj1, BulletBody obj2,
40 Vector3 frameInAloc, Quaternion frameInArot,
41 Vector3 frameInBloc, Quaternion frameInBrot,
42 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
43 : base(world)
44 {
45 m_body1 = obj1;
46 m_body2 = obj2;
47 m_constraint = PhysicsScene.PE.CreateSliderConstraint(world, obj1, obj2,
48 frameInAloc, frameInArot, frameInBloc, frameInBrot,
49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
50 m_enabled = true;
51 }
52
53}
54
55}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSpring.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSpring.cs
new file mode 100755
index 0000000..8e7ddff
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintSpring.cs
@@ -0,0 +1,103 @@
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.Text;
30using OpenMetaverse;
31
32namespace OpenSim.Region.Physics.BulletSPlugin
33{
34
35public sealed class BSConstraintSpring : BSConstraint6Dof
36{
37 public override ConstraintType Type { get { return ConstraintType.D6_SPRING_CONSTRAINT_TYPE; } }
38
39 public BSConstraintSpring(BulletWorld world, BulletBody obj1, BulletBody obj2,
40 Vector3 frame1Loc, Quaternion frame1Rot,
41 Vector3 frame2Loc, Quaternion frame2Rot,
42 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
43 :base(world, obj1, obj2)
44 {
45 m_constraint = PhysicsScene.PE.Create6DofSpringConstraint(world, obj1, obj2,
46 frame1Loc, frame1Rot, frame2Loc, frame2Rot,
47 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
48 m_enabled = true;
49
50 PhysicsScene.DetailLog("{0},BSConstraintSpring,create,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}",
51 obj1.ID, world.worldID, obj1.ID, obj1.AddrString, obj2.ID, obj2.AddrString);
52 PhysicsScene.DetailLog("{0},BSConstraintSpring,create, f1Loc={1},f1Rot={2},f2Loc={3},f2Rot={4},usefA={5},disCol={6}",
53 m_body1.ID, frame1Loc, frame1Rot, frame2Loc, frame2Rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies);
54 }
55
56 public bool SetAxisEnable(int pIndex, bool pAxisEnable)
57 {
58 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetEnable,obj1ID={1},obj2ID={2},indx={3},enable={4}",
59 m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pAxisEnable);
60 PhysicsScene.PE.SpringEnable(m_constraint, pIndex, BSParam.NumericBool(pAxisEnable));
61 return true;
62 }
63
64 public bool SetStiffness(int pIndex, float pStiffness)
65 {
66 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetStiffness,obj1ID={1},obj2ID={2},indx={3},stiff={4}",
67 m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pStiffness);
68 PhysicsScene.PE.SpringSetStiffness(m_constraint, pIndex, pStiffness);
69 return true;
70 }
71
72 public bool SetDamping(int pIndex, float pDamping)
73 {
74 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetDamping,obj1ID={1},obj2ID={2},indx={3},damp={4}",
75 m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pDamping);
76 PhysicsScene.PE.SpringSetDamping(m_constraint, pIndex, pDamping);
77 return true;
78 }
79
80 public bool SetEquilibriumPoint(int pIndex, float pEqPoint)
81 {
82 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetEquilibriumPoint,obj1ID={1},obj2ID={2},indx={3},eqPoint={4}",
83 m_body1.ID, m_body1.ID, m_body2.ID, pIndex, pEqPoint);
84 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, pIndex, pEqPoint);
85 return true;
86 }
87
88 public bool SetEquilibriumPoint(Vector3 linearEq, Vector3 angularEq)
89 {
90 PhysicsScene.DetailLog("{0},BSConstraintSpring.SetEquilibriumPoint,obj1ID={1},obj2ID={2},linearEq={3},angularEq={4}",
91 m_body1.ID, m_body1.ID, m_body2.ID, linearEq, angularEq);
92 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 0, linearEq.X);
93 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 1, linearEq.Y);
94 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 2, linearEq.Z);
95 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 3, angularEq.X);
96 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 4, angularEq.Y);
97 PhysicsScene.PE.SpringSetEquilibriumPoint(m_constraint, 5, angularEq.Z);
98 return true;
99 }
100
101}
102
103} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 3afd52e..77f69a5 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -77,6 +77,10 @@ public abstract class BSLinkset
77 { 77 {
78 member = pMember; 78 member = pMember;
79 } 79 }
80 public virtual void ResetLink() { }
81 public virtual void SetLinkParameters(BSConstraint constrain) { }
82 // Returns 'true' if physical property updates from the child should be reported to the simulator
83 public virtual bool ShouldUpdateChildProperties() { return false; }
80 } 84 }
81 85
82 public LinksetImplementation LinksetImpl { get; protected set; } 86 public LinksetImplementation LinksetImpl { get; protected set; }
@@ -148,7 +152,7 @@ public abstract class BSLinkset
148 // Returns a new linkset for the child which is a linkset of one (just the 152 // Returns a new linkset for the child which is a linkset of one (just the
149 // orphened child). 153 // orphened child).
150 // Called at runtime. 154 // Called at runtime.
151 public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child) 155 public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child, bool inTaintTime)
152 { 156 {
153 lock (m_linksetActivityLock) 157 lock (m_linksetActivityLock)
154 { 158 {
@@ -157,7 +161,7 @@ public abstract class BSLinkset
157 // Cannot remove the root from a linkset. 161 // Cannot remove the root from a linkset.
158 return this; 162 return this;
159 } 163 }
160 RemoveChildFromLinkset(child); 164 RemoveChildFromLinkset(child, inTaintTime);
161 LinksetMass = ComputeLinksetMass(); 165 LinksetMass = ComputeLinksetMass();
162 } 166 }
163 167
@@ -205,6 +209,17 @@ public abstract class BSLinkset
205 return ret; 209 return ret;
206 } 210 }
207 211
212 public bool TryGetLinkInfo(BSPrimLinkable child, out BSLinkInfo foundInfo)
213 {
214 bool ret = false;
215 BSLinkInfo found = null;
216 lock (m_linksetActivityLock)
217 {
218 ret = m_children.TryGetValue(child, out found);
219 }
220 foundInfo = found;
221 return ret;
222 }
208 // Perform an action on each member of the linkset including root prim. 223 // Perform an action on each member of the linkset including root prim.
209 // Depends on the action on whether this should be done at taint time. 224 // Depends on the action on whether this should be done at taint time.
210 public delegate bool ForEachLinkInfoAction(BSLinkInfo obj); 225 public delegate bool ForEachLinkInfoAction(BSLinkInfo obj);
@@ -222,6 +237,21 @@ public abstract class BSLinkset
222 return ret; 237 return ret;
223 } 238 }
224 239
240 // Check the type of the link and return 'true' if the link is flexible and the
241 // updates from the child should be sent to the simulator so things change.
242 public virtual bool ShouldReportPropertyUpdates(BSPrimLinkable child)
243 {
244 bool ret = false;
245
246 BSLinkInfo linkInfo;
247 if (m_children.TryGetValue(child, out linkInfo))
248 {
249 ret = linkInfo.ShouldUpdateChildProperties();
250 }
251
252 return ret;
253 }
254
225 // Called after a simulation step to post a collision with this object. 255 // Called after a simulation step to post a collision with this object.
226 // Return 'true' if linkset processed the collision. 'false' says the linkset didn't have 256 // Return 'true' if linkset processed the collision. 'false' says the linkset didn't have
227 // anything to add for the collision and it should be passed through normal processing. 257 // anything to add for the collision and it should be passed through normal processing.
@@ -255,7 +285,7 @@ public abstract class BSLinkset
255 285
256 // I am the root of a linkset and one of my children is being removed. 286 // I am the root of a linkset and one of my children is being removed.
257 // Safe to call even if the child is not really in my linkset. 287 // Safe to call even if the child is not really in my linkset.
258 protected abstract void RemoveChildFromLinkset(BSPrimLinkable child); 288 protected abstract void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime);
259 289
260 // When physical properties are changed the linkset needs to recalculate 290 // When physical properties are changed the linkset needs to recalculate
261 // its internal properties. 291 // its internal properties.
@@ -430,6 +460,13 @@ public abstract class BSLinkset
430 return com; 460 return com;
431 } 461 }
432 462
463 #region Extension
464 public virtual object Extension(string pFunct, params object[] pParams)
465 {
466 return null;
467 }
468 #endregion // Extension
469
433 // Invoke the detailed logger and output something if it's enabled. 470 // Invoke the detailed logger and output something if it's enabled.
434 protected void DetailLog(string msg, params Object[] args) 471 protected void DetailLog(string msg, params Object[] args)
435 { 472 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index 085d195..8f12189 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -90,10 +90,9 @@ public sealed class BSLinksetCompound : BSLinkset
90 // its internal properties. 90 // its internal properties.
91 public override void Refresh(BSPrimLinkable requestor) 91 public override void Refresh(BSPrimLinkable requestor)
92 { 92 {
93 base.Refresh(requestor);
94
95 // Something changed so do the rebuilding thing 93 // Something changed so do the rebuilding thing
96 // ScheduleRebuild(); 94 ScheduleRebuild(requestor);
95 base.Refresh(requestor);
97 } 96 }
98 97
99 // Schedule a refresh to happen after all the other taint processing. 98 // Schedule a refresh to happen after all the other taint processing.
@@ -127,7 +126,7 @@ public sealed class BSLinksetCompound : BSLinkset
127 if (IsRoot(child)) 126 if (IsRoot(child))
128 { 127 {
129 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly. 128 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
130 ScheduleRebuild(LinksetRoot); 129 Refresh(LinksetRoot);
131 } 130 }
132 return ret; 131 return ret;
133 } 132 }
@@ -144,7 +143,7 @@ public sealed class BSLinksetCompound : BSLinkset
144 if (IsRoot(child)) 143 if (IsRoot(child))
145 { 144 {
146 // Schedule a rebuild to verify that the root shape is set to the real shape. 145 // Schedule a rebuild to verify that the root shape is set to the real shape.
147 ScheduleRebuild(LinksetRoot); 146 Refresh(LinksetRoot);
148 } 147 }
149 return ret; 148 return ret;
150 } 149 }
@@ -227,7 +226,7 @@ public sealed class BSLinksetCompound : BSLinkset
227 // there will already be a rebuild scheduled. 226 // there will already be a rebuild scheduled.
228 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}", 227 DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}",
229 updated.LocalID, whichUpdated); 228 updated.LocalID, whichUpdated);
230 ScheduleRebuild(updated); 229 Refresh(updated);
231 } 230 }
232 } 231 }
233 } 232 }
@@ -242,10 +241,10 @@ public sealed class BSLinksetCompound : BSLinkset
242 { 241 {
243 bool ret = false; 242 bool ret = false;
244 243
245 DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", 244 DetailLog("{0},BSLinksetCompound.RemoveDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}",
246 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child)); 245 child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child));
247 246
248 ScheduleRebuild(child); 247 Refresh(child);
249 248
250 return ret; 249 return ret;
251 } 250 }
@@ -263,14 +262,14 @@ public sealed class BSLinksetCompound : BSLinkset
263 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); 262 DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
264 263
265 // Rebuild the compound shape with the new child shape included 264 // Rebuild the compound shape with the new child shape included
266 ScheduleRebuild(child); 265 Refresh(child);
267 } 266 }
268 return; 267 return;
269 } 268 }
270 269
271 // Remove the specified child from the linkset. 270 // Remove the specified child from the linkset.
272 // Safe to call even if the child is not really in the linkset. 271 // Safe to call even if the child is not really in the linkset.
273 protected override void RemoveChildFromLinkset(BSPrimLinkable child) 272 protected override void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime)
274 { 273 {
275 child.ClearDisplacement(); 274 child.ClearDisplacement();
276 275
@@ -282,17 +281,17 @@ public sealed class BSLinksetCompound : BSLinkset
282 child.LocalID, child.PhysBody.AddrString); 281 child.LocalID, child.PhysBody.AddrString);
283 282
284 // Cause the child's body to be rebuilt and thus restored to normal operation 283 // Cause the child's body to be rebuilt and thus restored to normal operation
285 child.ForceBodyShapeRebuild(false); 284 child.ForceBodyShapeRebuild(inTaintTime);
286 285
287 if (!HasAnyChildren) 286 if (!HasAnyChildren)
288 { 287 {
289 // The linkset is now empty. The root needs rebuilding. 288 // The linkset is now empty. The root needs rebuilding.
290 LinksetRoot.ForceBodyShapeRebuild(false); 289 LinksetRoot.ForceBodyShapeRebuild(inTaintTime);
291 } 290 }
292 else 291 else
293 { 292 {
294 // Rebuild the compound shape with the child removed 293 // Rebuild the compound shape with the child removed
295 ScheduleRebuild(LinksetRoot); 294 Refresh(LinksetRoot);
296 } 295 }
297 } 296 }
298 return; 297 return;
@@ -318,10 +317,10 @@ public sealed class BSLinksetCompound : BSLinkset
318 // being destructed and going non-physical. 317 // being destructed and going non-physical.
319 LinksetRoot.ForceBodyShapeRebuild(true); 318 LinksetRoot.ForceBodyShapeRebuild(true);
320 319
321 // There is no reason to build all this physical stuff for a non-physical linkset. 320 // There is no reason to build all this physical stuff for a non-physical or empty linkset.
322 if (!LinksetRoot.IsPhysicallyActive) 321 if (!LinksetRoot.IsPhysicallyActive || !HasAnyChildren)
323 { 322 {
324 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysical", LinksetRoot.LocalID); 323 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysicalOrNoChildren", LinksetRoot.LocalID);
325 return; // Note the 'finally' clause at the botton which will get executed. 324 return; // Note the 'finally' clause at the botton which will get executed.
326 } 325 }
327 326
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
index 4bac222..aaf92c8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs
@@ -1,4 +1,4 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
@@ -28,6 +28,8 @@ using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Text; 29using System.Text;
30 30
31using OpenSim.Region.OptionalModules.Scripting;
32
31using OMV = OpenMetaverse; 33using OMV = OpenMetaverse;
32 34
33namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
@@ -51,18 +53,32 @@ public sealed class BSLinksetConstraints : BSLinkset
51 public float cfm; 53 public float cfm;
52 public float erp; 54 public float erp;
53 public float solverIterations; 55 public float solverIterations;
56 //
57 public OMV.Vector3 frameInAloc;
58 public OMV.Quaternion frameInArot;
59 public OMV.Vector3 frameInBloc;
60 public OMV.Quaternion frameInBrot;
61 public bool useLinearReferenceFrameA;
62 // Spring
63 public bool[] springAxisEnable;
64 public float[] springDamping;
65 public float[] springStiffness;
66 public OMV.Vector3 springLinearEquilibriumPoint;
67 public OMV.Vector3 springAngularEquilibriumPoint;
54 68
55 public BSLinkInfoConstraint(BSPrimLinkable pMember) 69 public BSLinkInfoConstraint(BSPrimLinkable pMember)
56 : base(pMember) 70 : base(pMember)
57 { 71 {
58 constraint = null; 72 constraint = null;
59 ResetToFixedConstraint(); 73 ResetLink();
74 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.creation", member.LocalID);
60 } 75 }
61 76
62 // Set all the parameters for this constraint to a fixed, non-movable constraint. 77 // Set all the parameters for this constraint to a fixed, non-movable constraint.
63 public void ResetToFixedConstraint() 78 public override void ResetLink()
64 { 79 {
65 constraintType = ConstraintType.D6_CONSTRAINT_TYPE; 80 // constraintType = ConstraintType.D6_CONSTRAINT_TYPE;
81 constraintType = ConstraintType.FIXED_CONSTRAINT_TYPE;
66 linearLimitLow = OMV.Vector3.Zero; 82 linearLimitLow = OMV.Vector3.Zero;
67 linearLimitHigh = OMV.Vector3.Zero; 83 linearLimitHigh = OMV.Vector3.Zero;
68 angularLimitLow = OMV.Vector3.Zero; 84 angularLimitLow = OMV.Vector3.Zero;
@@ -74,17 +90,37 @@ public sealed class BSLinksetConstraints : BSLinkset
74 cfm = BSParam.LinkConstraintCFM; 90 cfm = BSParam.LinkConstraintCFM;
75 erp = BSParam.LinkConstraintERP; 91 erp = BSParam.LinkConstraintERP;
76 solverIterations = BSParam.LinkConstraintSolverIterations; 92 solverIterations = BSParam.LinkConstraintSolverIterations;
93 frameInAloc = OMV.Vector3.Zero;
94 frameInArot = OMV.Quaternion.Identity;
95 frameInBloc = OMV.Vector3.Zero;
96 frameInBrot = OMV.Quaternion.Identity;
97 useLinearReferenceFrameA = true;
98 springAxisEnable = new bool[6];
99 springDamping = new float[6];
100 springStiffness = new float[6];
101 for (int ii = 0; ii < springAxisEnable.Length; ii++)
102 {
103 springAxisEnable[ii] = false;
104 springDamping[ii] = BSAPITemplate.SPRING_NOT_SPECIFIED;
105 springStiffness[ii] = BSAPITemplate.SPRING_NOT_SPECIFIED;
106 }
107 springLinearEquilibriumPoint = OMV.Vector3.Zero;
108 springAngularEquilibriumPoint = OMV.Vector3.Zero;
109 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.ResetLink", member.LocalID);
77 } 110 }
78 111
79 // Given a constraint, apply the current constraint parameters to same. 112 // Given a constraint, apply the current constraint parameters to same.
80 public void SetConstraintParameters(BSConstraint constrain) 113 public override void SetLinkParameters(BSConstraint constrain)
81 { 114 {
115 member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.SetLinkParameters,type={1}", member.LocalID, constraintType);
82 switch (constraintType) 116 switch (constraintType)
83 { 117 {
118 case ConstraintType.FIXED_CONSTRAINT_TYPE:
84 case ConstraintType.D6_CONSTRAINT_TYPE: 119 case ConstraintType.D6_CONSTRAINT_TYPE:
85 BSConstraint6Dof constrain6dof = constrain as BSConstraint6Dof; 120 BSConstraint6Dof constrain6dof = constrain as BSConstraint6Dof;
86 if (constrain6dof != null) 121 if (constrain6dof != null)
87 { 122 {
123 // NOTE: D6_SPRING_CONSTRAINT_TYPE should be updated if you change any of this code.
88 // zero linear and angular limits makes the objects unable to move in relation to each other 124 // zero linear and angular limits makes the objects unable to move in relation to each other
89 constrain6dof.SetLinearLimits(linearLimitLow, linearLimitHigh); 125 constrain6dof.SetLinearLimits(linearLimitLow, linearLimitHigh);
90 constrain6dof.SetAngularLimits(angularLimitLow, angularLimitHigh); 126 constrain6dof.SetAngularLimits(angularLimitLow, angularLimitHigh);
@@ -99,10 +135,55 @@ public sealed class BSLinksetConstraints : BSLinkset
99 } 135 }
100 } 136 }
101 break; 137 break;
138 case ConstraintType.D6_SPRING_CONSTRAINT_TYPE:
139 BSConstraintSpring constrainSpring = constrain as BSConstraintSpring;
140 if (constrainSpring != null)
141 {
142 // zero linear and angular limits makes the objects unable to move in relation to each other
143 constrainSpring.SetLinearLimits(linearLimitLow, linearLimitHigh);
144 constrainSpring.SetAngularLimits(angularLimitLow, angularLimitHigh);
145
146 // tweek the constraint to increase stability
147 constrainSpring.UseFrameOffset(useFrameOffset);
148 constrainSpring.TranslationalLimitMotor(enableTransMotor, transMotorMaxVel, transMotorMaxForce);
149 constrainSpring.SetCFMAndERP(cfm, erp);
150 if (solverIterations != 0f)
151 {
152 constrainSpring.SetSolverIterations(solverIterations);
153 }
154 for (int ii = 0; ii < springAxisEnable.Length; ii++)
155 {
156 constrainSpring.SetAxisEnable(ii, springAxisEnable[ii]);
157 if (springDamping[ii] != BSAPITemplate.SPRING_NOT_SPECIFIED)
158 constrainSpring.SetDamping(ii, springDamping[ii]);
159 if (springStiffness[ii] != BSAPITemplate.SPRING_NOT_SPECIFIED)
160 constrainSpring.SetStiffness(ii, springStiffness[ii]);
161 }
162 constrainSpring.CalculateTransforms();
163
164 if (springLinearEquilibriumPoint != OMV.Vector3.Zero)
165 constrainSpring.SetEquilibriumPoint(springLinearEquilibriumPoint, springAngularEquilibriumPoint);
166 else
167 constrainSpring.SetEquilibriumPoint(BSAPITemplate.SPRING_NOT_SPECIFIED, BSAPITemplate.SPRING_NOT_SPECIFIED);
168 }
169 break;
102 default: 170 default:
103 break; 171 break;
104 } 172 }
105 } 173 }
174
175 // Return 'true' if the property updates from the physics engine should be reported
176 // to the simulator.
177 // If the constraint is fixed, we don't need to report as the simulator and viewer will
178 // report the right things.
179 public override bool ShouldUpdateChildProperties()
180 {
181 bool ret = true;
182 if (constraintType == ConstraintType.FIXED_CONSTRAINT_TYPE)
183 ret = false;
184
185 return ret;
186 }
106 } 187 }
107 188
108 public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent) 189 public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent)
@@ -110,12 +191,15 @@ public sealed class BSLinksetConstraints : BSLinkset
110 LinksetImpl = LinksetImplementation.Constraint; 191 LinksetImpl = LinksetImplementation.Constraint;
111 } 192 }
112 193
194 private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINT]";
195
113 // When physical properties are changed the linkset needs to recalculate 196 // When physical properties are changed the linkset needs to recalculate
114 // its internal properties. 197 // its internal properties.
115 // This is queued in the 'post taint' queue so the 198 // This is queued in the 'post taint' queue so the
116 // refresh will happen once after all the other taints are applied. 199 // refresh will happen once after all the other taints are applied.
117 public override void Refresh(BSPrimLinkable requestor) 200 public override void Refresh(BSPrimLinkable requestor)
118 { 201 {
202 ScheduleRebuild(requestor);
119 base.Refresh(requestor); 203 base.Refresh(requestor);
120 204
121 } 205 }
@@ -132,10 +216,16 @@ public sealed class BSLinksetConstraints : BSLinkset
132 { 216 {
133 // Queue to happen after all the other taint processing 217 // Queue to happen after all the other taint processing
134 m_physicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() 218 m_physicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
219 {
220 if (HasAnyChildren)
135 { 221 {
136 if (HasAnyChildren) 222 // Constraints that have not been changed are not rebuild but make sure
137 RecomputeLinksetConstraints(); 223 // the constraint of the requestor is rebuilt.
138 }); 224 PhysicallyUnlinkAChildFromRoot(LinksetRoot, requestor);
225 // Rebuild the linkset and all its constraints.
226 RecomputeLinksetConstraints();
227 }
228 });
139 } 229 }
140 } 230 }
141 231
@@ -152,7 +242,7 @@ public sealed class BSLinksetConstraints : BSLinkset
152 if (IsRoot(child)) 242 if (IsRoot(child))
153 { 243 {
154 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly. 244 // The root is going dynamic. Rebuild the linkset so parts and mass get computed properly.
155 ScheduleRebuild(LinksetRoot); 245 Refresh(LinksetRoot);
156 } 246 }
157 return ret; 247 return ret;
158 } 248 }
@@ -171,7 +261,7 @@ public sealed class BSLinksetConstraints : BSLinkset
171 if (IsRoot(child)) 261 if (IsRoot(child))
172 { 262 {
173 // Schedule a rebuild to verify that the root shape is set to the real shape. 263 // Schedule a rebuild to verify that the root shape is set to the real shape.
174 ScheduleRebuild(LinksetRoot); 264 Refresh(LinksetRoot);
175 } 265 }
176 return ret; 266 return ret;
177 } 267 }
@@ -199,7 +289,7 @@ public sealed class BSLinksetConstraints : BSLinkset
199 // Just undo all the constraints for this linkset. Rebuild at the end of the step. 289 // Just undo all the constraints for this linkset. Rebuild at the end of the step.
200 ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); 290 ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
201 // Cause the constraints, et al to be rebuilt before the next simulation step. 291 // Cause the constraints, et al to be rebuilt before the next simulation step.
202 ScheduleRebuild(LinksetRoot); 292 Refresh(LinksetRoot);
203 } 293 }
204 return ret; 294 return ret;
205 } 295 }
@@ -217,14 +307,14 @@ public sealed class BSLinksetConstraints : BSLinkset
217 DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); 307 DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);
218 308
219 // Cause constraints and assorted properties to be recomputed before the next simulation step. 309 // Cause constraints and assorted properties to be recomputed before the next simulation step.
220 ScheduleRebuild(LinksetRoot); 310 Refresh(LinksetRoot);
221 } 311 }
222 return; 312 return;
223 } 313 }
224 314
225 // Remove the specified child from the linkset. 315 // Remove the specified child from the linkset.
226 // Safe to call even if the child is not really in my linkset. 316 // Safe to call even if the child is not really in my linkset.
227 protected override void RemoveChildFromLinkset(BSPrimLinkable child) 317 protected override void RemoveChildFromLinkset(BSPrimLinkable child, bool inTaintTime)
228 { 318 {
229 if (m_children.Remove(child)) 319 if (m_children.Remove(child))
230 { 320 {
@@ -236,12 +326,12 @@ public sealed class BSLinksetConstraints : BSLinkset
236 rootx.LocalID, rootx.PhysBody.AddrString, 326 rootx.LocalID, rootx.PhysBody.AddrString,
237 childx.LocalID, childx.PhysBody.AddrString); 327 childx.LocalID, childx.PhysBody.AddrString);
238 328
239 m_physicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() 329 m_physicsScene.TaintedObject(inTaintTime, childx.LocalID, "BSLinksetConstraints.RemoveChildFromLinkset", delegate()
240 { 330 {
241 PhysicallyUnlinkAChildFromRoot(rootx, childx); 331 PhysicallyUnlinkAChildFromRoot(rootx, childx);
242 }); 332 });
243 // See that the linkset parameters are recomputed at the end of the taint time. 333 // See that the linkset parameters are recomputed at the end of the taint time.
244 ScheduleRebuild(LinksetRoot); 334 Refresh(LinksetRoot);
245 } 335 }
246 else 336 else
247 { 337 {
@@ -262,8 +352,8 @@ public sealed class BSLinksetConstraints : BSLinkset
262 // Create a static constraint between the two passed objects 352 // Create a static constraint between the two passed objects
263 private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li) 353 private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li)
264 { 354 {
265 BSLinkInfoConstraint liConstraint = li as BSLinkInfoConstraint; 355 BSLinkInfoConstraint linkInfo = li as BSLinkInfoConstraint;
266 if (liConstraint == null) 356 if (linkInfo == null)
267 return null; 357 return null;
268 358
269 // Zero motion for children so they don't interpolate 359 // Zero motion for children so they don't interpolate
@@ -271,27 +361,26 @@ public sealed class BSLinksetConstraints : BSLinkset
271 361
272 BSConstraint constrain = null; 362 BSConstraint constrain = null;
273 363
274 switch (liConstraint.constraintType) 364 switch (linkInfo.constraintType)
275 { 365 {
366 case ConstraintType.FIXED_CONSTRAINT_TYPE:
276 case ConstraintType.D6_CONSTRAINT_TYPE: 367 case ConstraintType.D6_CONSTRAINT_TYPE:
277 // Relative position normalized to the root prim 368 // Relative position normalized to the root prim
278 // Essentually a vector pointing from center of rootPrim to center of li.member 369 // Essentually a vector pointing from center of rootPrim to center of li.member
279 OMV.Vector3 childRelativePosition = liConstraint.member.Position - rootPrim.Position; 370 OMV.Vector3 childRelativePosition = linkInfo.member.Position - rootPrim.Position;
280 371
281 // real world coordinate of midpoint between the two objects 372 // real world coordinate of midpoint between the two objects
282 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); 373 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
283 374
284 DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", 375 DetailLog("{0},BSLinksetConstraint.BuildConstraint,6Dof,rBody={1},cBody={2},rLoc={3},cLoc={4},midLoc={5}",
285 rootPrim.LocalID, 376 rootPrim.LocalID, rootPrim.PhysBody, linkInfo.member.PhysBody,
286 rootPrim.LocalID, rootPrim.PhysBody.AddrString, 377 rootPrim.Position, linkInfo.member.Position, midPoint);
287 liConstraint.member.LocalID, liConstraint.member.PhysBody.AddrString,
288 rootPrim.Position, liConstraint.member.Position, midPoint);
289 378
290 // create a constraint that allows no freedom of movement between the two objects 379 // create a constraint that allows no freedom of movement between the two objects
291 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 380 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
292 381
293 constrain = new BSConstraint6Dof( 382 constrain = new BSConstraint6Dof(
294 m_physicsScene.World, rootPrim.PhysBody, liConstraint.member.PhysBody, midPoint, true, true ); 383 m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody, midPoint, true, true );
295 384
296 /* NOTE: below is an attempt to build constraint with full frame computation, etc. 385 /* NOTE: below is an attempt to build constraint with full frame computation, etc.
297 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms 386 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
@@ -320,11 +409,23 @@ public sealed class BSLinksetConstraints : BSLinkset
320 */ 409 */
321 410
322 break; 411 break;
412 case ConstraintType.D6_SPRING_CONSTRAINT_TYPE:
413 constrain = new BSConstraintSpring(m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody,
414 linkInfo.frameInAloc, linkInfo.frameInArot, linkInfo.frameInBloc, linkInfo.frameInBrot,
415 linkInfo.useLinearReferenceFrameA,
416 true /*disableCollisionsBetweenLinkedBodies*/);
417 DetailLog("{0},BSLinksetConstraint.BuildConstraint,spring,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6}",
418 rootPrim.LocalID,
419 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
420 linkInfo.member.LocalID, linkInfo.member.PhysBody.AddrString,
421 rootPrim.Position, linkInfo.member.Position);
422
423 break;
323 default: 424 default:
324 break; 425 break;
325 } 426 }
326 427
327 liConstraint.SetConstraintParameters(constrain); 428 linkInfo.SetLinkParameters(constrain);
328 429
329 m_physicsScene.Constraints.AddConstraint(constrain); 430 m_physicsScene.Constraints.AddConstraint(constrain);
330 431
@@ -343,13 +444,22 @@ public sealed class BSLinksetConstraints : BSLinkset
343 rootPrim.LocalID, rootPrim.PhysBody.AddrString, 444 rootPrim.LocalID, rootPrim.PhysBody.AddrString,
344 childPrim.LocalID, childPrim.PhysBody.AddrString); 445 childPrim.LocalID, childPrim.PhysBody.AddrString);
345 446
346 // Find the constraint for this link and get rid of it from the overall collection and from my list 447 // If asked to unlink root from root, just remove all the constraints
347 if (m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) 448 if (rootPrim == childPrim || childPrim == LinksetRoot)
348 { 449 {
349 // Make the child refresh its location 450 PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot);
350 m_physicsScene.PE.PushUpdate(childPrim.PhysBody);
351 ret = true; 451 ret = true;
352 } 452 }
453 else
454 {
455 // Find the constraint for this link and get rid of it from the overall collection and from my list
456 if (m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody))
457 {
458 // Make the child refresh its location
459 m_physicsScene.PE.PushUpdate(childPrim.PhysBody);
460 ret = true;
461 }
462 }
353 463
354 return ret; 464 return ret;
355 } 465 }
@@ -382,9 +492,9 @@ public sealed class BSLinksetConstraints : BSLinkset
382 Rebuilding = true; 492 Rebuilding = true;
383 493
384 // There is no reason to build all this physical stuff for a non-physical linkset. 494 // There is no reason to build all this physical stuff for a non-physical linkset.
385 if (!LinksetRoot.IsPhysicallyActive) 495 if (!LinksetRoot.IsPhysicallyActive || !HasAnyChildren)
386 { 496 {
387 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetCompound,notPhysical", LinksetRoot.LocalID); 497 DetailLog("{0},BSLinksetConstraint.RecomputeLinksetCompound,notPhysicalOrNoChildren", LinksetRoot.LocalID);
388 return; // Note the 'finally' clause at the botton which will get executed. 498 return; // Note the 'finally' clause at the botton which will get executed.
389 } 499 }
390 500
@@ -401,6 +511,7 @@ public sealed class BSLinksetConstraints : BSLinkset
401 // If constraint doesn't exist yet, create it. 511 // If constraint doesn't exist yet, create it.
402 constrain = BuildConstraint(LinksetRoot, li); 512 constrain = BuildConstraint(LinksetRoot, li);
403 } 513 }
514 li.SetLinkParameters(constrain);
404 constrain.RecomputeConstraintVariables(linksetMass); 515 constrain.RecomputeConstraintVariables(linksetMass);
405 516
406 // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG 517 // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG
@@ -412,5 +523,324 @@ public sealed class BSLinksetConstraints : BSLinkset
412 Rebuilding = false; 523 Rebuilding = false;
413 } 524 }
414 } 525 }
526
527 #region Extension
528 public override object Extension(string pFunct, params object[] pParams)
529 {
530 object ret = null;
531 switch (pFunct)
532 {
533 // pParams = [ BSPhysObject root, BSPhysObject child, integer linkType ]
534 case ExtendedPhysics.PhysFunctChangeLinkType:
535 if (pParams.Length > 2)
536 {
537 int requestedType = (int)pParams[2];
538 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,requestedType={1}", LinksetRoot.LocalID, requestedType);
539 if (requestedType == (int)ConstraintType.FIXED_CONSTRAINT_TYPE
540 || requestedType == (int)ConstraintType.D6_CONSTRAINT_TYPE
541 || requestedType == (int)ConstraintType.D6_SPRING_CONSTRAINT_TYPE
542 || requestedType == (int)ConstraintType.HINGE_CONSTRAINT_TYPE
543 || requestedType == (int)ConstraintType.CONETWIST_CONSTRAINT_TYPE
544 || requestedType == (int)ConstraintType.SLIDER_CONSTRAINT_TYPE)
545 {
546 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
547 if (child != null)
548 {
549 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,rootID={1},childID={2},type={3}",
550 LinksetRoot.LocalID, LinksetRoot.LocalID, child.LocalID, requestedType);
551 m_physicsScene.TaintedObject(child.LocalID, "BSLinksetConstraint.PhysFunctChangeLinkType", delegate()
552 {
553 // Pick up all the constraints currently created.
554 RemoveDependencies(child);
555
556 BSLinkInfo linkInfo = null;
557 if (TryGetLinkInfo(child, out linkInfo))
558 {
559 BSLinkInfoConstraint linkInfoC = linkInfo as BSLinkInfoConstraint;
560 if (linkInfoC != null)
561 {
562 linkInfoC.constraintType = (ConstraintType)requestedType;
563 ret = (object)true;
564 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,link={1},type={2}",
565 linkInfo.member.LocalID, linkInfo.member.LocalID, linkInfoC.constraintType);
566 }
567 else
568 {
569 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,linkInfoNotConstraint,childID={1}", LinksetRoot.LocalID, child.LocalID);
570 }
571 }
572 else
573 {
574 DetailLog("{0},BSLinksetConstraint.ChangeLinkType,noLinkInfoForChild,childID={1}", LinksetRoot.LocalID, child.LocalID);
575 }
576 // Cause the whole linkset to be rebuilt in post-taint time.
577 Refresh(child);
578 });
579 }
580 else
581 {
582 DetailLog("{0},BSLinksetConstraint.SetLinkType,childNotBSPrimLinkable", LinksetRoot.LocalID);
583 }
584 }
585 else
586 {
587 DetailLog("{0},BSLinksetConstraint.SetLinkType,illegalRequestedType,reqested={1},spring={2}",
588 LinksetRoot.LocalID, requestedType, ((int)ConstraintType.D6_SPRING_CONSTRAINT_TYPE));
589 }
590 }
591 break;
592 // pParams = [ BSPhysObject root, BSPhysObject child ]
593 case ExtendedPhysics.PhysFunctGetLinkType:
594 if (pParams.Length > 0)
595 {
596 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
597 if (child != null)
598 {
599 BSLinkInfo linkInfo = null;
600 if (TryGetLinkInfo(child, out linkInfo))
601 {
602 BSLinkInfoConstraint linkInfoC = linkInfo as BSLinkInfoConstraint;
603 if (linkInfoC != null)
604 {
605 ret = (object)(int)linkInfoC.constraintType;
606 DetailLog("{0},BSLinksetConstraint.GetLinkType,link={1},type={2}",
607 linkInfo.member.LocalID, linkInfo.member.LocalID, linkInfoC.constraintType);
608
609 }
610 }
611 }
612 }
613 break;
614 // pParams = [ BSPhysObject root, BSPhysObject child, int op, object opParams, int op, object opParams, ... ]
615 case ExtendedPhysics.PhysFunctChangeLinkParams:
616 // There should be two parameters: the childActor and a list of parameters to set
617 if (pParams.Length > 2)
618 {
619 BSPrimLinkable child = pParams[1] as BSPrimLinkable;
620 BSLinkInfo baseLinkInfo = null;
621 if (TryGetLinkInfo(child, out baseLinkInfo))
622 {
623 BSLinkInfoConstraint linkInfo = baseLinkInfo as BSLinkInfoConstraint;
624 if (linkInfo != null)
625 {
626 int valueInt;
627 float valueFloat;
628 bool valueBool;
629 OMV.Vector3 valueVector;
630 OMV.Vector3 valueVector2;
631 OMV.Quaternion valueQuaternion;
632 int axisLow, axisHigh;
633
634 int opIndex = 2;
635 while (opIndex < pParams.Length)
636 {
637 int thisOp = 0;
638 string errMsg = "";
639 try
640 {
641 thisOp = (int)pParams[opIndex];
642 DetailLog("{0},BSLinksetConstraint.ChangeLinkParams2,op={1},val={2}",
643 linkInfo.member.LocalID, thisOp, pParams[opIndex + 1]);
644 switch (thisOp)
645 {
646 case ExtendedPhysics.PHYS_PARAM_LINK_TYPE:
647 valueInt = (int)pParams[opIndex + 1];
648 ConstraintType valueType = (ConstraintType)valueInt;
649 if (valueType == ConstraintType.FIXED_CONSTRAINT_TYPE
650 || valueType == ConstraintType.D6_CONSTRAINT_TYPE
651 || valueType == ConstraintType.D6_SPRING_CONSTRAINT_TYPE
652 || valueType == ConstraintType.HINGE_CONSTRAINT_TYPE
653 || valueType == ConstraintType.CONETWIST_CONSTRAINT_TYPE
654 || valueType == ConstraintType.SLIDER_CONSTRAINT_TYPE)
655 {
656 linkInfo.constraintType = valueType;
657 }
658 opIndex += 2;
659 break;
660 case ExtendedPhysics.PHYS_PARAM_FRAMEINA_LOC:
661 errMsg = "PHYS_PARAM_FRAMEINA_LOC takes one parameter of type vector";
662 valueVector = (OMV.Vector3)pParams[opIndex + 1];
663 linkInfo.frameInAloc = valueVector;
664 opIndex += 2;
665 break;
666 case ExtendedPhysics.PHYS_PARAM_FRAMEINA_ROT:
667 errMsg = "PHYS_PARAM_FRAMEINA_ROT takes one parameter of type rotation";
668 valueQuaternion = (OMV.Quaternion)pParams[opIndex + 1];
669 linkInfo.frameInArot = valueQuaternion;
670 opIndex += 2;
671 break;
672 case ExtendedPhysics.PHYS_PARAM_FRAMEINB_LOC:
673 errMsg = "PHYS_PARAM_FRAMEINB_LOC takes one parameter of type vector";
674 valueVector = (OMV.Vector3)pParams[opIndex + 1];
675 linkInfo.frameInBloc = valueVector;
676 opIndex += 2;
677 break;
678 case ExtendedPhysics.PHYS_PARAM_FRAMEINB_ROT:
679 errMsg = "PHYS_PARAM_FRAMEINB_ROT takes one parameter of type rotation";
680 valueQuaternion = (OMV.Quaternion)pParams[opIndex + 1];
681 linkInfo.frameInBrot = valueQuaternion;
682 opIndex += 2;
683 break;
684 case ExtendedPhysics.PHYS_PARAM_LINEAR_LIMIT_LOW:
685 errMsg = "PHYS_PARAM_LINEAR_LIMIT_LOW takes one parameter of type vector";
686 valueVector = (OMV.Vector3)pParams[opIndex + 1];
687 linkInfo.linearLimitLow = valueVector;
688 opIndex += 2;
689 break;
690 case ExtendedPhysics.PHYS_PARAM_LINEAR_LIMIT_HIGH:
691 errMsg = "PHYS_PARAM_LINEAR_LIMIT_HIGH takes one parameter of type vector";
692 valueVector = (OMV.Vector3)pParams[opIndex + 1];
693 linkInfo.linearLimitHigh = valueVector;
694 opIndex += 2;
695 break;
696 case ExtendedPhysics.PHYS_PARAM_ANGULAR_LIMIT_LOW:
697 errMsg = "PHYS_PARAM_ANGULAR_LIMIT_LOW takes one parameter of type vector";
698 valueVector = (OMV.Vector3)pParams[opIndex + 1];
699 linkInfo.angularLimitLow = valueVector;
700 opIndex += 2;
701 break;
702 case ExtendedPhysics.PHYS_PARAM_ANGULAR_LIMIT_HIGH:
703 errMsg = "PHYS_PARAM_ANGULAR_LIMIT_HIGH takes one parameter of type vector";
704 valueVector = (OMV.Vector3)pParams[opIndex + 1];
705 linkInfo.angularLimitHigh = valueVector;
706 opIndex += 2;
707 break;
708 case ExtendedPhysics.PHYS_PARAM_USE_FRAME_OFFSET:
709 errMsg = "PHYS_PARAM_USE_FRAME_OFFSET takes one parameter of type integer (bool)";
710 valueBool = ((int)pParams[opIndex + 1]) != 0;
711 linkInfo.useFrameOffset = valueBool;
712 opIndex += 2;
713 break;
714 case ExtendedPhysics.PHYS_PARAM_ENABLE_TRANSMOTOR:
715 errMsg = "PHYS_PARAM_ENABLE_TRANSMOTOR takes one parameter of type integer (bool)";
716 valueBool = ((int)pParams[opIndex + 1]) != 0;
717 linkInfo.enableTransMotor = valueBool;
718 opIndex += 2;
719 break;
720 case ExtendedPhysics.PHYS_PARAM_TRANSMOTOR_MAXVEL:
721 errMsg = "PHYS_PARAM_TRANSMOTOR_MAXVEL takes one parameter of type float";
722 valueFloat = (float)pParams[opIndex + 1];
723 linkInfo.transMotorMaxVel = valueFloat;
724 opIndex += 2;
725 break;
726 case ExtendedPhysics.PHYS_PARAM_TRANSMOTOR_MAXFORCE:
727 errMsg = "PHYS_PARAM_TRANSMOTOR_MAXFORCE takes one parameter of type float";
728 valueFloat = (float)pParams[opIndex + 1];
729 linkInfo.transMotorMaxForce = valueFloat;
730 opIndex += 2;
731 break;
732 case ExtendedPhysics.PHYS_PARAM_CFM:
733 errMsg = "PHYS_PARAM_CFM takes one parameter of type float";
734 valueFloat = (float)pParams[opIndex + 1];
735 linkInfo.cfm = valueFloat;
736 opIndex += 2;
737 break;
738 case ExtendedPhysics.PHYS_PARAM_ERP:
739 errMsg = "PHYS_PARAM_ERP takes one parameter of type float";
740 valueFloat = (float)pParams[opIndex + 1];
741 linkInfo.erp = valueFloat;
742 opIndex += 2;
743 break;
744 case ExtendedPhysics.PHYS_PARAM_SOLVER_ITERATIONS:
745 errMsg = "PHYS_PARAM_SOLVER_ITERATIONS takes one parameter of type float";
746 valueFloat = (float)pParams[opIndex + 1];
747 linkInfo.solverIterations = valueFloat;
748 opIndex += 2;
749 break;
750 case ExtendedPhysics.PHYS_PARAM_SPRING_AXIS_ENABLE:
751 errMsg = "PHYS_PARAM_SPRING_AXIS_ENABLE takes two parameters of types integer and integer (bool)";
752 valueInt = (int)pParams[opIndex + 1];
753 valueBool = ((int)pParams[opIndex + 2]) != 0;
754 GetAxisRange(valueInt, out axisLow, out axisHigh);
755 for (int ii = axisLow; ii <= axisHigh; ii++)
756 linkInfo.springAxisEnable[ii] = valueBool;
757 opIndex += 3;
758 break;
759 case ExtendedPhysics.PHYS_PARAM_SPRING_DAMPING:
760 errMsg = "PHYS_PARAM_SPRING_DAMPING takes two parameters of types integer and float";
761 valueInt = (int)pParams[opIndex + 1];
762 valueFloat = (float)pParams[opIndex + 2];
763 GetAxisRange(valueInt, out axisLow, out axisHigh);
764 for (int ii = axisLow; ii <= axisHigh; ii++)
765 linkInfo.springDamping[ii] = valueFloat;
766 opIndex += 3;
767 break;
768 case ExtendedPhysics.PHYS_PARAM_SPRING_STIFFNESS:
769 errMsg = "PHYS_PARAM_SPRING_STIFFNESS takes two parameters of types integer and float";
770 valueInt = (int)pParams[opIndex + 1];
771 valueFloat = (float)pParams[opIndex + 2];
772 GetAxisRange(valueInt, out axisLow, out axisHigh);
773 for (int ii = axisLow; ii <= axisHigh; ii++)
774 linkInfo.springStiffness[ii] = valueFloat;
775 opIndex += 3;
776 break;
777 case ExtendedPhysics.PHYS_PARAM_SPRING_EQUILIBRIUM_POINT:
778 errMsg = "PHYS_PARAM_SPRING_EQUILIBRIUM_POINT takes two parameters of type vector";
779 valueVector = (OMV.Vector3)pParams[opIndex + 1];
780 valueVector2 = (OMV.Vector3)pParams[opIndex + 2];
781 linkInfo.springLinearEquilibriumPoint = valueVector;
782 linkInfo.springAngularEquilibriumPoint = valueVector2;
783 opIndex += 3;
784 break;
785 case ExtendedPhysics.PHYS_PARAM_USE_LINEAR_FRAMEA:
786 errMsg = "PHYS_PARAM_USE_LINEAR_FRAMEA takes one parameter of type integer (bool)";
787 valueBool = ((int)pParams[opIndex + 1]) != 0;
788 linkInfo.useLinearReferenceFrameA = valueBool;
789 opIndex += 2;
790 break;
791 default:
792 break;
793 }
794 }
795 catch (InvalidCastException e)
796 {
797 m_physicsScene.Logger.WarnFormat("{0} value of wrong type in physSetLinksetParams: {1}, err={2}",
798 LogHeader, errMsg, e);
799 }
800 catch (Exception e)
801 {
802 m_physicsScene.Logger.WarnFormat("{0} bad parameters in physSetLinksetParams: {1}", LogHeader, e);
803 }
804 }
805 }
806 // Something changed so a rebuild is in order
807 Refresh(child);
808 }
809 }
810 break;
811 default:
812 ret = base.Extension(pFunct, pParams);
813 break;
814 }
815 return ret;
816 }
817
818 // Bullet constraints keep some limit parameters for each linear and angular axis.
819 // Setting same is easier if there is an easy way to see all or types.
820 // This routine returns the array limits for the set of axis.
821 private void GetAxisRange(int rangeSpec, out int low, out int high)
822 {
823 switch (rangeSpec)
824 {
825 case ExtendedPhysics.PHYS_AXIS_LINEAR_ALL:
826 low = 0;
827 high = 2;
828 break;
829 case ExtendedPhysics.PHYS_AXIS_ANGULAR_ALL:
830 low = 3;
831 high = 5;
832 break;
833 case ExtendedPhysics.PHYS_AXIS_ALL:
834 low = 0;
835 high = 5;
836 break;
837 default:
838 low = high = rangeSpec;
839 break;
840 }
841 return;
842 }
843 #endregion // Extension
844
415} 845}
416} 846}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index fcb892a..43aa63e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -134,6 +134,7 @@ public static class BSParam
134 public static float AvatarHeightMidFudge { get; private set; } 134 public static float AvatarHeightMidFudge { get; private set; }
135 public static float AvatarHeightHighFudge { get; private set; } 135 public static float AvatarHeightHighFudge { get; private set; }
136 public static float AvatarContactProcessingThreshold { get; private set; } 136 public static float AvatarContactProcessingThreshold { get; private set; }
137 public static float AvatarStopZeroThreshold { get; private set; }
137 public static int AvatarJumpFrames { get; private set; } 138 public static int AvatarJumpFrames { get; private set; }
138 public static float AvatarBelowGroundUpCorrectionMeters { get; private set; } 139 public static float AvatarBelowGroundUpCorrectionMeters { get; private set; }
139 public static float AvatarStepHeight { get; private set; } 140 public static float AvatarStepHeight { get; private set; }
@@ -570,11 +571,13 @@ public static class BSParam
570 new ParameterDefn<float>("AvatarHeightLowFudge", "A fudge factor to make small avatars stand on the ground", 571 new ParameterDefn<float>("AvatarHeightLowFudge", "A fudge factor to make small avatars stand on the ground",
571 -0.2f ), 572 -0.2f ),
572 new ParameterDefn<float>("AvatarHeightMidFudge", "A fudge distance to adjust average sized avatars to be standing on ground", 573 new ParameterDefn<float>("AvatarHeightMidFudge", "A fudge distance to adjust average sized avatars to be standing on ground",
573 0.2f ), 574 0.1f ),
574 new ParameterDefn<float>("AvatarHeightHighFudge", "A fudge factor to make tall avatars stand on the ground", 575 new ParameterDefn<float>("AvatarHeightHighFudge", "A fudge factor to make tall avatars stand on the ground",
575 0.2f ), 576 0.1f ),
576 new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 577 new ParameterDefn<float>("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
577 0.1f ), 578 0.1f ),
579 new ParameterDefn<float>("AvatarStopZeroThreshold", "Movement velocity below which avatar is assumed to be stopped",
580 0.1f ),
578 new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground", 581 new ParameterDefn<float>("AvatarBelowGroundUpCorrectionMeters", "Meters to move avatar up if it seems to be below ground",
579 1.0f ), 582 1.0f ),
580 new ParameterDefn<int>("AvatarJumpFrames", "Number of frames to allow jump forces. Changes jump height.", 583 new ParameterDefn<int>("AvatarJumpFrames", "Number of frames to allow jump forces. Changes jump height.",
@@ -683,21 +686,21 @@ public static class BSParam
683 0f ), 686 0f ),
684 687
685 new ParameterDefn<float>("BHullMaxVerticesPerHull", "Bullet impl: max number of vertices per created hull", 688 new ParameterDefn<float>("BHullMaxVerticesPerHull", "Bullet impl: max number of vertices per created hull",
686 100f ), 689 200f ),
687 new ParameterDefn<float>("BHullMinClusters", "Bullet impl: minimum number of hulls to create per mesh", 690 new ParameterDefn<float>("BHullMinClusters", "Bullet impl: minimum number of hulls to create per mesh",
688 2f ), 691 10f ),
689 new ParameterDefn<float>("BHullCompacityWeight", "Bullet impl: weight factor for how compact to make hulls", 692 new ParameterDefn<float>("BHullCompacityWeight", "Bullet impl: weight factor for how compact to make hulls",
690 0.1f ), 693 20f ),
691 new ParameterDefn<float>("BHullVolumeWeight", "Bullet impl: weight factor for volume in created hull", 694 new ParameterDefn<float>("BHullVolumeWeight", "Bullet impl: weight factor for volume in created hull",
692 0f ), 695 0.1f ),
693 new ParameterDefn<float>("BHullConcavity", "Bullet impl: weight factor for how convex a created hull can be", 696 new ParameterDefn<float>("BHullConcavity", "Bullet impl: weight factor for how convex a created hull can be",
694 100f ), 697 10f ),
695 new ParameterDefn<bool>("BHullAddExtraDistPoints", "Bullet impl: whether to add extra vertices for long distance vectors", 698 new ParameterDefn<bool>("BHullAddExtraDistPoints", "Bullet impl: whether to add extra vertices for long distance vectors",
696 false ), 699 true ),
697 new ParameterDefn<bool>("BHullAddNeighboursDistPoints", "Bullet impl: whether to add extra vertices between neighbor hulls", 700 new ParameterDefn<bool>("BHullAddNeighboursDistPoints", "Bullet impl: whether to add extra vertices between neighbor hulls",
698 false ), 701 true ),
699 new ParameterDefn<bool>("BHullAddFacesPoints", "Bullet impl: whether to add extra vertices to break up hull faces", 702 new ParameterDefn<bool>("BHullAddFacesPoints", "Bullet impl: whether to add extra vertices to break up hull faces",
700 false ), 703 true ),
701 new ParameterDefn<bool>("BHullShouldAdjustCollisionMargin", "Bullet impl: whether to shrink resulting hulls to account for collision margin", 704 new ParameterDefn<bool>("BHullShouldAdjustCollisionMargin", "Bullet impl: whether to shrink resulting hulls to account for collision margin",
702 false ), 705 false ),
703 706
@@ -826,7 +829,7 @@ public static class BSParam
826 private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v) 829 private static void ResetConstraintSolverTainted(BSScene pPhysScene, float v)
827 { 830 {
828 BSScene physScene = pPhysScene; 831 BSScene physScene = pPhysScene;
829 physScene.TaintedObject("BSParam.ResetConstraintSolver", delegate() 832 physScene.TaintedObject(BSScene.DetailLogZero, "BSParam.ResetConstraintSolver", delegate()
830 { 833 {
831 physScene.PE.ResetConstraintSolver(physScene.World); 834 physScene.PE.ResetConstraintSolver(physScene.World);
832 }); 835 });
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 9dc52d5..f89b376 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -121,7 +121,7 @@ public abstract class BSPhysObject : PhysicsActor
121 public virtual void Destroy() 121 public virtual void Destroy()
122 { 122 {
123 PhysicalActors.Enable(false); 123 PhysicalActors.Enable(false);
124 PhysScene.TaintedObject("BSPhysObject.Destroy", delegate() 124 PhysScene.TaintedObject(LocalID, "BSPhysObject.Destroy", delegate()
125 { 125 {
126 PhysicalActors.Dispose(); 126 PhysicalActors.Dispose();
127 }); 127 });
@@ -300,8 +300,19 @@ public abstract class BSPhysObject : PhysicsActor
300 // Called in taint-time!! 300 // Called in taint-time!!
301 public void ActivateIfPhysical(bool forceIt) 301 public void ActivateIfPhysical(bool forceIt)
302 { 302 {
303 if (IsPhysical && PhysBody.HasPhysicalBody) 303 if (PhysBody.HasPhysicalBody)
304 PhysScene.PE.Activate(PhysBody, forceIt); 304 {
305 if (IsPhysical)
306 {
307 // Physical objects might need activating
308 PhysScene.PE.Activate(PhysBody, forceIt);
309 }
310 else
311 {
312 // Clear the collision cache since we've changed some properties.
313 PhysScene.PE.ClearCollisionProxyCache(PhysScene.World, PhysBody);
314 }
315 }
305 } 316 }
306 317
307 // 'actors' act on the physical object to change or constrain its motion. These can range from 318 // 'actors' act on the physical object to change or constrain its motion. These can range from
@@ -509,7 +520,7 @@ public abstract class BSPhysObject : PhysicsActor
509 // make sure first collision happens 520 // make sure first collision happens
510 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); 521 NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs);
511 522
512 PhysScene.TaintedObject(TypeName+".SubscribeEvents", delegate() 523 PhysScene.TaintedObject(LocalID, TypeName+".SubscribeEvents", delegate()
513 { 524 {
514 if (PhysBody.HasPhysicalBody) 525 if (PhysBody.HasPhysicalBody)
515 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); 526 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
@@ -524,7 +535,7 @@ public abstract class BSPhysObject : PhysicsActor
524 public override void UnSubscribeEvents() { 535 public override void UnSubscribeEvents() {
525 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); 536 // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
526 SubscribedEventsMs = 0; 537 SubscribedEventsMs = 0;
527 PhysScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 538 PhysScene.TaintedObject(LocalID, TypeName+".UnSubscribeEvents", delegate()
528 { 539 {
529 // Make sure there is a body there because sometimes destruction happens in an un-ideal order. 540 // Make sure there is a body there because sometimes destruction happens in an un-ideal order.
530 if (PhysBody.HasPhysicalBody) 541 if (PhysBody.HasPhysicalBody)
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index d5b999d..15b7090 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
41 [Serializable] 41 [Serializable]
42public class BSPrim : BSPhysObject 42public class BSPrim : BSPhysObject
43{ 43{
44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 protected static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
45 private static readonly string LogHeader = "[BULLETS PRIM]"; 45 private static readonly string LogHeader = "[BULLETS PRIM]";
46 46
47 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. 47 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
@@ -102,7 +102,7 @@ public class BSPrim : BSPhysObject
102 102
103 // DetailLog("{0},BSPrim.constructor,call", LocalID); 103 // DetailLog("{0},BSPrim.constructor,call", LocalID);
104 // do the actual object creation at taint time 104 // do the actual object creation at taint time
105 PhysScene.TaintedObject("BSPrim.create", delegate() 105 PhysScene.TaintedObject(LocalID, "BSPrim.create", delegate()
106 { 106 {
107 // Make sure the object is being created with some sanity. 107 // Make sure the object is being created with some sanity.
108 ExtremeSanityCheck(true /* inTaintTime */); 108 ExtremeSanityCheck(true /* inTaintTime */);
@@ -126,7 +126,7 @@ public class BSPrim : BSPhysObject
126 // Undo any vehicle properties 126 // Undo any vehicle properties
127 this.VehicleType = (int)Vehicle.TYPE_NONE; 127 this.VehicleType = (int)Vehicle.TYPE_NONE;
128 128
129 PhysScene.TaintedObject("BSPrim.Destroy", delegate() 129 PhysScene.TaintedObject(LocalID, "BSPrim.Destroy", delegate()
130 { 130 {
131 DetailLog("{0},BSPrim.Destroy,taint,", LocalID); 131 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
132 // If there are physical body and shape, release my use of same. 132 // If there are physical body and shape, release my use of same.
@@ -161,7 +161,7 @@ public class BSPrim : BSPhysObject
161 } 161 }
162 public override bool ForceBodyShapeRebuild(bool inTaintTime) 162 public override bool ForceBodyShapeRebuild(bool inTaintTime)
163 { 163 {
164 PhysScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate() 164 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ForceBodyShapeRebuild", delegate()
165 { 165 {
166 _mass = CalculateMass(); // changing the shape changes the mass 166 _mass = CalculateMass(); // changing the shape changes the mass
167 CreateGeomAndObject(true); 167 CreateGeomAndObject(true);
@@ -178,7 +178,7 @@ public class BSPrim : BSPhysObject
178 if (value != _isSelected) 178 if (value != _isSelected)
179 { 179 {
180 _isSelected = value; 180 _isSelected = value;
181 PhysScene.TaintedObject("BSPrim.setSelected", delegate() 181 PhysScene.TaintedObject(LocalID, "BSPrim.setSelected", delegate()
182 { 182 {
183 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); 183 DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected);
184 SetObjectDynamic(false); 184 SetObjectDynamic(false);
@@ -224,7 +224,7 @@ public class BSPrim : BSPhysObject
224 _rotationalVelocity = OMV.Vector3.Zero; 224 _rotationalVelocity = OMV.Vector3.Zero;
225 225
226 // Zero some other properties in the physics engine 226 // Zero some other properties in the physics engine
227 PhysScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 227 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ZeroMotion", delegate()
228 { 228 {
229 if (PhysBody.HasPhysicalBody) 229 if (PhysBody.HasPhysicalBody)
230 PhysScene.PE.ClearAllForces(PhysBody); 230 PhysScene.PE.ClearAllForces(PhysBody);
@@ -234,7 +234,7 @@ public class BSPrim : BSPhysObject
234 { 234 {
235 _rotationalVelocity = OMV.Vector3.Zero; 235 _rotationalVelocity = OMV.Vector3.Zero;
236 // Zero some other properties in the physics engine 236 // Zero some other properties in the physics engine
237 PhysScene.TaintedObject(inTaintTime, "BSPrim.ZeroMotion", delegate() 237 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ZeroMotion", delegate()
238 { 238 {
239 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity); 239 // DetailLog("{0},BSPrim.ZeroAngularMotion,call,rotVel={1}", LocalID, _rotationalVelocity);
240 if (PhysBody.HasPhysicalBody) 240 if (PhysBody.HasPhysicalBody)
@@ -262,7 +262,7 @@ public class BSPrim : BSPhysObject
262 }); 262 });
263 263
264 // Update parameters so the new actor's Refresh() action is called at the right time. 264 // Update parameters so the new actor's Refresh() action is called at the right time.
265 PhysScene.TaintedObject("BSPrim.LockAngularMotion", delegate() 265 PhysScene.TaintedObject(LocalID, "BSPrim.LockAngularMotion", delegate()
266 { 266 {
267 UpdatePhysicalParameters(); 267 UpdatePhysicalParameters();
268 }); 268 });
@@ -287,7 +287,7 @@ public class BSPrim : BSPhysObject
287 RawPosition = value; 287 RawPosition = value;
288 PositionSanityCheck(false); 288 PositionSanityCheck(false);
289 289
290 PhysScene.TaintedObject("BSPrim.setPosition", delegate() 290 PhysScene.TaintedObject(LocalID, "BSPrim.setPosition", delegate()
291 { 291 {
292 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation); 292 DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, RawPosition, RawOrientation);
293 ForcePosition = RawPosition; 293 ForcePosition = RawPosition;
@@ -531,7 +531,7 @@ public class BSPrim : BSPhysObject
531 set { 531 set {
532 Vehicle type = (Vehicle)value; 532 Vehicle type = (Vehicle)value;
533 533
534 PhysScene.TaintedObject("setVehicleType", delegate() 534 PhysScene.TaintedObject(LocalID, "setVehicleType", delegate()
535 { 535 {
536 // Some vehicle scripts change vehicle type on the fly as an easy way to 536 // Some vehicle scripts change vehicle type on the fly as an easy way to
537 // change all the parameters. Like a plane changing to CAR when on the 537 // change all the parameters. Like a plane changing to CAR when on the
@@ -561,7 +561,7 @@ public class BSPrim : BSPhysObject
561 } 561 }
562 public override void VehicleFloatParam(int param, float value) 562 public override void VehicleFloatParam(int param, float value)
563 { 563 {
564 PhysScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() 564 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleFloatParam", delegate()
565 { 565 {
566 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); 566 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
567 if (vehicleActor != null) 567 if (vehicleActor != null)
@@ -573,7 +573,7 @@ public class BSPrim : BSPhysObject
573 } 573 }
574 public override void VehicleVectorParam(int param, OMV.Vector3 value) 574 public override void VehicleVectorParam(int param, OMV.Vector3 value)
575 { 575 {
576 PhysScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() 576 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleVectorParam", delegate()
577 { 577 {
578 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); 578 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
579 if (vehicleActor != null) 579 if (vehicleActor != null)
@@ -585,7 +585,7 @@ public class BSPrim : BSPhysObject
585 } 585 }
586 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 586 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
587 { 587 {
588 PhysScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() 588 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleRotationParam", delegate()
589 { 589 {
590 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); 590 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
591 if (vehicleActor != null) 591 if (vehicleActor != null)
@@ -597,7 +597,7 @@ public class BSPrim : BSPhysObject
597 } 597 }
598 public override void VehicleFlags(int param, bool remove) 598 public override void VehicleFlags(int param, bool remove)
599 { 599 {
600 PhysScene.TaintedObject("BSPrim.VehicleFlags", delegate() 600 PhysScene.TaintedObject(LocalID, "BSPrim.VehicleFlags", delegate()
601 { 601 {
602 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */); 602 BSDynamics vehicleActor = GetVehicleActor(true /* createIfNone */);
603 if (vehicleActor != null) 603 if (vehicleActor != null)
@@ -613,7 +613,7 @@ public class BSPrim : BSPhysObject
613 if (_isVolumeDetect != newValue) 613 if (_isVolumeDetect != newValue)
614 { 614 {
615 _isVolumeDetect = newValue; 615 _isVolumeDetect = newValue;
616 PhysScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() 616 PhysScene.TaintedObject(LocalID, "BSPrim.SetVolumeDetect", delegate()
617 { 617 {
618 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); 618 // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect);
619 SetObjectDynamic(true); 619 SetObjectDynamic(true);
@@ -628,7 +628,7 @@ public class BSPrim : BSPhysObject
628 public override void SetMaterial(int material) 628 public override void SetMaterial(int material)
629 { 629 {
630 base.SetMaterial(material); 630 base.SetMaterial(material);
631 PhysScene.TaintedObject("BSPrim.SetMaterial", delegate() 631 PhysScene.TaintedObject(LocalID, "BSPrim.SetMaterial", delegate()
632 { 632 {
633 UpdatePhysicalParameters(); 633 UpdatePhysicalParameters();
634 }); 634 });
@@ -641,7 +641,7 @@ public class BSPrim : BSPhysObject
641 if (base.Friction != value) 641 if (base.Friction != value)
642 { 642 {
643 base.Friction = value; 643 base.Friction = value;
644 PhysScene.TaintedObject("BSPrim.setFriction", delegate() 644 PhysScene.TaintedObject(LocalID, "BSPrim.setFriction", delegate()
645 { 645 {
646 UpdatePhysicalParameters(); 646 UpdatePhysicalParameters();
647 }); 647 });
@@ -656,7 +656,7 @@ public class BSPrim : BSPhysObject
656 if (base.Restitution != value) 656 if (base.Restitution != value)
657 { 657 {
658 base.Restitution = value; 658 base.Restitution = value;
659 PhysScene.TaintedObject("BSPrim.setRestitution", delegate() 659 PhysScene.TaintedObject(LocalID, "BSPrim.setRestitution", delegate()
660 { 660 {
661 UpdatePhysicalParameters(); 661 UpdatePhysicalParameters();
662 }); 662 });
@@ -673,7 +673,7 @@ public class BSPrim : BSPhysObject
673 if (base.Density != value) 673 if (base.Density != value)
674 { 674 {
675 base.Density = value; 675 base.Density = value;
676 PhysScene.TaintedObject("BSPrim.setDensity", delegate() 676 PhysScene.TaintedObject(LocalID, "BSPrim.setDensity", delegate()
677 { 677 {
678 UpdatePhysicalParameters(); 678 UpdatePhysicalParameters();
679 }); 679 });
@@ -688,7 +688,7 @@ public class BSPrim : BSPhysObject
688 if (base.GravModifier != value) 688 if (base.GravModifier != value)
689 { 689 {
690 base.GravModifier = value; 690 base.GravModifier = value;
691 PhysScene.TaintedObject("BSPrim.setGravityModifier", delegate() 691 PhysScene.TaintedObject(LocalID, "BSPrim.setGravityModifier", delegate()
692 { 692 {
693 UpdatePhysicalParameters(); 693 UpdatePhysicalParameters();
694 }); 694 });
@@ -699,7 +699,7 @@ public class BSPrim : BSPhysObject
699 get { return RawVelocity; } 699 get { return RawVelocity; }
700 set { 700 set {
701 RawVelocity = value; 701 RawVelocity = value;
702 PhysScene.TaintedObject("BSPrim.setVelocity", delegate() 702 PhysScene.TaintedObject(LocalID, "BSPrim.setVelocity", delegate()
703 { 703 {
704 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity); 704 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, RawVelocity);
705 ForceVelocity = RawVelocity; 705 ForceVelocity = RawVelocity;
@@ -745,7 +745,7 @@ public class BSPrim : BSPhysObject
745 return; 745 return;
746 RawOrientation = value; 746 RawOrientation = value;
747 747
748 PhysScene.TaintedObject("BSPrim.setOrientation", delegate() 748 PhysScene.TaintedObject(LocalID, "BSPrim.setOrientation", delegate()
749 { 749 {
750 ForceOrientation = RawOrientation; 750 ForceOrientation = RawOrientation;
751 }); 751 });
@@ -776,7 +776,7 @@ public class BSPrim : BSPhysObject
776 if (_isPhysical != value) 776 if (_isPhysical != value)
777 { 777 {
778 _isPhysical = value; 778 _isPhysical = value;
779 PhysScene.TaintedObject("BSPrim.setIsPhysical", delegate() 779 PhysScene.TaintedObject(LocalID, "BSPrim.setIsPhysical", delegate()
780 { 780 {
781 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); 781 DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical);
782 SetObjectDynamic(true); 782 SetObjectDynamic(true);
@@ -1020,7 +1020,7 @@ public class BSPrim : BSPhysObject
1020 public override bool FloatOnWater { 1020 public override bool FloatOnWater {
1021 set { 1021 set {
1022 _floatOnWater = value; 1022 _floatOnWater = value;
1023 PhysScene.TaintedObject("BSPrim.setFloatOnWater", delegate() 1023 PhysScene.TaintedObject(LocalID, "BSPrim.setFloatOnWater", delegate()
1024 { 1024 {
1025 if (_floatOnWater) 1025 if (_floatOnWater)
1026 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER); 1026 CurrentCollisionFlags = PhysScene.PE.AddToCollisionFlags(PhysBody, CollisionFlags.BS_FLOATS_ON_WATER);
@@ -1037,7 +1037,7 @@ public class BSPrim : BSPhysObject
1037 _rotationalVelocity = value; 1037 _rotationalVelocity = value;
1038 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity); 1038 Util.ClampV(_rotationalVelocity, BSParam.MaxAngularVelocity);
1039 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 1039 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
1040 PhysScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() 1040 PhysScene.TaintedObject(LocalID, "BSPrim.setRotationalVelocity", delegate()
1041 { 1041 {
1042 ForceRotationalVelocity = _rotationalVelocity; 1042 ForceRotationalVelocity = _rotationalVelocity;
1043 }); 1043 });
@@ -1068,7 +1068,7 @@ public class BSPrim : BSPhysObject
1068 get { return _buoyancy; } 1068 get { return _buoyancy; }
1069 set { 1069 set {
1070 _buoyancy = value; 1070 _buoyancy = value;
1071 PhysScene.TaintedObject("BSPrim.setBuoyancy", delegate() 1071 PhysScene.TaintedObject(LocalID, "BSPrim.setBuoyancy", delegate()
1072 { 1072 {
1073 ForceBuoyancy = _buoyancy; 1073 ForceBuoyancy = _buoyancy;
1074 }); 1074 });
@@ -1142,7 +1142,7 @@ public class BSPrim : BSPhysObject
1142 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce); 1142 // DetailLog("{0},BSPrim.addForce,call,force={1}", LocalID, addForce);
1143 1143
1144 OMV.Vector3 addForce = force; 1144 OMV.Vector3 addForce = force;
1145 PhysScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() 1145 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddForce", delegate()
1146 { 1146 {
1147 // Bullet adds this central force to the total force for this tick. 1147 // Bullet adds this central force to the total force for this tick.
1148 // Deep down in Bullet: 1148 // Deep down in Bullet:
@@ -1172,7 +1172,7 @@ public class BSPrim : BSPhysObject
1172 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude); 1172 OMV.Vector3 addImpulse = Util.ClampV(impulse, BSParam.MaxAddForceMagnitude);
1173 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse); 1173 // DetailLog("{0},BSPrim.addForceImpulse,call,impulse={1}", LocalID, impulse);
1174 1174
1175 PhysScene.TaintedObject(inTaintTime, "BSPrim.AddImpulse", delegate() 1175 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddImpulse", delegate()
1176 { 1176 {
1177 // Bullet adds this impulse immediately to the velocity 1177 // Bullet adds this impulse immediately to the velocity
1178 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse); 1178 DetailLog("{0},BSPrim.addForceImpulse,taint,impulseforce={1}", LocalID, addImpulse);
@@ -1197,7 +1197,7 @@ public class BSPrim : BSPhysObject
1197 if (force.IsFinite()) 1197 if (force.IsFinite())
1198 { 1198 {
1199 OMV.Vector3 angForce = force; 1199 OMV.Vector3 angForce = force;
1200 PhysScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() 1200 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.AddAngularForce", delegate()
1201 { 1201 {
1202 if (PhysBody.HasPhysicalBody) 1202 if (PhysBody.HasPhysicalBody)
1203 { 1203 {
@@ -1221,7 +1221,7 @@ public class BSPrim : BSPhysObject
1221 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) 1221 public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime)
1222 { 1222 {
1223 OMV.Vector3 applyImpulse = impulse; 1223 OMV.Vector3 applyImpulse = impulse;
1224 PhysScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() 1224 PhysScene.TaintedObject(inTaintTime, LocalID, "BSPrim.ApplyTorqueImpulse", delegate()
1225 { 1225 {
1226 if (PhysBody.HasPhysicalBody) 1226 if (PhysBody.HasPhysicalBody)
1227 { 1227 {
@@ -1552,39 +1552,10 @@ public class BSPrim : BSPhysObject
1552 #region Extension 1552 #region Extension
1553 public override object Extension(string pFunct, params object[] pParams) 1553 public override object Extension(string pFunct, params object[] pParams)
1554 { 1554 {
1555 DetailLog("{0} BSPrim.Extension,op={1}", LocalID, pFunct);
1555 object ret = null; 1556 object ret = null;
1556 switch (pFunct) 1557 switch (pFunct)
1557 { 1558 {
1558 case BSScene.PhysFunctGetLinksetType:
1559 {
1560 BSPrimLinkable myHandle = this as BSPrimLinkable;
1561 if (myHandle != null)
1562 {
1563 ret = (object)myHandle.LinksetType;
1564 }
1565 m_log.DebugFormat("{0} Extension.physGetLinksetType, type={1}", LogHeader, ret);
1566 break;
1567 }
1568 case BSScene.PhysFunctSetLinksetType:
1569 {
1570 if (pParams.Length > 0)
1571 {
1572 BSLinkset.LinksetImplementation linksetType = (BSLinkset.LinksetImplementation)pParams[0];
1573 BSPrimLinkable myHandle = this as BSPrimLinkable;
1574 if (myHandle != null && myHandle.Linkset.IsRoot(myHandle))
1575 {
1576 PhysScene.TaintedObject("BSPrim.PhysFunctSetLinksetType", delegate()
1577 {
1578 // Cause the linkset type to change
1579 m_log.DebugFormat("{0} Extension.physSetLinksetType, oldType={1}, newType={2}",
1580 LogHeader, myHandle.Linkset.LinksetImpl, linksetType);
1581 myHandle.ConvertLinkset(linksetType);
1582 });
1583 }
1584 ret = (object)(int)linksetType;
1585 }
1586 break;
1587 }
1588 default: 1559 default:
1589 ret = base.Extension(pFunct, pParams); 1560 ret = base.Extension(pFunct, pParams);
1590 break; 1561 break;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
index 7179a6d..126b146 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
@@ -30,6 +30,7 @@ using System.Linq;
30using System.Text; 30using System.Text;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.OptionalModules.Scripting;
33 34
34using OMV = OpenMetaverse; 35using OMV = OpenMetaverse;
35 36
@@ -41,6 +42,8 @@ public class BSPrimLinkable : BSPrimDisplaced
41 // operations necessary for keeping the linkset created and, additionally, this 42 // operations necessary for keeping the linkset created and, additionally, this
42 // calls the linkset implementation for its creation and management. 43 // calls the linkset implementation for its creation and management.
43 44
45 private static readonly string LogHeader = "[BULLETS PRIMLINKABLE]";
46
44 // This adds the overrides for link() and delink() so the prim is linkable. 47 // This adds the overrides for link() and delink() so the prim is linkable.
45 48
46 public BSLinkset Linkset { get; set; } 49 public BSLinkset Linkset { get; set; }
@@ -58,15 +61,12 @@ public class BSPrimLinkable : BSPrimDisplaced
58 61
59 Linkset = BSLinkset.Factory(PhysScene, this); 62 Linkset = BSLinkset.Factory(PhysScene, this);
60 63
61 PhysScene.TaintedObject("BSPrimLinksetCompound.Refresh", delegate() 64 Linkset.Refresh(this);
62 {
63 Linkset.Refresh(this);
64 });
65 } 65 }
66 66
67 public override void Destroy() 67 public override void Destroy()
68 { 68 {
69 Linkset = Linkset.RemoveMeFromLinkset(this); 69 Linkset = Linkset.RemoveMeFromLinkset(this, false /* inTaintTime */);
70 base.Destroy(); 70 base.Destroy();
71 } 71 }
72 72
@@ -80,7 +80,7 @@ public class BSPrimLinkable : BSPrimDisplaced
80 80
81 Linkset = parent.Linkset.AddMeToLinkset(this); 81 Linkset = parent.Linkset.AddMeToLinkset(this);
82 82
83 DetailLog("{0},BSPrimLinkset.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", 83 DetailLog("{0},BSPrimLinkable.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
84 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); 84 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
85 } 85 }
86 return; 86 return;
@@ -94,9 +94,9 @@ public class BSPrimLinkable : BSPrimDisplaced
94 BSPhysObject parentBefore = Linkset.LinksetRoot; // DEBUG 94 BSPhysObject parentBefore = Linkset.LinksetRoot; // DEBUG
95 int childrenBefore = Linkset.NumberOfChildren; // DEBUG 95 int childrenBefore = Linkset.NumberOfChildren; // DEBUG
96 96
97 Linkset = Linkset.RemoveMeFromLinkset(this); 97 Linkset = Linkset.RemoveMeFromLinkset(this, false /* inTaintTime*/);
98 98
99 DetailLog("{0},BSPrimLinkset.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", 99 DetailLog("{0},BSPrimLinkable.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
100 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); 100 LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
101 return; 101 return;
102 } 102 }
@@ -108,7 +108,7 @@ public class BSPrimLinkable : BSPrimDisplaced
108 set 108 set
109 { 109 {
110 base.Position = value; 110 base.Position = value;
111 PhysScene.TaintedObject("BSPrimLinkset.setPosition", delegate() 111 PhysScene.TaintedObject(LocalID, "BSPrimLinkable.setPosition", delegate()
112 { 112 {
113 Linkset.UpdateProperties(UpdatedProperties.Position, this); 113 Linkset.UpdateProperties(UpdatedProperties.Position, this);
114 }); 114 });
@@ -122,7 +122,7 @@ public class BSPrimLinkable : BSPrimDisplaced
122 set 122 set
123 { 123 {
124 base.Orientation = value; 124 base.Orientation = value;
125 PhysScene.TaintedObject("BSPrimLinkset.setOrientation", delegate() 125 PhysScene.TaintedObject(LocalID, "BSPrimLinkable.setOrientation", delegate()
126 { 126 {
127 Linkset.UpdateProperties(UpdatedProperties.Orientation, this); 127 Linkset.UpdateProperties(UpdatedProperties.Orientation, this);
128 }); 128 });
@@ -180,7 +180,7 @@ public class BSPrimLinkable : BSPrimDisplaced
180 // Do any filtering/modification needed for linksets. 180 // Do any filtering/modification needed for linksets.
181 public override void UpdateProperties(EntityProperties entprop) 181 public override void UpdateProperties(EntityProperties entprop)
182 { 182 {
183 if (Linkset.IsRoot(this)) 183 if (Linkset.IsRoot(this) || Linkset.ShouldReportPropertyUpdates(this))
184 { 184 {
185 // Properties are only updated for the roots of a linkset. 185 // Properties are only updated for the roots of a linkset.
186 // TODO: this will have to change when linksets are articulated. 186 // TODO: this will have to change when linksets are articulated.
@@ -240,6 +240,8 @@ public class BSPrimLinkable : BSPrimDisplaced
240 bool ret = false; 240 bool ret = false;
241 if (LinksetType != newType) 241 if (LinksetType != newType)
242 { 242 {
243 DetailLog("{0},BSPrimLinkable.ConvertLinkset,oldT={1},newT={2}", LocalID, LinksetType, newType);
244
243 // Set the implementation type first so the call to BSLinkset.Factory gets the new type. 245 // Set the implementation type first so the call to BSLinkset.Factory gets the new type.
244 this.LinksetType = newType; 246 this.LinksetType = newType;
245 247
@@ -263,7 +265,10 @@ public class BSPrimLinkable : BSPrimDisplaced
263 // Remove the children from the old linkset and add to the new (will be a new instance from the factory) 265 // Remove the children from the old linkset and add to the new (will be a new instance from the factory)
264 foreach (BSPrimLinkable child in children) 266 foreach (BSPrimLinkable child in children)
265 { 267 {
266 oldLinkset.RemoveMeFromLinkset(child); 268 oldLinkset.RemoveMeFromLinkset(child, true /*inTaintTime*/);
269 }
270 foreach (BSPrimLinkable child in children)
271 {
267 newLinkset.AddMeToLinkset(child); 272 newLinkset.AddMeToLinkset(child);
268 child.Linkset = newLinkset; 273 child.Linkset = newLinkset;
269 } 274 }
@@ -274,5 +279,70 @@ public class BSPrimLinkable : BSPrimDisplaced
274 } 279 }
275 return ret; 280 return ret;
276 } 281 }
282
283 #region Extension
284 public override object Extension(string pFunct, params object[] pParams)
285 {
286 DetailLog("{0} BSPrimLinkable.Extension,op={1},nParam={2}", LocalID, pFunct, pParams.Length);
287 object ret = null;
288 switch (pFunct)
289 {
290 // physGetLinksetType();
291 // pParams = [ BSPhysObject root, null ]
292 case ExtendedPhysics.PhysFunctGetLinksetType:
293 {
294 ret = (object)LinksetType;
295 DetailLog("{0},BSPrimLinkable.Extension.physGetLinksetType,type={1}", LocalID, ret);
296 break;
297 }
298 // physSetLinksetType(type);
299 // pParams = [ BSPhysObject root, null, integer type ]
300 case ExtendedPhysics.PhysFunctSetLinksetType:
301 {
302 if (pParams.Length > 2)
303 {
304 BSLinkset.LinksetImplementation linksetType = (BSLinkset.LinksetImplementation)pParams[2];
305 if (Linkset.IsRoot(this))
306 {
307 PhysScene.TaintedObject(LocalID, "BSPrim.PhysFunctSetLinksetType", delegate()
308 {
309 // Cause the linkset type to change
310 DetailLog("{0},BSPrimLinkable.Extension.physSetLinksetType, oldType={1},newType={2}",
311 LocalID, Linkset.LinksetImpl, linksetType);
312 ConvertLinkset(linksetType);
313 });
314 }
315 ret = (object)(int)linksetType;
316 }
317 break;
318 }
319 // physChangeLinkType(linknum, typeCode);
320 // pParams = [ BSPhysObject root, BSPhysObject child, integer linkType ]
321 case ExtendedPhysics.PhysFunctChangeLinkType:
322 {
323 ret = Linkset.Extension(pFunct, pParams);
324 break;
325 }
326 // physGetLinkType(linknum);
327 // pParams = [ BSPhysObject root, BSPhysObject child ]
328 case ExtendedPhysics.PhysFunctGetLinkType:
329 {
330 ret = Linkset.Extension(pFunct, pParams);
331 break;
332 }
333 // physChangeLinkParams(linknum, [code, value, code, value, ...]);
334 // pParams = [ BSPhysObject root, BSPhysObject child, object[] [ string op, object opParam, string op, object opParam, ... ] ]
335 case ExtendedPhysics.PhysFunctChangeLinkParams:
336 {
337 ret = Linkset.Extension(pFunct, pParams);
338 break;
339 }
340 default:
341 ret = base.Extension(pFunct, pParams);
342 break;
343 }
344 return ret;
345 }
346 #endregion // Extension
277} 347}
278} 348}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index c92c9b9..b3dfa41 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -157,12 +157,20 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
157 public delegate void TaintCallback(); 157 public delegate void TaintCallback();
158 private struct TaintCallbackEntry 158 private struct TaintCallbackEntry
159 { 159 {
160 public String originator;
160 public String ident; 161 public String ident;
161 public TaintCallback callback; 162 public TaintCallback callback;
162 public TaintCallbackEntry(string i, TaintCallback c) 163 public TaintCallbackEntry(string pIdent, TaintCallback pCallBack)
163 { 164 {
164 ident = i; 165 originator = BSScene.DetailLogZero;
165 callback = c; 166 ident = pIdent;
167 callback = pCallBack;
168 }
169 public TaintCallbackEntry(string pOrigin, string pIdent, TaintCallback pCallBack)
170 {
171 originator = pOrigin;
172 ident = pIdent;
173 callback = pCallBack;
166 } 174 }
167 } 175 }
168 private Object _taintLock = new Object(); // lock for using the next object 176 private Object _taintLock = new Object(); // lock for using the next object
@@ -867,18 +875,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
867 public override bool IsThreaded { get { return false; } } 875 public override bool IsThreaded { get { return false; } }
868 876
869 #region Extensions 877 #region Extensions
870 // =============================================================
871 // Per scene functions. See below.
872
873 // Per avatar functions. See BSCharacter.
874
875 // Per prim functions. See BSPrim.
876 public const string PhysFunctGetLinksetType = "BulletSim.GetLinksetType";
877 public const string PhysFunctSetLinksetType = "BulletSim.SetLinksetType";
878 // =============================================================
879
880 public override object Extension(string pFunct, params object[] pParams) 878 public override object Extension(string pFunct, params object[] pParams)
881 { 879 {
880 DetailLog("{0} BSScene.Extension,op={1}", DetailLogZero, pFunct);
882 return base.Extension(pFunct, pParams); 881 return base.Extension(pFunct, pParams);
883 } 882 }
884 #endregion // Extensions 883 #endregion // Extensions
@@ -897,26 +896,37 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
897 // Calls to the PhysicsActors can't directly call into the physics engine 896 // Calls to the PhysicsActors can't directly call into the physics engine
898 // because it might be busy. We delay changes to a known time. 897 // because it might be busy. We delay changes to a known time.
899 // We rely on C#'s closure to save and restore the context for the delegate. 898 // We rely on C#'s closure to save and restore the context for the delegate.
900 public void TaintedObject(String ident, TaintCallback callback) 899 public void TaintedObject(string pOriginator, string pIdent, TaintCallback pCallback)
901 { 900 {
902 if (!m_initialized) return; 901 TaintedObject(false /*inTaintTime*/, pOriginator, pIdent, pCallback);
903 902 }
904 lock (_taintLock) 903 public void TaintedObject(uint pOriginator, String pIdent, TaintCallback pCallback)
905 { 904 {
906 _taintOperations.Add(new TaintCallbackEntry(ident, callback)); 905 TaintedObject(false /*inTaintTime*/, m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback);
907 } 906 }
908 907 public void TaintedObject(bool inTaintTime, String pIdent, TaintCallback pCallback)
909 return; 908 {
909 TaintedObject(inTaintTime, BSScene.DetailLogZero, pIdent, pCallback);
910 }
911 public void TaintedObject(bool inTaintTime, uint pOriginator, String pIdent, TaintCallback pCallback)
912 {
913 TaintedObject(inTaintTime, m_physicsLoggingEnabled ? pOriginator.ToString() : BSScene.DetailLogZero, pIdent, pCallback);
910 } 914 }
911
912 // Sometimes a potentially tainted operation can be used in and out of taint time. 915 // Sometimes a potentially tainted operation can be used in and out of taint time.
913 // This routine executes the command immediately if in taint-time otherwise it is queued. 916 // This routine executes the command immediately if in taint-time otherwise it is queued.
914 public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback) 917 public void TaintedObject(bool inTaintTime, string pOriginator, string pIdent, TaintCallback pCallback)
915 { 918 {
919 if (!m_initialized) return;
920
916 if (inTaintTime) 921 if (inTaintTime)
917 callback(); 922 pCallback();
918 else 923 else
919 TaintedObject(ident, callback); 924 {
925 lock (_taintLock)
926 {
927 _taintOperations.Add(new TaintCallbackEntry(pOriginator, pIdent, pCallback));
928 }
929 }
920 } 930 }
921 931
922 private void TriggerPreStepEvent(float timeStep) 932 private void TriggerPreStepEvent(float timeStep)
@@ -960,7 +970,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
960 { 970 {
961 try 971 try
962 { 972 {
963 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG 973 DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", tcbe.originator, tcbe.ident); // DEBUG DEBUG DEBUG
964 tcbe.callback(); 974 tcbe.callback();
965 } 975 }
966 catch (Exception e) 976 catch (Exception e)
@@ -977,10 +987,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
977 // will replace any previous operation by the same object. 987 // will replace any previous operation by the same object.
978 public void PostTaintObject(String ident, uint ID, TaintCallback callback) 988 public void PostTaintObject(String ident, uint ID, TaintCallback callback)
979 { 989 {
980 string uniqueIdent = ident + "-" + ID.ToString(); 990 string IDAsString = ID.ToString();
991 string uniqueIdent = ident + "-" + IDAsString;
981 lock (_taintLock) 992 lock (_taintLock)
982 { 993 {
983 _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback); 994 _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(IDAsString, uniqueIdent, callback);
984 } 995 }
985 996
986 return; 997 return;
@@ -1090,7 +1101,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1090 string xval = val; 1101 string xval = val;
1091 List<uint> xlIDs = lIDs; 1102 List<uint> xlIDs = lIDs;
1092 string xparm = parm; 1103 string xparm = parm;
1093 TaintedObject("BSScene.UpdateParameterSet", delegate() { 1104 TaintedObject(DetailLogZero, "BSScene.UpdateParameterSet", delegate() {
1094 BSParam.ParameterDefnBase thisParam; 1105 BSParam.ParameterDefnBase thisParam;
1095 if (BSParam.TryGetParameter(xparm, out thisParam)) 1106 if (BSParam.TryGetParameter(xparm, out thisParam))
1096 { 1107 {
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index f05aaa9..8892b69 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -8900,8 +8900,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8900 int idx=0; 8900 int idx=0;
8901 while (idx < rules.Length) 8901 while (idx < rules.Length)
8902 { 8902 {
8903 int code=(int)rules.GetLSLIntegerItem(idx++); 8903 int code = (int)rules.GetLSLIntegerItem(idx++);
8904 int remain=rules.Length-idx; 8904 int remain = rules.Length - idx;
8905 8905
8906 switch (code) 8906 switch (code)
8907 { 8907 {
@@ -8974,7 +8974,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8974 break; 8974 break;
8975 8975
8976 case ScriptBaseClass.PRIM_TYPE_SCULPT: 8976 case ScriptBaseClass.PRIM_TYPE_SCULPT:
8977 res.Add(Shape.SculptTexture.ToString()); 8977 res.Add(new LSL_String(Shape.SculptTexture.ToString()));
8978 res.Add(new LSL_Integer(Shape.SculptType)); 8978 res.Add(new LSL_Integer(Shape.SculptType));
8979 break; 8979 break;
8980 8980
@@ -9316,7 +9316,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9316 )); 9316 ));
9317 break; 9317 break;
9318 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 9318 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
9319 if(remain < 3) 9319
9320 // TODO: Should be issuing a runtime script warning in this case.
9321 if (remain < 2)
9320 return null; 9322 return null;
9321 9323
9322 return rules.GetSublist(idx, -1); 9324 return rules.GetSublist(idx, -1);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index f4e4f44..5c57971 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -3043,7 +3043,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3043 sp.ControllingClient.Kick(alert); 3043 sp.ControllingClient.Kick(alert);
3044 3044
3045 // ...and close on our side 3045 // ...and close on our side
3046 sp.Scene.IncomingCloseAgent(sp.UUID, false); 3046 sp.Scene.CloseAgent(sp.UUID, false);
3047 } 3047 }
3048 }); 3048 });
3049 } 3049 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs
new file mode 100644
index 0000000..ed61dc0
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiObjectTests.cs
@@ -0,0 +1,399 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the 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
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text;
32using log4net;
33using Nini.Config;
34using NUnit.Framework;
35using OpenMetaverse;
36using OpenMetaverse.Assets;
37using OpenMetaverse.StructuredData;
38using OpenSim.Framework;
39using OpenSim.Region.CoreModules.Avatar.AvatarFactory;
40using OpenSim.Region.OptionalModules.World.NPC;
41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Region.ScriptEngine.Shared;
43using OpenSim.Region.ScriptEngine.Shared.Api;
44using OpenSim.Region.ScriptEngine.Shared.Instance;
45using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
46using OpenSim.Services.Interfaces;
47using OpenSim.Tests.Common;
48using OpenSim.Tests.Common.Mock;
49using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
50using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
51
52namespace OpenSim.Region.ScriptEngine.Shared.Tests
53{
54 [TestFixture]
55 public class LSL_ApiObjectTests : OpenSimTestCase
56 {
57 private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d;
58 private const float FLOAT_ACCURACY = 0.00005f;
59
60 protected Scene m_scene;
61 protected XEngine.XEngine m_engine;
62
63 [SetUp]
64 public override void SetUp()
65 {
66 base.SetUp();
67
68 IConfigSource initConfigSource = new IniConfigSource();
69 IConfig config = initConfigSource.AddConfig("XEngine");
70 config.Set("Enabled", "true");
71
72 m_scene = new SceneHelpers().SetupScene();
73 SceneHelpers.SetupSceneModules(m_scene, initConfigSource);
74
75 m_engine = new XEngine.XEngine();
76 m_engine.Initialise(initConfigSource);
77 m_engine.AddRegion(m_scene);
78 }
79
80 [Test]
81 public void TestllGetLinkPrimitiveParams()
82 {
83 TestHelpers.InMethod();
84 TestHelpers.EnableLogging();
85
86 UUID ownerId = TestHelpers.ParseTail(0x1);
87
88 SceneObjectGroup grp1 = SceneHelpers.CreateSceneObject(2, ownerId, "grp1-", 0x10);
89 grp1.AbsolutePosition = new Vector3(10, 11, 12);
90 m_scene.AddSceneObject(grp1);
91
92 LSL_Api apiGrp1 = new LSL_Api();
93 apiGrp1.Initialize(m_engine, grp1.RootPart, null, null);
94
95 // Check simple 1 prim case
96 {
97 LSL_List resList
98 = apiGrp1.llGetLinkPrimitiveParams(1, new LSL_List(new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
99
100 Assert.That(resList.Length, Is.EqualTo(1));
101 }
102
103 // Check 2 prim case
104 {
105 LSL_List resList
106 = apiGrp1.llGetLinkPrimitiveParams(
107 1,
108 new LSL_List(
109 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION),
110 new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET),
111 new LSL_Integer(2),
112 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
113
114 Assert.That(resList.Length, Is.EqualTo(2));
115 }
116
117 // Check invalid parameters are ignored
118 {
119 LSL_List resList
120 = apiGrp1.llGetLinkPrimitiveParams(3, new LSL_List(new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
121
122 Assert.That(resList.Length, Is.EqualTo(0));
123 }
124
125 // Check all parameters are ignored if an initial bad link is given
126 {
127 LSL_List resList
128 = apiGrp1.llGetLinkPrimitiveParams(
129 3,
130 new LSL_List(
131 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION),
132 new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET),
133 new LSL_Integer(1),
134 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
135
136 Assert.That(resList.Length, Is.EqualTo(0));
137 }
138
139 // Check only subsequent parameters are ignored when we hit the first bad link number
140 {
141 LSL_List resList
142 = apiGrp1.llGetLinkPrimitiveParams(
143 1,
144 new LSL_List(
145 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION),
146 new LSL_Integer(ScriptBaseClass.PRIM_LINK_TARGET),
147 new LSL_Integer(3),
148 new LSL_Integer(ScriptBaseClass.PRIM_ROTATION)));
149
150 Assert.That(resList.Length, Is.EqualTo(1));
151 }
152 }
153
154 [Test]
155 // llSetPrimitiveParams and llGetPrimitiveParams test.
156 public void TestllSetPrimitiveParams()
157 {
158 TestHelpers.InMethod();
159
160 // Create Prim1.
161 Scene scene = new SceneHelpers().SetupScene();
162 string obj1Name = "Prim1";
163 UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001");
164 SceneObjectPart part1 =
165 new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default,
166 Vector3.Zero, Quaternion.Identity,
167 Vector3.Zero) { Name = obj1Name, UUID = objUuid };
168 Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part1), false), Is.True);
169
170 LSL_Api apiGrp1 = new LSL_Api();
171 apiGrp1.Initialize(m_engine, part1, null, null);
172
173 // Note that prim hollow check is passed with the other prim params in order to allow the
174 // specification of a different check value from the prim param. A cylinder, prism, sphere,
175 // torus or ring, with a hole shape of square, is limited to a hollow of 70%. Test 5 below
176 // specifies a value of 95% and checks to see if 70% was properly returned.
177
178 // Test a sphere.
179 CheckllSetPrimitiveParams(
180 apiGrp1,
181 "test 1", // Prim test identification string
182 new LSL_Types.Vector3(6.0d, 9.9d, 9.9d), // Prim size
183 ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type
184 ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type
185 new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut
186 0.80f, // Prim hollow
187 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
188 new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple
189 0.80f); // Prim hollow check
190
191 // Test a prism.
192 CheckllSetPrimitiveParams(
193 apiGrp1,
194 "test 2", // Prim test identification string
195 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
196 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
197 ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type
198 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
199 0.90f, // Prim hollow
200 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
201 new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper
202 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
203 0.90f); // Prim hollow check
204
205 // Test a box.
206 CheckllSetPrimitiveParams(
207 apiGrp1,
208 "test 3", // Prim test identification string
209 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
210 ScriptBaseClass.PRIM_TYPE_BOX, // Prim type
211 ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type
212 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
213 0.95f, // Prim hollow
214 new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist
215 new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper
216 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
217 0.95f); // Prim hollow check
218
219 // Test a tube.
220 CheckllSetPrimitiveParams(
221 apiGrp1,
222 "test 4", // Prim test identification string
223 new LSL_Types.Vector3(4.2d, 4.2d, 4.2d), // Prim size
224 ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type
225 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
226 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
227 0.00f, // Prim hollow
228 new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist
229 new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size
230 // Expression for y selected to test precision problems during byte
231 // cast in SetPrimitiveShapeParams.
232 new LSL_Types.Vector3(0.0d, 0.35d + 0.1d, 0.0d), // Prim shear
233 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut
234 // Expression for y selected to test precision problems during sbyte
235 // cast in SetPrimitiveShapeParams.
236 new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper
237 1.11f, // Prim revolutions
238 0.88f, // Prim radius
239 0.95f, // Prim skew
240 0.00f); // Prim hollow check
241
242 // Test a prism.
243 CheckllSetPrimitiveParams(
244 apiGrp1,
245 "test 5", // Prim test identification string
246 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
247 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
248 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
249 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
250 0.95f, // Prim hollow
251 // Expression for x selected to test precision problems during sbyte
252 // cast in SetPrimitiveShapeBlockParams.
253 new LSL_Types.Vector3(0.7d + 0.2d, 0.0d, 0.0d), // Prim twist
254 // Expression for y selected to test precision problems during sbyte
255 // cast in SetPrimitiveShapeParams.
256 new LSL_Types.Vector3(2.0d, (1.3d + 0.1d), 0.0d), // Prim taper
257 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
258 0.70f); // Prim hollow check
259
260 // Test a sculpted prim.
261 CheckllSetPrimitiveParams(
262 apiGrp1,
263 "test 6", // Prim test identification string
264 new LSL_Types.Vector3(2.0d, 2.0d, 2.0d), // Prim size
265 ScriptBaseClass.PRIM_TYPE_SCULPT, // Prim type
266 "be293869-d0d9-0a69-5989-ad27f1946fd4", // Prim map
267 ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE); // Prim sculpt type
268 }
269
270 // Set prim params for a box, cylinder or prism and check results.
271 public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
272 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
273 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear,
274 float primHollowCheck)
275 {
276 // Set the prim params.
277 api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
278 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
279 primCut, primHollow, primTwist, primTaper, primShear));
280
281 // Get params for prim to validate settings.
282 LSL_Types.list primParams =
283 api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
284
285 // Validate settings.
286 CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
287 Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
288 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
289 Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2),
290 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
291 CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut");
292 Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY,
293 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
294 CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist");
295 CheckllSetPrimitiveParamsVector(primTaper, api.llList2Vector(primParams, 6), primTest + " prim taper");
296 CheckllSetPrimitiveParamsVector(primShear, api.llList2Vector(primParams, 7), primTest + " prim shear");
297 }
298
299 // Set prim params for a sphere and check results.
300 public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
301 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
302 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, float primHollowCheck)
303 {
304 // Set the prim params.
305 api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
306 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
307 primCut, primHollow, primTwist, primDimple));
308
309 // Get params for prim to validate settings.
310 LSL_Types.list primParams =
311 api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
312
313 // Validate settings.
314 CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
315 Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
316 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
317 Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2),
318 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
319 CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut");
320 Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY,
321 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
322 CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist");
323 CheckllSetPrimitiveParamsVector(primDimple, api.llList2Vector(primParams, 6), primTest + " prim dimple");
324 }
325
326 // Set prim params for a torus, tube or ring and check results.
327 public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
328 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
329 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize,
330 LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper,
331 float primRev, float primRadius, float primSkew, float primHollowCheck)
332 {
333 // Set the prim params.
334 api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
335 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
336 primCut, primHollow, primTwist, primHoleSize, primShear, primProfCut,
337 primTaper, primRev, primRadius, primSkew));
338
339 // Get params for prim to validate settings.
340 LSL_Types.list primParams =
341 api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
342
343 // Valdate settings.
344 CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
345 Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
346 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
347 Assert.AreEqual(primHoleType, api.llList2Integer(primParams, 2),
348 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
349 CheckllSetPrimitiveParamsVector(primCut, api.llList2Vector(primParams, 3), primTest + " prim cut");
350 Assert.AreEqual(primHollowCheck, api.llList2Float(primParams, 4), FLOAT_ACCURACY,
351 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
352 CheckllSetPrimitiveParamsVector(primTwist, api.llList2Vector(primParams, 5), primTest + " prim twist");
353 CheckllSetPrimitiveParamsVector(primHoleSize, api.llList2Vector(primParams, 6), primTest + " prim hole size");
354 CheckllSetPrimitiveParamsVector(primShear, api.llList2Vector(primParams, 7), primTest + " prim shear");
355 CheckllSetPrimitiveParamsVector(primProfCut, api.llList2Vector(primParams, 8), primTest + " prim profile cut");
356 CheckllSetPrimitiveParamsVector(primTaper, api.llList2Vector(primParams, 9), primTest + " prim taper");
357 Assert.AreEqual(primRev, api.llList2Float(primParams, 10), FLOAT_ACCURACY,
358 "TestllSetPrimitiveParams " + primTest + " prim revolutions fail");
359 Assert.AreEqual(primRadius, api.llList2Float(primParams, 11), FLOAT_ACCURACY,
360 "TestllSetPrimitiveParams " + primTest + " prim radius fail");
361 Assert.AreEqual(primSkew, api.llList2Float(primParams, 12), FLOAT_ACCURACY,
362 "TestllSetPrimitiveParams " + primTest + " prim skew fail");
363 }
364
365 // Set prim params for a sculpted prim and check results.
366 public void CheckllSetPrimitiveParams(LSL_Api api, string primTest,
367 LSL_Types.Vector3 primSize, int primType, string primMap, int primSculptType)
368 {
369 // Set the prim params.
370 api.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
371 ScriptBaseClass.PRIM_TYPE, primType, primMap, primSculptType));
372
373 // Get params for prim to validate settings.
374 LSL_Types.list primParams =
375 api.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
376
377 // Validate settings.
378 CheckllSetPrimitiveParamsVector(primSize, api.llList2Vector(primParams, 0), primTest + " prim size");
379 Assert.AreEqual(primType, api.llList2Integer(primParams, 1),
380 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
381 Assert.AreEqual(primMap, (string)api.llList2String(primParams, 2),
382 "TestllSetPrimitiveParams " + primTest + " prim map check fail");
383 Assert.AreEqual(primSculptType, api.llList2Integer(primParams, 3),
384 "TestllSetPrimitiveParams " + primTest + " prim type scuplt check fail");
385 }
386
387 public void CheckllSetPrimitiveParamsVector(LSL_Types.Vector3 vecCheck, LSL_Types.Vector3 vecReturned, string msg)
388 {
389 // Check each vector component against expected result.
390 Assert.AreEqual(vecCheck.x, vecReturned.x, VECTOR_COMPONENT_ACCURACY,
391 "TestllSetPrimitiveParams " + msg + " vector check fail on x component");
392 Assert.AreEqual(vecCheck.y, vecReturned.y, VECTOR_COMPONENT_ACCURACY,
393 "TestllSetPrimitiveParams " + msg + " vector check fail on y component");
394 Assert.AreEqual(vecCheck.z, vecReturned.z, VECTOR_COMPONENT_ACCURACY,
395 "TestllSetPrimitiveParams " + msg + " vector check fail on z component");
396 }
397
398 }
399} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
index e97ae06..7e3726a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
@@ -47,9 +47,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
47 [TestFixture, LongRunning] 47 [TestFixture, LongRunning]
48 public class LSL_ApiTest 48 public class LSL_ApiTest
49 { 49 {
50 private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6;
51 private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d; 50 private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d;
52 private const float FLOAT_ACCURACY = 0.00005f; 51 private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6;
53 private LSL_Api m_lslApi; 52 private LSL_Api m_lslApi;
54 53
55 [SetUp] 54 [SetUp]
@@ -255,241 +254,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
255 } 254 }
256 255
257 [Test] 256 [Test]
258 // llSetPrimitiveParams and llGetPrimitiveParams test.
259 public void TestllSetPrimitiveParams()
260 {
261 TestHelpers.InMethod();
262
263 // Create Prim1.
264 Scene scene = new SceneHelpers().SetupScene();
265 string obj1Name = "Prim1";
266 UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001");
267 SceneObjectPart part1 =
268 new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default,
269 Vector3.Zero, Quaternion.Identity,
270 Vector3.Zero) { Name = obj1Name, UUID = objUuid };
271 Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part1), false), Is.True);
272
273 // Note that prim hollow check is passed with the other prim params in order to allow the
274 // specification of a different check value from the prim param. A cylinder, prism, sphere,
275 // torus or ring, with a hole shape of square, is limited to a hollow of 70%. Test 5 below
276 // specifies a value of 95% and checks to see if 70% was properly returned.
277
278 // Test a sphere.
279 CheckllSetPrimitiveParams(
280 "test 1", // Prim test identification string
281 new LSL_Types.Vector3(6.0d, 9.9d, 9.9d), // Prim size
282 ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type
283 ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type
284 new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut
285 0.80f, // Prim hollow
286 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
287 new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple
288 0.80f); // Prim hollow check
289
290 // Test a prism.
291 CheckllSetPrimitiveParams(
292 "test 2", // Prim test identification string
293 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
294 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
295 ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type
296 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
297 0.90f, // Prim hollow
298 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
299 new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper
300 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
301 0.90f); // Prim hollow check
302
303 // Test a box.
304 CheckllSetPrimitiveParams(
305 "test 3", // Prim test identification string
306 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
307 ScriptBaseClass.PRIM_TYPE_BOX, // Prim type
308 ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type
309 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
310 0.95f, // Prim hollow
311 new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist
312 new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper
313 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
314 0.95f); // Prim hollow check
315
316 // Test a tube.
317 CheckllSetPrimitiveParams(
318 "test 4", // Prim test identification string
319 new LSL_Types.Vector3(4.2d, 4.2d, 4.2d), // Prim size
320 ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type
321 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
322 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
323 0.00f, // Prim hollow
324 new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist
325 new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size
326 // Expression for y selected to test precision problems during byte
327 // cast in SetPrimitiveShapeParams.
328 new LSL_Types.Vector3(0.0d, 0.35d + 0.1d, 0.0d), // Prim shear
329 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut
330 // Expression for y selected to test precision problems during sbyte
331 // cast in SetPrimitiveShapeParams.
332 new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper
333 1.11f, // Prim revolutions
334 0.88f, // Prim radius
335 0.95f, // Prim skew
336 0.00f); // Prim hollow check
337
338 // Test a prism.
339 CheckllSetPrimitiveParams(
340 "test 5", // Prim test identification string
341 new LSL_Types.Vector3(3.5d, 3.5d, 3.5d), // Prim size
342 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
343 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
344 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
345 0.95f, // Prim hollow
346 // Expression for x selected to test precision problems during sbyte
347 // cast in SetPrimitiveShapeBlockParams.
348 new LSL_Types.Vector3(0.7d + 0.2d, 0.0d, 0.0d), // Prim twist
349 // Expression for y selected to test precision problems during sbyte
350 // cast in SetPrimitiveShapeParams.
351 new LSL_Types.Vector3(2.0d, (1.3d + 0.1d), 0.0d), // Prim taper
352 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
353 0.70f); // Prim hollow check
354
355 // Test a sculpted prim.
356 CheckllSetPrimitiveParams(
357 "test 6", // Prim test identification string
358 new LSL_Types.Vector3(2.0d, 2.0d, 2.0d), // Prim size
359 ScriptBaseClass.PRIM_TYPE_SCULPT, // Prim type
360 "be293869-d0d9-0a69-5989-ad27f1946fd4", // Prim map
361 ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE); // Prim sculpt type
362 }
363
364 // Set prim params for a box, cylinder or prism and check results.
365 public void CheckllSetPrimitiveParams(string primTest,
366 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
367 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear,
368 float primHollowCheck)
369 {
370 // Set the prim params.
371 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
372 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
373 primCut, primHollow, primTwist, primTaper, primShear));
374
375 // Get params for prim to validate settings.
376 LSL_Types.list primParams =
377 m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
378
379 // Validate settings.
380 CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
381 Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
382 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
383 Assert.AreEqual(primHoleType, m_lslApi.llList2Integer(primParams, 2),
384 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
385 CheckllSetPrimitiveParamsVector(primCut, m_lslApi.llList2Vector(primParams, 3), primTest + " prim cut");
386 Assert.AreEqual(primHollowCheck, m_lslApi.llList2Float(primParams, 4), FLOAT_ACCURACY,
387 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
388 CheckllSetPrimitiveParamsVector(primTwist, m_lslApi.llList2Vector(primParams, 5), primTest + " prim twist");
389 CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 6), primTest + " prim taper");
390 CheckllSetPrimitiveParamsVector(primShear, m_lslApi.llList2Vector(primParams, 7), primTest + " prim shear");
391 }
392
393 // Set prim params for a sphere and check results.
394 public void CheckllSetPrimitiveParams(string primTest,
395 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
396 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, float primHollowCheck)
397 {
398 // Set the prim params.
399 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
400 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
401 primCut, primHollow, primTwist, primDimple));
402
403 // Get params for prim to validate settings.
404 LSL_Types.list primParams =
405 m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
406
407 // Validate settings.
408 CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
409 Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
410 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
411 Assert.AreEqual(primHoleType, m_lslApi.llList2Integer(primParams, 2),
412 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
413 CheckllSetPrimitiveParamsVector(primCut, m_lslApi.llList2Vector(primParams, 3), primTest + " prim cut");
414 Assert.AreEqual(primHollowCheck, m_lslApi.llList2Float(primParams, 4), FLOAT_ACCURACY,
415 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
416 CheckllSetPrimitiveParamsVector(primTwist, m_lslApi.llList2Vector(primParams, 5), primTest + " prim twist");
417 CheckllSetPrimitiveParamsVector(primDimple, m_lslApi.llList2Vector(primParams, 6), primTest + " prim dimple");
418 }
419
420 // Set prim params for a torus, tube or ring and check results.
421 public void CheckllSetPrimitiveParams(string primTest,
422 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
423 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize,
424 LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper,
425 float primRev, float primRadius, float primSkew, float primHollowCheck)
426 {
427 // Set the prim params.
428 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
429 ScriptBaseClass.PRIM_TYPE, primType, primHoleType,
430 primCut, primHollow, primTwist, primHoleSize, primShear, primProfCut,
431 primTaper, primRev, primRadius, primSkew));
432
433 // Get params for prim to validate settings.
434 LSL_Types.list primParams =
435 m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
436
437 // Valdate settings.
438 CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
439 Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
440 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
441 Assert.AreEqual(primHoleType, m_lslApi.llList2Integer(primParams, 2),
442 "TestllSetPrimitiveParams " + primTest + " prim hole default check fail");
443 CheckllSetPrimitiveParamsVector(primCut, m_lslApi.llList2Vector(primParams, 3), primTest + " prim cut");
444 Assert.AreEqual(primHollowCheck, m_lslApi.llList2Float(primParams, 4), FLOAT_ACCURACY,
445 "TestllSetPrimitiveParams " + primTest + " prim hollow check fail");
446 CheckllSetPrimitiveParamsVector(primTwist, m_lslApi.llList2Vector(primParams, 5), primTest + " prim twist");
447 CheckllSetPrimitiveParamsVector(primHoleSize, m_lslApi.llList2Vector(primParams, 6), primTest + " prim hole size");
448 CheckllSetPrimitiveParamsVector(primShear, m_lslApi.llList2Vector(primParams, 7), primTest + " prim shear");
449 CheckllSetPrimitiveParamsVector(primProfCut, m_lslApi.llList2Vector(primParams, 8), primTest + " prim profile cut");
450 CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 9), primTest + " prim taper");
451 Assert.AreEqual(primRev, m_lslApi.llList2Float(primParams, 10), FLOAT_ACCURACY,
452 "TestllSetPrimitiveParams " + primTest + " prim revolutions fail");
453 Assert.AreEqual(primRadius, m_lslApi.llList2Float(primParams, 11), FLOAT_ACCURACY,
454 "TestllSetPrimitiveParams " + primTest + " prim radius fail");
455 Assert.AreEqual(primSkew, m_lslApi.llList2Float(primParams, 12), FLOAT_ACCURACY,
456 "TestllSetPrimitiveParams " + primTest + " prim skew fail");
457 }
458
459 // Set prim params for a sculpted prim and check results.
460 public void CheckllSetPrimitiveParams(string primTest,
461 LSL_Types.Vector3 primSize, int primType, string primMap, int primSculptType)
462 {
463 // Set the prim params.
464 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
465 ScriptBaseClass.PRIM_TYPE, primType, primMap, primSculptType));
466
467 // Get params for prim to validate settings.
468 LSL_Types.list primParams =
469 m_lslApi.llGetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, ScriptBaseClass.PRIM_TYPE));
470
471 // Validate settings.
472 CheckllSetPrimitiveParamsVector(primSize, m_lslApi.llList2Vector(primParams, 0), primTest + " prim size");
473 Assert.AreEqual(primType, m_lslApi.llList2Integer(primParams, 1),
474 "TestllSetPrimitiveParams " + primTest + " prim type check fail");
475 Assert.AreEqual(primMap, (string)m_lslApi.llList2String(primParams, 2),
476 "TestllSetPrimitiveParams " + primTest + " prim map check fail");
477 Assert.AreEqual(primSculptType, m_lslApi.llList2Integer(primParams, 3),
478 "TestllSetPrimitiveParams " + primTest + " prim type scuplt check fail");
479 }
480
481 public void CheckllSetPrimitiveParamsVector(LSL_Types.Vector3 vecCheck, LSL_Types.Vector3 vecReturned, string msg)
482 {
483 // Check each vector component against expected result.
484 Assert.AreEqual(vecCheck.x, vecReturned.x, VECTOR_COMPONENT_ACCURACY,
485 "TestllSetPrimitiveParams " + msg + " vector check fail on x component");
486 Assert.AreEqual(vecCheck.y, vecReturned.y, VECTOR_COMPONENT_ACCURACY,
487 "TestllSetPrimitiveParams " + msg + " vector check fail on y component");
488 Assert.AreEqual(vecCheck.z, vecReturned.z, VECTOR_COMPONENT_ACCURACY,
489 "TestllSetPrimitiveParams " + msg + " vector check fail on z component");
490 }
491
492 [Test]
493 public void TestllVecNorm() 257 public void TestllVecNorm()
494 { 258 {
495 TestHelpers.InMethod(); 259 TestHelpers.InMethod();