aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Application/OpenSim.cs15
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs9
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs7
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs234
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs49
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs13
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionConsole.cs39
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs6
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs54
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs19
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs189
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs24
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs72
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs118
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs176
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs79
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs108
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs55
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs302
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs232
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs124
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs104
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs375
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs25
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs2
35 files changed, 1756 insertions, 740 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index ba8aa9f..6255515 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -294,14 +294,13 @@ namespace OpenSim
294 "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [<OAR path>]", 294 "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [<OAR path>]",
295 "Save a region's data to an OAR archive.", 295 "Save a region's data to an OAR archive.",
296// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine 296// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine
297 "-h|--home=<url> adds the url of the profile service to the saved user information." + Environment.NewLine 297 "-h|--home=<url> adds the url of the profile service to the saved user information.\n"
298 + "--noassets stops assets being saved to the OAR." + Environment.NewLine 298 + "--noassets stops assets being saved to the OAR.\n"
299 + "--publish saves an OAR stripped of owner and last owner information." + Environment.NewLine 299 + "--publish saves an OAR stripped of owner and last owner information.\n"
300 + " on reload, the estate owner will be the owner of all objects" + Environment.NewLine 300 + " on reload, the estate owner will be the owner of all objects\n"
301 + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published" + Environment.NewLine 301 + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n"
302 + " this option is EXPERIMENTAL" + Environment.NewLine 302 + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n"
303 + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR." + Environment.NewLine 303 + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n"
304 + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer" + Environment.NewLine
305 + "The OAR path must be a filesystem path." 304 + "The OAR path must be a filesystem path."
306 + " If this is not given then the oar is saved to region.oar in the current directory.", 305 + " If this is not given then the oar is saved to region.oar in the current directory.",
307 SaveOar); 306 SaveOar);
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index aed10f6..d107b7a 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -320,8 +320,13 @@ namespace OpenSim
320 m_httpServerPort = m_networkServersInfo.HttpListenerPort; 320 m_httpServerPort = m_networkServersInfo.HttpListenerPort;
321 SceneManager.OnRestartSim += handleRestartRegion; 321 SceneManager.OnRestartSim += handleRestartRegion;
322 322
323 // Only start the memory watchdog once all regions are ready 323 // Only enable the watchdogs when all regions are ready. Otherwise we get false positives when cpu is
324 SceneManager.OnRegionsReadyStatusChange += sm => MemoryWatchdog.Enabled = sm.AllRegionsReady; 324 // heavily used during initial startup.
325 //
326 // FIXME: It's also possible that region ready status should be flipped during an OAR load since this
327 // also makes heavy use of the CPU.
328 SceneManager.OnRegionsReadyStatusChange
329 += sm => { MemoryWatchdog.Enabled = sm.AllRegionsReady; Watchdog.Enabled = sm.AllRegionsReady; };
325 } 330 }
326 331
327 /// <summary> 332 /// <summary>
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index d397893..88c4d7f 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -126,9 +126,14 @@ namespace OpenSim.Region.ClientStack.Linden
126 IConfig sconfig = config.Configs["Startup"]; 126 IConfig sconfig = config.Configs["Startup"];
127 if (sconfig != null) 127 if (sconfig != null)
128 { 128 {
129 m_persistBakedTextures = sconfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
130 m_levelUpload = sconfig.GetInt("LevelUpload", 0); 129 m_levelUpload = sconfig.GetInt("LevelUpload", 0);
131 } 130 }
131
132 IConfig appearanceConfig = config.Configs["Appearance"];
133 if (appearanceConfig != null)
134 {
135 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
136 }
132 } 137 }
133 138
134 m_assetService = m_Scene.AssetService; 139 m_assetService = m_Scene.AssetService;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
new file mode 100644
index 0000000..36af55f
--- /dev/null
+++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
@@ -0,0 +1,234 @@
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;
30using System.Collections.Generic;
31using System.Collections.Specialized;
32using System.Drawing;
33using System.Drawing.Imaging;
34using System.Reflection;
35using System.IO;
36using System.Web;
37using log4net;
38using Nini.Config;
39using Mono.Addins;
40using OpenMetaverse;
41using OpenMetaverse.StructuredData;
42using OpenMetaverse.Imaging;
43using OpenSim.Framework;
44using OpenSim.Framework.Console;
45using OpenSim.Framework.Servers;
46using OpenSim.Framework.Servers.HttpServer;
47using OpenSim.Region.Framework.Interfaces;
48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Services.Interfaces;
50using Caps = OpenSim.Framework.Capabilities.Caps;
51using OpenSim.Capabilities.Handlers;
52
53namespace OpenSim.Region.ClientStack.Linden
54{
55
56 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RegionConsoleModule")]
57 public class RegionConsoleModule : INonSharedRegionModule, IRegionConsole
58 {
59 private static readonly ILog m_log =
60 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
61
62 private Scene m_scene;
63 private IEventQueue m_eventQueue;
64 private Commands m_commands = new Commands();
65 public ICommands Commands { get { return m_commands; } }
66
67 public void Initialise(IConfigSource source)
68 {
69 m_commands.AddCommand( "Help", false, "help", "help [<item>]", "Display help on a particular command or on a list of commands in a category", Help);
70 }
71
72 public void AddRegion(Scene s)
73 {
74 m_scene = s;
75 m_scene.RegisterModuleInterface<IRegionConsole>(this);
76 }
77
78 public void RemoveRegion(Scene s)
79 {
80 m_scene.EventManager.OnRegisterCaps -= RegisterCaps;
81 m_scene = null;
82 }
83
84 public void RegionLoaded(Scene s)
85 {
86 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
87 m_eventQueue = m_scene.RequestModuleInterface<IEventQueue>();
88 }
89
90 public void PostInitialise()
91 {
92 }
93
94 public void Close() { }
95
96 public string Name { get { return "RegionConsoleModule"; } }
97
98 public Type ReplaceableInterface
99 {
100 get { return null; }
101 }
102
103 public void RegisterCaps(UUID agentID, Caps caps)
104 {
105 if (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(agentID))
106 return;
107
108 UUID capID = UUID.Random();
109
110 m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName);
111 caps.RegisterHandler(
112 "SimConsoleAsync",
113 new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene));
114 }
115
116 public void SendConsoleOutput(UUID agentID, string message)
117 {
118 OSD osd = OSD.FromString(message);
119
120 m_eventQueue.Enqueue(EventQueueHelper.BuildEvent("SimConsoleResponse", osd), agentID);
121 }
122
123 public bool RunCommand(string command, UUID invokerID)
124 {
125 string[] parts = Parser.Parse(command);
126 Array.Resize(ref parts, parts.Length + 1);
127 parts[parts.Length - 1] = invokerID.ToString();
128
129 if (m_commands.Resolve(parts).Length == 0)
130 return false;
131
132 return true;
133 }
134
135 private void Help(string module, string[] cmd)
136 {
137 UUID agentID = new UUID(cmd[cmd.Length - 1]);
138 Array.Resize(ref cmd, cmd.Length - 1);
139
140 List<string> help = Commands.GetHelp(cmd);
141
142 string reply = String.Empty;
143
144 foreach (string s in help)
145 {
146 reply += s + "\n";
147 }
148
149 SendConsoleOutput(agentID, reply);
150 }
151
152 public void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn)
153 {
154 m_commands.AddCommand(module, shared, command, help, longhelp, fn);
155 }
156 }
157
158 public class ConsoleHandler : BaseStreamHandler
159 {
160 private static readonly ILog m_log =
161 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
162
163 private RegionConsoleModule m_consoleModule;
164 private UUID m_agentID;
165 private bool m_isGod;
166 private Scene m_scene;
167 private bool m_consoleIsOn = false;
168
169 public ConsoleHandler(string path, string name, UUID agentID, RegionConsoleModule module, Scene scene)
170 :base("POST", path, name, agentID.ToString())
171 {
172 m_agentID = agentID;
173 m_consoleModule = module;
174 m_scene = scene;
175
176 m_isGod = m_scene.Permissions.IsGod(agentID);
177 }
178
179 public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse)
180 {
181 StreamReader reader = new StreamReader(request);
182 string message = reader.ReadToEnd();
183
184 OSD osd = OSDParser.DeserializeLLSDXml(message);
185
186 string cmd = osd.AsString();
187 if (cmd == "set console on")
188 {
189 if (m_isGod)
190 {
191 MainConsole.Instance.OnOutput += ConsoleSender;
192 m_consoleIsOn = true;
193 m_consoleModule.SendConsoleOutput(m_agentID, "Console is now on");
194 }
195 return new byte[0];
196 }
197 else if (cmd == "set console off")
198 {
199 MainConsole.Instance.OnOutput -= ConsoleSender;
200 m_consoleIsOn = false;
201 m_consoleModule.SendConsoleOutput(m_agentID, "Console is now off");
202 return new byte[0];
203 }
204
205 if (m_consoleIsOn == false && m_consoleModule.RunCommand(osd.AsString().Trim(), m_agentID))
206 return new byte[0];
207
208 if (m_isGod && m_consoleIsOn)
209 {
210 MainConsole.Instance.RunCommand(osd.AsString().Trim());
211 }
212 else
213 {
214 m_consoleModule.SendConsoleOutput(m_agentID, "Unknown command");
215 }
216
217 return new byte[0];
218 }
219
220 private void ConsoleSender(string text)
221 {
222 m_consoleModule.SendConsoleOutput(m_agentID, text);
223 }
224
225 private void OnMakeChildAgent(ScenePresence presence)
226 {
227 if (presence.UUID == m_agentID)
228 {
229 MainConsole.Instance.OnOutput -= ConsoleSender;
230 m_consoleIsOn = false;
231 }
232 }
233 }
234}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
index b3d61a8..6aac591 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
@@ -66,9 +66,9 @@ namespace OpenSim.Region.ClientStack.Linden
66 66
67 public void Initialise(IConfigSource source) 67 public void Initialise(IConfigSource source)
68 { 68 {
69 IConfig sconfig = source.Configs["Startup"]; 69 IConfig appearanceConfig = source.Configs["Appearance"];
70 if (sconfig != null) 70 if (appearanceConfig != null)
71 m_persistBakedTextures = sconfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); 71 m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
72 } 72 }
73 73
74 public void AddRegion(Scene s) 74 public void AddRegion(Scene s)
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index b588704..88ca9db 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -284,7 +284,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
284 sp.ClearAttachments(); 284 sp.ClearAttachments();
285 } 285 }
286 286
287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData) 287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp)
288 { 288 {
289 lock (sp.AttachmentsSyncLock) 289 lock (sp.AttachmentsSyncLock)
290 { 290 {
@@ -361,7 +361,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
361 group.AbsolutePosition = attachPos; 361 group.AbsolutePosition = attachPos;
362 362
363 if (sp.PresenceType != PresenceType.Npc) 363 if (sp.PresenceType != PresenceType.Npc)
364 UpdateUserInventoryWithAttachment(sp, group, attachmentPt); 364 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp);
365 365
366 AttachToAgent(sp, group, attachmentPt, attachPos, silent); 366 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
367 } 367 }
@@ -369,7 +369,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
369 return true; 369 return true;
370 } 370 }
371 371
372 private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt) 372 private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool temp)
373 { 373 {
374 // Remove any previous attachments 374 // Remove any previous attachments
375 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); 375 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
@@ -379,18 +379,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
379 { 379 {
380 if (attachments[0].FromItemID != UUID.Zero) 380 if (attachments[0].FromItemID != UUID.Zero)
381 DetachSingleAttachmentToInvInternal(sp, attachments[0]); 381 DetachSingleAttachmentToInvInternal(sp, attachments[0]);
382 else 382 // Error logging commented because UUID.Zero now means temp attachment
383 m_log.WarnFormat( 383// else
384 "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!", 384// m_log.WarnFormat(
385 attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); 385// "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
386// attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
386 } 387 }
387 388
388 // Add the new attachment to inventory if we don't already have it. 389 // Add the new attachment to inventory if we don't already have it.
389 UUID newAttachmentItemID = group.FromItemID; 390 if (!temp)
390 if (newAttachmentItemID == UUID.Zero) 391 {
391 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID; 392 UUID newAttachmentItemID = group.FromItemID;
393 if (newAttachmentItemID == UUID.Zero)
394 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
392 395
393 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); 396 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
397 }
394 } 398 }
395 399
396 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) 400 public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
@@ -474,6 +478,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
474 478
475 UUID inventoryID = so.FromItemID; 479 UUID inventoryID = so.FromItemID;
476 480
481 // As per Linden spec, drop is disabled for temp attachs
482 if (inventoryID == UUID.Zero)
483 return;
484
477// m_log.DebugFormat( 485// m_log.DebugFormat(
478// "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}", 486// "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}",
479// so.Name, so.LocalId, inventoryID); 487// so.Name, so.LocalId, inventoryID);
@@ -484,7 +492,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
484 so.PrimCount, sp.UUID, sp.AbsolutePosition)) 492 so.PrimCount, sp.UUID, sp.AbsolutePosition))
485 return; 493 return;
486 494
487 bool changed = sp.Appearance.DetachAttachment(inventoryID); 495 bool changed = false;
496 if (inventoryID != UUID.Zero)
497 changed = sp.Appearance.DetachAttachment(inventoryID);
488 if (changed && m_scene.AvatarFactory != null) 498 if (changed && m_scene.AvatarFactory != null)
489 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); 499 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
490 500
@@ -516,6 +526,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
516 526
517 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) 527 public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so)
518 { 528 {
529 // As per Linden spec, detach (take) is disabled for temp attachs
530 if (so.FromItemID == UUID.Zero)
531 return;
532
519 lock (sp.AttachmentsSyncLock) 533 lock (sp.AttachmentsSyncLock)
520 { 534 {
521 // Save avatar attachment information 535 // Save avatar attachment information
@@ -589,6 +603,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
589 /// <param name="saveAllScripted"></param> 603 /// <param name="saveAllScripted"></param>
590 private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, string scriptedState) 604 private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, string scriptedState)
591 { 605 {
606 if (grp.FromItemID == UUID.Zero)
607 {
608 // We can't save temp attachments
609 grp.HasGroupChanged = false;
610 return;
611 }
612
592 // Saving attachments for NPCs messes them up for the real owner! 613 // Saving attachments for NPCs messes them up for the real owner!
593 INPCModule module = m_scene.RequestModuleInterface<INPCModule>(); 614 INPCModule module = m_scene.RequestModuleInterface<INPCModule>();
594 if (module != null) 615 if (module != null)
@@ -845,7 +866,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
845 // This will throw if the attachment fails 866 // This will throw if the attachment fails
846 try 867 try
847 { 868 {
848 AttachObject(sp, objatt, attachmentPt, false, false); 869 AttachObject(sp, objatt, attachmentPt, false, false, false);
849 } 870 }
850 catch (Exception e) 871 catch (Exception e)
851 { 872 {
@@ -1005,7 +1026,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1005 AttachmentPt &= 0x7f; 1026 AttachmentPt &= 0x7f;
1006 1027
1007 // Calls attach with a Zero position 1028 // Calls attach with a Zero position
1008 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true)) 1029 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, false))
1009 { 1030 {
1010// m_log.Debug( 1031// m_log.Debug(
1011// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId 1032// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 273e290..d9a619d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -189,7 +189,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
189 189
190 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); 190 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
191 191
192 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false); 192 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false);
193 193
194 // Check status on scene presence 194 // Check status on scene presence
195 Assert.That(sp.HasAttachments(), Is.True); 195 Assert.That(sp.HasAttachments(), Is.True);
@@ -243,7 +243,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
243 sp2.AbsolutePosition = new Vector3(0, 0, 0); 243 sp2.AbsolutePosition = new Vector3(0, 0, 0);
244 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); 244 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
245 245
246 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false); 246 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false);
247 247
248 Assert.That(sp.HasAttachments(), Is.False); 248 Assert.That(sp.HasAttachments(), Is.False);
249 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 249 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 89cc4f6..bd7bd82 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -66,11 +66,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
66 scene.RegisterModuleInterface<IAvatarFactoryModule>(this); 66 scene.RegisterModuleInterface<IAvatarFactoryModule>(this);
67 scene.EventManager.OnNewClient += SubscribeToClientEvents; 67 scene.EventManager.OnNewClient += SubscribeToClientEvents;
68 68
69 IConfig sconfig = config.Configs["Startup"]; 69 IConfig appearanceConfig = config.Configs["Appearance"];
70 if (sconfig != null) 70 if (appearanceConfig != null)
71 { 71 {
72 m_savetime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime))); 72 m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
73 m_sendtime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime))); 73 m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime)));
74 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime); 74 // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime);
75 } 75 }
76 76
diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
index ae4d52a..8b2f2f8 100644
--- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs
@@ -596,9 +596,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
596 } 596 }
597 break; 597 break;
598 case "R": 598 case "R":
599 Font anewFont = new Font(myFont, FontStyle.Regular); 599 // We need to place this newFont inside its own context so that the .NET compiler
600 myFont.Dispose(); 600 // doesn't complain about a redefinition of an existing newFont, even though there is none
601 myFont = anewFont; 601 // The mono compiler doesn't produce this error.
602 {
603 Font newFont = new Font(myFont, FontStyle.Regular);
604 myFont.Dispose();
605 myFont = newFont;
606 }
602 break; 607 break;
603 } 608 }
604 } 609 }
@@ -768,4 +773,4 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
768 return null; 773 return null;
769 } 774 }
770 } 775 }
771} \ No newline at end of file 776}
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
index 9484a5a..25ee4c6 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Authentication/LocalAuthenticationServiceConnector.cs
@@ -137,6 +137,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication
137 137
138 #region IAuthenticationService 138 #region IAuthenticationService
139 139
140 public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
141 {
142 // Not implemented at the regions
143 return string.Empty;
144 }
145
140 public string Authenticate(UUID principalID, string password, int lifetime) 146 public string Authenticate(UUID principalID, string password, int lifetime)
141 { 147 {
142 // Not implemented at the regions 148 // Not implemented at the regions
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs
index c179a34..0780d86 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs
@@ -124,7 +124,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
124 LandData landData = lo.LandData; 124 LandData landData = lo.LandData;
125 string landDataPath = String.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH, 125 string landDataPath = String.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH,
126 landData.GlobalID.ToString()); 126 landData.GlobalID.ToString());
127 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData)); 127 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
128 } 128 }
129 129
130 m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive."); 130 m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive.");
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index 11a13e1..90a13a7 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Region.Framework.Interfaces
84 /// <param name="AttachmentPt"></param> 84 /// <param name="AttachmentPt"></param>
85 /// <param name="silent"></param> 85 /// <param name="silent"></param>
86 /// <returns>true if the object was successfully attached, false otherwise</returns> 86 /// <returns>true if the object was successfully attached, false otherwise</returns>
87 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo); 87 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo, bool temp);
88 88
89 /// <summary> 89 /// <summary>
90 /// Rez an attachment from user inventory and change inventory status to match. 90 /// Rez an attachment from user inventory and change inventory status to match.
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs b/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs
new file mode 100644
index 0000000..4d261d6
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs
@@ -0,0 +1,39 @@
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 OpenMetaverse;
29using OpenSim.Framework;
30
31namespace OpenSim.Region.Framework.Interfaces
32{
33 public interface IRegionConsole
34 {
35 bool RunCommand(string command, UUID invokerID);
36 void SendConsoleOutput(UUID agentID, string message);
37 void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn);
38 }
39}
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
index ccb583d..3e97a7a 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
@@ -117,5 +117,11 @@ namespace OpenSim.Region.Framework.Interfaces
117 void RemoveRegionEnvironmentSettings(UUID regionUUID); 117 void RemoveRegionEnvironmentSettings(UUID regionUUID);
118 118
119 UUID[] GetObjectIDs(UUID regionID); 119 UUID[] GetObjectIDs(UUID regionID);
120
121 void SaveExtra(UUID regionID, string name, string value);
122
123 void RemoveExtra(UUID regionID, string name);
124
125 Dictionary<string, string> GetExtra(UUID regionID);
120 } 126 }
121} 127}
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
index d7c80f7..17bd48b 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
@@ -128,6 +128,12 @@ namespace OpenSim.Region.Framework.Interfaces
128 /// <param name="regionUUID">the region UUID</param> 128 /// <param name="regionUUID">the region UUID</param>
129 void RemoveRegionEnvironmentSettings(UUID regionUUID); 129 void RemoveRegionEnvironmentSettings(UUID regionUUID);
130 130
131 void SaveExtra(UUID regionID, string name, string val);
132
133 void RemoveExtra(UUID regionID, string name);
134
135 Dictionary<string, string> GetExtra(UUID regionID);
136
131 void Shutdown(); 137 void Shutdown();
132 } 138 }
133} 139}
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 7cb3811..eee5960 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -217,6 +217,9 @@ namespace OpenSim.Region.Framework.Scenes
217 /// </remarks> 217 /// </remarks>
218 public event NewScript OnNewScript; 218 public event NewScript OnNewScript;
219 219
220 public delegate void ExtraSettingChangedDelegate(Scene scene, string name, string value);
221 public event ExtraSettingChangedDelegate OnExtraSettingChanged;
222
220 public virtual void TriggerNewScript(UUID clientID, SceneObjectPart part, UUID itemID) 223 public virtual void TriggerNewScript(UUID clientID, SceneObjectPart part, UUID itemID)
221 { 224 {
222 NewScript handlerNewScript = OnNewScript; 225 NewScript handlerNewScript = OnNewScript;
@@ -2616,5 +2619,25 @@ namespace OpenSim.Region.Framework.Scenes
2616 } 2619 }
2617 } 2620 }
2618 2621
2622 public void TriggerExtraSettingChanged(Scene scene, string name, string val)
2623 {
2624 ExtraSettingChangedDelegate handler = OnExtraSettingChanged;
2625
2626 if (handler != null)
2627 {
2628 foreach (ExtraSettingChangedDelegate d in handler.GetInvocationList())
2629 {
2630 try
2631 {
2632 d(scene, name, val);
2633 }
2634 catch (Exception e)
2635 {
2636 m_log.ErrorFormat("[EVENT MANAGER]: Delegate for ExtraSettingChanged failed - continuing {0} - {1}",
2637 e.Message, e.StackTrace);
2638 }
2639 }
2640 }
2641 }
2619 } 2642 }
2620} 2643}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 3db7c7d..a5f0bff 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -177,6 +177,8 @@ namespace OpenSim.Region.Framework.Scenes
177 protected ICapabilitiesModule m_capsModule; 177 protected ICapabilitiesModule m_capsModule;
178 protected IGroupsModule m_groupsModule; 178 protected IGroupsModule m_groupsModule;
179 179
180 private Dictionary<string, string> m_extraSettings;
181
180 /// <summary> 182 /// <summary>
181 /// Current scene frame number 183 /// Current scene frame number
182 /// </summary> 184 /// </summary>
@@ -658,6 +660,8 @@ namespace OpenSim.Region.Framework.Scenes
658 // FIXME: It shouldn't be up to the database plugins to create this data - we should do it when a new 660 // FIXME: It shouldn't be up to the database plugins to create this data - we should do it when a new
659 // region is set up and avoid these gyrations. 661 // region is set up and avoid these gyrations.
660 RegionSettings rs = simDataService.LoadRegionSettings(RegionInfo.RegionID); 662 RegionSettings rs = simDataService.LoadRegionSettings(RegionInfo.RegionID);
663 m_extraSettings = simDataService.GetExtra(RegionInfo.RegionID);
664
661 bool updatedTerrainTextures = false; 665 bool updatedTerrainTextures = false;
662 if (rs.TerrainTexture1 == UUID.Zero) 666 if (rs.TerrainTexture1 == UUID.Zero)
663 { 667 {
@@ -842,7 +846,6 @@ namespace OpenSim.Region.Framework.Scenes
842 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences); 846 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
843 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); 847 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
844 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); 848 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
845 SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates);
846 } 849 }
847 } 850 }
848 catch (Exception e) 851 catch (Exception e)
@@ -850,6 +853,14 @@ namespace OpenSim.Region.Framework.Scenes
850 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString()); 853 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
851 } 854 }
852 855
856 // FIXME: Ultimately this should be in a module.
857 IConfig appearanceConfig = m_config.Configs["Appearance"];
858 if (appearanceConfig != null)
859 {
860 SendPeriodicAppearanceUpdates
861 = appearanceConfig.GetBoolean("ResendAppearanceUpdates", SendPeriodicAppearanceUpdates);
862 }
863
853 #endregion Region Config 864 #endregion Region Config
854 865
855 #region Interest Management 866 #region Interest Management
@@ -2748,7 +2759,7 @@ namespace OpenSim.Region.Framework.Scenes
2748 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2759 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2749 2760
2750 if (AttachmentsModule != null) 2761 if (AttachmentsModule != null)
2751 AttachmentsModule.AttachObject(sp, grp, 0, false, false); 2762 AttachmentsModule.AttachObject(sp, grp, 0, false, false, false);
2752 } 2763 }
2753 else 2764 else
2754 { 2765 {
@@ -5843,5 +5854,44 @@ Environment.Exit(1);
5843 5854
5844 callback(asset); 5855 callback(asset);
5845 } 5856 }
5857
5858 public string GetExtraSetting(string name)
5859 {
5860 string val;
5861
5862 if (!m_extraSettings.TryGetValue(name, out val))
5863 return String.Empty;
5864
5865 return val;
5866 }
5867
5868 public void StoreExtraSetting(string name, string val)
5869 {
5870 string oldVal;
5871
5872 if (m_extraSettings.TryGetValue(name, out oldVal))
5873 {
5874 if (oldVal == val)
5875 return;
5876 }
5877
5878 m_extraSettings[name] = val;
5879
5880 m_SimulationDataService.SaveExtra(RegionInfo.RegionID, name, val);
5881
5882 m_eventManager.TriggerExtraSettingChanged(this, name, val);
5883 }
5884
5885 public void RemoveExtraSetting(string name)
5886 {
5887 if (!m_extraSettings.ContainsKey(name))
5888 return;
5889
5890 m_extraSettings.Remove(name);
5891
5892 m_SimulationDataService.RemoveExtra(RegionInfo.RegionID, name);
5893
5894 m_eventManager.TriggerExtraSettingChanged(this, name, String.Empty);
5895 }
5846 } 5896 }
5847} 5897}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e0260e2..e29b2c1 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -1793,7 +1793,6 @@ namespace OpenSim.Region.Framework.Scenes
1793 1793
1794 try 1794 try
1795 { 1795 {
1796 parentGroup.areUpdatesSuspended = true;
1797 1796
1798 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1797 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1799 1798
@@ -1850,7 +1849,6 @@ namespace OpenSim.Region.Framework.Scenes
1850 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup; 1849 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1851 } 1850 }
1852 1851
1853 parentGroup.areUpdatesSuspended = false;
1854 parentGroup.HasGroupChanged = true; 1852 parentGroup.HasGroupChanged = true;
1855 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); 1853 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1856 parentGroup.ScheduleGroupForFullUpdate(); 1854 parentGroup.ScheduleGroupForFullUpdate();
@@ -1896,7 +1894,6 @@ namespace OpenSim.Region.Framework.Scenes
1896 SceneObjectGroup group = part.ParentGroup; 1894 SceneObjectGroup group = part.ParentGroup;
1897 if (!affectedGroups.Contains(group)) 1895 if (!affectedGroups.Contains(group))
1898 { 1896 {
1899 group.areUpdatesSuspended = true;
1900 affectedGroups.Add(group); 1897 affectedGroups.Add(group);
1901 } 1898 }
1902 } 1899 }
@@ -1922,7 +1919,6 @@ namespace OpenSim.Region.Framework.Scenes
1922 // However, editing linked parts and unlinking may be different 1919 // However, editing linked parts and unlinking may be different
1923 // 1920 //
1924 SceneObjectGroup group = root.ParentGroup; 1921 SceneObjectGroup group = root.ParentGroup;
1925 group.areUpdatesSuspended = true;
1926 1922
1927 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1923 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1928 int numChildren = newSet.Count; 1924 int numChildren = newSet.Count;
@@ -1945,7 +1941,6 @@ namespace OpenSim.Region.Framework.Scenes
1945 group.DelinkFromGroup(p, sendEventsToRemainder); 1941 group.DelinkFromGroup(p, sendEventsToRemainder);
1946 if (numChildren > 2) 1942 if (numChildren > 2)
1947 { 1943 {
1948 p.ParentGroup.areUpdatesSuspended = true;
1949 } 1944 }
1950 else 1945 else
1951 { 1946 {
@@ -1980,7 +1975,6 @@ namespace OpenSim.Region.Framework.Scenes
1980 foreach (SceneObjectPart newChild in newSet) 1975 foreach (SceneObjectPart newChild in newSet)
1981 newChild.ClearUpdateSchedule(); 1976 newChild.ClearUpdateSchedule();
1982 1977
1983 newRoot.ParentGroup.areUpdatesSuspended = true;
1984 LinkObjects(newRoot, newSet); 1978 LinkObjects(newRoot, newSet);
1985 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1979 if (!affectedGroups.Contains(newRoot.ParentGroup))
1986 affectedGroups.Add(newRoot.ParentGroup); 1980 affectedGroups.Add(newRoot.ParentGroup);
@@ -1998,7 +1992,6 @@ namespace OpenSim.Region.Framework.Scenes
1998 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); 1992 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1999 g.TriggerScriptChangedEvent(Changed.LINK); 1993 g.TriggerScriptChangedEvent(Changed.LINK);
2000 g.HasGroupChanged = true; // Persist 1994 g.HasGroupChanged = true; // Persist
2001 g.areUpdatesSuspended = false;
2002 g.ScheduleGroupForFullUpdate(); 1995 g.ScheduleGroupForFullUpdate();
2003 } 1996 }
2004 } 1997 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index d51281d..6104c66 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -113,25 +113,8 @@ namespace OpenSim.Region.Framework.Scenes
113 private long m_maxPersistTime = 0; 113 private long m_maxPersistTime = 0;
114 private long m_minPersistTime = 0; 114 private long m_minPersistTime = 0;
115 private Random m_rand; 115 private Random m_rand;
116 private bool m_suspendUpdates;
117 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>(); 116 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
118 117
119 public bool areUpdatesSuspended
120 {
121 get
122 {
123 return m_suspendUpdates;
124 }
125 set
126 {
127 m_suspendUpdates = value;
128 if (!value)
129 {
130 QueueForUpdateCheck();
131 }
132 }
133 }
134
135 /// <summary> 118 /// <summary>
136 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage 119 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage
137 /// (the database). 120 /// (the database).
@@ -951,7 +934,7 @@ namespace OpenSim.Region.Framework.Scenes
951 /// its existing localID and UUID. 934 /// its existing localID and UUID.
952 /// </summary> 935 /// </summary>
953 /// <param name='part'>Root part for this scene object.</param> 936 /// <param name='part'>Root part for this scene object.</param>
954 public SceneObjectGroup(SceneObjectPart part) 937 public SceneObjectGroup(SceneObjectPart part) : this()
955 { 938 {
956 SetRootPart(part); 939 SetRootPart(part);
957 } 940 }
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
new file mode 100644
index 0000000..417b620
--- /dev/null
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
@@ -0,0 +1,189 @@
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.Linq;
31using System.Reflection;
32using System.Text;
33using log4net;
34using Mono.Addins;
35using Nini.Config;
36using OpenMetaverse;
37using OpenSim.Framework;
38using OpenSim.Framework.Console;
39using OpenSim.Framework.Monitoring;
40using OpenSim.Region.ClientStack.LindenUDP;
41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes;
43
44namespace OpenSim.Region.OptionalModules.Avatar.Attachments
45{
46 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TempAttachmentsModule")]
47 public class TempAttachmentsModule : INonSharedRegionModule
48 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50
51 private Scene m_scene;
52 private IRegionConsole m_console;
53
54 public void Initialise(IConfigSource configSource)
55 {
56 }
57
58 public void AddRegion(Scene scene)
59 {
60 }
61
62 public void RemoveRegion(Scene scene)
63 {
64 }
65
66 public void RegionLoaded(Scene scene)
67 {
68 m_scene = scene;
69
70 IScriptModuleComms comms = scene.RequestModuleInterface<IScriptModuleComms>();
71 if (comms != null)
72 {
73 comms.RegisterScriptInvocation( this, "llAttachToAvatarTemp");
74 m_log.DebugFormat("[TEMP ATTACHS]: Registered script functions");
75 m_console = scene.RequestModuleInterface<IRegionConsole>();
76
77 if (m_console != null)
78 {
79 m_console.AddCommand("TempATtachModule", false, "set auto_grant_attach_perms", "set auto_grant_attach_perms true|false", "Allow objects owned by the region owner os estate managers to obtain attach permissions without asking the user", SetAutoGrantAttachPerms);
80 }
81 }
82 else
83 {
84 m_log.ErrorFormat("[TEMP ATTACHS]: Failed to register script functions");
85 }
86 }
87
88 public void Close()
89 {
90 }
91
92 public Type ReplaceableInterface
93 {
94 get { return null; }
95 }
96
97 public string Name
98 {
99 get { return "TempAttachmentsModule"; }
100 }
101
102 private void SendConsoleOutput(UUID agentID, string text)
103 {
104 if (m_console == null)
105 return;
106
107 m_console.SendConsoleOutput(agentID, text);
108 }
109
110 private void SetAutoGrantAttachPerms(string module, string[] parms)
111 {
112 UUID agentID = new UUID(parms[parms.Length - 1]);
113 Array.Resize(ref parms, parms.Length - 1);
114
115 if (parms.Length != 3)
116 {
117 SendConsoleOutput(agentID, "Command parameter error");
118 return;
119 }
120
121 string val = parms[2];
122 if (val != "true" && val != "false")
123 {
124 SendConsoleOutput(agentID, "Command parameter error");
125 return;
126 }
127
128 m_scene.StoreExtraSetting("auto_grant_attach_perms", val);
129
130 SendConsoleOutput(agentID, String.Format("auto_grant_attach_perms set to {0}", val));
131 }
132
133 private void llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint)
134 {
135 SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host);
136
137 if (hostPart == null)
138 return;
139
140 if (hostPart.ParentGroup.IsAttachment)
141 return;
142
143 IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface<IAttachmentsModule>();
144 if (attachmentsModule == null)
145 return;
146
147 TaskInventoryItem item = hostPart.Inventory.GetInventoryItem(script);
148 if (item == null)
149 return;
150
151 if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH
152 return;
153
154 ScenePresence target;
155 if (!m_scene.TryGetScenePresence(item.PermsGranter, out target))
156 return;
157
158 if (target.UUID != hostPart.ParentGroup.OwnerID)
159 {
160 uint effectivePerms = hostPart.ParentGroup.GetEffectivePermissions();
161
162 if ((effectivePerms & (uint)PermissionMask.Transfer) == 0)
163 return;
164
165 hostPart.ParentGroup.SetOwnerId(target.UUID);
166 hostPart.ParentGroup.SetRootPartOwner(hostPart.ParentGroup.RootPart, target.UUID, target.ControllingClient.ActiveGroupId);
167
168 if (m_scene.Permissions.PropagatePermissions())
169 {
170 foreach (SceneObjectPart child in hostPart.ParentGroup.Parts)
171 {
172 child.Inventory.ChangeInventoryOwner(target.UUID);
173 child.TriggerScriptChangedEvent(Changed.OWNER);
174 child.ApplyNextOwnerPermissions();
175 }
176 }
177
178 hostPart.ParentGroup.RootPart.ObjectSaleType = 0;
179 hostPart.ParentGroup.RootPart.SalePrice = 10;
180
181 hostPart.ParentGroup.HasGroupChanged = true;
182 hostPart.ParentGroup.RootPart.SendPropertiesToClient(target.ControllingClient);
183 hostPart.ParentGroup.RootPart.ScheduleFullUpdate();
184 }
185
186 attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true);
187 }
188 }
189}
diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
index 396d4c5..a30a38d 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs
@@ -469,8 +469,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
469 avatarName = avatar.Name; 469 avatarName = avatar.Name;
470 470
471 m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: scene = {0}, agentID = {1}", scene, agentID); 471 m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: scene = {0}, agentID = {1}", scene, agentID);
472 m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}", 472// m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}",
473 request, path, param); 473// request, path, param);
474 474
475 XmlElement resp; 475 XmlElement resp;
476 bool retry = false; 476 bool retry = false;
@@ -577,7 +577,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
577 577
578 string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse); 578 string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
579 579
580 m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r); 580// m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r);
581 581
582 return r; 582 return r;
583 } 583 }
@@ -625,8 +625,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
625 // voice channel 625 // voice channel
626 LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 626 LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
627 627
628 m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", 628// m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}",
629 scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); 629// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param);
630 // m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: avatar \"{0}\": location: {1} {2} {3}", 630 // m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: avatar \"{0}\": location: {1} {2} {3}",
631 // avatarName, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); 631 // avatarName, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z);
632 632
@@ -656,8 +656,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
656 parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds); 656 parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds);
657 string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); 657 string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
658 658
659 m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}", 659// m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}",
660 scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r); 660// scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r);
661 return r; 661 return r;
662 } 662 }
663 catch (Exception e) 663 catch (Exception e)
@@ -684,11 +684,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
684 public string ChatSessionRequest(Scene scene, string request, string path, string param, 684 public string ChatSessionRequest(Scene scene, string request, string path, string param,
685 UUID agentID, Caps caps) 685 UUID agentID, Caps caps)
686 { 686 {
687 ScenePresence avatar = scene.GetScenePresence(agentID); 687// ScenePresence avatar = scene.GetScenePresence(agentID);
688 string avatarName = avatar.Name; 688// string avatarName = avatar.Name;
689 689
690 m_log.DebugFormat("[VivoxVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}", 690// m_log.DebugFormat("[VivoxVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}",
691 avatarName, request, path, param); 691// avatarName, request, path, param);
692 return "<llsd>true</llsd>"; 692 return "<llsd>true</llsd>";
693 } 693 }
694 694
@@ -1119,7 +1119,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
1119 try 1119 try
1120 { 1120 {
1121 // Otherwise prepare the request 1121 // Otherwise prepare the request
1122 m_log.DebugFormat("[VivoxVoice] Sending request <{0}>", requrl); 1122// m_log.DebugFormat("[VivoxVoice] Sending request <{0}>", requrl);
1123 1123
1124 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requrl); 1124 HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requrl);
1125 HttpWebResponse rsp = null; 1125 HttpWebResponse rsp = null;
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index b37aba3..f16927c 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -124,9 +124,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC
124 NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, owner, senseAsAgent, scene); 124 NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, owner, senseAsAgent, scene);
125 npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, int.MaxValue); 125 npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, int.MaxValue);
126 126
127 m_log.DebugFormat( 127// m_log.DebugFormat(
128 "[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}", 128// "[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}",
129 firstname, lastname, npcAvatar.AgentId, owner, senseAsAgent, position, scene.RegionInfo.RegionName); 129// firstname, lastname, npcAvatar.AgentId, owner, senseAsAgent, position, scene.RegionInfo.RegionName);
130 130
131 AgentCircuitData acd = new AgentCircuitData(); 131 AgentCircuitData acd = new AgentCircuitData();
132 acd.AgentID = npcAvatar.AgentId; 132 acd.AgentID = npcAvatar.AgentId;
@@ -157,7 +157,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
157 { 157 {
158 sp.CompleteMovement(npcAvatar, false); 158 sp.CompleteMovement(npcAvatar, false);
159 m_avatars.Add(npcAvatar.AgentId, npcAvatar); 159 m_avatars.Add(npcAvatar.AgentId, npcAvatar);
160 m_log.DebugFormat("[NPC MODULE]: Created NPC {0} {1}", npcAvatar.AgentId, sp.Name); 160// m_log.DebugFormat("[NPC MODULE]: Created NPC {0} {1}", npcAvatar.AgentId, sp.Name);
161 } 161 }
162 } 162 }
163 ev.Set(); 163 ev.Set();
@@ -177,16 +177,17 @@ namespace OpenSim.Region.OptionalModules.World.NPC
177 if (m_avatars.ContainsKey(agentID)) 177 if (m_avatars.ContainsKey(agentID))
178 { 178 {
179 ScenePresence sp; 179 ScenePresence sp;
180 scene.TryGetScenePresence(agentID, out sp); 180 if (scene.TryGetScenePresence(agentID, out sp))
181 181 {
182 m_log.DebugFormat( 182// m_log.DebugFormat(
183 "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}", 183// "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
184 sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget); 184// sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget);
185
186 sp.MoveToTarget(pos, noFly, landAtTarget);
187 sp.SetAlwaysRun = running;
188 185
189 return true; 186 sp.MoveToTarget(pos, noFly, landAtTarget);
187 sp.SetAlwaysRun = running;
188
189 return true;
190 }
190 } 191 }
191 } 192 }
192 193
@@ -200,12 +201,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC
200 if (m_avatars.ContainsKey(agentID)) 201 if (m_avatars.ContainsKey(agentID))
201 { 202 {
202 ScenePresence sp; 203 ScenePresence sp;
203 scene.TryGetScenePresence(agentID, out sp); 204 if (scene.TryGetScenePresence(agentID, out sp))
204 205 {
205 sp.Velocity = Vector3.Zero; 206 sp.Velocity = Vector3.Zero;
206 sp.ResetMoveToTarget(); 207 sp.ResetMoveToTarget();
207 208
208 return true; 209 return true;
210 }
209 } 211 }
210 } 212 }
211 213
@@ -223,9 +225,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
223 { 225 {
224 if (m_avatars.ContainsKey(agentID)) 226 if (m_avatars.ContainsKey(agentID))
225 { 227 {
226 ScenePresence sp;
227 scene.TryGetScenePresence(agentID, out sp);
228
229 m_avatars[agentID].Say(channel, text); 228 m_avatars[agentID].Say(channel, text);
230 229
231 return true; 230 return true;
@@ -241,9 +240,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
241 { 240 {
242 if (m_avatars.ContainsKey(agentID)) 241 if (m_avatars.ContainsKey(agentID))
243 { 242 {
244 ScenePresence sp;
245 scene.TryGetScenePresence(agentID, out sp);
246
247 m_avatars[agentID].Shout(channel, text); 243 m_avatars[agentID].Shout(channel, text);
248 244
249 return true; 245 return true;
@@ -260,11 +256,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC
260 if (m_avatars.ContainsKey(agentID)) 256 if (m_avatars.ContainsKey(agentID))
261 { 257 {
262 ScenePresence sp; 258 ScenePresence sp;
263 scene.TryGetScenePresence(agentID, out sp); 259 if (scene.TryGetScenePresence(agentID, out sp))
264 sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero); 260 {
265// sp.HandleAgentSit(m_avatars[agentID], agentID); 261 sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero);
266 262 // sp.HandleAgentSit(m_avatars[agentID], agentID);
267 return true; 263
264 return true;
265 }
268 } 266 }
269 } 267 }
270 268
@@ -277,9 +275,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
277 { 275 {
278 if (m_avatars.ContainsKey(agentID)) 276 if (m_avatars.ContainsKey(agentID))
279 { 277 {
280 ScenePresence sp;
281 scene.TryGetScenePresence(agentID, out sp);
282
283 m_avatars[agentID].Whisper(channel, text); 278 m_avatars[agentID].Whisper(channel, text);
284 279
285 return true; 280 return true;
@@ -296,10 +291,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC
296 if (m_avatars.ContainsKey(agentID)) 291 if (m_avatars.ContainsKey(agentID))
297 { 292 {
298 ScenePresence sp; 293 ScenePresence sp;
299 scene.TryGetScenePresence(agentID, out sp); 294 if (scene.TryGetScenePresence(agentID, out sp))
300 sp.StandUp(); 295 {
296 sp.StandUp();
301 297
302 return true; 298 return true;
299 }
303 } 300 }
304 } 301 }
305 302
@@ -312,6 +309,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
312 { 309 {
313 if (m_avatars.ContainsKey(agentID)) 310 if (m_avatars.ContainsKey(agentID))
314 return m_avatars[agentID].Touch(objectID); 311 return m_avatars[agentID].Touch(objectID);
312
315 return false; 313 return false;
316 } 314 }
317 } 315 }
@@ -322,9 +320,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
322 { 320 {
323 NPCAvatar av; 321 NPCAvatar av;
324 if (m_avatars.TryGetValue(agentID, out av)) 322 if (m_avatars.TryGetValue(agentID, out av))
325 {
326 return av.OwnerID; 323 return av.OwnerID;
327 }
328 } 324 }
329 325
330 return UUID.Zero; 326 return UUID.Zero;
@@ -352,7 +348,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
352 scene.RemoveClient(agentID, false); 348 scene.RemoveClient(agentID, false);
353 m_avatars.Remove(agentID); 349 m_avatars.Remove(agentID);
354 350
355 m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}", agentID, av.Name); 351// m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}", agentID, av.Name);
356 return true; 352 return true;
357 } 353 }
358 } 354 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
new file mode 100755
index 0000000..683bc51
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
@@ -0,0 +1,118 @@
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 class BS6DofConstraint : BSConstraint
36{
37 // Create a btGeneric6DofConstraint
38 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
39 Vector3 frame1, Quaternion frame1rot,
40 Vector3 frame2, Quaternion frame2rot,
41 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
42 {
43 m_world = world;
44 m_body1 = obj1;
45 m_body2 = obj2;
46 m_constraint = new BulletConstraint(
47 BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
48 frame1, frame1rot,
49 frame2, frame2rot,
50 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
51 m_enabled = true;
52 }
53
54 public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
55 Vector3 joinPoint,
56 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
57 {
58 m_world = world;
59 m_body1 = obj1;
60 m_body2 = obj2;
61 m_constraint = new BulletConstraint(
62 BulletSimAPI.Create6DofConstraintToPoint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
63 joinPoint,
64 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
65 m_enabled = true;
66 }
67
68 public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
69 {
70 bool ret = false;
71 if (m_enabled)
72 {
73 BulletSimAPI.SetFrames2(m_constraint.Ptr, frameA, frameArot, frameB, frameBrot);
74 ret = true;
75 }
76 return ret;
77 }
78
79 public bool SetCFMAndERP(float cfm, float erp)
80 {
81 bool ret = false;
82 if (m_enabled)
83 {
84 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
85 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
86 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
87 ret = true;
88 }
89 return ret;
90 }
91
92 public bool UseFrameOffset(bool useOffset)
93 {
94 bool ret = false;
95 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
96 if (m_enabled)
97 ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
98 return ret;
99 }
100
101 public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
102 {
103 bool ret = false;
104 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
105 if (m_enabled)
106 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
107 return ret;
108 }
109
110 public bool SetBreakingImpulseThreshold(float threshold)
111 {
112 bool ret = false;
113 if (m_enabled)
114 ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold);
115 return ret;
116 }
117}
118}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index 09e1f0c..e2f7af9 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -40,6 +40,7 @@ public class BSCharacter : PhysicsActor
40 private static readonly string LogHeader = "[BULLETS CHAR]"; 40 private static readonly string LogHeader = "[BULLETS CHAR]";
41 41
42 private BSScene _scene; 42 private BSScene _scene;
43 public BSScene Scene { get { return _scene; } }
43 private String _avName; 44 private String _avName;
44 // private bool _stopped; 45 // private bool _stopped;
45 private Vector3 _size; 46 private Vector3 _size;
@@ -73,6 +74,12 @@ public class BSCharacter : PhysicsActor
73 private bool _kinematic; 74 private bool _kinematic;
74 private float _buoyancy; 75 private float _buoyancy;
75 76
77 private BulletBody m_body;
78 public BulletBody Body {
79 get { return m_body; }
80 set { m_body = value; }
81 }
82
76 private int _subscribedEventsMs = 0; 83 private int _subscribedEventsMs = 0;
77 private int _nextCollisionOkTime = 0; 84 private int _nextCollisionOkTime = 0;
78 85
@@ -95,7 +102,9 @@ public class BSCharacter : PhysicsActor
95 _orientation = Quaternion.Identity; 102 _orientation = Quaternion.Identity;
96 _velocity = Vector3.Zero; 103 _velocity = Vector3.Zero;
97 _buoyancy = ComputeBuoyancyFromFlying(isFlying); 104 _buoyancy = ComputeBuoyancyFromFlying(isFlying);
98 _scale = new Vector3(1f, 1f, 1f); 105 // The dimensions of the avatar capsule are kept in the scale.
106 // Physics creates a unit capsule which is scaled by the physics engine.
107 _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z);
99 _density = _scene.Params.avatarDensity; 108 _density = _scene.Params.avatarDensity;
100 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale 109 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale
101 110
@@ -113,9 +122,13 @@ public class BSCharacter : PhysicsActor
113 shapeData.Restitution = _scene.Params.avatarRestitution; 122 shapeData.Restitution = _scene.Params.avatarRestitution;
114 123
115 // do actual create at taint time 124 // do actual create at taint time
116 _scene.TaintedObject(delegate() 125 _scene.TaintedObject("BSCharacter.create", delegate()
117 { 126 {
118 BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); 127 BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData);
128
129 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
130 // avatars get all collisions no matter what
131 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
119 }); 132 });
120 133
121 return; 134 return;
@@ -124,7 +137,8 @@ public class BSCharacter : PhysicsActor
124 // called when this character is being destroyed and the resources should be released 137 // called when this character is being destroyed and the resources should be released
125 public void Destroy() 138 public void Destroy()
126 { 139 {
127 _scene.TaintedObject(delegate() 140 // DetailLog("{0},BSCharacter.Destroy", LocalID);
141 _scene.TaintedObject("BSCharacter.destroy", delegate()
128 { 142 {
129 BulletSimAPI.DestroyObject(_scene.WorldID, _localID); 143 BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
130 }); 144 });
@@ -138,9 +152,28 @@ public class BSCharacter : PhysicsActor
138 public override bool Stopped { 152 public override bool Stopped {
139 get { return false; } 153 get { return false; }
140 } 154 }
141 public override Vector3 Size { 155 public override Vector3 Size {
142 get { return _size; } 156 get
143 set { _size = value; 157 {
158 // Avatar capsule size is kept in the scale parameter.
159 return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z);
160 }
161
162 set {
163 // When an avatar's size is set, only the height is changed
164 // and that really only depends on the radius.
165 _size = value;
166 _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y);
167
168 // TODO: something has to be done with the avatar's vertical position
169
170 ComputeAvatarVolumeAndMass();
171
172 _scene.TaintedObject("BSCharacter.setSize", delegate()
173 {
174 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true);
175 });
176
144 } 177 }
145 } 178 }
146 public override PrimitiveBaseShape Shape { 179 public override PrimitiveBaseShape Shape {
@@ -172,12 +205,37 @@ public class BSCharacter : PhysicsActor
172 } 205 }
173 set { 206 set {
174 _position = value; 207 _position = value;
175 _scene.TaintedObject(delegate() 208 PositionSanityCheck();
209
210 _scene.TaintedObject("BSCharacter.setPosition", delegate()
176 { 211 {
212 DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
177 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 213 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
178 }); 214 });
179 } 215 }
180 } 216 }
217
218 // Check that the current position is sane and, if not, modify the position to make it so.
219 // Check for being below terrain and being out of bounds.
220 // Returns 'true' of the position was made sane by some action.
221 private bool PositionSanityCheck()
222 {
223 bool ret = false;
224
225 // If below the ground, move the avatar up
226 float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position);
227 if (_position.Z < terrainHeight)
228 {
229 DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation);
230 _position.Z = terrainHeight + 2.0f;
231 ret = true;
232 }
233
234 // TODO: check for out of bounds
235
236 return ret;
237 }
238
181 public override float Mass { 239 public override float Mass {
182 get { 240 get {
183 return _mass; 241 return _mass;
@@ -188,9 +246,10 @@ public class BSCharacter : PhysicsActor
188 set { 246 set {
189 _force = value; 247 _force = value;
190 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); 248 // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
191 _scene.TaintedObject(delegate() 249 Scene.TaintedObject("BSCharacter.SetForce", delegate()
192 { 250 {
193 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 251 DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
252 BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force);
194 }); 253 });
195 } 254 }
196 } 255 }
@@ -214,8 +273,9 @@ public class BSCharacter : PhysicsActor
214 set { 273 set {
215 _velocity = value; 274 _velocity = value;
216 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); 275 // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
217 _scene.TaintedObject(delegate() 276 _scene.TaintedObject("BSCharacter.setVelocity", delegate()
218 { 277 {
278 DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
219 BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); 279 BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity);
220 }); 280 });
221 } 281 }
@@ -239,7 +299,7 @@ public class BSCharacter : PhysicsActor
239 set { 299 set {
240 _orientation = value; 300 _orientation = value;
241 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); 301 // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
242 _scene.TaintedObject(delegate() 302 _scene.TaintedObject("BSCharacter.setOrientation", delegate()
243 { 303 {
244 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 304 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
245 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 305 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
@@ -259,9 +319,12 @@ public class BSCharacter : PhysicsActor
259 public override bool Flying { 319 public override bool Flying {
260 get { return _flying; } 320 get { return _flying; }
261 set { 321 set {
262 _flying = value; 322 if (_flying != value)
263 // simulate flying by changing the effect of gravity 323 {
264 this.Buoyancy = ComputeBuoyancyFromFlying(_flying); 324 _flying = value;
325 // simulate flying by changing the effect of gravity
326 this.Buoyancy = ComputeBuoyancyFromFlying(_flying);
327 }
265 } 328 }
266 } 329 }
267 private float ComputeBuoyancyFromFlying(bool ifFlying) { 330 private float ComputeBuoyancyFromFlying(bool ifFlying) {
@@ -303,8 +366,9 @@ public class BSCharacter : PhysicsActor
303 public override float Buoyancy { 366 public override float Buoyancy {
304 get { return _buoyancy; } 367 get { return _buoyancy; }
305 set { _buoyancy = value; 368 set { _buoyancy = value;
306 _scene.TaintedObject(delegate() 369 _scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
307 { 370 {
371 DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
308 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); 372 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
309 }); 373 });
310 } 374 }
@@ -349,9 +413,10 @@ public class BSCharacter : PhysicsActor
349 _force.Y += force.Y; 413 _force.Y += force.Y;
350 _force.Z += force.Z; 414 _force.Z += force.Z;
351 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); 415 // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
352 _scene.TaintedObject(delegate() 416 _scene.TaintedObject("BSCharacter.AddForce", delegate()
353 { 417 {
354 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 418 DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
419 BulletSimAPI.AddObjectForce2(Body.Ptr, _force);
355 }); 420 });
356 } 421 }
357 else 422 else
@@ -369,11 +434,25 @@ public class BSCharacter : PhysicsActor
369 // Turn on collision events at a rate no faster than one every the given milliseconds 434 // Turn on collision events at a rate no faster than one every the given milliseconds
370 public override void SubscribeEvents(int ms) { 435 public override void SubscribeEvents(int ms) {
371 _subscribedEventsMs = ms; 436 _subscribedEventsMs = ms;
372 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen 437 if (ms > 0)
438 {
439 // make sure first collision happens
440 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
441
442 Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate()
443 {
444 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
445 });
446 }
373 } 447 }
374 // Stop collision events 448 // Stop collision events
375 public override void UnSubscribeEvents() { 449 public override void UnSubscribeEvents() {
376 _subscribedEventsMs = 0; 450 _subscribedEventsMs = 0;
451 // Avatars get all their collision events
452 // Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate()
453 // {
454 // BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
455 // });
377 } 456 }
378 // Return 'true' if someone has subscribed to events 457 // Return 'true' if someone has subscribed to events
379 public override bool SubscribedEvents() { 458 public override bool SubscribedEvents() {
@@ -385,9 +464,15 @@ public class BSCharacter : PhysicsActor
385 { 464 {
386 _avatarVolume = (float)( 465 _avatarVolume = (float)(
387 Math.PI 466 Math.PI
388 * _scene.Params.avatarCapsuleRadius * _scale.X 467 * _scale.X
389 * _scene.Params.avatarCapsuleRadius * _scale.Y 468 * _scale.Y // the area of capsule cylinder
390 * _scene.Params.avatarCapsuleHeight * _scale.Z); 469 * _scale.Z // times height of capsule cylinder
470 + 1.33333333f
471 * Math.PI
472 * _scale.X
473 * Math.Min(_scale.X, _scale.Y)
474 * _scale.Y // plus the volume of the capsule end caps
475 );
391 _mass = _density * _avatarVolume; 476 _mass = _density * _avatarVolume;
392 } 477 }
393 478
@@ -395,43 +480,19 @@ public class BSCharacter : PhysicsActor
395 // the world that things have changed. 480 // the world that things have changed.
396 public void UpdateProperties(EntityProperties entprop) 481 public void UpdateProperties(EntityProperties entprop)
397 { 482 {
398 /*
399 bool changed = false;
400 // we assign to the local variables so the normal set action does not happen
401 if (_position != entprop.Position) {
402 _position = entprop.Position;
403 changed = true;
404 }
405 if (_orientation != entprop.Rotation) {
406 _orientation = entprop.Rotation;
407 changed = true;
408 }
409 if (_velocity != entprop.Velocity) {
410 _velocity = entprop.Velocity;
411 changed = true;
412 }
413 if (_acceleration != entprop.Acceleration) {
414 _acceleration = entprop.Acceleration;
415 changed = true;
416 }
417 if (_rotationalVelocity != entprop.RotationalVelocity) {
418 _rotationalVelocity = entprop.RotationalVelocity;
419 changed = true;
420 }
421 if (changed) {
422 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
423 // Avatar movement is not done by generating this event. There is code in the heartbeat
424 // loop that updates avatars.
425 // base.RequestPhysicsterseUpdate();
426 }
427 */
428 _position = entprop.Position; 483 _position = entprop.Position;
429 _orientation = entprop.Rotation; 484 _orientation = entprop.Rotation;
430 _velocity = entprop.Velocity; 485 _velocity = entprop.Velocity;
431 _acceleration = entprop.Acceleration; 486 _acceleration = entprop.Acceleration;
432 _rotationalVelocity = entprop.RotationalVelocity; 487 _rotationalVelocity = entprop.RotationalVelocity;
433 // Avatars don't report theirr changes the usual way. Changes are checked for in the heartbeat loop. 488 // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
434 // base.RequestPhysicsterseUpdate(); 489 // base.RequestPhysicsterseUpdate();
490
491 /*
492 DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
493 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
494 entprop.Acceleration, entprop.RotationalVelocity);
495 */
435 } 496 }
436 497
437 // Called by the scene when a collision with this object is reported 498 // Called by the scene when a collision with this object is reported
@@ -448,6 +509,7 @@ public class BSCharacter : PhysicsActor
448 { 509 {
449 _collidingGroundStep = _scene.SimulationStep; 510 _collidingGroundStep = _scene.SimulationStep;
450 } 511 }
512 // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
451 513
452 // throttle collisions to the rate specified in the subscription 514 // throttle collisions to the rate specified in the subscription
453 if (_subscribedEventsMs != 0) { 515 if (_subscribedEventsMs != 0) {
@@ -476,9 +538,17 @@ public class BSCharacter : PhysicsActor
476 if (collisionCollection == null) 538 if (collisionCollection == null)
477 collisionCollection = new CollisionEventUpdate(); 539 collisionCollection = new CollisionEventUpdate();
478 base.SendCollisionUpdate(collisionCollection); 540 base.SendCollisionUpdate(collisionCollection);
479 collisionCollection.Clear(); 541 // If there were any collisions in the collection, make sure we don't use the
542 // same instance next time.
543 if (collisionCollection.Count > 0)
544 collisionCollection = null;
480 // End kludge 545 // End kludge
481 } 546 }
482 547
548 // Invoke the detailed logger and output something if it's enabled.
549 private void DetailLog(string msg, params Object[] args)
550 {
551 Scene.PhysicsLogging.Write(msg, args);
552 }
483} 553}
484} 554}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
index ea3093a..25084d8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -32,35 +32,26 @@ using OpenMetaverse;
32namespace OpenSim.Region.Physics.BulletSPlugin 32namespace OpenSim.Region.Physics.BulletSPlugin
33{ 33{
34 34
35public class BSConstraint : IDisposable 35public abstract class BSConstraint : IDisposable
36{ 36{
37 private BulletSim m_world; 37 protected BulletSim m_world;
38 private BulletBody m_body1; 38 protected BulletBody m_body1;
39 private BulletBody m_body2; 39 protected BulletBody m_body2;
40 private BulletConstraint m_constraint; 40 protected BulletConstraint m_constraint;
41 private bool m_enabled = false; 41 protected bool m_enabled = false;
42 42
43 public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, 43 public BSConstraint()
44 Vector3 frame1, Quaternion frame1rot,
45 Vector3 frame2, Quaternion frame2rot
46 )
47 { 44 {
48 m_world = world;
49 m_body1 = obj1;
50 m_body2 = obj2;
51 m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
52 frame1, frame1rot,
53 frame2, frame2rot,
54 true /*useLinearReferenceFrameA*/, true /*disableCollisionsBetweenLinkedBodies*/));
55 m_enabled = true;
56 } 45 }
57 46
58 public void Dispose() 47 public virtual void Dispose()
59 { 48 {
60 if (m_enabled) 49 if (m_enabled)
61 { 50 {
62 // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID); 51 // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
63 BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr); 52 bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
53 m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success);
54 m_constraint.Ptr = System.IntPtr.Zero;
64 m_enabled = false; 55 m_enabled = false;
65 } 56 }
66 } 57 }
@@ -68,7 +59,7 @@ public class BSConstraint : IDisposable
68 public BulletBody Body1 { get { return m_body1; } } 59 public BulletBody Body1 { get { return m_body1; } }
69 public BulletBody Body2 { get { return m_body2; } } 60 public BulletBody Body2 { get { return m_body2; } }
70 61
71 public bool SetLinearLimits(Vector3 low, Vector3 high) 62 public virtual bool SetLinearLimits(Vector3 low, Vector3 high)
72 { 63 {
73 bool ret = false; 64 bool ret = false;
74 if (m_enabled) 65 if (m_enabled)
@@ -76,7 +67,7 @@ public class BSConstraint : IDisposable
76 return ret; 67 return ret;
77 } 68 }
78 69
79 public bool SetAngularLimits(Vector3 low, Vector3 high) 70 public virtual bool SetAngularLimits(Vector3 low, Vector3 high)
80 { 71 {
81 bool ret = false; 72 bool ret = false;
82 if (m_enabled) 73 if (m_enabled)
@@ -84,40 +75,36 @@ public class BSConstraint : IDisposable
84 return ret; 75 return ret;
85 } 76 }
86 77
87 public bool SetCFMAndERP(float cfm, float erp) 78 public virtual bool CalculateTransforms()
88 {
89 bool ret = true;
90 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
91 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
92 BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
93 return ret;
94 }
95
96 public bool UseFrameOffset(bool useOffset)
97 {
98 bool ret = false;
99 float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
100 if (m_enabled)
101 ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
102 return ret;
103 }
104
105 public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
106 { 79 {
107 bool ret = false; 80 bool ret = false;
108 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
109 if (m_enabled) 81 if (m_enabled)
110 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); 82 {
83 // Recompute the internal transforms
84 BulletSimAPI.CalculateTransforms2(m_constraint.Ptr);
85 ret = true;
86 }
111 return ret; 87 return ret;
112 } 88 }
113 89
114 public bool CalculateTransforms() 90 // Reset this constraint making sure it has all its internal structures
91 // recomputed and is enabled and ready to go.
92 public virtual bool RecomputeConstraintVariables(float mass)
115 { 93 {
116 bool ret = false; 94 bool ret = false;
117 if (m_enabled) 95 if (m_enabled)
118 { 96 {
119 BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); 97 ret = CalculateTransforms();
120 ret = true; 98 if (ret)
99 {
100 // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}",
101 // BSScene.DetailLogZero, Body1.ID, Body2.ID);
102 BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true));
103 }
104 else
105 {
106 m_world.scene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID);
107 }
121 } 108 }
122 return ret; 109 return ret;
123 } 110 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
index c88e645..22ea367 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
@@ -56,29 +56,25 @@ public class BSConstraintCollection : IDisposable
56 56
57 public void Clear() 57 public void Clear()
58 { 58 {
59 foreach (BSConstraint cons in m_constraints) 59 lock (m_constraints)
60 { 60 {
61 cons.Dispose(); 61 foreach (BSConstraint cons in m_constraints)
62 {
63 cons.Dispose();
64 }
65 m_constraints.Clear();
62 } 66 }
63 m_constraints.Clear();
64 }
65
66 public BSConstraint CreateConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
67 Vector3 frame1, Quaternion frame1rot,
68 Vector3 frame2, Quaternion frame2rot)
69 {
70 BSConstraint constrain = new BSConstraint(world, obj1, obj2, frame1, frame1rot, frame2, frame2rot);
71
72 this.AddConstraint(constrain);
73 return constrain;
74 } 67 }
75 68
76 public bool AddConstraint(BSConstraint cons) 69 public bool AddConstraint(BSConstraint cons)
77 { 70 {
78 // There is only one constraint between any bodies. Remove any old just to make sure. 71 lock (m_constraints)
79 RemoveAndDestroyConstraint(cons.Body1, cons.Body2); 72 {
73 // There is only one constraint between any bodies. Remove any old just to make sure.
74 RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
80 75
81 m_constraints.Add(cons); 76 m_constraints.Add(cons);
77 }
82 78
83 return true; 79 return true;
84 } 80 }
@@ -92,16 +88,19 @@ public class BSConstraintCollection : IDisposable
92 88
93 uint lookingID1 = body1.ID; 89 uint lookingID1 = body1.ID;
94 uint lookingID2 = body2.ID; 90 uint lookingID2 = body2.ID;
95 ForEachConstraint(delegate(BSConstraint constrain) 91 lock (m_constraints)
96 { 92 {
97 if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) 93 foreach (BSConstraint constrain in m_constraints)
98 || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
99 { 94 {
100 foundConstraint = constrain; 95 if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
101 found = true; 96 || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
97 {
98 foundConstraint = constrain;
99 found = true;
100 break;
101 }
102 } 102 }
103 return found; 103 }
104 });
105 returnConstraint = foundConstraint; 104 returnConstraint = foundConstraint;
106 return found; 105 return found;
107 } 106 }
@@ -111,22 +110,33 @@ public class BSConstraintCollection : IDisposable
111 // Return 'true' if a constraint was found and destroyed. 110 // Return 'true' if a constraint was found and destroyed.
112 public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) 111 public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2)
113 { 112 {
114 // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID);
115
116 bool ret = false; 113 bool ret = false;
117 BSConstraint constrain; 114 lock (m_constraints)
115 {
116 BSConstraint constrain;
117 if (this.TryGetConstraint(body1, body2, out constrain))
118 {
119 // remove the constraint from our collection
120 RemoveAndDestroyConstraint(constrain);
121 ret = true;
122 }
123 }
118 124
119 if (this.TryGetConstraint(body1, body2, out constrain)) 125 return ret;
126 }
127
128 // The constraint MUST exist in the collection
129 public bool RemoveAndDestroyConstraint(BSConstraint constrain)
130 {
131 lock (m_constraints)
120 { 132 {
121 // remove the constraint from our collection 133 // remove the constraint from our collection
122 m_constraints.Remove(constrain); 134 m_constraints.Remove(constrain);
123 // tell the engine that all its structures need to be freed
124 constrain.Dispose();
125 // we destroyed something
126 ret = true;
127 } 135 }
128 136 // tell the engine that all its structures need to be freed
129 return ret; 137 constrain.Dispose();
138 // we destroyed something
139 return true;
130 } 140 }
131 141
132 // Remove all constraints that reference the passed body. 142 // Remove all constraints that reference the passed body.
@@ -137,16 +147,15 @@ public class BSConstraintCollection : IDisposable
137 147
138 List<BSConstraint> toRemove = new List<BSConstraint>(); 148 List<BSConstraint> toRemove = new List<BSConstraint>();
139 uint lookingID = body1.ID; 149 uint lookingID = body1.ID;
140 ForEachConstraint(delegate(BSConstraint constrain) 150 lock (m_constraints)
141 { 151 {
142 if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) 152 foreach (BSConstraint constrain in m_constraints)
143 { 153 {
144 toRemove.Add(constrain); 154 if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
155 {
156 toRemove.Add(constrain);
157 }
145 } 158 }
146 return false;
147 });
148 lock (m_constraints)
149 {
150 foreach (BSConstraint constrain in toRemove) 159 foreach (BSConstraint constrain in toRemove)
151 { 160 {
152 m_constraints.Remove(constrain); 161 m_constraints.Remove(constrain);
@@ -158,27 +167,16 @@ public class BSConstraintCollection : IDisposable
158 167
159 public bool RecalculateAllConstraints() 168 public bool RecalculateAllConstraints()
160 { 169 {
161 foreach (BSConstraint constrain in m_constraints) 170 bool ret = false;
162 {
163 constrain.CalculateTransforms();
164 }
165 return true;
166 }
167
168 // Lock the constraint list and loop through it.
169 // The constraint action returns 'true' if it wants the loop aborted.
170 private void ForEachConstraint(ConstraintAction action)
171 {
172 lock (m_constraints) 171 lock (m_constraints)
173 { 172 {
174 foreach (BSConstraint constrain in m_constraints) 173 foreach (BSConstraint constrain in m_constraints)
175 { 174 {
176 if (action(constrain)) 175 constrain.CalculateTransforms();
177 break; 176 ret = true;
178 } 177 }
179 } 178 }
179 return ret;
180 } 180 }
181
182
183} 181}
184} 182}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index c197e61..5a9f135 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -613,7 +613,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
613 MoveAngular(pTimestep); 613 MoveAngular(pTimestep);
614 LimitRotation(pTimestep); 614 LimitRotation(pTimestep);
615 615
616 DetailLog("{0},Dynamics,done,pos={1},force={2},velocity={3},angvel={4}", 616 DetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
617 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); 617 m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity);
618 }// end Step 618 }// end Step
619 619
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs
new file mode 100755
index 0000000..d68048b
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.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
35class BSHingeConstraint : BSConstraint
36{
37 public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
38 Vector3 pivotInA, Vector3 pivotInB,
39 Vector3 axisInA, Vector3 axisInB,
40 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
41 {
42 m_world = world;
43 m_body1 = obj1;
44 m_body2 = obj2;
45 m_constraint = new BulletConstraint(
46 BulletSimAPI.CreateHingeConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
47 pivotInA, pivotInB,
48 axisInA, axisInB,
49 useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
50 m_enabled = true;
51 }
52
53}
54
55}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 6f8430c..087b9bb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -37,10 +37,12 @@ public class BSLinkset
37 private static string LogHeader = "[BULLETSIM LINKSET]"; 37 private static string LogHeader = "[BULLETSIM LINKSET]";
38 38
39 private BSPrim m_linksetRoot; 39 private BSPrim m_linksetRoot;
40 public BSPrim Root { get { return m_linksetRoot; } } 40 public BSPrim LinksetRoot { get { return m_linksetRoot; } }
41 41
42 private BSScene m_scene; 42 private BSScene m_physicsScene;
43 public BSScene PhysicsScene { get { return m_physicsScene; } }
43 44
45 // The children under the root in this linkset
44 private List<BSPrim> m_children; 46 private List<BSPrim> m_children;
45 47
46 // We lock the diddling of linkset classes to prevent any badness. 48 // We lock the diddling of linkset classes to prevent any badness.
@@ -72,7 +74,7 @@ public class BSLinkset
72 public BSLinkset(BSScene scene, BSPrim parent) 74 public BSLinkset(BSScene scene, BSPrim parent)
73 { 75 {
74 // A simple linkset of one (no children) 76 // A simple linkset of one (no children)
75 m_scene = scene; 77 m_physicsScene = scene;
76 m_linksetRoot = parent; 78 m_linksetRoot = parent;
77 m_children = new List<BSPrim>(); 79 m_children = new List<BSPrim>();
78 m_mass = parent.MassRaw; 80 m_mass = parent.MassRaw;
@@ -80,16 +82,19 @@ public class BSLinkset
80 82
81 // Link to a linkset where the child knows the parent. 83 // Link to a linkset where the child knows the parent.
82 // Parent changing should not happen so do some sanity checking. 84 // Parent changing should not happen so do some sanity checking.
83 // We return the parent's linkset so the child can track it's membership. 85 // We return the parent's linkset so the child can track its membership.
84 public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent) 86 public BSLinkset AddMeToLinkset(BSPrim child)
85 { 87 {
86 lock (m_linksetActivityLock) 88 lock (m_linksetActivityLock)
87 { 89 {
88 parent.Linkset.AddChildToLinkset(child); 90 AddChildToLinkset(child);
89 } 91 }
90 return parent.Linkset; 92 return this;
91 } 93 }
92 94
95 // Remove a child from a linkset.
96 // Returns a new linkset for the child which is a linkset of one (just the
97 // orphened child).
93 public BSLinkset RemoveMeFromLinkset(BSPrim child) 98 public BSLinkset RemoveMeFromLinkset(BSPrim child)
94 { 99 {
95 lock (m_linksetActivityLock) 100 lock (m_linksetActivityLock)
@@ -101,7 +106,7 @@ public class BSLinkset
101 { 106 {
102 // Note that we don't do a foreach because the remove routine 107 // Note that we don't do a foreach because the remove routine
103 // takes it out of the list. 108 // takes it out of the list.
104 RemoveChildFromLinkset(m_children[0]); 109 RemoveChildFromOtherLinkset(m_children[0]);
105 } 110 }
106 m_children.Clear(); // just to make sure 111 m_children.Clear(); // just to make sure
107 } 112 }
@@ -113,63 +118,17 @@ public class BSLinkset
113 } 118 }
114 119
115 // The child is down to a linkset of just itself 120 // The child is down to a linkset of just itself
116 return new BSLinkset(m_scene, child); 121 return new BSLinkset(PhysicsScene, child);
117 } 122 }
118 123
119 // An existing linkset had one of its members rebuilt or something.
120 // Go through the linkset and rebuild the pointers to the bodies of the linkset members.
121 public BSLinkset RefreshLinkset(BSPrim requestor)
122 {
123 BSLinkset ret = requestor.Linkset;
124
125 lock (m_linksetActivityLock)
126 {
127 System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID);
128 if (aPtr == System.IntPtr.Zero)
129 {
130 // That's odd. We can't find the root of the linkset.
131 // The linkset is somehow dead. The requestor is now a member of a linkset of one.
132 DetailLog("{0},RefreshLinkset.RemoveRoot,child={1}", m_linksetRoot.LocalID, m_linksetRoot.LocalID);
133 ret = RemoveMeFromLinkset(m_linksetRoot);
134 }
135 else
136 {
137 // Reconstruct the pointer to the body of the linkset root.
138 DetailLog("{0},RefreshLinkset.RebuildRoot,rootID={1},ptr={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, aPtr);
139 m_linksetRoot.Body = new BulletBody(m_linksetRoot.LocalID, aPtr);
140
141 List<BSPrim> toRemove = new List<BSPrim>();
142 foreach (BSPrim bsp in m_children)
143 {
144 aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, bsp.LocalID);
145 if (aPtr == System.IntPtr.Zero)
146 {
147 toRemove.Add(bsp);
148 }
149 else
150 {
151 // Reconstruct the pointer to the body of the linkset root.
152 DetailLog("{0},RefreshLinkset.RebuildChild,rootID={1},ptr={2}", bsp.LocalID, m_linksetRoot.LocalID, aPtr);
153 bsp.Body = new BulletBody(bsp.LocalID, aPtr);
154 }
155 }
156 foreach (BSPrim bsp in toRemove)
157 {
158 RemoveChildFromLinkset(bsp);
159 }
160 }
161 }
162
163 return ret;
164 }
165
166
167 // Return 'true' if the passed object is the root object of this linkset 124 // Return 'true' if the passed object is the root object of this linkset
168 public bool IsRoot(BSPrim requestor) 125 public bool IsRoot(BSPrim requestor)
169 { 126 {
170 return (requestor.LocalID == m_linksetRoot.LocalID); 127 return (requestor.LocalID == m_linksetRoot.LocalID);
171 } 128 }
172 129
130 public int NumberOfChildren { get { return m_children.Count; } }
131
173 // Return 'true' if this linkset has any children (more than the root member) 132 // Return 'true' if this linkset has any children (more than the root member)
174 public bool HasAnyChildren { get { return (m_children.Count > 0); } } 133 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
175 134
@@ -177,12 +136,15 @@ public class BSLinkset
177 public bool HasChild(BSPrim child) 136 public bool HasChild(BSPrim child)
178 { 137 {
179 bool ret = false; 138 bool ret = false;
180 foreach (BSPrim bp in m_children) 139 lock (m_linksetActivityLock)
181 { 140 {
182 if (child.LocalID == bp.LocalID) 141 foreach (BSPrim bp in m_children)
183 { 142 {
184 ret = true; 143 if (child.LocalID == bp.LocalID)
185 break; 144 {
145 ret = true;
146 break;
147 }
186 } 148 }
187 } 149 }
188 return ret; 150 return ret;
@@ -203,12 +165,16 @@ public class BSLinkset
203 OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; 165 OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw;
204 float totalMass = m_linksetRoot.MassRaw; 166 float totalMass = m_linksetRoot.MassRaw;
205 167
206 foreach (BSPrim bp in m_children) 168 lock (m_linksetActivityLock)
207 { 169 {
208 com += bp.Position * bp.MassRaw; 170 foreach (BSPrim bp in m_children)
209 totalMass += bp.MassRaw; 171 {
172 com += bp.Position * bp.MassRaw;
173 totalMass += bp.MassRaw;
174 }
175 if (totalMass != 0f)
176 com /= totalMass;
210 } 177 }
211 com /= totalMass;
212 178
213 return com; 179 return com;
214 } 180 }
@@ -217,135 +183,237 @@ public class BSLinkset
217 { 183 {
218 OMV.Vector3 com = m_linksetRoot.Position; 184 OMV.Vector3 com = m_linksetRoot.Position;
219 185
220 foreach (BSPrim bp in m_children) 186 lock (m_linksetActivityLock)
221 { 187 {
222 com += bp.Position * bp.MassRaw; 188 foreach (BSPrim bp in m_children)
189 {
190 com += bp.Position * bp.MassRaw;
191 }
192 com /= (m_children.Count + 1);
223 } 193 }
224 com /= m_children.Count + 1;
225 194
226 return com; 195 return com;
227 } 196 }
228 197
198 // When physical properties are changed the linkset needs to recalculate
199 // its internal properties.
200 public void Refresh(BSPrim requestor)
201 {
202 // If there are no children, there aren't any constraints to recompute
203 if (!HasAnyChildren)
204 return;
205
206 // Only the root does the recomputation
207 if (IsRoot(requestor))
208 {
209 PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate()
210 {
211 RecomputeLinksetConstraintVariables();
212 });
213 }
214 }
215
216 // Call each of the constraints that make up this linkset and recompute the
217 // various transforms and variables. Used when objects are added or removed
218 // from a linkset to make sure the constraints know about the new mass and
219 // geometry.
220 // Must only be called at taint time!!
221 private bool RecomputeLinksetConstraintVariables()
222 {
223 float linksetMass = LinksetMass;
224 lock (m_linksetActivityLock)
225 {
226 foreach (BSPrim child in m_children)
227 {
228 BSConstraint constrain;
229 if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain))
230 {
231 // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}",
232 // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
233 constrain.RecomputeConstraintVariables(linksetMass);
234 }
235 else
236 {
237 // Non-fatal error that can happen when children are being added to the linkset but
238 // their constraints have not been created yet.
239 // Caused by the fact that m_children is built at run time but building constraints
240 // happens at taint time.
241 // m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}",
242 // m_linksetRoot.Body.ID, child.Body.ID);
243 }
244 }
245 }
246 return false;
247 }
248
229 // I am the root of a linkset and a new child is being added 249 // I am the root of a linkset and a new child is being added
230 public void AddChildToLinkset(BSPrim pchild) 250 // Called while LinkActivity is locked.
251 private void AddChildToLinkset(BSPrim child)
231 { 252 {
232 BSPrim child = pchild;
233 if (!HasChild(child)) 253 if (!HasChild(child))
234 { 254 {
235 m_children.Add(child); 255 m_children.Add(child);
236 256
237 m_scene.TaintedObject(delegate() 257 BSPrim rootx = LinksetRoot; // capture the root as of now
258 BSPrim childx = child;
259 m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
238 { 260 {
239 DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); 261 // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID);
240 DetailLog("{0},AddChildToLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); 262 // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
241 PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child 263 PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child
242 }); 264 });
243 } 265 }
244 return; 266 return;
245 } 267 }
246 268
269 // Forcefully removing a child from a linkset.
270 // This is not being called by the child so we have to make sure the child doesn't think
271 // it's still connected to the linkset.
272 // Normal OpenSimulator operation will never do this because other SceneObjectPart information
273 // has to be updated also (like pointer to prim's parent).
274 private void RemoveChildFromOtherLinkset(BSPrim pchild)
275 {
276 pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
277 RemoveChildFromLinkset(pchild);
278 }
279
247 // I am the root of a linkset and one of my children is being removed. 280 // I am the root of a linkset and one of my children is being removed.
248 // Safe to call even if the child is not really in my linkset. 281 // Safe to call even if the child is not really in my linkset.
249 public void RemoveChildFromLinkset(BSPrim pchild) 282 private void RemoveChildFromLinkset(BSPrim child)
250 { 283 {
251 BSPrim child = pchild;
252
253 if (m_children.Remove(child)) 284 if (m_children.Remove(child))
254 { 285 {
255 m_scene.TaintedObject(delegate() 286 BSPrim rootx = LinksetRoot; // capture the root as of now
287 BSPrim childx = child;
288 m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
256 { 289 {
257 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); 290 // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
258 DetailLog("{0},RemoveChildFromLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); 291 // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
259 292
260 if (m_children.Count == 0) 293 PhysicallyUnlinkAChildFromRoot(rootx, childx);
261 {
262 // if the linkset is empty, make sure all linkages have been removed
263 PhysicallyUnlinkAllChildrenFromRoot();
264 }
265 else
266 {
267 PhysicallyUnlinkAChildFromRoot(pchild);
268 }
269 }); 294 });
295
296 RecomputeLinksetConstraintVariables();
270 } 297 }
271 else 298 else
272 { 299 {
273 // This will happen if we remove the root of the linkset first. Non-fatal occurance. 300 // This will happen if we remove the root of the linkset first. Non-fatal occurance.
274 // m_scene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); 301 // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
275 } 302 }
276 return; 303 return;
277 } 304 }
278 305
279 // Create a constraint between me (root of linkset) and the passed prim (the child). 306 // Create a constraint between me (root of linkset) and the passed prim (the child).
280 // Called at taint time! 307 // Called at taint time!
281 private void PhysicallyLinkAChildToRoot(BSPrim childPrim) 308 private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim)
282 { 309 {
283 // Zero motion for children so they don't interpolate 310 // Zero motion for children so they don't interpolate
284 childPrim.ZeroMotion(); 311 childPrim.ZeroMotion();
285 312
313 // Relative position normalized to the root prim
314 // Essentually a vector pointing from center of rootPrim to center of childPrim
315 OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;
316
317 // real world coordinate of midpoint between the two objects
318 OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
319
320 // create a constraint that allows no freedom of movement between the two objects
321 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
322 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
323 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}",
324 rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint);
325 BS6DofConstraint constrain = new BS6DofConstraint(
326 m_physicsScene.World, rootPrim.Body, childPrim.Body,
327 midPoint,
328 true,
329 true
330 );
331 /* NOTE: attempt to build constraint with full frame computation, etc.
332 * Using the midpoint is easier since it lets the Bullet code use the transforms
333 * of the objects.
334 * Code left here as an example.
335 // ==================================================================================
286 // relative position normalized to the root prim 336 // relative position normalized to the root prim
287 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation); 337 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
288 OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation; 338 OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
289 339
290 // relative rotation of the child to the parent 340 // relative rotation of the child to the parent
291 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; 341 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
342 OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
292 343
293 // create a constraint that allows no freedom of movement between the two objects 344 // create a constraint that allows no freedom of movement between the two objects
294 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 345 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
295 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); 346 // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
296 DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); 347 DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
297 BSConstraint constrain = m_scene.Constraints.CreateConstraint( 348 BS6DofConstraint constrain = new BS6DofConstraint(
298 m_scene.World, m_linksetRoot.Body, childPrim.Body, 349 PhysicsScene.World, rootPrim.Body, childPrim.Body,
299 // childRelativePosition,
300 // childRelativeRotation,
301 OMV.Vector3.Zero, 350 OMV.Vector3.Zero,
302 OMV.Quaternion.Identity, 351 OMV.Quaternion.Inverse(rootPrim.Orientation),
303 OMV.Vector3.Zero, 352 OMV.Vector3.Zero,
304 OMV.Quaternion.Identity 353 OMV.Quaternion.Inverse(childPrim.Orientation),
354 // A point half way between the parent and child
355 // childRelativePosition/2,
356 // childRelativeRotation,
357 // childRelativePosition/2,
358 // inverseChildRelativeRotation,
359 true,
360 true
305 ); 361 );
362 // ==================================================================================
363 */
364
365 m_physicsScene.Constraints.AddConstraint(constrain);
366
367 // zero linear and angular limits makes the objects unable to move in relation to each other
306 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 368 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
307 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); 369 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
308 370
309 // tweek the constraint to increase stability 371 // tweek the constraint to increase stability
310 constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset)); 372 constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset));
311 constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor), 373 constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor),
312 m_scene.Params.linkConstraintTransMotorMaxVel, 374 PhysicsScene.Params.linkConstraintTransMotorMaxVel,
313 m_scene.Params.linkConstraintTransMotorMaxForce); 375 PhysicsScene.Params.linkConstraintTransMotorMaxForce);
314 constrain.SetCFMAndERP(m_scene.Params.linkConstraintCFM, m_scene.Params.linkConstraintERP); 376 constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
315 377
378 RecomputeLinksetConstraintVariables();
316 } 379 }
317 380
318 // Remove linkage between myself and a particular child 381 // Remove linkage between myself and a particular child
319 // Called at taint time! 382 // Called at taint time!
320 private void PhysicallyUnlinkAChildFromRoot(BSPrim childPrim) 383 private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim)
321 { 384 {
322 DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", 385 // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
323 LogHeader, m_linksetRoot.LocalID, childPrim.LocalID); 386 // LogHeader, rootPrim.LocalID, childPrim.LocalID);
324 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); 387 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
325 // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID); 388
326 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body, childPrim.Body); 389 // Find the constraint for this link and get rid of it from the overall collection and from my list
390 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body);
391
392 // Make the child refresh its location
393 BulletSimAPI.PushUpdate2(childPrim.Body.Ptr);
327 } 394 }
328 395
329 // Remove linkage between myself and any possible children I might have 396 // Remove linkage between myself and any possible children I might have
330 // Called at taint time! 397 // Called at taint time!
331 private void PhysicallyUnlinkAllChildrenFromRoot() 398 private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim)
332 { 399 {
333 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); 400 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
334 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID); 401 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
335 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body); 402
336 // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); 403 m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body);
337 } 404 }
338 405
339 // Invoke the detailed logger and output something if it's enabled. 406 // Invoke the detailed logger and output something if it's enabled.
340 private void DebugLog(string msg, params Object[] args) 407 private void DebugLog(string msg, params Object[] args)
341 { 408 {
342 m_scene.Logger.DebugFormat(msg, args); 409 if (m_physicsScene.ShouldDebugLog)
410 m_physicsScene.Logger.DebugFormat(msg, args);
343 } 411 }
344 412
345 // Invoke the detailed logger and output something if it's enabled. 413 // Invoke the detailed logger and output something if it's enabled.
346 private void DetailLog(string msg, params Object[] args) 414 private void DetailLog(string msg, params Object[] args)
347 { 415 {
348 m_scene.PhysicsLogging.Write(msg, args); 416 m_physicsScene.PhysicsLogging.Write(msg, args);
349 } 417 }
350 418
351} 419}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index ebfd85b..9c20004 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -42,7 +42,7 @@ public sealed class BSPrim : PhysicsActor
42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 42 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
43 private static readonly string LogHeader = "[BULLETS PRIM]"; 43 private static readonly string LogHeader = "[BULLETS PRIM]";
44 44
45 private void DebugLog(string mm, params Object[] xx) { if (_scene.shouldDebugLog) m_log.DebugFormat(mm, xx); } 45 private void DebugLog(string mm, params Object[] xx) { if (_scene.ShouldDebugLog) m_log.DebugFormat(mm, xx); }
46 46
47 private IMesh _mesh; 47 private IMesh _mesh;
48 private PrimitiveBaseShape _pbs; 48 private PrimitiveBaseShape _pbs;
@@ -138,14 +138,15 @@ public sealed class BSPrim : PhysicsActor
138 _isPhysical = pisPhysical; 138 _isPhysical = pisPhysical;
139 _isVolumeDetect = false; 139 _isVolumeDetect = false;
140 _subscribedEventsMs = 0; 140 _subscribedEventsMs = 0;
141 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 141 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material
142 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 142 _density = _scene.Params.defaultDensity; // TODO: compute based on object material
143 _restitution = _scene.Params.defaultRestitution; 143 _restitution = _scene.Params.defaultRestitution;
144 _linkset = new BSLinkset(_scene, this); // a linkset of one 144 _linkset = new BSLinkset(_scene, this); // a linkset of one
145 _vehicle = new BSDynamics(this); // add vehicleness 145 _vehicle = new BSDynamics(this); // add vehicleness
146 _mass = CalculateMass(); 146 _mass = CalculateMass();
147 // do the actual object creation at taint time 147 // do the actual object creation at taint time
148 _scene.TaintedObject(delegate() 148 DetailLog("{0},BSPrim.constructor,call", LocalID);
149 _scene.TaintedObject("BSPrim.create", delegate()
149 { 150 {
150 RecreateGeomAndObject(); 151 RecreateGeomAndObject();
151 152
@@ -160,17 +161,22 @@ public sealed class BSPrim : PhysicsActor
160 public void Destroy() 161 public void Destroy()
161 { 162 {
162 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 163 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
163 // DetailLog("{0},Destroy", LocalID); 164
165 // Undo any links between me and any other object
166 BSPrim parentBefore = _linkset.LinksetRoot;
167 int childrenBefore = _linkset.NumberOfChildren;
168
169 _linkset = _linkset.RemoveMeFromLinkset(this);
170
171 DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
172 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
164 173
165 // Undo any vehicle properties 174 // Undo any vehicle properties
166 _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); 175 this.VehicleType = (int)Vehicle.TYPE_NONE;
167 _scene.RemoveVehiclePrim(this); // just to make sure
168 176
169 _scene.TaintedObject(delegate() 177 _scene.TaintedObject("BSPrim.destroy", delegate()
170 { 178 {
171 // Undo any links between me and any other object 179 DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
172 _linkset = _linkset.RemoveMeFromLinkset(this);
173
174 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. 180 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
175 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); 181 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID);
176 }); 182 });
@@ -183,11 +189,11 @@ public sealed class BSPrim : PhysicsActor
183 get { return _size; } 189 get { return _size; }
184 set { 190 set {
185 _size = value; 191 _size = value;
186 _scene.TaintedObject(delegate() 192 _scene.TaintedObject("BSPrim.setSize", delegate()
187 { 193 {
188 _mass = CalculateMass(); // changing size changes the mass 194 _mass = CalculateMass(); // changing size changes the mass
189 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); 195 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
190 DetailLog("{0}: setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); 196 // DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical);
191 RecreateGeomAndObject(); 197 RecreateGeomAndObject();
192 }); 198 });
193 } 199 }
@@ -195,7 +201,7 @@ public sealed class BSPrim : PhysicsActor
195 public override PrimitiveBaseShape Shape { 201 public override PrimitiveBaseShape Shape {
196 set { 202 set {
197 _pbs = value; 203 _pbs = value;
198 _scene.TaintedObject(delegate() 204 _scene.TaintedObject("BSPrim.setShape", delegate()
199 { 205 {
200 _mass = CalculateMass(); // changing the shape changes the mass 206 _mass = CalculateMass(); // changing the shape changes the mass
201 RecreateGeomAndObject(); 207 RecreateGeomAndObject();
@@ -213,7 +219,7 @@ public sealed class BSPrim : PhysicsActor
213 public override bool Selected { 219 public override bool Selected {
214 set { 220 set {
215 _isSelected = value; 221 _isSelected = value;
216 _scene.TaintedObject(delegate() 222 _scene.TaintedObject("BSPrim.setSelected", delegate()
217 { 223 {
218 SetObjectDynamic(); 224 SetObjectDynamic();
219 }); 225 });
@@ -224,10 +230,17 @@ public sealed class BSPrim : PhysicsActor
224 // link me to the specified parent 230 // link me to the specified parent
225 public override void link(PhysicsActor obj) { 231 public override void link(PhysicsActor obj) {
226 BSPrim parent = obj as BSPrim; 232 BSPrim parent = obj as BSPrim;
227 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); 233 if (parent != null)
228 DetailLog("{0},link,parent={1}", LocalID, obj.LocalID); 234 {
235 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID);
236 BSPrim parentBefore = _linkset.LinksetRoot;
237 int childrenBefore = _linkset.NumberOfChildren;
229 238
230 _linkset = _linkset.AddMeToLinkset(this, parent); 239 _linkset = parent.Linkset.AddMeToLinkset(this);
240
241 DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
242 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
243 }
231 return; 244 return;
232 } 245 }
233 246
@@ -236,10 +249,15 @@ public sealed class BSPrim : PhysicsActor
236 // TODO: decide if this parent checking needs to happen at taint time 249 // TODO: decide if this parent checking needs to happen at taint time
237 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 250 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
238 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, 251 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
239 _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString()); 252 _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString());
240 DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString()); 253
254 BSPrim parentBefore = _linkset.LinksetRoot;
255 int childrenBefore = _linkset.NumberOfChildren;
256
257 _linkset = _linkset.RemoveMeFromLinkset(this);
241 258
242 _linkset.RemoveMeFromLinkset(this); 259 DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
260 LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
243 return; 261 return;
244 } 262 }
245 263
@@ -262,7 +280,7 @@ public sealed class BSPrim : PhysicsActor
262 280
263 public override void LockAngularMotion(OMV.Vector3 axis) 281 public override void LockAngularMotion(OMV.Vector3 axis)
264 { 282 {
265 DetailLog("{0},LockAngularMotion,call,axis={1}", LocalID, axis); 283 // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
266 return; 284 return;
267 } 285 }
268 286
@@ -279,9 +297,9 @@ public sealed class BSPrim : PhysicsActor
279 set { 297 set {
280 _position = value; 298 _position = value;
281 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 299 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
282 _scene.TaintedObject(delegate() 300 _scene.TaintedObject("BSPrim.setPosition", delegate()
283 { 301 {
284 DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 302 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
285 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 303 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
286 }); 304 });
287 } 305 }
@@ -316,9 +334,9 @@ public sealed class BSPrim : PhysicsActor
316 get { return _force; } 334 get { return _force; }
317 set { 335 set {
318 _force = value; 336 _force = value;
319 _scene.TaintedObject(delegate() 337 _scene.TaintedObject("BSPrim.setForce", delegate()
320 { 338 {
321 DetailLog("{0},SetForce,taint,force={1}", LocalID, _force); 339 // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
322 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 340 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
323 BulletSimAPI.SetObjectForce2(Body.Ptr, _force); 341 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
324 }); 342 });
@@ -331,53 +349,41 @@ public sealed class BSPrim : PhysicsActor
331 } 349 }
332 set { 350 set {
333 Vehicle type = (Vehicle)value; 351 Vehicle type = (Vehicle)value;
334 _scene.TaintedObject(delegate() 352 BSPrim vehiclePrim = this;
353 _scene.TaintedObject("setVehicleType", delegate()
335 { 354 {
336 DetailLog("{0},SetVehicleType,taint,type={1}", LocalID, type); 355 // Done at taint time so we're sure the physics engine is not using the variables
356 // Vehicle code changes the parameters for this vehicle type.
337 _vehicle.ProcessTypeChange(type); 357 _vehicle.ProcessTypeChange(type);
338 if (type == Vehicle.TYPE_NONE) 358 // Tell the scene about the vehicle so it will get processing each frame.
339 { 359 _scene.VehicleInSceneTypeChanged(this, type);
340 _scene.RemoveVehiclePrim(this);
341 }
342 else
343 {
344 _scene.TaintedObject(delegate()
345 {
346 // Tell the physics engine to clear state
347 BulletSimAPI.ClearForces2(this.Body.Ptr);
348 });
349
350 // make it so the scene will call us each tick to do vehicle things
351 _scene.AddVehiclePrim(this);
352 }
353 return;
354 }); 360 });
355 } 361 }
356 } 362 }
357 public override void VehicleFloatParam(int param, float value) 363 public override void VehicleFloatParam(int param, float value)
358 { 364 {
359 _scene.TaintedObject(delegate() 365 _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
360 { 366 {
361 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 367 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
362 }); 368 });
363 } 369 }
364 public override void VehicleVectorParam(int param, OMV.Vector3 value) 370 public override void VehicleVectorParam(int param, OMV.Vector3 value)
365 { 371 {
366 _scene.TaintedObject(delegate() 372 _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
367 { 373 {
368 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); 374 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
369 }); 375 });
370 } 376 }
371 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 377 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
372 { 378 {
373 _scene.TaintedObject(delegate() 379 _scene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
374 { 380 {
375 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 381 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
376 }); 382 });
377 } 383 }
378 public override void VehicleFlags(int param, bool remove) 384 public override void VehicleFlags(int param, bool remove)
379 { 385 {
380 _scene.TaintedObject(delegate() 386 _scene.TaintedObject("BSPrim.VehicleFlags", delegate()
381 { 387 {
382 _vehicle.ProcessVehicleFlags(param, remove); 388 _vehicle.ProcessVehicleFlags(param, remove);
383 }); 389 });
@@ -395,7 +401,7 @@ public sealed class BSPrim : PhysicsActor
395 public override void SetVolumeDetect(int param) { 401 public override void SetVolumeDetect(int param) {
396 bool newValue = (param != 0); 402 bool newValue = (param != 0);
397 _isVolumeDetect = newValue; 403 _isVolumeDetect = newValue;
398 _scene.TaintedObject(delegate() 404 _scene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
399 { 405 {
400 SetObjectDynamic(); 406 SetObjectDynamic();
401 }); 407 });
@@ -406,9 +412,9 @@ public sealed class BSPrim : PhysicsActor
406 get { return _velocity; } 412 get { return _velocity; }
407 set { 413 set {
408 _velocity = value; 414 _velocity = value;
409 _scene.TaintedObject(delegate() 415 _scene.TaintedObject("BSPrim.setVelocity", delegate()
410 { 416 {
411 DetailLog("{0},SetVelocity,taint,vel={1}", LocalID, _velocity); 417 // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
412 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 418 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
413 }); 419 });
414 } 420 }
@@ -416,7 +422,7 @@ public sealed class BSPrim : PhysicsActor
416 public override OMV.Vector3 Torque { 422 public override OMV.Vector3 Torque {
417 get { return _torque; } 423 get { return _torque; }
418 set { _torque = value; 424 set { _torque = value;
419 DetailLog("{0},SetTorque,call,torque={1}", LocalID, _torque); 425 // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
420 } 426 }
421 } 427 }
422 public override float CollisionScore { 428 public override float CollisionScore {
@@ -440,10 +446,10 @@ public sealed class BSPrim : PhysicsActor
440 set { 446 set {
441 _orientation = value; 447 _orientation = value;
442 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? 448 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
443 _scene.TaintedObject(delegate() 449 _scene.TaintedObject("BSPrim.setOrientation", delegate()
444 { 450 {
445 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 451 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
446 DetailLog("{0},SetOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 452 // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
447 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 453 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
448 }); 454 });
449 } 455 }
@@ -457,7 +463,7 @@ public sealed class BSPrim : PhysicsActor
457 get { return _isPhysical; } 463 get { return _isPhysical; }
458 set { 464 set {
459 _isPhysical = value; 465 _isPhysical = value;
460 _scene.TaintedObject(delegate() 466 _scene.TaintedObject("BSPrim.setIsPhysical", delegate()
461 { 467 {
462 SetObjectDynamic(); 468 SetObjectDynamic();
463 }); 469 });
@@ -478,7 +484,6 @@ public sealed class BSPrim : PhysicsActor
478 484
479 // Make gravity work if the object is physical and not selected 485 // Make gravity work if the object is physical and not selected
480 // No locking here because only called when it is safe 486 // No locking here because only called when it is safe
481 // Only called at taint time so it is save to call into Bullet.
482 private void SetObjectDynamic() 487 private void SetObjectDynamic()
483 { 488 {
484 // RA: remove this for the moment. 489 // RA: remove this for the moment.
@@ -487,13 +492,16 @@ public sealed class BSPrim : PhysicsActor
487 // Maybe a VerifyCorrectPhysicalShape() routine? 492 // Maybe a VerifyCorrectPhysicalShape() routine?
488 // RecreateGeomAndObject(); 493 // RecreateGeomAndObject();
489 494
490 float mass = _mass; 495 // Bullet wants static objects to have a mass of zero
491 // Bullet wants static objects have a mass of zero 496 float mass = IsStatic ? 0f : _mass;
492 if (IsStatic)
493 mass = 0f;
494 497
495 DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, mass);
496 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); 498 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
499
500 // recompute any linkset parameters
501 _linkset.Refresh(this);
502
503 CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr);
504 // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf);
497 } 505 }
498 506
499 // prims don't fly 507 // prims don't fly
@@ -548,9 +556,9 @@ public sealed class BSPrim : PhysicsActor
548 set { 556 set {
549 _rotationalVelocity = value; 557 _rotationalVelocity = value;
550 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 558 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
551 _scene.TaintedObject(delegate() 559 _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
552 { 560 {
553 DetailLog("{0},SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); 561 // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
554 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 562 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
555 }); 563 });
556 } 564 }
@@ -565,9 +573,9 @@ public sealed class BSPrim : PhysicsActor
565 get { return _buoyancy; } 573 get { return _buoyancy; }
566 set { 574 set {
567 _buoyancy = value; 575 _buoyancy = value;
568 _scene.TaintedObject(delegate() 576 _scene.TaintedObject("BSPrim.setBuoyancy", delegate()
569 { 577 {
570 DetailLog("{0},SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); 578 // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
571 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 579 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
572 }); 580 });
573 } 581 }
@@ -607,6 +615,7 @@ public sealed class BSPrim : PhysicsActor
607 615
608 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); 616 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
609 public override void AddForce(OMV.Vector3 force, bool pushforce) { 617 public override void AddForce(OMV.Vector3 force, bool pushforce) {
618 // for an object, doesn't matter if force is a pushforce or not
610 if (force.IsFinite()) 619 if (force.IsFinite())
611 { 620 {
612 // _force += force; 621 // _force += force;
@@ -618,40 +627,48 @@ public sealed class BSPrim : PhysicsActor
618 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); 627 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
619 return; 628 return;
620 } 629 }
621 _scene.TaintedObject(delegate() 630 _scene.TaintedObject("BSPrim.AddForce", delegate()
622 { 631 {
632 OMV.Vector3 fSum = OMV.Vector3.Zero;
623 lock (m_accumulatedForces) 633 lock (m_accumulatedForces)
624 { 634 {
625 if (m_accumulatedForces.Count > 0) 635 foreach (OMV.Vector3 v in m_accumulatedForces)
626 { 636 {
627 OMV.Vector3 fSum = OMV.Vector3.Zero; 637 fSum += v;
628 foreach (OMV.Vector3 v in m_accumulatedForces)
629 {
630 fSum += v;
631 }
632 m_accumulatedForces.Clear();
633
634 DetailLog("{0},SetObjectForce,taint,force={1}", LocalID, fSum);
635 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, fSum);
636 } 638 }
639 m_accumulatedForces.Clear();
637 } 640 }
641 // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force);
642 BulletSimAPI.AddObjectForce2(Body.Ptr, fSum);
638 }); 643 });
639 } 644 }
640 645
641 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 646 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
642 DetailLog("{0},AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); 647 // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
643 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); 648 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
644 } 649 }
645 public override void SetMomentum(OMV.Vector3 momentum) { 650 public override void SetMomentum(OMV.Vector3 momentum) {
646 DetailLog("{0},SetMomentum,call,mom={1}", LocalID, momentum); 651 // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
647 } 652 }
648 public override void SubscribeEvents(int ms) { 653 public override void SubscribeEvents(int ms) {
649 _subscribedEventsMs = ms; 654 _subscribedEventsMs = ms;
650 // make sure first collision happens 655 if (ms > 0)
651 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; 656 {
657 // make sure first collision happens
658 _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
659
660 Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
661 {
662 BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
663 });
664 }
652 } 665 }
653 public override void UnSubscribeEvents() { 666 public override void UnSubscribeEvents() {
654 _subscribedEventsMs = 0; 667 _subscribedEventsMs = 0;
668 Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate()
669 {
670 BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
671 });
655 } 672 }
656 public override bool SubscribedEvents() { 673 public override bool SubscribedEvents() {
657 return (_subscribedEventsMs > 0); 674 return (_subscribedEventsMs > 0);
@@ -970,26 +987,26 @@ public sealed class BSPrim : PhysicsActor
970 { 987 {
971 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 988 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
972 { 989 {
973 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 990 // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
974 { 991 // {
975 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 992 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
976 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) 993 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
977 { 994 {
978 DetailLog("{0},CreateGeom,sphere", LocalID); 995 // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
979 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 996 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
980 // Bullet native objects are scaled by the Bullet engine so pass the size in 997 // Bullet native objects are scaled by the Bullet engine so pass the size in
981 _scale = _size; 998 _scale = _size;
982 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 999 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
983 ret = true; 1000 ret = true;
984 } 1001 }
985 } 1002 // }
986 } 1003 }
987 else 1004 else
988 { 1005 {
989 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); 1006 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
990 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) 1007 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
991 { 1008 {
992 DetailLog("{0},CreateGeom,box", LocalID); 1009 // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
993 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 1010 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
994 _scale = _size; 1011 _scale = _size;
995 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? 1012 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
@@ -1032,12 +1049,12 @@ public sealed class BSPrim : PhysicsActor
1032 // if this new shape is the same as last time, don't recreate the mesh 1049 // if this new shape is the same as last time, don't recreate the mesh
1033 if (_meshKey == newMeshKey) return; 1050 if (_meshKey == newMeshKey) return;
1034 1051
1035 DetailLog("{0},CreateGeomMesh,create,key={1}", LocalID, _meshKey); 1052 // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
1036 // Since we're recreating new, get rid of any previously generated shape 1053 // Since we're recreating new, get rid of any previously generated shape
1037 if (_meshKey != 0) 1054 if (_meshKey != 0)
1038 { 1055 {
1039 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); 1056 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1040 DetailLog("{0},CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); 1057 // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
1041 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1058 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1042 _mesh = null; 1059 _mesh = null;
1043 _meshKey = 0; 1060 _meshKey = 0;
@@ -1067,7 +1084,7 @@ public sealed class BSPrim : PhysicsActor
1067 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1084 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
1068 // meshes are already scaled by the meshmerizer 1085 // meshes are already scaled by the meshmerizer
1069 _scale = new OMV.Vector3(1f, 1f, 1f); 1086 _scale = new OMV.Vector3(1f, 1f, 1f);
1070 DetailLog("{0},CreateGeomMesh,done", LocalID); 1087 // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID);
1071 return; 1088 return;
1072 } 1089 }
1073 1090
@@ -1081,28 +1098,21 @@ public sealed class BSPrim : PhysicsActor
1081 // if the hull hasn't changed, don't rebuild it 1098 // if the hull hasn't changed, don't rebuild it
1082 if (newHullKey == _hullKey) return; 1099 if (newHullKey == _hullKey) return;
1083 1100
1084 DetailLog("{0},CreateGeomHull,create,key={1}", LocalID, _meshKey); 1101 // DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey);
1085 1102
1086 // Since we're recreating new, get rid of any previously generated shape 1103 // Since we're recreating new, get rid of any previously generated shape
1087 if (_hullKey != 0) 1104 if (_hullKey != 0)
1088 { 1105 {
1089 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); 1106 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1090 DetailLog("{0},CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey); 1107 // DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey);
1091 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); 1108 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1092 _hullKey = 0; 1109 _hullKey = 0;
1093 _hulls.Clear();
1094 DetailLog("{0},CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey);
1095 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1096 _mesh = null; // the mesh cannot match either
1097 _meshKey = 0;
1098 } 1110 }
1099 1111
1100 _hullKey = newHullKey; 1112 _hullKey = newHullKey;
1101 if (_meshKey != _hullKey) 1113
1102 { 1114 // Make sure the underlying mesh exists and is correct
1103 // if the underlying mesh has changed, rebuild it 1115 CreateGeomMesh();
1104 CreateGeomMesh();
1105 }
1106 1116
1107 int[] indices = _mesh.getIndexListAsInt(); 1117 int[] indices = _mesh.getIndexListAsInt();
1108 List<OMV.Vector3> vertices = _mesh.getVertexList(); 1118 List<OMV.Vector3> vertices = _mesh.getVertexList();
@@ -1128,7 +1138,7 @@ public sealed class BSPrim : PhysicsActor
1128 // create the hull into the _hulls variable 1138 // create the hull into the _hulls variable
1129 convexBuilder.process(dcomp); 1139 convexBuilder.process(dcomp);
1130 1140
1131 // Convert the vertices and indices for passing to unmanaged 1141 // Convert the vertices and indices for passing to unmanaged.
1132 // The hull information is passed as a large floating point array. 1142 // The hull information is passed as a large floating point array.
1133 // The format is: 1143 // The format is:
1134 // convHulls[0] = number of hulls 1144 // convHulls[0] = number of hulls
@@ -1188,7 +1198,7 @@ public sealed class BSPrim : PhysicsActor
1188 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; 1198 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1189 // meshes are already scaled by the meshmerizer 1199 // meshes are already scaled by the meshmerizer
1190 _scale = new OMV.Vector3(1f, 1f, 1f); 1200 _scale = new OMV.Vector3(1f, 1f, 1f);
1191 DetailLog("{0},CreateGeomHull,done", LocalID); 1201 // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
1192 return; 1202 return;
1193 } 1203 }
1194 1204
@@ -1214,7 +1224,7 @@ public sealed class BSPrim : PhysicsActor
1214 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); 1224 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1215 1225
1216 // the CreateObject() may have recreated the rigid body. Make sure we have the latest. 1226 // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
1217 m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID); 1227 Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
1218 1228
1219 return ret; 1229 return ret;
1220 } 1230 }
@@ -1326,8 +1336,8 @@ public sealed class BSPrim : PhysicsActor
1326 1336
1327 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", 1337 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
1328 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1338 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1329 DetailLog("{0},UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1339 // DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1330 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); 1340 // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1331 1341
1332 base.RequestPhysicsterseUpdate(); 1342 base.RequestPhysicsterseUpdate();
1333 } 1343 }
@@ -1335,7 +1345,7 @@ public sealed class BSPrim : PhysicsActor
1335 else 1345 else
1336 { 1346 {
1337 // For debugging, we also report the movement of children 1347 // For debugging, we also report the movement of children
1338 DetailLog("{0},UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", 1348 DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1339 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, 1349 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1340 entprop.Acceleration, entprop.RotationalVelocity); 1350 entprop.Acceleration, entprop.RotationalVelocity);
1341 } 1351 }
@@ -1343,7 +1353,7 @@ public sealed class BSPrim : PhysicsActor
1343 } 1353 }
1344 1354
1345 // I've collided with something 1355 // I've collided with something
1346 CollisionEventUpdate collisionCollection = null; 1356 CollisionEventUpdate collisionCollection;
1347 public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) 1357 public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
1348 { 1358 {
1349 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); 1359 // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
@@ -1355,6 +1365,8 @@ public sealed class BSPrim : PhysicsActor
1355 _collidingGroundStep = _scene.SimulationStep; 1365 _collidingGroundStep = _scene.SimulationStep;
1356 } 1366 }
1357 1367
1368 // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
1369
1358 // if someone is subscribed to collision events.... 1370 // if someone is subscribed to collision events....
1359 if (_subscribedEventsMs != 0) { 1371 if (_subscribedEventsMs != 0) {
1360 // throttle the collisions to the number of milliseconds specified in the subscription 1372 // throttle the collisions to the number of milliseconds specified in the subscription
@@ -1375,7 +1387,9 @@ public sealed class BSPrim : PhysicsActor
1375 if (collisionCollection != null && collisionCollection.Count > 0) 1387 if (collisionCollection != null && collisionCollection.Count > 0)
1376 { 1388 {
1377 base.SendCollisionUpdate(collisionCollection); 1389 base.SendCollisionUpdate(collisionCollection);
1378 collisionCollection.Clear(); 1390 // The collisionCollection structure is passed around in the simulator.
1391 // Make sure we don't have a handle to that one and that a new one is used next time.
1392 collisionCollection = null;
1379 } 1393 }
1380 } 1394 }
1381 1395
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 011033c..a31c578 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -73,7 +73,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 73 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
74 private static readonly string LogHeader = "[BULLETS SCENE]"; 74 private static readonly string LogHeader = "[BULLETS SCENE]";
75 75
76 public void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); } 76 public void DebugLog(string mm, params Object[] xx) { if (ShouldDebugLog) m_log.DebugFormat(mm, xx); }
77 77
78 public string BulletSimVersion = "?"; 78 public string BulletSimVersion = "?";
79 79
@@ -162,14 +162,24 @@ public class BSScene : PhysicsScene, IPhysicsParameters
162 } 162 }
163 163
164 public delegate void TaintCallback(); 164 public delegate void TaintCallback();
165 private List<TaintCallback> _taintedObjects; 165 private struct TaintCallbackEntry
166 {
167 public String ident;
168 public TaintCallback callback;
169 public TaintCallbackEntry(string i, TaintCallback c)
170 {
171 ident = i;
172 callback = c;
173 }
174 }
175 private List<TaintCallbackEntry> _taintedObjects;
166 private Object _taintLock = new Object(); 176 private Object _taintLock = new Object();
167 177
168 // A pointer to an instance if this structure is passed to the C++ code 178 // A pointer to an instance if this structure is passed to the C++ code
169 ConfigurationParameters[] m_params; 179 ConfigurationParameters[] m_params;
170 GCHandle m_paramsHandle; 180 GCHandle m_paramsHandle;
171 181
172 public bool shouldDebugLog { get; private set; } 182 public bool ShouldDebugLog { get; private set; }
173 183
174 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; 184 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
175 185
@@ -232,7 +242,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
232 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); 242 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
233 } 243 }
234 244
235 _taintedObjects = new List<TaintCallback>(); 245 _taintedObjects = new List<TaintCallbackEntry>();
236 246
237 mesher = meshmerizer; 247 mesher = meshmerizer;
238 // The bounding box for the simulated world 248 // The bounding box for the simulated world
@@ -245,7 +255,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
245 255
246 // Initialization to support the transition to a new API which puts most of the logic 256 // Initialization to support the transition to a new API which puts most of the logic
247 // into the C# code so it is easier to modify and add to. 257 // into the C# code so it is easier to modify and add to.
248 m_worldSim = new BulletSim(m_worldID, BulletSimAPI.GetSimHandle2(m_worldID)); 258 m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID));
249 m_constraintCollection = new BSConstraintCollection(World); 259 m_constraintCollection = new BSConstraintCollection(World);
250 260
251 m_initialized = true; 261 m_initialized = true;
@@ -352,7 +362,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
352 BSPrim bsprim = prim as BSPrim; 362 BSPrim bsprim = prim as BSPrim;
353 if (bsprim != null) 363 if (bsprim != null)
354 { 364 {
355 m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); 365 // DetailLog("{0},RemovePrim,call", bsprim.LocalID);
366 // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
356 try 367 try
357 { 368 {
358 lock (m_prims) m_prims.Remove(bsprim.LocalID); 369 lock (m_prims) m_prims.Remove(bsprim.LocalID);
@@ -377,6 +388,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
377 388
378 if (!m_initialized) return null; 389 if (!m_initialized) return null;
379 390
391 // DetailLog("{0},AddPrimShape,call", localID);
392
380 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); 393 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
381 lock (m_prims) m_prims.Add(localID, prim); 394 lock (m_prims) m_prims.Add(localID, prim);
382 return prim; 395 return prim;
@@ -400,7 +413,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
400 // prevent simulation until we've been initialized 413 // prevent simulation until we've been initialized
401 if (!m_initialized) return 10.0f; 414 if (!m_initialized) return 10.0f;
402 415
403 long simulateStartTime = Util.EnvironmentTickCount(); 416 int simulateStartTime = Util.EnvironmentTickCount();
404 417
405 // update the prim states while we know the physics engine is not busy 418 // update the prim states while we know the physics engine is not busy
406 ProcessTaints(); 419 ProcessTaints();
@@ -416,12 +429,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
416 { 429 {
417 numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, 430 numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
418 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); 431 out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
419 DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", "0000000000", numSubSteps, updatedEntityCount, collidersCount); 432 // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
420 } 433 }
421 catch (Exception e) 434 catch (Exception e)
422 { 435 {
423 m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); 436 m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e);
424 DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", "0000000000", numSubSteps, updatedEntityCount, collidersCount); 437 // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
425 // updatedEntityCount = 0; 438 // updatedEntityCount = 0;
426 collidersCount = 0; 439 collidersCount = 0;
427 } 440 }
@@ -498,8 +511,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
498 // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); 511 // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
499 // return (timeStep * (float)simulateTotalTime); 512 // return (timeStep * (float)simulateTotalTime);
500 513
501 // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. 514 // TODO: FIX THIS: fps calculation possibly wrong.
502 return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; 515 // This calculation says 1/timeStep is the ideal frame rate. Any time added to
516 // that by the physics simulation gives a slower frame rate.
517 long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
518 if (totalSimulationTime >= timeStep)
519 return 0;
520 return 1f / (timeStep + totalSimulationTime);
503 } 521 }
504 522
505 // Something has collided 523 // Something has collided
@@ -535,7 +553,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
535 553
536 public override void SetTerrain(float[] heightMap) { 554 public override void SetTerrain(float[] heightMap) {
537 m_heightMap = heightMap; 555 m_heightMap = heightMap;
538 this.TaintedObject(delegate() 556 this.TaintedObject("BSScene.SetTerrain", delegate()
539 { 557 {
540 BulletSimAPI.SetHeightmap(m_worldID, m_heightMap); 558 BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
541 }); 559 });
@@ -577,12 +595,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
577 // make sure no stepping happens while we're deleting stuff 595 // make sure no stepping happens while we're deleting stuff
578 m_initialized = false; 596 m_initialized = false;
579 597
580 if (m_constraintCollection != null)
581 {
582 m_constraintCollection.Dispose();
583 m_constraintCollection = null;
584 }
585
586 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) 598 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
587 { 599 {
588 kvp.Value.Destroy(); 600 kvp.Value.Destroy();
@@ -595,6 +607,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
595 } 607 }
596 m_prims.Clear(); 608 m_prims.Clear();
597 609
610 // Now that the prims are all cleaned up, there should be no constraints left
611 if (m_constraintCollection != null)
612 {
613 m_constraintCollection.Dispose();
614 m_constraintCollection = null;
615 }
616
598 // Anything left in the unmanaged code should be cleaned out 617 // Anything left in the unmanaged code should be cleaned out
599 BulletSimAPI.Shutdown(WorldID); 618 BulletSimAPI.Shutdown(WorldID);
600 619
@@ -727,12 +746,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
727 // Calls to the PhysicsActors can't directly call into the physics engine 746 // Calls to the PhysicsActors can't directly call into the physics engine
728 // because it might be busy. We delay changes to a known time. 747 // because it might be busy. We delay changes to a known time.
729 // We rely on C#'s closure to save and restore the context for the delegate. 748 // We rely on C#'s closure to save and restore the context for the delegate.
730 public void TaintedObject(TaintCallback callback) 749 public void TaintedObject(String ident, TaintCallback callback)
731 { 750 {
732 if (!m_initialized) return; 751 if (!m_initialized) return;
733 752
734 lock (_taintLock) 753 lock (_taintLock)
735 _taintedObjects.Add(callback); 754 _taintedObjects.Add(new TaintCallbackEntry(ident, callback));
736 return; 755 return;
737 } 756 }
738 757
@@ -744,22 +763,22 @@ public class BSScene : PhysicsScene, IPhysicsParameters
744 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process 763 if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process
745 { 764 {
746 // swizzle a new list into the list location so we can process what's there 765 // swizzle a new list into the list location so we can process what's there
747 List<TaintCallback> oldList; 766 List<TaintCallbackEntry> oldList;
748 lock (_taintLock) 767 lock (_taintLock)
749 { 768 {
750 oldList = _taintedObjects; 769 oldList = _taintedObjects;
751 _taintedObjects = new List<TaintCallback>(); 770 _taintedObjects = new List<TaintCallbackEntry>();
752 } 771 }
753 772
754 foreach (TaintCallback callback in oldList) 773 foreach (TaintCallbackEntry tcbe in oldList)
755 { 774 {
756 try 775 try
757 { 776 {
758 callback(); 777 tcbe.callback();
759 } 778 }
760 catch (Exception e) 779 catch (Exception e)
761 { 780 {
762 m_log.ErrorFormat("{0}: ProcessTaints: Exception: {1}", LogHeader, e); 781 m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e);
763 } 782 }
764 } 783 }
765 oldList.Clear(); 784 oldList.Clear();
@@ -767,6 +786,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters
767 } 786 }
768 787
769 #region Vehicles 788 #region Vehicles
789
790 public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType)
791 {
792 if (newType == Vehicle.TYPE_NONE)
793 {
794 RemoveVehiclePrim(vehic);
795 }
796 else
797 {
798 // make it so the scene will call us each tick to do vehicle things
799 AddVehiclePrim(vehic);
800 }
801 }
802
770 // Make so the scene will call this prim for vehicle actions each tick. 803 // Make so the scene will call this prim for vehicle actions each tick.
771 // Safe to call if prim is already in the vehicle list. 804 // Safe to call if prim is already in the vehicle list.
772 public void AddVehiclePrim(BSPrim vehicle) 805 public void AddVehiclePrim(BSPrim vehicle)
@@ -812,12 +845,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
812 845
813 private struct ParameterDefn 846 private struct ParameterDefn
814 { 847 {
815 public string name; 848 public string name; // string name of the parameter
816 public string desc; 849 public string desc; // a short description of what the parameter means
817 public float defaultValue; 850 public float defaultValue; // default value if not specified anywhere else
818 public ParamUser userParam; 851 public ParamUser userParam; // get the value from the configuration file
819 public ParamGet getter; 852 public ParamGet getter; // return the current value stored for this parameter
820 public ParamSet setter; 853 public ParamSet setter; // set the current value for this parameter
821 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) 854 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
822 { 855 {
823 name = n; 856 name = n;
@@ -834,7 +867,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
834 // To add a new externally referencable/settable parameter, add the paramter storage 867 // To add a new externally referencable/settable parameter, add the paramter storage
835 // location somewhere in the program and make an entry in this table with the 868 // location somewhere in the program and make an entry in this table with the
836 // getters and setters. 869 // getters and setters.
837 // To add a new variable, it is easiest to find an existing definition and copy it. 870 // It is easiest to find an existing definition and copy it.
838 // Parameter values are floats. Booleans are converted to a floating value. 871 // Parameter values are floats. Booleans are converted to a floating value.
839 // 872 //
840 // A ParameterDefn() takes the following parameters: 873 // A ParameterDefn() takes the following parameters:
@@ -870,7 +903,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
870 (s) => { return (float)s.m_meshLOD; }, 903 (s) => { return (float)s.m_meshLOD; },
871 (s,p,l,v) => { s.m_meshLOD = (int)v; } ), 904 (s,p,l,v) => { s.m_meshLOD = (int)v; } ),
872 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", 905 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
873 32, 906 32f,
874 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, 907 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); },
875 (s) => { return (float)s.m_sculptLOD; }, 908 (s) => { return (float)s.m_sculptLOD; },
876 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), 909 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ),
@@ -1027,14 +1060,19 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1027 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), 1060 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1028 1061
1029 1062
1030 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)", 1063 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
1031 0f, // zero to disable 1064 0f, // zero to disable
1032 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, 1065 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
1033 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, 1066 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
1034 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), 1067 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
1068 new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
1069 0f, // zero to disable
1070 (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
1071 (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; },
1072 (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ),
1035 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", 1073 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
1036 ConfigurationParameters.numericTrue, 1074 ConfigurationParameters.numericFalse,
1037 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1075 (s,cf,p,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1038 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; }, 1076 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; },
1039 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ), 1077 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ),
1040 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", 1078 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
@@ -1101,9 +1139,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1101 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), 1139 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
1102 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements", 1140 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
1103 ConfigurationParameters.numericFalse, 1141 ConfigurationParameters.numericFalse,
1104 (s,cf,p,v) => { s.shouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); }, 1142 (s,cf,p,v) => { s.ShouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
1105 (s) => { return s.NumericBool(s.shouldDebugLog); }, 1143 (s) => { return s.NumericBool(s.ShouldDebugLog); },
1106 (s,p,l,v) => { s.shouldDebugLog = s.BoolNumeric(v); } ), 1144 (s,p,l,v) => { s.ShouldDebugLog = s.BoolNumeric(v); } ),
1107 1145
1108 }; 1146 };
1109 1147
@@ -1243,7 +1281,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1243 List<uint> objectIDs = lIDs; 1281 List<uint> objectIDs = lIDs;
1244 string xparm = parm.ToLower(); 1282 string xparm = parm.ToLower();
1245 float xval = val; 1283 float xval = val;
1246 TaintedObject(delegate() { 1284 TaintedObject("BSScene.UpdateParameterSet", delegate() {
1247 foreach (uint lID in objectIDs) 1285 foreach (uint lID in objectIDs)
1248 { 1286 {
1249 BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval); 1287 BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval);
@@ -1263,7 +1301,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1263 uint xlocalID = localID; 1301 uint xlocalID = localID;
1264 string xparm = parm.ToLower(); 1302 string xparm = parm.ToLower();
1265 float xval = val; 1303 float xval = val;
1266 TaintedObject(delegate() { 1304 TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
1267 BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); 1305 BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval);
1268 }); 1306 });
1269 } 1307 }
@@ -1289,10 +1327,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1289 #endregion Runtime settable parameters 1327 #endregion Runtime settable parameters
1290 1328
1291 // Invoke the detailed logger and output something if it's enabled. 1329 // Invoke the detailed logger and output something if it's enabled.
1292 private void DetailLog(string msg, params Object[] args) 1330 public void DetailLog(string msg, params Object[] args)
1293 { 1331 {
1294 PhysicsLogging.Write(msg, args); 1332 PhysicsLogging.Write(msg, args);
1295 } 1333 }
1334 // used to fill in the LocalID when there isn't one
1335 public const string DetailLogZero = "0000000000";
1296 1336
1297} 1337}
1298} 1338}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 0ffbc94..504bd3c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -35,9 +35,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin {
35// Classes to allow some type checking for the API 35// Classes to allow some type checking for the API
36public struct BulletSim 36public struct BulletSim
37{ 37{
38 public BulletSim(uint id, IntPtr xx) { ID = id; Ptr = xx; } 38 public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; }
39 public IntPtr Ptr;
40 public uint ID; 39 public uint ID;
40 // The scene is only in here so very low level routines have a handle to print debug/error messages
41 public BSScene scene;
42 public IntPtr Ptr;
41} 43}
42 44
43public struct BulletBody 45public struct BulletBody
@@ -158,6 +160,7 @@ public struct ConfigurationParameters
158 public float avatarContactProcessingThreshold; 160 public float avatarContactProcessingThreshold;
159 161
160 public float maxPersistantManifoldPoolSize; 162 public float maxPersistantManifoldPoolSize;
163 public float maxCollisionAlgorithmPoolSize;
161 public float shouldDisableContactPoolDynamicAllocation; 164 public float shouldDisableContactPoolDynamicAllocation;
162 public float shouldForceUpdateAllAabbs; 165 public float shouldForceUpdateAllAabbs;
163 public float shouldRandomizeSolverOrder; 166 public float shouldRandomizeSolverOrder;
@@ -179,17 +182,18 @@ public struct ConfigurationParameters
179// Values used by Bullet and BulletSim to control collisions 182// Values used by Bullet and BulletSim to control collisions
180public enum CollisionFlags : uint 183public enum CollisionFlags : uint
181{ 184{
182 STATIC_OBJECT = 1 << 0, 185 CF_STATIC_OBJECT = 1 << 0,
183 KINEMATIC_OBJECT = 1 << 1, 186 CF_KINEMATIC_OBJECT = 1 << 1,
184 NO_CONTACT_RESPONSE = 1 << 2, 187 CF_NO_CONTACT_RESPONSE = 1 << 2,
185 CUSTOM_MATERIAL_CALLBACK = 1 << 3, 188 CF_CUSTOM_MATERIAL_CALLBACK = 1 << 3,
186 CHARACTER_OBJECT = 1 << 4, 189 CF_CHARACTER_OBJECT = 1 << 4,
187 DISABLE_VISUALIZE_OBJECT = 1 << 5, 190 CF_DISABLE_VISUALIZE_OBJECT = 1 << 5,
188 DISABLE_SPU_COLLISION_PROCESS = 1 << 6, 191 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
189 // Following used by BulletSim to control collisions 192 // Following used by BulletSim to control collisions
190 VOLUME_DETECT_OBJECT = 1 << 10, 193 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
191 PHANTOM_OBJECT = 1 << 11, 194 BS_VOLUME_DETECT_OBJECT = 1 << 11,
192 PHYSICAL_OBJECT = 1 << 12, 195 BS_PHANTOM_OBJECT = 1 << 12,
196 BS_PHYSICAL_OBJECT = 1 << 13,
193}; 197};
194 198
195// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 199// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
@@ -361,7 +365,7 @@ public static extern IntPtr GetSimHandle2(uint worldID);
361public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id); 365public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
362 366
363[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 367[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
364public static extern IntPtr GetBodyHandle2(IntPtr sim, uint id); 368public static extern IntPtr GetBodyHandle2(IntPtr world, uint id);
365 369
366// =============================================================================== 370// ===============================================================================
367[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 371[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -370,45 +374,69 @@ public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
370 int maxUpdates, IntPtr updateArray); 374 int maxUpdates, IntPtr updateArray);
371 375
372[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 376[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
373public static extern bool UpdateParameter2(IntPtr sim, uint localID, String parm, float value); 377public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
374 378
375[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 379[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
376public static extern void SetHeightmap2(IntPtr sim, float[] heightmap); 380public static extern void SetHeightmap2(IntPtr world, float[] heightmap);
377 381
378[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 382[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
379public static extern void Shutdown2(IntPtr sim); 383public static extern void Shutdown2(IntPtr sim);
380 384
381[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 385[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
382public static extern int PhysicsStep2(IntPtr sim, float timeStep, int maxSubSteps, float fixedTimeStep, 386public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep,
383 out int updatedEntityCount, 387 out int updatedEntityCount,
384 out IntPtr updatedEntitiesPtr, 388 out IntPtr updatedEntitiesPtr,
385 out int collidersCount, 389 out int collidersCount,
386 out IntPtr collidersPtr); 390 out IntPtr collidersPtr);
387 391
392[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
393public static extern bool PushUpdate2(IntPtr obj);
394
388/* 395/*
389[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 396[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
390public static extern IntPtr CreateMesh2(IntPtr sim, int indicesCount, int* indices, int verticesCount, float* vertices ); 397public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices );
391 398
392[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 399[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
393public static extern bool BuildHull2(IntPtr sim, IntPtr mesh); 400public static extern bool BuildHull2(IntPtr world, IntPtr mesh);
394 401
395[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 402[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
396public static extern bool ReleaseHull2(IntPtr sim, IntPtr mesh); 403public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh);
397 404
398[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 405[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
399public static extern bool DestroyMesh2(IntPtr sim, IntPtr mesh); 406public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh);
400 407
401[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 408[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
402public static extern IntPtr CreateObject2(IntPtr sim, ShapeData shapeData); 409public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData);
403*/ 410*/
404 411
405[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 412[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
406public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2, 413public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
407 Vector3 frame1loc, Quaternion frame1rot, 414 Vector3 frame1loc, Quaternion frame1rot,
408 Vector3 frame2loc, Quaternion frame2rot, 415 Vector3 frame2loc, Quaternion frame2rot,
409 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); 416 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
410 417
411[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 418[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
419public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr obj1, IntPtr obj2,
420 Vector3 joinPoint,
421 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
422
423[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
424public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
425 Vector3 pivotinA, Vector3 pivotinB,
426 Vector3 axisInA, Vector3 axisInB,
427 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
428
429[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
430public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse);
431
432[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
433public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations);
434
435[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
436public static extern bool SetFrames2(IntPtr constrain,
437 Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot);
438
439[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
412public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); 440public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
413 441
414[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 442[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -421,13 +449,22 @@ public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
421public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce); 449public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
422 450
423[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 451[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
452public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold);
453
454[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
424public static extern bool CalculateTransforms2(IntPtr constrain); 455public static extern bool CalculateTransforms2(IntPtr constrain);
425 456
426[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 457[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
427public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis); 458public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
428 459
429[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 460[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
430public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain); 461public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
462
463[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
464public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj);
465
466[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
467public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
431 468
432[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
433public static extern Vector3 GetPosition2(IntPtr obj); 470public static extern Vector3 GetPosition2(IntPtr obj);
@@ -448,6 +485,9 @@ public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocit
448public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); 485public static extern bool SetObjectForce2(IntPtr obj, Vector3 force);
449 486
450[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 487[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
488public static extern bool AddObjectForce2(IntPtr obj, Vector3 force);
489
490[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
451public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); 491public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val);
452 492
453[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 493[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -478,13 +518,16 @@ public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val);
478public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); 518public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang);
479 519
480[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 520[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
481public static extern IntPtr SetCollisionFlags2(IntPtr obj, uint flags); 521public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
482 522
483[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 523[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
484public static extern IntPtr AddToCollisionFlags2(IntPtr obj, uint flags); 524public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
485 525
486[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 526[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
487public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, uint flags); 527public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
528
529[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
530public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
488 531
489[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 532[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
490public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); 533public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
@@ -499,16 +542,13 @@ public static extern bool SetGravity2(IntPtr obj, Vector3 val);
499public static extern IntPtr ClearForces2(IntPtr obj); 542public static extern IntPtr ClearForces2(IntPtr obj);
500 543
501[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 544[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
502public static extern bool SetMargin2(IntPtr obj, float val); 545public static extern IntPtr ClearAllForces2(IntPtr obj);
503
504[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
505public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
506 546
507[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 547[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
508public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj); 548public static extern bool SetMargin2(IntPtr obj, float val);
509 549
510[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 550[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
511public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj); 551public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
512 552
513[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 553[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
514public static extern bool DestroyObject2(IntPtr world, uint id); 554public static extern bool DestroyObject2(IntPtr world, uint id);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index ce1c364..d6aafaf 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -226,6 +226,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
226 public void llResetScript() 226 public void llResetScript()
227 { 227 {
228 m_host.AddScriptLPS(1); 228 m_host.AddScriptLPS(1);
229
230 // We need to tell the URL module, if we hav one, to release
231 // the allocated URLs
232 if (m_UrlModule != null)
233 m_UrlModule.ScriptRemoved(m_item.ItemID);
234
229 m_ScriptEngine.ApiResetScript(m_item.ItemID); 235 m_ScriptEngine.ApiResetScript(m_item.ItemID);
230 } 236 }
231 237
@@ -332,34 +338,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
332 338
333 public List<SceneObjectPart> GetLinkParts(int linkType) 339 public List<SceneObjectPart> GetLinkParts(int linkType)
334 { 340 {
341 return GetLinkParts(m_host, linkType);
342 }
343
344 private List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
345 {
335 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 346 List<SceneObjectPart> ret = new List<SceneObjectPart>();
336 if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted) 347 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
337 return ret; 348 return ret;
338 ret.Add(m_host); 349 ret.Add(part);
339 350
340 switch (linkType) 351 switch (linkType)
341 { 352 {
342 case ScriptBaseClass.LINK_SET: 353 case ScriptBaseClass.LINK_SET:
343 return new List<SceneObjectPart>(m_host.ParentGroup.Parts); 354 return new List<SceneObjectPart>(part.ParentGroup.Parts);
344 355
345 case ScriptBaseClass.LINK_ROOT: 356 case ScriptBaseClass.LINK_ROOT:
346 ret = new List<SceneObjectPart>(); 357 ret = new List<SceneObjectPart>();
347 ret.Add(m_host.ParentGroup.RootPart); 358 ret.Add(part.ParentGroup.RootPart);
348 return ret; 359 return ret;
349 360
350 case ScriptBaseClass.LINK_ALL_OTHERS: 361 case ScriptBaseClass.LINK_ALL_OTHERS:
351 ret = new List<SceneObjectPart>(m_host.ParentGroup.Parts); 362 ret = new List<SceneObjectPart>(part.ParentGroup.Parts);
352 363
353 if (ret.Contains(m_host)) 364 if (ret.Contains(part))
354 ret.Remove(m_host); 365 ret.Remove(part);
355 366
356 return ret; 367 return ret;
357 368
358 case ScriptBaseClass.LINK_ALL_CHILDREN: 369 case ScriptBaseClass.LINK_ALL_CHILDREN:
359 ret = new List<SceneObjectPart>(m_host.ParentGroup.Parts); 370 ret = new List<SceneObjectPart>(part.ParentGroup.Parts);
360 371
361 if (ret.Contains(m_host.ParentGroup.RootPart)) 372 if (ret.Contains(part.ParentGroup.RootPart))
362 ret.Remove(m_host.ParentGroup.RootPart); 373 ret.Remove(part.ParentGroup.RootPart);
363 return ret; 374 return ret;
364 375
365 case ScriptBaseClass.LINK_THIS: 376 case ScriptBaseClass.LINK_THIS:
@@ -369,7 +380,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
369 if (linkType < 0) 380 if (linkType < 0)
370 return new List<SceneObjectPart>(); 381 return new List<SceneObjectPart>();
371 382
372 SceneObjectPart target = m_host.ParentGroup.GetLinkNumPart(linkType); 383 SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType);
373 if (target == null) 384 if (target == null)
374 return new List<SceneObjectPart>(); 385 return new List<SceneObjectPart>();
375 ret = new List<SceneObjectPart>(); 386 ret = new List<SceneObjectPart>();
@@ -1764,13 +1775,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1764 { 1775 {
1765 try 1776 try
1766 { 1777 {
1767 parts[0].ParentGroup.areUpdatesSuspended = true;
1768 foreach (SceneObjectPart part in parts) 1778 foreach (SceneObjectPart part in parts)
1769 SetAlpha(part, alpha, face); 1779 SetAlpha(part, alpha, face);
1770 } 1780 }
1771 finally 1781 finally
1772 { 1782 {
1773 parts[0].ParentGroup.areUpdatesSuspended = false;
1774 } 1783 }
1775 } 1784 }
1776 } 1785 }
@@ -1951,13 +1960,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1951 { 1960 {
1952 try 1961 try
1953 { 1962 {
1954 parts[0].ParentGroup.areUpdatesSuspended = true;
1955 foreach (SceneObjectPart part in parts) 1963 foreach (SceneObjectPart part in parts)
1956 SetTexture(part, texture, face); 1964 SetTexture(part, texture, face);
1957 } 1965 }
1958 finally 1966 finally
1959 { 1967 {
1960 parts[0].ParentGroup.areUpdatesSuspended = false;
1961 } 1968 }
1962 } 1969 }
1963 ScriptSleep(200); 1970 ScriptSleep(200);
@@ -3340,7 +3347,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3340 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 3347 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3341 3348
3342 if (attachmentsModule != null) 3349 if (attachmentsModule != null)
3343 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true); 3350 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, false);
3344 else 3351 else
3345 return false; 3352 return false;
3346 } 3353 }
@@ -3747,29 +3754,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3747 3754
3748 m_host.AddScriptLPS(1); 3755 m_host.AddScriptLPS(1);
3749 3756
3757 int implicitPerms = 0;
3758
3750 if (m_host.ParentGroup.IsAttachment && (UUID)agent == m_host.ParentGroup.AttachedAvatar) 3759 if (m_host.ParentGroup.IsAttachment && (UUID)agent == m_host.ParentGroup.AttachedAvatar)
3751 { 3760 {
3752 // When attached, certain permissions are implicit if requested from owner 3761 // When attached, certain permissions are implicit if requested from owner
3753 int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3762 implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3754 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3763 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3755 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3764 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3756 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3765 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3757 ScriptBaseClass.PERMISSION_ATTACH; 3766 ScriptBaseClass.PERMISSION_ATTACH;
3758 3767
3759 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3760 {
3761 m_host.TaskInventory.LockItemsForWrite(true);
3762 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3763 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3764 m_host.TaskInventory.LockItemsForWrite(false);
3765
3766 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3767 "run_time_permissions", new Object[] {
3768 new LSL_Integer(perm) },
3769 new DetectParams[0]));
3770
3771 return;
3772 }
3773 } 3768 }
3774 else 3769 else
3775 { 3770 {
@@ -3790,26 +3785,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3790 if (sitting) 3785 if (sitting)
3791 { 3786 {
3792 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3787 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3793 int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3788 implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3794 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3789 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3795 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3790 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3796 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3791 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3792 }
3793 else
3794 {
3795 if (World.GetExtraSetting("auto_grant_attach_perms") == "true")
3796 implicitPerms = ScriptBaseClass.PERMISSION_ATTACH;
3797 }
3798 }
3797 3799
3798 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3800 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3799 { 3801 {
3800 m_host.TaskInventory.LockItemsForWrite(true); 3802 m_host.TaskInventory.LockItemsForWrite(true);
3801 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3803 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3802 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3804 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3803 m_host.TaskInventory.LockItemsForWrite(false); 3805 m_host.TaskInventory.LockItemsForWrite(false);
3804 3806
3805 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3807 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3806 "run_time_permissions", new Object[] { 3808 "run_time_permissions", new Object[] {
3807 new LSL_Integer(perm) }, 3809 new LSL_Integer(perm) },
3808 new DetectParams[0])); 3810 new DetectParams[0]));
3809 3811
3810 return; 3812 return;
3811 }
3812 }
3813 } 3813 }
3814 3814
3815 ScenePresence presence = World.GetScenePresence(agentID); 3815 ScenePresence presence = World.GetScenePresence(agentID);
@@ -3927,13 +3927,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3927 { 3927 {
3928 try 3928 try
3929 { 3929 {
3930 parts[0].ParentGroup.areUpdatesSuspended = true;
3931 foreach (SceneObjectPart part in parts) 3930 foreach (SceneObjectPart part in parts)
3932 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); 3931 part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
3933 } 3932 }
3934 finally 3933 finally
3935 { 3934 {
3936 parts[0].ParentGroup.areUpdatesSuspended = false;
3937 } 3935 }
3938 } 3936 }
3939 } 3937 }
@@ -4051,7 +4049,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4051 { 4049 {
4052 try 4050 try
4053 { 4051 {
4054 parts[0].ParentGroup.areUpdatesSuspended = true;
4055 foreach (SceneObjectPart part in parts) 4052 foreach (SceneObjectPart part in parts)
4056 { 4053 {
4057 parentPrim.DelinkFromGroup(part.LocalId, true); 4054 parentPrim.DelinkFromGroup(part.LocalId, true);
@@ -4059,7 +4056,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4059 } 4056 }
4060 finally 4057 finally
4061 { 4058 {
4062 parts[0].ParentGroup.areUpdatesSuspended = false;
4063 } 4059 }
4064 } 4060 }
4065 4061
@@ -4074,7 +4070,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4074 4070
4075 try 4071 try
4076 { 4072 {
4077 parts[0].ParentGroup.areUpdatesSuspended = true;
4078 foreach (SceneObjectPart part in parts) 4073 foreach (SceneObjectPart part in parts)
4079 { 4074 {
4080 part.ClearUpdateSchedule(); 4075 part.ClearUpdateSchedule();
@@ -4083,7 +4078,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4083 } 4078 }
4084 finally 4079 finally
4085 { 4080 {
4086 parts[0].ParentGroup.areUpdatesSuspended = false;
4087 } 4081 }
4088 4082
4089 4083
@@ -5369,12 +5363,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5369 { 5363 {
5370 return 0; 5364 return 0;
5371 } 5365 }
5366
5367 // Vectors & Rotations always return zero in SL, but
5368 // keys don't always return zero, it seems to be a bit complex.
5369 else if (src.Data[index] is LSL_Vector ||
5370 src.Data[index] is LSL_Rotation)
5371 {
5372 return 0;
5373 }
5372 try 5374 try
5373 { 5375 {
5376
5374 if (src.Data[index] is LSL_Integer) 5377 if (src.Data[index] is LSL_Integer)
5375 return (LSL_Integer) src.Data[index]; 5378 return (LSL_Integer)src.Data[index];
5376 else if (src.Data[index] is LSL_Float) 5379 else if (src.Data[index] is LSL_Float)
5377 return Convert.ToInt32(((LSL_Float) src.Data[index]).value); 5380 return Convert.ToInt32(((LSL_Float)src.Data[index]).value);
5378 return new LSL_Integer(src.Data[index].ToString()); 5381 return new LSL_Integer(src.Data[index].ToString());
5379 } 5382 }
5380 catch (FormatException) 5383 catch (FormatException)
@@ -5394,12 +5397,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5394 { 5397 {
5395 return 0.0; 5398 return 0.0;
5396 } 5399 }
5400
5401 // Vectors & Rotations always return zero in SL
5402 else if (src.Data[index] is LSL_Vector ||
5403 src.Data[index] is LSL_Rotation)
5404 {
5405 return 0;
5406 }
5407 // valid keys seem to get parsed as integers then converted to floats
5408 else
5409 {
5410 UUID uuidt;
5411 if (src.Data[index] is LSL_Key && UUID.TryParse(src.Data[index].ToString(), out uuidt))
5412 {
5413 return Convert.ToDouble(new LSL_Integer(src.Data[index].ToString()).value);
5414 }
5415 }
5397 try 5416 try
5398 { 5417 {
5399 if (src.Data[index] is LSL_Integer) 5418 if (src.Data[index] is LSL_Integer)
5400 return Convert.ToDouble(((LSL_Integer) src.Data[index]).value); 5419 return Convert.ToDouble(((LSL_Integer)src.Data[index]).value);
5401 else if (src.Data[index] is LSL_Float) 5420 else if (src.Data[index] is LSL_Float)
5402 return Convert.ToDouble(((LSL_Float) src.Data[index]).value); 5421 return Convert.ToDouble(((LSL_Float)src.Data[index]).value);
5403 else if (src.Data[index] is LSL_String) 5422 else if (src.Data[index] is LSL_String)
5404 { 5423 {
5405 string str = ((LSL_String) src.Data[index]).m_string; 5424 string str = ((LSL_String) src.Data[index]).m_string;
@@ -5437,17 +5456,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5437 return src.Data[index].ToString(); 5456 return src.Data[index].ToString();
5438 } 5457 }
5439 5458
5440 public LSL_String llList2Key(LSL_List src, int index) 5459 public LSL_Key llList2Key(LSL_List src, int index)
5441 { 5460 {
5442 m_host.AddScriptLPS(1); 5461 m_host.AddScriptLPS(1);
5443 if (index < 0) 5462 if (index < 0)
5444 { 5463 {
5445 index = src.Length + index; 5464 index = src.Length + index;
5446 } 5465 }
5466
5447 if (index >= src.Length || index < 0) 5467 if (index >= src.Length || index < 0)
5448 { 5468 {
5449 return ""; 5469 return "";
5450 } 5470 }
5471
5472 // SL spits out an empty string for types other than key & string
5473 // At the time of patching, LSL_Key is currently LSL_String,
5474 // so the OR check may be a little redundant, but it's being done
5475 // for completion and should LSL_Key ever be implemented
5476 // as it's own struct
5477 else if (!(src.Data[index] is LSL_String ||
5478 src.Data[index] is LSL_Key))
5479 {
5480 return "";
5481 }
5482
5451 return src.Data[index].ToString(); 5483 return src.Data[index].ToString();
5452 } 5484 }
5453 5485
@@ -5466,6 +5498,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5466 { 5498 {
5467 return (LSL_Vector)src.Data[index]; 5499 return (LSL_Vector)src.Data[index];
5468 } 5500 }
5501
5502 // SL spits always out ZERO_VECTOR for anything other than
5503 // strings or vectors. Although keys always return ZERO_VECTOR,
5504 // it is currently difficult to make the distinction between
5505 // a string, a key as string and a string that by coincidence
5506 // is a string, so we're going to leave that up to the
5507 // LSL_Vector constructor.
5508 else if (!(src.Data[index] is LSL_String ||
5509 src.Data[index] is LSL_Vector))
5510 {
5511 return new LSL_Vector(0, 0, 0);
5512 }
5469 else 5513 else
5470 { 5514 {
5471 return new LSL_Vector(src.Data[index].ToString()); 5515 return new LSL_Vector(src.Data[index].ToString());
@@ -5483,7 +5527,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5483 { 5527 {
5484 return new LSL_Rotation(0, 0, 0, 1); 5528 return new LSL_Rotation(0, 0, 0, 1);
5485 } 5529 }
5486 if (src.Data[index].GetType() == typeof(LSL_Rotation)) 5530
5531 // SL spits always out ZERO_ROTATION for anything other than
5532 // strings or vectors. Although keys always return ZERO_ROTATION,
5533 // it is currently difficult to make the distinction between
5534 // a string, a key as string and a string that by coincidence
5535 // is a string, so we're going to leave that up to the
5536 // LSL_Rotation constructor.
5537 else if (!(src.Data[index] is LSL_String ||
5538 src.Data[index] is LSL_Rotation))
5539 {
5540 return new LSL_Rotation(0, 0, 0, 1);
5541 }
5542 else if (src.Data[index].GetType() == typeof(LSL_Rotation))
5487 { 5543 {
5488 return (LSL_Rotation)src.Data[index]; 5544 return (LSL_Rotation)src.Data[index];
5489 } 5545 }
@@ -6236,7 +6292,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6236 { 6292 {
6237 try 6293 try
6238 { 6294 {
6239 parts[0].ParentGroup.areUpdatesSuspended = true;
6240 foreach (var part in parts) 6295 foreach (var part in parts)
6241 { 6296 {
6242 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6297 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
@@ -6244,7 +6299,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6244 } 6299 }
6245 finally 6300 finally
6246 { 6301 {
6247 parts[0].ParentGroup.areUpdatesSuspended = false;
6248 } 6302 }
6249 } 6303 }
6250 } 6304 }
@@ -7689,7 +7743,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7689 public void llSetPrimitiveParams(LSL_List rules) 7743 public void llSetPrimitiveParams(LSL_List rules)
7690 { 7744 {
7691 m_host.AddScriptLPS(1); 7745 m_host.AddScriptLPS(1);
7692 SetPrimParams(m_host, rules); 7746
7747 setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules);
7693 7748
7694 ScriptSleep(200); 7749 ScriptSleep(200);
7695 } 7750 }
@@ -7703,26 +7758,47 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7703 7758
7704 private void setLinkPrimParams(int linknumber, LSL_List rules) 7759 private void setLinkPrimParams(int linknumber, LSL_List rules)
7705 { 7760 {
7706 List<SceneObjectPart> parts = GetLinkParts(linknumber); 7761 List<object> parts = new List<object>();
7762 List<SceneObjectPart> prims = GetLinkParts(linknumber);
7707 List<ScenePresence> avatars = GetLinkAvatars(linknumber); 7763 List<ScenePresence> avatars = GetLinkAvatars(linknumber);
7708 if (parts.Count>0) 7764 foreach (SceneObjectPart p in prims)
7765 parts.Add(p);
7766 foreach (ScenePresence p in avatars)
7767 parts.Add(p);
7768
7769 LSL_List remaining = null;
7770
7771 if (parts.Count > 0)
7709 { 7772 {
7710 try 7773 foreach (object part in parts)
7711 { 7774 {
7712 parts[0].ParentGroup.areUpdatesSuspended = true; 7775 if (part is SceneObjectPart)
7713 foreach (SceneObjectPart part in parts) 7776 remaining = SetPrimParams((SceneObjectPart)part, rules);
7714 SetPrimParams(part, rules); 7777 else
7778 remaining = SetPrimParams((ScenePresence)part, rules);
7715 } 7779 }
7716 finally 7780
7781 while((object)remaining != null && remaining.Length > 2)
7717 { 7782 {
7718 parts[0].ParentGroup.areUpdatesSuspended = false; 7783 linknumber = remaining.GetLSLIntegerItem(0);
7784 rules = remaining.GetSublist(1,-1);
7785 parts.Clear();
7786 prims = GetLinkParts(linknumber);
7787 avatars = GetLinkAvatars(linknumber);
7788 foreach (SceneObjectPart p in prims)
7789 parts.Add(p);
7790 foreach (ScenePresence p in avatars)
7791 parts.Add(p);
7792
7793 foreach (object part in parts)
7794 {
7795 if (part is SceneObjectPart)
7796 remaining = SetPrimParams((SceneObjectPart)part, rules);
7797 else
7798 remaining = SetPrimParams((ScenePresence)part, rules);
7799 }
7719 } 7800 }
7720 } 7801 }
7721 if (avatars.Count > 0)
7722 {
7723 foreach (ScenePresence avatar in avatars)
7724 SetPrimParams(avatar, rules);
7725 }
7726 } 7802 }
7727 7803
7728 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits, 7804 private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
@@ -7784,7 +7860,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7784 return new Vector3((float)x, (float)y, (float)z); 7860 return new Vector3((float)x, (float)y, (float)z);
7785 } 7861 }
7786 7862
7787 protected void SetPrimParams(ScenePresence av, LSL_List rules) 7863 protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules)
7788 { 7864 {
7789 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset. 7865 //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
7790 7866
@@ -7807,7 +7883,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7807 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 7883 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
7808 { 7884 {
7809 if (remain < 1) 7885 if (remain < 1)
7810 return; 7886 return null;
7811 7887
7812 LSL_Vector v; 7888 LSL_Vector v;
7813 v = rules.GetVector3Item(idx++); 7889 v = rules.GetVector3Item(idx++);
@@ -7841,7 +7917,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7841 case (int)ScriptBaseClass.PRIM_ROTATION: 7917 case (int)ScriptBaseClass.PRIM_ROTATION:
7842 { 7918 {
7843 if (remain < 1) 7919 if (remain < 1)
7844 return; 7920 return null;
7845 7921
7846 LSL_Rotation r; 7922 LSL_Rotation r;
7847 r = rules.GetQuaternionItem(idx++); 7923 r = rules.GetQuaternionItem(idx++);
@@ -7872,7 +7948,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7872 case (int)ScriptBaseClass.PRIM_NAME: 7948 case (int)ScriptBaseClass.PRIM_NAME:
7873 case (int)ScriptBaseClass.PRIM_DESC: 7949 case (int)ScriptBaseClass.PRIM_DESC:
7874 if (remain < 1) 7950 if (remain < 1)
7875 return; 7951 return null;
7876 idx++; 7952 idx++;
7877 break; 7953 break;
7878 7954
@@ -7880,13 +7956,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7880 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 7956 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
7881 case (int)ScriptBaseClass.PRIM_TEXGEN: 7957 case (int)ScriptBaseClass.PRIM_TEXGEN:
7882 if (remain < 2) 7958 if (remain < 2)
7883 return; 7959 return null;
7884 idx += 2; 7960 idx += 2;
7885 break; 7961 break;
7886 7962
7887 case (int)ScriptBaseClass.PRIM_TYPE: 7963 case (int)ScriptBaseClass.PRIM_TYPE:
7888 if (remain < 3) 7964 if (remain < 3)
7889 return; 7965 return null;
7890 code = (int)rules.GetLSLIntegerItem(idx++); 7966 code = (int)rules.GetLSLIntegerItem(idx++);
7891 remain = rules.Length - idx; 7967 remain = rules.Length - idx;
7892 switch (code) 7968 switch (code)
@@ -7895,13 +7971,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7895 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: 7971 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
7896 case (int)ScriptBaseClass.PRIM_TYPE_PRISM: 7972 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
7897 if (remain < 6) 7973 if (remain < 6)
7898 return; 7974 return null;
7899 idx += 6; 7975 idx += 6;
7900 break; 7976 break;
7901 7977
7902 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: 7978 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
7903 if (remain < 5) 7979 if (remain < 5)
7904 return; 7980 return null;
7905 idx += 5; 7981 idx += 5;
7906 break; 7982 break;
7907 7983
@@ -7909,13 +7985,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7909 case (int)ScriptBaseClass.PRIM_TYPE_TUBE: 7985 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
7910 case (int)ScriptBaseClass.PRIM_TYPE_RING: 7986 case (int)ScriptBaseClass.PRIM_TYPE_RING:
7911 if (remain < 11) 7987 if (remain < 11)
7912 return; 7988 return null;
7913 idx += 11; 7989 idx += 11;
7914 break; 7990 break;
7915 7991
7916 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: 7992 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
7917 if (remain < 2) 7993 if (remain < 2)
7918 return; 7994 return null;
7919 idx += 2; 7995 idx += 2;
7920 break; 7996 break;
7921 } 7997 }
@@ -7926,7 +8002,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7926 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8002 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
7927 case (int)ScriptBaseClass.PRIM_OMEGA: 8003 case (int)ScriptBaseClass.PRIM_OMEGA:
7928 if (remain < 3) 8004 if (remain < 3)
7929 return; 8005 return null;
7930 idx += 3; 8006 idx += 3;
7931 break; 8007 break;
7932 8008
@@ -7934,33 +8010,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7934 case (int)ScriptBaseClass.PRIM_POINT_LIGHT: 8010 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
7935 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL: 8011 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
7936 if (remain < 5) 8012 if (remain < 5)
7937 return; 8013 return null;
7938 idx += 5; 8014 idx += 5;
7939 break; 8015 break;
7940 8016
7941 case (int)ScriptBaseClass.PRIM_FLEXIBLE: 8017 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
7942 if (remain < 7) 8018 if (remain < 7)
7943 return; 8019 return null;
7944 8020
7945 idx += 7; 8021 idx += 7;
7946 break; 8022 break;
7947 8023
7948 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 8024 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
7949 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. 8025 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
7950 return; 8026 return null;
7951 8027
7952 if (positionChanged) 8028 return rules.GetSublist(idx, -1);
7953 {
7954 positionChanged = false;
7955 av.OffsetPosition = finalPos;
7956// av.SendAvatarDataToAllAgents();
7957 av.SendTerseUpdateToAllClients();
7958 }
7959
7960 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
7961 LSL_List new_rules = rules.GetSublist(idx, -1);
7962 setLinkPrimParams((int)new_linknumber, new_rules);
7963 return;
7964 } 8029 }
7965 } 8030 }
7966 } 8031 }
@@ -7975,12 +8040,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7975 positionChanged = false; 8040 positionChanged = false;
7976 } 8041 }
7977 } 8042 }
8043 return null;
7978 } 8044 }
7979 8045
7980 protected void SetPrimParams(SceneObjectPart part, LSL_List rules) 8046 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules)
7981 { 8047 {
7982 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 8048 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7983 return; 8049 return null;
7984 8050
7985 int idx = 0; 8051 int idx = 0;
7986 8052
@@ -8005,7 +8071,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8005 case (int)ScriptBaseClass.PRIM_POSITION: 8071 case (int)ScriptBaseClass.PRIM_POSITION:
8006 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 8072 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
8007 if (remain < 1) 8073 if (remain < 1)
8008 return; 8074 return null;
8009 8075
8010 v=rules.GetVector3Item(idx++); 8076 v=rules.GetVector3Item(idx++);
8011 currentPosition = GetSetPosTarget(part, v, currentPosition); 8077 currentPosition = GetSetPosTarget(part, v, currentPosition);
@@ -8014,7 +8080,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8014 break; 8080 break;
8015 case (int)ScriptBaseClass.PRIM_SIZE: 8081 case (int)ScriptBaseClass.PRIM_SIZE:
8016 if (remain < 1) 8082 if (remain < 1)
8017 return; 8083 return null;
8018 8084
8019 v=rules.GetVector3Item(idx++); 8085 v=rules.GetVector3Item(idx++);
8020 SetScale(part, v); 8086 SetScale(part, v);
@@ -8022,7 +8088,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8022 break; 8088 break;
8023 case (int)ScriptBaseClass.PRIM_ROTATION: 8089 case (int)ScriptBaseClass.PRIM_ROTATION:
8024 if (remain < 1) 8090 if (remain < 1)
8025 return; 8091 return null;
8026 8092
8027 LSL_Rotation q = rules.GetQuaternionItem(idx++); 8093 LSL_Rotation q = rules.GetQuaternionItem(idx++);
8028 SceneObjectPart rootPart = parentgrp.RootPart; 8094 SceneObjectPart rootPart = parentgrp.RootPart;
@@ -8043,7 +8109,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8043 8109
8044 case (int)ScriptBaseClass.PRIM_TYPE: 8110 case (int)ScriptBaseClass.PRIM_TYPE:
8045 if (remain < 3) 8111 if (remain < 3)
8046 return; 8112 return null;
8047 8113
8048 code = (int)rules.GetLSLIntegerItem(idx++); 8114 code = (int)rules.GetLSLIntegerItem(idx++);
8049 8115
@@ -8062,7 +8128,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8062 { 8128 {
8063 case (int)ScriptBaseClass.PRIM_TYPE_BOX: 8129 case (int)ScriptBaseClass.PRIM_TYPE_BOX:
8064 if (remain < 6) 8130 if (remain < 6)
8065 return; 8131 return null;
8066 8132
8067 face = (int)rules.GetLSLIntegerItem(idx++); 8133 face = (int)rules.GetLSLIntegerItem(idx++);
8068 v = rules.GetVector3Item(idx++); // cut 8134 v = rules.GetVector3Item(idx++); // cut
@@ -8077,7 +8143,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8077 8143
8078 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: 8144 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
8079 if (remain < 6) 8145 if (remain < 6)
8080 return; 8146 return null;
8081 8147
8082 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8148 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
8083 v = rules.GetVector3Item(idx++); // cut 8149 v = rules.GetVector3Item(idx++); // cut
@@ -8091,7 +8157,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8091 8157
8092 case (int)ScriptBaseClass.PRIM_TYPE_PRISM: 8158 case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
8093 if (remain < 6) 8159 if (remain < 6)
8094 return; 8160 return null;
8095 8161
8096 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8162 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
8097 v = rules.GetVector3Item(idx++); //cut 8163 v = rules.GetVector3Item(idx++); //cut
@@ -8105,7 +8171,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8105 8171
8106 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: 8172 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
8107 if (remain < 5) 8173 if (remain < 5)
8108 return; 8174 return null;
8109 8175
8110 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8176 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
8111 v = rules.GetVector3Item(idx++); // cut 8177 v = rules.GetVector3Item(idx++); // cut
@@ -8118,7 +8184,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8118 8184
8119 case (int)ScriptBaseClass.PRIM_TYPE_TORUS: 8185 case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
8120 if (remain < 11) 8186 if (remain < 11)
8121 return; 8187 return null;
8122 8188
8123 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8189 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
8124 v = rules.GetVector3Item(idx++); //cut 8190 v = rules.GetVector3Item(idx++); //cut
@@ -8137,7 +8203,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8137 8203
8138 case (int)ScriptBaseClass.PRIM_TYPE_TUBE: 8204 case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
8139 if (remain < 11) 8205 if (remain < 11)
8140 return; 8206 return null;
8141 8207
8142 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8208 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
8143 v = rules.GetVector3Item(idx++); //cut 8209 v = rules.GetVector3Item(idx++); //cut
@@ -8156,7 +8222,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8156 8222
8157 case (int)ScriptBaseClass.PRIM_TYPE_RING: 8223 case (int)ScriptBaseClass.PRIM_TYPE_RING:
8158 if (remain < 11) 8224 if (remain < 11)
8159 return; 8225 return null;
8160 8226
8161 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8227 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
8162 v = rules.GetVector3Item(idx++); //cut 8228 v = rules.GetVector3Item(idx++); //cut
@@ -8175,7 +8241,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8175 8241
8176 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: 8242 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
8177 if (remain < 2) 8243 if (remain < 2)
8178 return; 8244 return null;
8179 8245
8180 string map = rules.Data[idx++].ToString(); 8246 string map = rules.Data[idx++].ToString();
8181 face = (int)rules.GetLSLIntegerItem(idx++); // type 8247 face = (int)rules.GetLSLIntegerItem(idx++); // type
@@ -8187,7 +8253,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8187 8253
8188 case (int)ScriptBaseClass.PRIM_TEXTURE: 8254 case (int)ScriptBaseClass.PRIM_TEXTURE:
8189 if (remain < 5) 8255 if (remain < 5)
8190 return; 8256 return null;
8191 8257
8192 face=(int)rules.GetLSLIntegerItem(idx++); 8258 face=(int)rules.GetLSLIntegerItem(idx++);
8193 string tex=rules.Data[idx++].ToString(); 8259 string tex=rules.Data[idx++].ToString();
@@ -8204,7 +8270,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8204 8270
8205 case (int)ScriptBaseClass.PRIM_COLOR: 8271 case (int)ScriptBaseClass.PRIM_COLOR:
8206 if (remain < 3) 8272 if (remain < 3)
8207 return; 8273 return null;
8208 8274
8209 face=(int)rules.GetLSLIntegerItem(idx++); 8275 face=(int)rules.GetLSLIntegerItem(idx++);
8210 LSL_Vector color=rules.GetVector3Item(idx++); 8276 LSL_Vector color=rules.GetVector3Item(idx++);
@@ -8217,7 +8283,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8217 8283
8218 case (int)ScriptBaseClass.PRIM_FLEXIBLE: 8284 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
8219 if (remain < 7) 8285 if (remain < 7)
8220 return; 8286 return null;
8221 8287
8222 bool flexi = rules.GetLSLIntegerItem(idx++); 8288 bool flexi = rules.GetLSLIntegerItem(idx++);
8223 int softness = rules.GetLSLIntegerItem(idx++); 8289 int softness = rules.GetLSLIntegerItem(idx++);
@@ -8233,7 +8299,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8233 8299
8234 case (int)ScriptBaseClass.PRIM_POINT_LIGHT: 8300 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
8235 if (remain < 5) 8301 if (remain < 5)
8236 return; 8302 return null;
8237 bool light = rules.GetLSLIntegerItem(idx++); 8303 bool light = rules.GetLSLIntegerItem(idx++);
8238 LSL_Vector lightcolor = rules.GetVector3Item(idx++); 8304 LSL_Vector lightcolor = rules.GetVector3Item(idx++);
8239 float intensity = (float)rules.GetLSLFloatItem(idx++); 8305 float intensity = (float)rules.GetLSLFloatItem(idx++);
@@ -8246,7 +8312,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8246 8312
8247 case (int)ScriptBaseClass.PRIM_GLOW: 8313 case (int)ScriptBaseClass.PRIM_GLOW:
8248 if (remain < 2) 8314 if (remain < 2)
8249 return; 8315 return null;
8250 face = rules.GetLSLIntegerItem(idx++); 8316 face = rules.GetLSLIntegerItem(idx++);
8251 float glow = (float)rules.GetLSLFloatItem(idx++); 8317 float glow = (float)rules.GetLSLFloatItem(idx++);
8252 8318
@@ -8256,7 +8322,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8256 8322
8257 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 8323 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8258 if (remain < 3) 8324 if (remain < 3)
8259 return; 8325 return null;
8260 face = (int)rules.GetLSLIntegerItem(idx++); 8326 face = (int)rules.GetLSLIntegerItem(idx++);
8261 int shiny = (int)rules.GetLSLIntegerItem(idx++); 8327 int shiny = (int)rules.GetLSLIntegerItem(idx++);
8262 Bumpiness bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++); 8328 Bumpiness bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++);
@@ -8267,7 +8333,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8267 8333
8268 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 8334 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8269 if (remain < 2) 8335 if (remain < 2)
8270 return; 8336 return null;
8271 face = rules.GetLSLIntegerItem(idx++); 8337 face = rules.GetLSLIntegerItem(idx++);
8272 bool st = rules.GetLSLIntegerItem(idx++); 8338 bool st = rules.GetLSLIntegerItem(idx++);
8273 SetFullBright(part, face , st); 8339 SetFullBright(part, face , st);
@@ -8275,17 +8341,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8275 8341
8276 case (int)ScriptBaseClass.PRIM_MATERIAL: 8342 case (int)ScriptBaseClass.PRIM_MATERIAL:
8277 if (remain < 1) 8343 if (remain < 1)
8278 return; 8344 return null;
8279 int mat = rules.GetLSLIntegerItem(idx++); 8345 int mat = rules.GetLSLIntegerItem(idx++);
8280 if (mat < 0 || mat > 7) 8346 if (mat < 0 || mat > 7)
8281 return; 8347 return null;
8282 8348
8283 part.Material = Convert.ToByte(mat); 8349 part.Material = Convert.ToByte(mat);
8284 break; 8350 break;
8285 8351
8286 case (int)ScriptBaseClass.PRIM_PHANTOM: 8352 case (int)ScriptBaseClass.PRIM_PHANTOM:
8287 if (remain < 1) 8353 if (remain < 1)
8288 return; 8354 return null;
8289 8355
8290 string ph = rules.Data[idx++].ToString(); 8356 string ph = rules.Data[idx++].ToString();
8291 parentgrp.ScriptSetPhantomStatus(ph.Equals("1")); 8357 parentgrp.ScriptSetPhantomStatus(ph.Equals("1"));
@@ -8294,7 +8360,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8294 8360
8295 case (int)ScriptBaseClass.PRIM_PHYSICS: 8361 case (int)ScriptBaseClass.PRIM_PHYSICS:
8296 if (remain < 1) 8362 if (remain < 1)
8297 return; 8363 return null;
8298 string phy = rules.Data[idx++].ToString(); 8364 string phy = rules.Data[idx++].ToString();
8299 bool physics; 8365 bool physics;
8300 8366
@@ -8308,7 +8374,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8308 8374
8309 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: 8375 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
8310 if (remain < 1) 8376 if (remain < 1)
8311 return; 8377 return null;
8312 8378
8313 int shape_type = rules.GetLSLIntegerItem(idx++); 8379 int shape_type = rules.GetLSLIntegerItem(idx++);
8314 8380
@@ -8324,7 +8390,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8324 8390
8325 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL: 8391 case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
8326 if (remain < 5) 8392 if (remain < 5)
8327 return; 8393 return null;
8328 8394
8329 int material_bits = rules.GetLSLIntegerItem(idx++); 8395 int material_bits = rules.GetLSLIntegerItem(idx++);
8330 float material_density = (float)rules.GetLSLFloatItem(idx++); 8396 float material_density = (float)rules.GetLSLFloatItem(idx++);
@@ -8338,7 +8404,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8338 8404
8339 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 8405 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
8340 if (remain < 1) 8406 if (remain < 1)
8341 return; 8407 return null;
8342 string temp = rules.Data[idx++].ToString(); 8408 string temp = rules.Data[idx++].ToString();
8343 8409
8344 parentgrp.ScriptSetTemporaryStatus(temp.Equals("1")); 8410 parentgrp.ScriptSetTemporaryStatus(temp.Equals("1"));
@@ -8347,7 +8413,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8347 8413
8348 case (int)ScriptBaseClass.PRIM_TEXGEN: 8414 case (int)ScriptBaseClass.PRIM_TEXGEN:
8349 if (remain < 2) 8415 if (remain < 2)
8350 return; 8416 return null;
8351 //face,type 8417 //face,type
8352 face = rules.GetLSLIntegerItem(idx++); 8418 face = rules.GetLSLIntegerItem(idx++);
8353 int style = rules.GetLSLIntegerItem(idx++); 8419 int style = rules.GetLSLIntegerItem(idx++);
@@ -8355,7 +8421,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8355 break; 8421 break;
8356 case (int)ScriptBaseClass.PRIM_TEXT: 8422 case (int)ScriptBaseClass.PRIM_TEXT:
8357 if (remain < 3) 8423 if (remain < 3)
8358 return; 8424 return null;
8359 string primText = rules.GetLSLStringItem(idx++); 8425 string primText = rules.GetLSLStringItem(idx++);
8360 LSL_Vector primTextColor = rules.GetVector3Item(idx++); 8426 LSL_Vector primTextColor = rules.GetVector3Item(idx++);
8361 LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); 8427 LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++);
@@ -8367,26 +8433,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8367 break; 8433 break;
8368 case (int)ScriptBaseClass.PRIM_NAME: 8434 case (int)ScriptBaseClass.PRIM_NAME:
8369 if (remain < 1) 8435 if (remain < 1)
8370 return; 8436 return null;
8371 string primName = rules.GetLSLStringItem(idx++); 8437 string primName = rules.GetLSLStringItem(idx++);
8372 part.Name = primName; 8438 part.Name = primName;
8373 break; 8439 break;
8374 case (int)ScriptBaseClass.PRIM_DESC: 8440 case (int)ScriptBaseClass.PRIM_DESC:
8375 if (remain < 1) 8441 if (remain < 1)
8376 return; 8442 return null;
8377 string primDesc = rules.GetLSLStringItem(idx++); 8443 string primDesc = rules.GetLSLStringItem(idx++);
8378 part.Description = primDesc; 8444 part.Description = primDesc;
8379 break; 8445 break;
8380 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 8446 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8381 if (remain < 1) 8447 if (remain < 1)
8382 return; 8448 return null;
8383
8384 LSL_Rotation lr = rules.GetQuaternionItem(idx++); 8449 LSL_Rotation lr = rules.GetQuaternionItem(idx++);
8385 SetRot(part, Rot2Quaternion(lr)); 8450 SetRot(part, Rot2Quaternion(lr));
8386 break; 8451 break;
8387 case (int)ScriptBaseClass.PRIM_OMEGA: 8452 case (int)ScriptBaseClass.PRIM_OMEGA:
8388 if (remain < 3) 8453 if (remain < 3)
8389 return; 8454 return null;
8390 LSL_Vector axis = rules.GetVector3Item(idx++); 8455 LSL_Vector axis = rules.GetVector3Item(idx++);
8391 LSL_Float spinrate = rules.GetLSLFloatItem(idx++); 8456 LSL_Float spinrate = rules.GetLSLFloatItem(idx++);
8392 LSL_Float gain = rules.GetLSLFloatItem(idx++); 8457 LSL_Float gain = rules.GetLSLFloatItem(idx++);
@@ -8395,35 +8460,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8395 8460
8396 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 8461 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
8397 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. 8462 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
8398 return; 8463 return null;
8399
8400 // do a pending position change before jumping to other part/avatar
8401 if (positionChanged)
8402 {
8403 positionChanged = false;
8404 if (parentgrp == null)
8405 return;
8406 8464
8407 if (parentgrp.RootPart == part) 8465 return rules.GetSublist(idx, -1);
8408 {
8409
8410 Util.FireAndForget(delegate(object x)
8411 {
8412 parentgrp.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
8413 });
8414 }
8415 else
8416 {
8417 part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
8418 parentgrp.HasGroupChanged = true;
8419 parentgrp.ScheduleGroupForTerseUpdate();
8420 }
8421 }
8422
8423 LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
8424 LSL_List new_rules = rules.GetSublist(idx, -1);
8425 setLinkPrimParams((int)new_linknumber, new_rules);
8426 return;
8427 } 8466 }
8428 } 8467 }
8429 } 8468 }
@@ -8447,6 +8486,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8447 } 8486 }
8448 } 8487 }
8449 } 8488 }
8489 return null;
8450 } 8490 }
8451 8491
8452 public LSL_String llStringToBase64(string str) 8492 public LSL_String llStringToBase64(string str)
@@ -12082,7 +12122,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
12082 if (obj.OwnerID != m_host.OwnerID) 12122 if (obj.OwnerID != m_host.OwnerID)
12083 return; 12123 return;
12084 12124
12085 SetPrimParams(obj, rules); 12125 LSL_List remaining = SetPrimParams(obj, rules);
12126
12127 while ((object)remaining != null && remaining.Length > 2)
12128 {
12129 LSL_Integer newLink = remaining.GetLSLIntegerItem(0);
12130 LSL_List newrules = remaining.GetSublist(1, -1);
12131 foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){
12132 remaining = SetPrimParams(part, newrules);
12133 }
12134 }
12086 } 12135 }
12087 12136
12088 public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules) 12137 public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 0bb933c..2f02f1f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -2466,8 +2466,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2466 if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) 2466 if (!npcModule.CheckPermissions(npcId, m_host.OwnerID))
2467 return new LSL_Vector(0, 0, 0); 2467 return new LSL_Vector(0, 0, 0);
2468 2468
2469 Vector3 pos = World.GetScenePresence(npcId).AbsolutePosition; 2469 ScenePresence sp = World.GetScenePresence(npcId);
2470 return new LSL_Vector(pos.X, pos.Y, pos.Z); 2470
2471 if (sp != null)
2472 {
2473 Vector3 pos = sp.AbsolutePosition;
2474 return new LSL_Vector(pos.X, pos.Y, pos.Z);
2475 }
2471 } 2476 }
2472 2477
2473 return new LSL_Vector(0, 0, 0); 2478 return new LSL_Vector(0, 0, 0);
@@ -2535,9 +2540,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2535 return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W); 2540 return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W);
2536 2541
2537 ScenePresence sp = World.GetScenePresence(npcId); 2542 ScenePresence sp = World.GetScenePresence(npcId);
2538 Quaternion rot = sp.Rotation;
2539 2543
2540 return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W); 2544 if (sp != null)
2545 {
2546 Quaternion rot = sp.Rotation;
2547 return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W);
2548 }
2541 } 2549 }
2542 2550
2543 return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W); 2551 return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W);
@@ -2559,7 +2567,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2559 return; 2567 return;
2560 2568
2561 ScenePresence sp = World.GetScenePresence(npcId); 2569 ScenePresence sp = World.GetScenePresence(npcId);
2562 sp.Rotation = LSL_Api.Rot2Quaternion(rotation); 2570
2571 if (sp != null)
2572 sp.Rotation = LSL_Api.Rot2Quaternion(rotation);
2563 } 2573 }
2564 } 2574 }
2565 2575
@@ -2737,6 +2747,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2737 { 2747 {
2738 CheckThreatLevel(ThreatLevel.High, "osNpcTouch"); 2748 CheckThreatLevel(ThreatLevel.High, "osNpcTouch");
2739 m_host.AddScriptLPS(1); 2749 m_host.AddScriptLPS(1);
2750
2740 INPCModule module = World.RequestModuleInterface<INPCModule>(); 2751 INPCModule module = World.RequestModuleInterface<INPCModule>();
2741 int linkNum = link_num.value; 2752 int linkNum = link_num.value;
2742 if (module != null || (linkNum < 0 && linkNum != ScriptBaseClass.LINK_THIS)) 2753 if (module != null || (linkNum < 0 && linkNum != ScriptBaseClass.LINK_THIS))
@@ -2744,12 +2755,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2744 UUID npcId; 2755 UUID npcId;
2745 if (!UUID.TryParse(npcLSL_Key, out npcId) || !module.CheckPermissions(npcId, m_host.OwnerID)) 2756 if (!UUID.TryParse(npcLSL_Key, out npcId) || !module.CheckPermissions(npcId, m_host.OwnerID))
2746 return; 2757 return;
2758
2747 SceneObjectPart part = null; 2759 SceneObjectPart part = null;
2748 UUID objectId; 2760 UUID objectId;
2749 if (UUID.TryParse(LSL_String.ToString(object_key), out objectId)) 2761 if (UUID.TryParse(LSL_String.ToString(object_key), out objectId))
2750 part = World.GetSceneObjectPart(objectId); 2762 part = World.GetSceneObjectPart(objectId);
2763
2751 if (part == null) 2764 if (part == null)
2752 return; 2765 return;
2766
2753 if (linkNum != ScriptBaseClass.LINK_THIS) 2767 if (linkNum != ScriptBaseClass.LINK_THIS)
2754 { 2768 {
2755 if (linkNum == 0 || linkNum == ScriptBaseClass.LINK_ROOT) 2769 if (linkNum == 0 || linkNum == ScriptBaseClass.LINK_ROOT)
@@ -2764,6 +2778,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2764 return; 2778 return;
2765 } 2779 }
2766 } 2780 }
2781
2767 module.Touch(npcId, part.UUID); 2782 module.Touch(npcId, part.UUID);
2768 } 2783 }
2769 } 2784 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
index a08cc42..f989cc6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs
@@ -226,6 +226,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
226 public const int ATTACH_BELLY = 28; 226 public const int ATTACH_BELLY = 28;
227 public const int ATTACH_RPEC = 29; 227 public const int ATTACH_RPEC = 29;
228 public const int ATTACH_LPEC = 30; 228 public const int ATTACH_LPEC = 30;
229 public const int ATTACH_LEFT_PEC = 29; // Same value as ATTACH_RPEC, see https://jira.secondlife.com/browse/SVC-580
230 public const int ATTACH_RIGHT_PEC = 30; // Same value as ATTACH_LPEC, see https://jira.secondlife.com/browse/SVC-580
229 public const int ATTACH_HUD_CENTER_2 = 31; 231 public const int ATTACH_HUD_CENTER_2 = 31;
230 public const int ATTACH_HUD_TOP_RIGHT = 32; 232 public const int ATTACH_HUD_TOP_RIGHT = 32;
231 public const int ATTACH_HUD_TOP_CENTER = 33; 233 public const int ATTACH_HUD_TOP_CENTER = 33;