aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Application/OpenSim.cs76
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs39
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs61
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs31
-rw-r--r--OpenSim/Region/ClientStack/RegionApplicationBase.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs51
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs20
-rw-r--r--OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs19
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs5
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs5
-rw-r--r--OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs2
-rwxr-xr-xOpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs161
-rw-r--r--OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs24
-rw-r--r--OpenSim/Region/CoreModules/World/Access/AccessModule.cs10
-rw-r--r--OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs9
-rw-r--r--OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs11
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScenePresence.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs50
-rw-r--r--OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs69
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs129
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs36
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs60
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs27
-rw-r--r--OpenSim/Region/Framework/Scenes/SimStatsReporter.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs302
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs1
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs1
-rw-r--r--OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs73
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs1
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs2
-rwxr-xr-xOpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs130
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs33
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs69
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs125
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs184
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs187
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs352
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs614
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs828
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs272
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs5
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs15
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs30
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs16
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs44
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs89
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs23
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs15
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs39
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Helpers.cs34
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs14
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs22
-rw-r--r--OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs2
-rw-r--r--OpenSim/Region/UserStatistics/Default_Report.cs2
-rw-r--r--OpenSim/Region/UserStatistics/LogLinesAJAX.cs2
-rw-r--r--OpenSim/Region/UserStatistics/SimStatsAJAX.cs2
75 files changed, 3217 insertions, 1260 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index e6b57c2..ba8aa9f 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -40,7 +40,7 @@ using OpenMetaverse;
40using OpenSim.Framework; 40using OpenSim.Framework;
41using OpenSim.Framework.Console; 41using OpenSim.Framework.Console;
42using OpenSim.Framework.Servers; 42using OpenSim.Framework.Servers;
43using OpenSim.Framework.Statistics; 43using OpenSim.Framework.Monitoring;
44using OpenSim.Region.Framework.Interfaces; 44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes; 45using OpenSim.Region.Framework.Scenes;
46 46
@@ -200,9 +200,9 @@ namespace OpenSim
200 PrintFileToConsole("startuplogo.txt"); 200 PrintFileToConsole("startuplogo.txt");
201 201
202 // For now, start at the 'root' level by default 202 // For now, start at the 'root' level by default
203 if (m_sceneManager.Scenes.Count == 1) // If there is only one region, select it 203 if (SceneManager.Scenes.Count == 1) // If there is only one region, select it
204 ChangeSelectedRegion("region", 204 ChangeSelectedRegion("region",
205 new string[] {"change", "region", m_sceneManager.Scenes[0].RegionInfo.RegionName}); 205 new string[] {"change", "region", SceneManager.Scenes[0].RegionInfo.RegionName});
206 else 206 else
207 ChangeSelectedRegion("region", new string[] {"change", "region", "root"}); 207 ChangeSelectedRegion("region", new string[] {"change", "region", "root"});
208 208
@@ -461,7 +461,7 @@ namespace OpenSim
461 if (cmdparams.Length > 4) 461 if (cmdparams.Length > 4)
462 alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); 462 alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4));
463 463
464 IList agents = m_sceneManager.GetCurrentSceneAvatars(); 464 IList agents = SceneManager.GetCurrentSceneAvatars();
465 465
466 foreach (ScenePresence presence in agents) 466 foreach (ScenePresence presence in agents)
467 { 467 {
@@ -542,7 +542,7 @@ namespace OpenSim
542 private void HandleForceUpdate(string module, string[] args) 542 private void HandleForceUpdate(string module, string[] args)
543 { 543 {
544 MainConsole.Instance.Output("Updating all clients"); 544 MainConsole.Instance.Output("Updating all clients");
545 m_sceneManager.ForceCurrentSceneClientUpdate(); 545 SceneManager.ForceCurrentSceneClientUpdate();
546 } 546 }
547 547
548 /// <summary> 548 /// <summary>
@@ -554,7 +554,7 @@ namespace OpenSim
554 { 554 {
555 if (args.Length == 6) 555 if (args.Length == 6)
556 { 556 {
557 m_sceneManager.HandleEditCommandOnCurrentScene(args); 557 SceneManager.HandleEditCommandOnCurrentScene(args);
558 } 558 }
559 else 559 else
560 { 560 {
@@ -765,7 +765,7 @@ namespace OpenSim
765 case "load": 765 case "load":
766 if (cmdparams.Length > 1) 766 if (cmdparams.Length > 1)
767 { 767 {
768 foreach (Scene s in new ArrayList(m_sceneManager.Scenes)) 768 foreach (Scene s in new ArrayList(SceneManager.Scenes))
769 { 769 {
770 MainConsole.Instance.Output(String.Format("Loading module: {0}", cmdparams[1])); 770 MainConsole.Instance.Output(String.Format("Loading module: {0}", cmdparams[1]));
771 m_moduleLoader.LoadRegionModules(cmdparams[1], s); 771 m_moduleLoader.LoadRegionModules(cmdparams[1], s);
@@ -803,14 +803,14 @@ namespace OpenSim
803 803
804 case "backup": 804 case "backup":
805 MainConsole.Instance.Output("Triggering save of pending object updates to persistent store"); 805 MainConsole.Instance.Output("Triggering save of pending object updates to persistent store");
806 m_sceneManager.BackupCurrentScene(); 806 SceneManager.BackupCurrentScene();
807 break; 807 break;
808 808
809 case "remove-region": 809 case "remove-region":
810 string regRemoveName = CombineParams(cmdparams, 0); 810 string regRemoveName = CombineParams(cmdparams, 0);
811 811
812 Scene removeScene; 812 Scene removeScene;
813 if (m_sceneManager.TryGetScene(regRemoveName, out removeScene)) 813 if (SceneManager.TryGetScene(regRemoveName, out removeScene))
814 RemoveRegion(removeScene, false); 814 RemoveRegion(removeScene, false);
815 else 815 else
816 MainConsole.Instance.Output("No region with that name"); 816 MainConsole.Instance.Output("No region with that name");
@@ -820,14 +820,14 @@ namespace OpenSim
820 string regDeleteName = CombineParams(cmdparams, 0); 820 string regDeleteName = CombineParams(cmdparams, 0);
821 821
822 Scene killScene; 822 Scene killScene;
823 if (m_sceneManager.TryGetScene(regDeleteName, out killScene)) 823 if (SceneManager.TryGetScene(regDeleteName, out killScene))
824 RemoveRegion(killScene, true); 824 RemoveRegion(killScene, true);
825 else 825 else
826 MainConsole.Instance.Output("no region with that name"); 826 MainConsole.Instance.Output("no region with that name");
827 break; 827 break;
828 828
829 case "restart": 829 case "restart":
830 m_sceneManager.RestartCurrentScene(); 830 SceneManager.RestartCurrentScene();
831 break; 831 break;
832 } 832 }
833 } 833 }
@@ -842,7 +842,7 @@ namespace OpenSim
842 { 842 {
843 string newRegionName = CombineParams(cmdparams, 2); 843 string newRegionName = CombineParams(cmdparams, 2);
844 844
845 if (!m_sceneManager.TrySetCurrentScene(newRegionName)) 845 if (!SceneManager.TrySetCurrentScene(newRegionName))
846 MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName)); 846 MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName));
847 } 847 }
848 else 848 else
@@ -850,7 +850,7 @@ namespace OpenSim
850 MainConsole.Instance.Output("Usage: change region <region name>"); 850 MainConsole.Instance.Output("Usage: change region <region name>");
851 } 851 }
852 852
853 string regionName = (m_sceneManager.CurrentScene == null ? "root" : m_sceneManager.CurrentScene.RegionInfo.RegionName); 853 string regionName = (SceneManager.CurrentScene == null ? "root" : SceneManager.CurrentScene.RegionInfo.RegionName);
854 MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName)); 854 MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName));
855 855
856// m_log.DebugFormat("Original prompt is {0}", m_consolePrompt); 856// m_log.DebugFormat("Original prompt is {0}", m_consolePrompt);
@@ -868,7 +868,7 @@ namespace OpenSim
868 }); 868 });
869 869
870 m_console.DefaultPrompt = prompt; 870 m_console.DefaultPrompt = prompt;
871 m_console.ConsoleScene = m_sceneManager.CurrentScene; 871 m_console.ConsoleScene = SceneManager.CurrentScene;
872 } 872 }
873 873
874 /// <summary> 874 /// <summary>
@@ -892,7 +892,7 @@ namespace OpenSim
892 int newDebug; 892 int newDebug;
893 if (int.TryParse(args[2], out newDebug)) 893 if (int.TryParse(args[2], out newDebug))
894 { 894 {
895 m_sceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name); 895 SceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name);
896 // We provide user information elsewhere if any clients had their debug level set. 896 // We provide user information elsewhere if any clients had their debug level set.
897// MainConsole.Instance.OutputFormat("Debug packet level set to {0}", newDebug); 897// MainConsole.Instance.OutputFormat("Debug packet level set to {0}", newDebug);
898 } 898 }
@@ -907,7 +907,7 @@ namespace OpenSim
907 case "scene": 907 case "scene":
908 if (args.Length == 4) 908 if (args.Length == 4)
909 { 909 {
910 if (m_sceneManager.CurrentScene == null) 910 if (SceneManager.CurrentScene == null)
911 { 911 {
912 MainConsole.Instance.Output("Please use 'change region <regioname>' first"); 912 MainConsole.Instance.Output("Please use 'change region <regioname>' first");
913 } 913 }
@@ -915,7 +915,7 @@ namespace OpenSim
915 { 915 {
916 string key = args[2]; 916 string key = args[2];
917 string value = args[3]; 917 string value = args[3];
918 m_sceneManager.CurrentScene.SetSceneCoreDebug( 918 SceneManager.CurrentScene.SetSceneCoreDebug(
919 new Dictionary<string, string>() { { key, value } }); 919 new Dictionary<string, string>() { { key, value } });
920 920
921 MainConsole.Instance.OutputFormat("Set debug scene {0} = {1}", key, value); 921 MainConsole.Instance.OutputFormat("Set debug scene {0} = {1}", key, value);
@@ -954,10 +954,10 @@ namespace OpenSim
954 IList agents; 954 IList agents;
955 if (showParams.Length > 1 && showParams[1] == "full") 955 if (showParams.Length > 1 && showParams[1] == "full")
956 { 956 {
957 agents = m_sceneManager.GetCurrentScenePresences(); 957 agents = SceneManager.GetCurrentScenePresences();
958 } else 958 } else
959 { 959 {
960 agents = m_sceneManager.GetCurrentSceneAvatars(); 960 agents = SceneManager.GetCurrentSceneAvatars();
961 } 961 }
962 962
963 MainConsole.Instance.Output(String.Format("\nAgents connected: {0}\n", agents.Count)); 963 MainConsole.Instance.Output(String.Format("\nAgents connected: {0}\n", agents.Count));
@@ -1037,7 +1037,7 @@ namespace OpenSim
1037 MainConsole.Instance.Output("Shared Module: " + module.Name); 1037 MainConsole.Instance.Output("Shared Module: " + module.Name);
1038 } 1038 }
1039 1039
1040 m_sceneManager.ForEachScene( 1040 SceneManager.ForEachScene(
1041 delegate(Scene scene) { 1041 delegate(Scene scene) {
1042 m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:"); 1042 m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:");
1043 foreach (IRegionModule module in scene.Modules.Values) 1043 foreach (IRegionModule module in scene.Modules.Values)
@@ -1050,7 +1050,7 @@ namespace OpenSim
1050 } 1050 }
1051 ); 1051 );
1052 1052
1053 m_sceneManager.ForEachScene( 1053 SceneManager.ForEachScene(
1054 delegate(Scene scene) { 1054 delegate(Scene scene) {
1055 MainConsole.Instance.Output("Loaded new region modules in" + scene.RegionInfo.RegionName + " are:"); 1055 MainConsole.Instance.Output("Loaded new region modules in" + scene.RegionInfo.RegionName + " are:");
1056 foreach (IRegionModuleBase module in scene.RegionModules.Values) 1056 foreach (IRegionModuleBase module in scene.RegionModules.Values)
@@ -1066,7 +1066,7 @@ namespace OpenSim
1066 break; 1066 break;
1067 1067
1068 case "regions": 1068 case "regions":
1069 m_sceneManager.ForEachScene( 1069 SceneManager.ForEachScene(
1070 delegate(Scene scene) 1070 delegate(Scene scene)
1071 { 1071 {
1072 MainConsole.Instance.Output(String.Format( 1072 MainConsole.Instance.Output(String.Format(
@@ -1080,7 +1080,7 @@ namespace OpenSim
1080 break; 1080 break;
1081 1081
1082 case "ratings": 1082 case "ratings":
1083 m_sceneManager.ForEachScene( 1083 SceneManager.ForEachScene(
1084 delegate(Scene scene) 1084 delegate(Scene scene)
1085 { 1085 {
1086 string rating = ""; 1086 string rating = "";
@@ -1115,7 +1115,7 @@ namespace OpenSim
1115 cdt.AddColumn("IP", 16); 1115 cdt.AddColumn("IP", 16);
1116 cdt.AddColumn("Viewer Name", 24); 1116 cdt.AddColumn("Viewer Name", 24);
1117 1117
1118 m_sceneManager.ForEachScene( 1118 SceneManager.ForEachScene(
1119 s => 1119 s =>
1120 { 1120 {
1121 foreach (AgentCircuitData aCircuit in s.AuthenticateHandler.GetAgentCircuits().Values) 1121 foreach (AgentCircuitData aCircuit in s.AuthenticateHandler.GetAgentCircuits().Values)
@@ -1140,13 +1140,13 @@ namespace OpenSim
1140 cdt.AddColumn("Endpoint", 23); 1140 cdt.AddColumn("Endpoint", 23);
1141 cdt.AddColumn("Active?", 7); 1141 cdt.AddColumn("Active?", 7);
1142 1142
1143 m_sceneManager.ForEachScene( 1143 SceneManager.ForEachScene(
1144 s => s.ForEachClient( 1144 s => s.ForEachClient(
1145 c => cdt.AddRow( 1145 c => cdt.AddRow(
1146 s.Name, 1146 s.Name,
1147 c.Name, 1147 c.Name,
1148 c.RemoteEndPoint.ToString(),
1149 c.CircuitCode.ToString(), 1148 c.CircuitCode.ToString(),
1149 c.RemoteEndPoint.ToString(),
1150 c.IsActive.ToString()))); 1150 c.IsActive.ToString())));
1151 1151
1152 MainConsole.Instance.Output(cdt.ToString()); 1152 MainConsole.Instance.Output(cdt.ToString());
@@ -1161,11 +1161,11 @@ namespace OpenSim
1161 { 1161 {
1162 if (cmdparams.Length > 5) 1162 if (cmdparams.Length > 5)
1163 { 1163 {
1164 m_sceneManager.SaveNamedPrimsToXml2(cmdparams[3], cmdparams[4]); 1164 SceneManager.SaveNamedPrimsToXml2(cmdparams[3], cmdparams[4]);
1165 } 1165 }
1166 else 1166 else
1167 { 1167 {
1168 m_sceneManager.SaveNamedPrimsToXml2("Primitive", DEFAULT_PRIM_BACKUP_FILENAME); 1168 SceneManager.SaveNamedPrimsToXml2("Primitive", DEFAULT_PRIM_BACKUP_FILENAME);
1169 } 1169 }
1170 } 1170 }
1171 1171
@@ -1180,11 +1180,11 @@ namespace OpenSim
1180 1180
1181 if (cmdparams.Length > 0) 1181 if (cmdparams.Length > 0)
1182 { 1182 {
1183 m_sceneManager.SaveCurrentSceneToXml(cmdparams[2]); 1183 SceneManager.SaveCurrentSceneToXml(cmdparams[2]);
1184 } 1184 }
1185 else 1185 else
1186 { 1186 {
1187 m_sceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME); 1187 SceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME);
1188 } 1188 }
1189 } 1189 }
1190 1190
@@ -1221,13 +1221,13 @@ namespace OpenSim
1221 MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z)); 1221 MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z));
1222 } 1222 }
1223 } 1223 }
1224 m_sceneManager.LoadCurrentSceneFromXml(cmdparams[0], generateNewIDS, loadOffset); 1224 SceneManager.LoadCurrentSceneFromXml(cmdparams[2], generateNewIDS, loadOffset);
1225 } 1225 }
1226 else 1226 else
1227 { 1227 {
1228 try 1228 try
1229 { 1229 {
1230 m_sceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset); 1230 SceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset);
1231 } 1231 }
1232 catch (FileNotFoundException) 1232 catch (FileNotFoundException)
1233 { 1233 {
@@ -1244,11 +1244,11 @@ namespace OpenSim
1244 { 1244 {
1245 if (cmdparams.Length > 2) 1245 if (cmdparams.Length > 2)
1246 { 1246 {
1247 m_sceneManager.SaveCurrentSceneToXml2(cmdparams[2]); 1247 SceneManager.SaveCurrentSceneToXml2(cmdparams[2]);
1248 } 1248 }
1249 else 1249 else
1250 { 1250 {
1251 m_sceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME); 1251 SceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME);
1252 } 1252 }
1253 } 1253 }
1254 1254
@@ -1263,7 +1263,7 @@ namespace OpenSim
1263 { 1263 {
1264 try 1264 try
1265 { 1265 {
1266 m_sceneManager.LoadCurrentSceneFromXml2(cmdparams[2]); 1266 SceneManager.LoadCurrentSceneFromXml2(cmdparams[2]);
1267 } 1267 }
1268 catch (FileNotFoundException) 1268 catch (FileNotFoundException)
1269 { 1269 {
@@ -1274,7 +1274,7 @@ namespace OpenSim
1274 { 1274 {
1275 try 1275 try
1276 { 1276 {
1277 m_sceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME); 1277 SceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME);
1278 } 1278 }
1279 catch (FileNotFoundException) 1279 catch (FileNotFoundException)
1280 { 1280 {
@@ -1291,7 +1291,7 @@ namespace OpenSim
1291 { 1291 {
1292 try 1292 try
1293 { 1293 {
1294 m_sceneManager.LoadArchiveToCurrentScene(cmdparams); 1294 SceneManager.LoadArchiveToCurrentScene(cmdparams);
1295 } 1295 }
1296 catch (Exception e) 1296 catch (Exception e)
1297 { 1297 {
@@ -1305,7 +1305,7 @@ namespace OpenSim
1305 /// <param name="cmdparams"></param> 1305 /// <param name="cmdparams"></param>
1306 protected void SaveOar(string module, string[] cmdparams) 1306 protected void SaveOar(string module, string[] cmdparams)
1307 { 1307 {
1308 m_sceneManager.SaveCurrentSceneToArchive(cmdparams); 1308 SceneManager.SaveCurrentSceneToArchive(cmdparams);
1309 } 1309 }
1310 1310
1311 private static string CombineParams(string[] commandParams, int pos) 1311 private static string CombineParams(string[] commandParams, int pos)
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 76ac246..aed10f6 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -40,7 +40,7 @@ using OpenSim.Framework.Communications;
40using OpenSim.Framework.Console; 40using OpenSim.Framework.Console;
41using OpenSim.Framework.Servers; 41using OpenSim.Framework.Servers;
42using OpenSim.Framework.Servers.HttpServer; 42using OpenSim.Framework.Servers.HttpServer;
43using OpenSim.Framework.Statistics; 43using OpenSim.Framework.Monitoring;
44using OpenSim.Region.ClientStack; 44using OpenSim.Region.ClientStack;
45using OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts; 45using OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts;
46using OpenSim.Region.Framework; 46using OpenSim.Region.Framework;
@@ -300,7 +300,7 @@ namespace OpenSim
300 300
301 private void HandleCommanderCommand(string module, string[] cmd) 301 private void HandleCommanderCommand(string module, string[] cmd)
302 { 302 {
303 m_sceneManager.SendCommandToPluginModules(cmd); 303 SceneManager.SendCommandToPluginModules(cmd);
304 } 304 }
305 305
306 private void HandleCommanderHelp(string module, string[] cmd) 306 private void HandleCommanderHelp(string module, string[] cmd)
@@ -318,7 +318,10 @@ namespace OpenSim
318 // Called from base.StartUp() 318 // Called from base.StartUp()
319 319
320 m_httpServerPort = m_networkServersInfo.HttpListenerPort; 320 m_httpServerPort = m_networkServersInfo.HttpListenerPort;
321 m_sceneManager.OnRestartSim += handleRestartRegion; 321 SceneManager.OnRestartSim += handleRestartRegion;
322
323 // Only start the memory watchdog once all regions are ready
324 SceneManager.OnRegionsReadyStatusChange += sm => MemoryWatchdog.Enabled = sm.AllRegionsReady;
322 } 325 }
323 326
324 /// <summary> 327 /// <summary>
@@ -480,7 +483,7 @@ namespace OpenSim
480 scene.SnmpService.BootInfo("ScriptEngine started", scene); 483 scene.SnmpService.BootInfo("ScriptEngine started", scene);
481 } 484 }
482 485
483 m_sceneManager.Add(scene); 486 SceneManager.Add(scene);
484 487
485 if (m_autoCreateClientStack) 488 if (m_autoCreateClientStack)
486 { 489 {
@@ -510,7 +513,6 @@ namespace OpenSim
510 } 513 }
511 514
512 scene.Start(); 515 scene.Start();
513
514 scene.StartScripts(); 516 scene.StartScripts();
515 517
516 return clientServer; 518 return clientServer;
@@ -644,14 +646,14 @@ namespace OpenSim
644 { 646 {
645 // only need to check this if we are not at the 647 // only need to check this if we are not at the
646 // root level 648 // root level
647 if ((m_sceneManager.CurrentScene != null) && 649 if ((SceneManager.CurrentScene != null) &&
648 (m_sceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID)) 650 (SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
649 { 651 {
650 m_sceneManager.TrySetCurrentScene(".."); 652 SceneManager.TrySetCurrentScene("..");
651 } 653 }
652 654
653 scene.DeleteAllSceneObjects(); 655 scene.DeleteAllSceneObjects();
654 m_sceneManager.CloseScene(scene); 656 SceneManager.CloseScene(scene);
655 ShutdownClientServer(scene.RegionInfo); 657 ShutdownClientServer(scene.RegionInfo);
656 658
657 if (!cleanup) 659 if (!cleanup)
@@ -693,7 +695,7 @@ namespace OpenSim
693 public void RemoveRegion(string name, bool cleanUp) 695 public void RemoveRegion(string name, bool cleanUp)
694 { 696 {
695 Scene target; 697 Scene target;
696 if (m_sceneManager.TryGetScene(name, out target)) 698 if (SceneManager.TryGetScene(name, out target))
697 RemoveRegion(target, cleanUp); 699 RemoveRegion(target, cleanUp);
698 } 700 }
699 701
@@ -706,13 +708,13 @@ namespace OpenSim
706 { 708 {
707 // only need to check this if we are not at the 709 // only need to check this if we are not at the
708 // root level 710 // root level
709 if ((m_sceneManager.CurrentScene != null) && 711 if ((SceneManager.CurrentScene != null) &&
710 (m_sceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID)) 712 (SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID))
711 { 713 {
712 m_sceneManager.TrySetCurrentScene(".."); 714 SceneManager.TrySetCurrentScene("..");
713 } 715 }
714 716
715 m_sceneManager.CloseScene(scene); 717 SceneManager.CloseScene(scene);
716 ShutdownClientServer(scene.RegionInfo); 718 ShutdownClientServer(scene.RegionInfo);
717 } 719 }
718 720
@@ -724,7 +726,7 @@ namespace OpenSim
724 public void CloseRegion(string name) 726 public void CloseRegion(string name)
725 { 727 {
726 Scene target; 728 Scene target;
727 if (m_sceneManager.TryGetScene(name, out target)) 729 if (SceneManager.TryGetScene(name, out target))
728 CloseRegion(target); 730 CloseRegion(target);
729 } 731 }
730 732
@@ -781,6 +783,7 @@ namespace OpenSim
781 scene.LoadWorldMap(); 783 scene.LoadWorldMap();
782 784
783 scene.PhysicsScene = GetPhysicsScene(scene.RegionInfo.RegionName); 785 scene.PhysicsScene = GetPhysicsScene(scene.RegionInfo.RegionName);
786 scene.PhysicsScene.RequestAssetMethod = scene.PhysicsRequestAsset;
784 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised()); 787 scene.PhysicsScene.SetTerrain(scene.Heightmap.GetFloatsSerialised());
785 scene.PhysicsScene.SetWaterLevel((float) regionInfo.RegionSettings.WaterHeight); 788 scene.PhysicsScene.SetWaterLevel((float) regionInfo.RegionSettings.WaterHeight);
786 789
@@ -980,7 +983,7 @@ namespace OpenSim
980 983
981 try 984 try
982 { 985 {
983 m_sceneManager.Close(); 986 SceneManager.Close();
984 } 987 }
985 catch (Exception e) 988 catch (Exception e)
986 { 989 {
@@ -1005,7 +1008,7 @@ namespace OpenSim
1005 /// <param name="usernum">The first out parameter describing the number of all the avatars in the Region server</param> 1008 /// <param name="usernum">The first out parameter describing the number of all the avatars in the Region server</param>
1006 public void GetAvatarNumber(out int usernum) 1009 public void GetAvatarNumber(out int usernum)
1007 { 1010 {
1008 usernum = m_sceneManager.GetCurrentSceneAvatars().Count; 1011 usernum = SceneManager.GetCurrentSceneAvatars().Count;
1009 } 1012 }
1010 1013
1011 /// <summary> 1014 /// <summary>
@@ -1014,7 +1017,7 @@ namespace OpenSim
1014 /// <param name="regionnum">The first out parameter describing the number of regions</param> 1017 /// <param name="regionnum">The first out parameter describing the number of regions</param>
1015 public void GetRegionNumber(out int regionnum) 1018 public void GetRegionNumber(out int regionnum)
1016 { 1019 {
1017 regionnum = m_sceneManager.Scenes.Count; 1020 regionnum = SceneManager.Scenes.Count;
1018 } 1021 }
1019 1022
1020 /// <summary> 1023 /// <summary>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index ad9074c..f7bb817 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -41,7 +41,7 @@ using OpenMetaverse.Messages.Linden;
41using OpenMetaverse.StructuredData; 41using OpenMetaverse.StructuredData;
42using OpenSim.Framework; 42using OpenSim.Framework;
43using OpenSim.Framework.Client; 43using OpenSim.Framework.Client;
44using OpenSim.Framework.Statistics; 44using OpenSim.Framework.Monitoring;
45using OpenSim.Region.Framework.Interfaces; 45using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 46using OpenSim.Region.Framework.Scenes;
47using OpenSim.Services.Interfaces; 47using OpenSim.Services.Interfaces;
@@ -355,8 +355,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
355 private int m_animationSequenceNumber = 1; 355 private int m_animationSequenceNumber = 1;
356 private bool m_SendLogoutPacketWhenClosing = true; 356 private bool m_SendLogoutPacketWhenClosing = true;
357 private AgentUpdateArgs lastarg; 357 private AgentUpdateArgs lastarg;
358 private bool m_IsActive = true;
359 private bool m_IsLoggingOut = false;
360 358
361 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 359 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
362 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 360 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -428,16 +426,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
428 public uint CircuitCode { get { return m_circuitCode; } } 426 public uint CircuitCode { get { return m_circuitCode; } }
429 public int MoneyBalance { get { return m_moneyBalance; } } 427 public int MoneyBalance { get { return m_moneyBalance; } }
430 public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } } 428 public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } }
431 public bool IsActive 429
432 { 430 /// <summary>
433 get { return m_IsActive; } 431 /// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to
434 set { m_IsActive = value; } 432 /// prevent race conditions by different threads calling Close().
435 } 433 /// </summary>
436 public bool IsLoggingOut 434 public bool IsActive { get; set; }
437 { 435
438 get { return m_IsLoggingOut; } 436 /// <summary>
439 set { m_IsLoggingOut = value; } 437 /// Used to synchronise threads when client is being closed.
440 } 438 /// </summary>
439 public Object CloseSyncLock { get; private set; }
440
441 public bool IsLoggingOut { get; set; }
441 442
442 public bool DisableFacelights 443 public bool DisableFacelights
443 { 444 {
@@ -462,6 +463,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
462 { 463 {
463// DebugPacketLevel = 1; 464// DebugPacketLevel = 1;
464 465
466 CloseSyncLock = new Object();
467
465 RegisterInterface<IClientIM>(this); 468 RegisterInterface<IClientIM>(this);
466 RegisterInterface<IClientInventory>(this); 469 RegisterInterface<IClientInventory>(this);
467 RegisterInterface<IClientChat>(this); 470 RegisterInterface<IClientChat>(this);
@@ -494,13 +497,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
494 m_prioritizer = new Prioritizer(m_scene); 497 m_prioritizer = new Prioritizer(m_scene);
495 498
496 RegisterLocalPacketHandlers(); 499 RegisterLocalPacketHandlers();
500
501 IsActive = true;
497 } 502 }
498 503
499 #region Client Methods 504 #region Client Methods
500 505
501 506
502 /// <summary> 507 /// <summary>
503 /// Shut down the client view 508 /// Close down the client view
504 /// </summary> 509 /// </summary>
505 public void Close() 510 public void Close()
506 { 511 {
@@ -513,7 +518,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
513 public void Close(bool sendStop) 518 public void Close(bool sendStop)
514 { 519 {
515 IsActive = false; 520 IsActive = false;
521 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
522 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
523 lock (CloseSyncLock)
524 {
525 if (!IsActive)
526 return;
527
528 IsActive = false;
529 CloseWithoutChecks(sendStop);
530 }
531 }
516 532
533 /// <summary>
534 /// Closes down the client view without first checking whether it is active.
535 /// </summary>
536 /// <remarks>
537 /// This exists because LLUDPServer has to set IsActive = false in earlier synchronous code before calling
538 /// CloseWithoutIsActiveCheck asynchronously.
539 ///
540 /// Callers must lock ClosingSyncLock before calling.
541 /// </remarks>
542 public void CloseWithoutChecks(bool sendStop)
543 {
517 m_log.DebugFormat( 544 m_log.DebugFormat(
518 "[CLIENT]: Close has been called for {0} attached to scene {1}", 545 "[CLIENT]: Close has been called for {0} attached to scene {1}",
519 Name, m_scene.RegionInfo.RegionName); 546 Name, m_scene.RegionInfo.RegionName);
@@ -3634,7 +3661,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3634 3661
3635 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 3662 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
3636 { 3663 {
3637 if (!IsActive) return; // We don't need to update inactive clients. 3664 // We don't need to update inactive clients.
3665 if (!IsActive)
3666 return;
3638 3667
3639 CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); 3668 CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate);
3640 loc.Header.Reliable = false; 3669 loc.Header.Reliable = false;
@@ -5267,7 +5296,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5267 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); 5296 AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer);
5268 AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate); 5297 AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate);
5269 AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply); 5298 AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply);
5270 AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage, false); 5299 AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage);
5271 AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship); 5300 AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship);
5272 AddLocalPacketHandler(PacketType.DeclineFriendship, HandlerDeclineFriendship); 5301 AddLocalPacketHandler(PacketType.DeclineFriendship, HandlerDeclineFriendship);
5273 AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFriendship); 5302 AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFriendship);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index ae72175..c472176 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -279,7 +279,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
279 public string GetStats() 279 public string GetStats()
280 { 280 {
281 return string.Format( 281 return string.Format(
282 "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}", 282 "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7} {12,7}",
283 Util.EnvironmentTickCountSubtract(TickLastPacketReceived),
283 PacketsReceived, 284 PacketsReceived,
284 PacketsSent, 285 PacketsSent,
285 PacketsResent, 286 PacketsResent,
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index b09f607..6c2e71b 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -37,7 +37,7 @@ using log4net;
37using Nini.Config; 37using Nini.Config;
38using OpenMetaverse.Packets; 38using OpenMetaverse.Packets;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Statistics; 40using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenMetaverse; 42using OpenMetaverse;
43 43
@@ -1181,22 +1181,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1181 /// regular client pings. 1181 /// regular client pings.
1182 /// </remarks> 1182 /// </remarks>
1183 /// <param name='client'></param> 1183 /// <param name='client'></param>
1184 private void DeactivateClientDueToTimeout(IClientAPI client) 1184 private void DeactivateClientDueToTimeout(LLClientView client)
1185 { 1185 {
1186 // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even 1186 lock (client.CloseSyncLock)
1187 // though it's set later on by LLClientView.Close() 1187 {
1188 client.IsActive = false; 1188 m_log.WarnFormat(
1189 1189 "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}",
1190 m_log.WarnFormat( 1190 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName);
1191 "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}", 1191
1192 client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName); 1192 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination();
1193 1193
1194 StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); 1194 if (!client.SceneAgent.IsChildAgent)
1195 1195 client.Kick("Simulator logged you out due to connection timeout");
1196 if (!client.SceneAgent.IsChildAgent) 1196
1197 client.Kick("Simulator logged you out due to connection timeout"); 1197 client.CloseWithoutChecks(true);
1198 1198 }
1199 Util.FireAndForget(o => client.Close());
1200 } 1199 }
1201 1200
1202 private void IncomingPacketHandler() 1201 private void IncomingPacketHandler()
diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
index c4324e8..4672f8a 100644
--- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs
+++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs
@@ -53,9 +53,8 @@ namespace OpenSim.Region.ClientStack
53 protected ISimulationDataService m_simulationDataService; 53 protected ISimulationDataService m_simulationDataService;
54 protected IEstateDataService m_estateDataService; 54 protected IEstateDataService m_estateDataService;
55 protected ClientStackManager m_clientStackManager; 55 protected ClientStackManager m_clientStackManager;
56 protected SceneManager m_sceneManager = new SceneManager();
57 56
58 public SceneManager SceneManager { get { return m_sceneManager; } } 57 public SceneManager SceneManager { get; protected set; }
59 public NetworkServersInfo NetServersInfo { get { return m_networkServersInfo; } } 58 public NetworkServersInfo NetServersInfo { get { return m_networkServersInfo; } }
60 public ISimulationDataService SimulationDataService { get { return m_simulationDataService; } } 59 public ISimulationDataService SimulationDataService { get { return m_simulationDataService; } }
61 public IEstateDataService EstateDataService { get { return m_estateDataService; } } 60 public IEstateDataService EstateDataService { get { return m_estateDataService; } }
@@ -77,6 +76,7 @@ namespace OpenSim.Region.ClientStack
77 76
78 protected override void StartupSpecific() 77 protected override void StartupSpecific()
79 { 78 {
79 SceneManager = new SceneManager();
80 m_clientStackManager = CreateClientStackManager(); 80 m_clientStackManager = CreateClientStackManager();
81 81
82 Initialize(); 82 Initialize();
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 31e8a2e..b588704 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -626,10 +626,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
626 626
627 m_scene.InventoryService.UpdateItem(item); 627 m_scene.InventoryService.UpdateItem(item);
628 628
629 // this gets called when the agent logs off! 629 // If the name of the object has been changed whilst attached then we want to update the inventory
630 // item in the viewer.
630 if (sp.ControllingClient != null) 631 if (sp.ControllingClient != null)
631 sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0); 632 sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
632 } 633 }
634
633 grp.HasGroupChanged = false; // Prevent it being saved over and over 635 grp.HasGroupChanged = false; // Prevent it being saved over and over
634 } 636 }
635// else 637// else
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index cd1e1c1..273e290 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -47,6 +47,7 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
47using OpenSim.Region.CoreModules.World.Serialiser; 47using OpenSim.Region.CoreModules.World.Serialiser;
48using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
49using OpenSim.Region.Framework.Interfaces; 49using OpenSim.Region.Framework.Interfaces;
50using OpenSim.Region.ScriptEngine.Interfaces;
50using OpenSim.Region.ScriptEngine.XEngine; 51using OpenSim.Region.ScriptEngine.XEngine;
51using OpenSim.Services.Interfaces; 52using OpenSim.Services.Interfaces;
52using OpenSim.Tests.Common; 53using OpenSim.Tests.Common;
@@ -289,21 +290,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
289 { 290 {
290 TestHelpers.InMethod(); 291 TestHelpers.InMethod();
291 292
292 Scene scene = CreateTestScene(); 293 Scene scene = CreateScriptingEnabledTestScene();
293 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); 294 UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1);
294 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); 295 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
295 296
296 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); 297 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
297 TaskInventoryHelpers.AddScript(scene, so.RootPart); 298 TaskInventoryItem scriptItem
299 = TaskInventoryHelpers.AddScript(
300 scene,
301 so.RootPart,
302 "scriptItem",
303 "default { attach(key id) { if (id != NULL_KEY) { llSay(0, \"Hello World\"); } } }");
304
298 InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); 305 InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
299 306
307 // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running.
308 // In the future, we need to be able to do this programatically more predicably.
309 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
310
300 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 311 scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest);
301 312
313 m_chatEvent.WaitOne(60000);
314
302 // TODO: Need to have a test that checks the script is actually started but this involves a lot more 315 // TODO: Need to have a test that checks the script is actually started but this involves a lot more
303 // plumbing of the script engine and either pausing for events or more infrastructure to turn off various 316 // plumbing of the script engine and either pausing for events or more infrastructure to turn off various
304 // script engine delays/asychronicity that isn't helpful in an automated regression testing context. 317 // script engine delays/asychronicity that isn't helpful in an automated regression testing context.
305 SceneObjectGroup attSo = scene.GetSceneObjectGroup(so.Name); 318 SceneObjectGroup attSo = scene.GetSceneObjectGroup(so.Name);
306 Assert.That(attSo.ContainsScripts(), Is.True); 319 Assert.That(attSo.ContainsScripts(), Is.True);
320
321 TaskInventoryItem reRezzedScriptItem = attSo.RootPart.Inventory.GetInventoryItem(scriptItem.Name);
322 IScriptModule xengine = scene.RequestModuleInterface<IScriptModule>();
323 Assert.That(xengine.GetScriptState(reRezzedScriptItem.ItemID), Is.True);
307 } 324 }
308 325
309 [Test] 326 [Test]
@@ -379,29 +396,49 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
379 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); 396 ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1);
380 397
381 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); 398 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10);
382 TaskInventoryHelpers.AddScript(scene, so.RootPart); 399 TaskInventoryItem scriptTaskItem
400 = TaskInventoryHelpers.AddScript(
401 scene,
402 so.RootPart,
403 "scriptItem",
404 "default { attach(key id) { if (id != NULL_KEY) { llSay(0, \"Hello World\"); } } }");
405
383 InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); 406 InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000);
384 407
385 // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running. 408 // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running.
386 // In the future, we need to be able to do this programatically more predicably. 409 // In the future, we need to be able to do this programatically more predicably.
387 scene.EventManager.OnChatFromWorld += OnChatFromWorld; 410 scene.EventManager.OnChatFromWorld += OnChatFromWorld;
388 411
389 SceneObjectGroup soRezzed 412 SceneObjectGroup rezzedSo
390 = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); 413 = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
391 414
392 // Wait for chat to signal rezzed script has been started. 415 // Wait for chat to signal rezzed script has been started.
393 m_chatEvent.WaitOne(60000); 416 m_chatEvent.WaitOne(60000);
394 417
395 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, soRezzed); 418 scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo);
396 419
397 InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem); 420 InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem);
398 AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString()); 421 AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString());
399 422
423 // TODO: It would probably be better here to check script state via the saving and retrieval of state
424 // information at a higher level, rather than having to inspect the serialization.
400 XmlDocument soXml = new XmlDocument(); 425 XmlDocument soXml = new XmlDocument();
401 soXml.LoadXml(Encoding.UTF8.GetString(asset.Data)); 426 soXml.LoadXml(Encoding.UTF8.GetString(asset.Data));
402 427
403 XmlNodeList scriptStateNodes = soXml.GetElementsByTagName("ScriptState"); 428 XmlNodeList scriptStateNodes = soXml.GetElementsByTagName("ScriptState");
404 Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); 429 Assert.That(scriptStateNodes.Count, Is.EqualTo(1));
430
431 // Re-rez the attachment to check script running state
432 SceneObjectGroup reRezzedSo = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest));
433
434 // Wait for chat to signal rezzed script has been started.
435 m_chatEvent.WaitOne(60000);
436
437 TaskInventoryItem reRezzedScriptItem = reRezzedSo.RootPart.Inventory.GetInventoryItem(scriptTaskItem.Name);
438 IScriptModule xengine = scene.RequestModuleInterface<IScriptModule>();
439 Assert.That(xengine.GetScriptState(reRezzedScriptItem.ItemID), Is.True);
440
441// Console.WriteLine(soXml.OuterXml);
405 } 442 }
406 443
407 /// <summary> 444 /// <summary>
diff --git a/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
index 4bcd2ac..764adf9 100644
--- a/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs
@@ -37,7 +37,7 @@ using Nini.Config;
37using OpenMetaverse; 37using OpenMetaverse;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Framework.Console; 39using OpenSim.Framework.Console;
40using OpenSim.Framework.Statistics; 40using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43 43
diff --git a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
index 31363e5..b258e13 100644
--- a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs
@@ -96,7 +96,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
96 96
97 scene.EventManager.OnNewClient += OnNewClient; 97 scene.EventManager.OnNewClient += OnNewClient;
98 scene.EventManager.OnClientClosed += OnClientClosed; 98 scene.EventManager.OnClientClosed += OnClientClosed;
99 scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; 99// scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage;
100 } 100 }
101 101
102 public void PostInitialise() 102 public void PostInitialise()
@@ -133,7 +133,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
133 private void OnNewClient(IClientAPI client) 133 private void OnNewClient(IClientAPI client)
134 { 134 {
135 // Subscribe to instant messages 135 // Subscribe to instant messages
136 client.OnInstantMessage += OnInstantMessage; 136// client.OnInstantMessage += OnInstantMessage;
137 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; 137 client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest;
138 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; 138 client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest;
139 lock (m_ClientMap) 139 lock (m_ClientMap)
@@ -171,15 +171,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups
171 ActiveGroupTitle); 171 ActiveGroupTitle);
172 } 172 }
173 173
174 private void OnInstantMessage(IClientAPI client, GridInstantMessage im) 174// private void OnInstantMessage(IClientAPI client, GridInstantMessage im)
175 { 175// {
176 } 176// }
177 177
178 private void OnGridInstantMessage(GridInstantMessage msg) 178// private void OnGridInstantMessage(GridInstantMessage msg)
179 { 179// {
180 // Trigger the above event handler 180// // Trigger the above event handler
181 OnInstantMessage(null, msg); 181// OnInstantMessage(null, msg);
182 } 182// }
183 183
184 private void HandleUUIDGroupNameRequest(UUID id,IClientAPI remote_client) 184 private void HandleUUIDGroupNameRequest(UUID id,IClientAPI remote_client)
185 { 185 {
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
index 6064ddc..1406aae 100644
--- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs
@@ -141,13 +141,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
141 foreach (Scene scene in m_Scenes) 141 foreach (Scene scene in m_Scenes)
142 { 142 {
143// m_log.DebugFormat( 143// m_log.DebugFormat(
144// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", 144// "[INSTANT MESSAGE]: Looking for root agent {0} in {1}",
145// toAgentID.ToString(), scene.RegionInfo.RegionName); 145// toAgentID.ToString(), scene.RegionInfo.RegionName);
146
146 ScenePresence sp = scene.GetScenePresence(toAgentID); 147 ScenePresence sp = scene.GetScenePresence(toAgentID);
147 if (sp != null && !sp.IsChildAgent) 148 if (sp != null && !sp.IsChildAgent)
148 { 149 {
149 // Local message 150 // Local message
150// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); 151 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID);
152
151 sp.ControllingClient.SendInstantMessage(im); 153 sp.ControllingClient.SendInstantMessage(im);
152 154
153 // Message sent 155 // Message sent
@@ -159,13 +161,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
159 // try child avatar second 161 // try child avatar second
160 foreach (Scene scene in m_Scenes) 162 foreach (Scene scene in m_Scenes)
161 { 163 {
162// m_log.DebugFormat( 164 m_log.DebugFormat(
163// "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); 165 "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName);
166
164 ScenePresence sp = scene.GetScenePresence(toAgentID); 167 ScenePresence sp = scene.GetScenePresence(toAgentID);
165 if (sp != null) 168 if (sp != null)
166 { 169 {
167 // Local message 170 // Local message
168// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); 171 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID);
172
169 sp.ControllingClient.SendInstantMessage(im); 173 sp.ControllingClient.SendInstantMessage(im);
170 174
171 // Message sent 175 // Message sent
@@ -174,10 +178,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage
174 } 178 }
175 } 179 }
176 180
177// m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); 181 m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID);
178 SendGridInstantMessageViaXMLRPC(im, result);
179 182
180 return; 183 SendGridInstantMessageViaXMLRPC(im, result);
181 } 184 }
182 185
183 private void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result) 186 private void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result)
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
index 80554fb..81de29c 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs
@@ -313,8 +313,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer
313 m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); 313 m_TransferModule.SendInstantMessage(im, delegate(bool success) {});
314 } 314 }
315 } 315 }
316 else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined || 316 else if (
317 im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined) 317 im.dialog == (byte)InstantMessageDialog.InventoryDeclined
318 || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined)
318 { 319 {
319 // Here, the recipient is local and we can assume that the 320 // Here, the recipient is local and we can assume that the
320 // inventory is loaded. Courtesy of the above bulk update, 321 // inventory is loaded. Courtesy of the above bulk update,
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index d30c2e2..9a56f42 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -204,8 +204,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
204 204
205 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); 205 AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId);
206 m_Scene.AssetService.Store(asset); 206 m_Scene.AssetService.Store(asset);
207 207 m_Scene.CreateNewInventoryItem(
208 m_Scene.CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, asset.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate); 208 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
209 name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate);
209 } 210 }
210 else 211 else
211 { 212 {
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs
index a75ff62..fb74cc6 100644
--- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs
@@ -39,7 +39,7 @@ using OpenSim.Region.Framework;
39using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
40using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
41 41
42namespace OpenSim.Region.CoreModules.Avatar.Attachments 42namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
43{ 43{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BinaryLoggingModule")] 44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BinaryLoggingModule")]
45 public class BinaryLoggingModule : INonSharedRegionModule 45 public class BinaryLoggingModule : INonSharedRegionModule
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
new file mode 100755
index 0000000..65e4c90
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs
@@ -0,0 +1,161 @@
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.IO;
30using System.Text;
31using log4net;
32
33namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
34{
35 /// <summary>
36 /// Class for writing a high performance, high volume log file.
37 /// Sometimes, to debug, one has a high volume logging to do and the regular
38 /// log file output is not appropriate.
39 /// Create a new instance with the parameters needed and
40 /// call Write() to output a line. Call Close() when finished.
41 /// If created with no parameters, it will not log anything.
42 /// </summary>
43 public class LogWriter : IDisposable
44 {
45 public bool Enabled { get; private set; }
46
47 private string m_logDirectory = ".";
48 private int m_logMaxFileTimeMin = 5; // 5 minutes
49 public String LogFileHeader { get; set; }
50
51 private StreamWriter m_logFile = null;
52 private TimeSpan m_logFileLife;
53 private DateTime m_logFileEndTime;
54 private Object m_logFileWriteLock = new Object();
55
56 // set externally when debugging. If let 'null', this does not write any error messages.
57 public ILog ErrorLogger = null;
58 private string LogHeader = "[LOG WRITER]";
59
60 /// <summary>
61 /// Create a log writer that will not write anything. Good for when not enabled
62 /// but the write statements are still in the code.
63 /// </summary>
64 public LogWriter()
65 {
66 Enabled = false;
67 m_logFile = null;
68 }
69
70 /// <summary>
71 /// Create a log writer instance.
72 /// </summary>
73 /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param>
74 /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param>
75 /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param>
76 public LogWriter(string dir, string headr, int maxFileTime)
77 {
78 m_logDirectory = dir == null ? "." : dir;
79
80 LogFileHeader = headr == null ? "log-" : headr;
81
82 m_logMaxFileTimeMin = maxFileTime;
83 if (m_logMaxFileTimeMin < 1)
84 m_logMaxFileTimeMin = 5;
85
86 m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0);
87 m_logFileEndTime = DateTime.Now + m_logFileLife;
88
89 Enabled = true;
90 }
91
92 public void Dispose()
93 {
94 this.Close();
95 }
96
97 public void Close()
98 {
99 Enabled = false;
100 if (m_logFile != null)
101 {
102 m_logFile.Close();
103 m_logFile.Dispose();
104 m_logFile = null;
105 }
106 }
107
108 public void Write(string line, params object[] args)
109 {
110 if (!Enabled) return;
111 Write(String.Format(line, args));
112 }
113
114 public void Write(string line)
115 {
116 if (!Enabled) return;
117 try
118 {
119 lock (m_logFileWriteLock)
120 {
121 DateTime now = DateTime.Now;
122 if (m_logFile == null || now > m_logFileEndTime)
123 {
124 if (m_logFile != null)
125 {
126 m_logFile.Close();
127 m_logFile.Dispose();
128 m_logFile = null;
129 }
130
131 // First log file or time has expired, start writing to a new log file
132 m_logFileEndTime = now + m_logFileLife;
133 string path = (m_logDirectory.Length > 0 ? m_logDirectory
134 + System.IO.Path.DirectorySeparatorChar.ToString() : "")
135 + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss"));
136 m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write));
137 }
138 if (m_logFile != null)
139 {
140 StringBuilder buff = new StringBuilder(line.Length + 25);
141 buff.Append(now.ToString("yyyyMMddHHmmssfff"));
142 // buff.Append(now.ToString("yyyyMMddHHmmss"));
143 buff.Append(",");
144 buff.Append(line);
145 buff.Append("\r\n");
146 m_logFile.Write(buff.ToString());
147 }
148 }
149 }
150 catch (Exception e)
151 {
152 if (ErrorLogger != null)
153 {
154 ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e);
155 }
156 Enabled = false;
157 }
158 return;
159 }
160 }
161} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
index a6e2548..4a76b00 100644
--- a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
+++ b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs
@@ -40,6 +40,7 @@ using OpenMetaverse;
40using OpenMetaverse.StructuredData; 40using OpenMetaverse.StructuredData;
41using OpenSim.Framework; 41using OpenSim.Framework;
42using OpenSim.Framework.Capabilities; 42using OpenSim.Framework.Capabilities;
43using OpenSim.Framework.Monitoring;
43using OpenSim.Framework.Servers; 44using OpenSim.Framework.Servers;
44using OpenSim.Region.Framework.Interfaces; 45using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes; 46using OpenSim.Region.Framework.Scenes;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
index 990dffb..11e0150 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
@@ -31,7 +31,7 @@ using System.Collections.Generic;
31using System.Reflection; 31using System.Reflection;
32using Nini.Config; 32using Nini.Config;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Statistics; 34using OpenSim.Framework.Monitoring;
35using OpenSim.Services.Connectors; 35using OpenSim.Services.Connectors;
36using OpenSim.Region.Framework.Interfaces; 36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
index 6cd077a..e4c6c1a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs
@@ -134,11 +134,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
134 ///<summary> 134 ///<summary>
135 /// 135 ///
136 ///</summary> 136 ///</summary>
137
138
139 ///<summary>
140 ///
141 ///</summary>
142 public void AddRegion(Scene scene) 137 public void AddRegion(Scene scene)
143 { 138 {
144 if (! m_enabled) 139 if (! m_enabled)
@@ -149,10 +144,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
149 lock (m_scenes) 144 lock (m_scenes)
150 m_scenes[scene.RegionInfo.RegionID] = scene; 145 m_scenes[scene.RegionInfo.RegionID] = scene;
151 146
152 scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; 147 scene.EventManager.OnRegionReadyStatusChange += s => { if (s.Ready) UploadMapTile(s); };
153 } 148 }
154 149
155
156 ///<summary> 150 ///<summary>
157 /// 151 ///
158 ///</summary> 152 ///</summary>
@@ -166,21 +160,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage
166 } 160 }
167 161
168 #endregion ISharedRegionModule 162 #endregion ISharedRegionModule
169 163
170 void OnLoginsEnabled(string regionName)
171 {
172 Scene scene = null;
173 foreach (Scene s in m_scenes.Values)
174 if (s.RegionInfo.RegionName == regionName)
175 {
176 scene = s;
177 break;
178 }
179 if (scene != null)
180 UploadMapTile(scene);
181 }
182
183
184 ///<summary> 164 ///<summary>
185 /// 165 ///
186 ///</summary> 166 ///</summary>
diff --git a/OpenSim/Region/CoreModules/World/Access/AccessModule.cs b/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
index 553a32d..e7b1454 100644
--- a/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
+++ b/OpenSim/Region/CoreModules/World/Access/AccessModule.cs
@@ -129,18 +129,18 @@ namespace OpenSim.Region.CoreModules.World
129 switch (cmd[1]) 129 switch (cmd[1])
130 { 130 {
131 case "enable": 131 case "enable":
132 scene.LoginsDisabled = false; 132 scene.LoginsEnabled = true;
133 MainConsole.Instance.Output(String.Format("Logins are enabled for region {0}", scene.RegionInfo.RegionName)); 133 MainConsole.Instance.Output(String.Format("Logins are enabled for region {0}", scene.RegionInfo.RegionName));
134 break; 134 break;
135 case "disable": 135 case "disable":
136 scene.LoginsDisabled = true; 136 scene.LoginsEnabled = false;
137 MainConsole.Instance.Output(String.Format("Logins are disabled for region {0}", scene.RegionInfo.RegionName)); 137 MainConsole.Instance.Output(String.Format("Logins are disabled for region {0}", scene.RegionInfo.RegionName));
138 break; 138 break;
139 case "status": 139 case "status":
140 if (scene.LoginsDisabled) 140 if (scene.LoginsEnabled)
141 MainConsole.Instance.Output(String.Format("Login in {0} are disabled", scene.RegionInfo.RegionName));
142 else
143 MainConsole.Instance.Output(String.Format("Login in {0} are enabled", scene.RegionInfo.RegionName)); 141 MainConsole.Instance.Output(String.Format("Login in {0} are enabled", scene.RegionInfo.RegionName));
142 else
143 MainConsole.Instance.Output(String.Format("Login in {0} are disabled", scene.RegionInfo.RegionName));
144 break; 144 break;
145 default: 145 default:
146 MainConsole.Instance.Output("Syntax: login enable|disable|status"); 146 MainConsole.Instance.Output("Syntax: login enable|disable|status");
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
index e5cd3e2..09f6758 100644
--- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs
@@ -37,7 +37,7 @@ using Nini.Config;
37using OpenMetaverse; 37using OpenMetaverse;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Framework.Console; 39using OpenSim.Framework.Console;
40using OpenSim.Framework.Statistics; 40using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43 43
diff --git a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
index 2838e0c..7d35473 100644
--- a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs
@@ -37,7 +37,7 @@ using Nini.Config;
37using OpenMetaverse; 37using OpenMetaverse;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Framework.Console; 39using OpenSim.Framework.Console;
40using OpenSim.Framework.Statistics; 40using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
43 43
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index d768a1a..14c1a39 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -119,17 +119,20 @@ namespace OpenSim.Region.CoreModules.World.Sound
119 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) 119 m_scene.ForEachRootScenePresence(delegate(ScenePresence sp)
120 { 120 {
121 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); 121 double dis = Util.GetDistanceTo(sp.AbsolutePosition, position);
122
122 if (dis > 100.0) // Max audio distance 123 if (dis > 100.0) // Max audio distance
123 return; 124 return;
124 125
126 float thisSpGain;
127
125 // Scale by distance 128 // Scale by distance
126 if (radius == 0) 129 if (radius == 0)
127 gain = (float)((double)gain * ((100.0 - dis) / 100.0)); 130 thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0));
128 else 131 else
129 gain = (float)((double)gain * ((radius - dis) / radius)); 132 thisSpGain = (float)((double)gain * ((radius - dis) / radius));
130 133
131 sp.ControllingClient.SendTriggeredSound( 134 sp.ControllingClient.SendTriggeredSound(
132 soundId, ownerID, objectID, parentID, handle, position, (float)gain); 135 soundId, ownerID, objectID, parentID, handle, position, thisSpGain);
133 }); 136 });
134 } 137 }
135 } 138 }
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
index 309856f..26b406e 100644
--- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
+++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs
@@ -42,6 +42,7 @@ using OpenMetaverse.Imaging;
42using OpenMetaverse.StructuredData; 42using OpenMetaverse.StructuredData;
43using OpenSim.Framework; 43using OpenSim.Framework;
44using OpenSim.Framework.Capabilities; 44using OpenSim.Framework.Capabilities;
45using OpenSim.Framework.Monitoring;
45using OpenSim.Framework.Servers; 46using OpenSim.Framework.Servers;
46using OpenSim.Framework.Servers.HttpServer; 47using OpenSim.Framework.Servers.HttpServer;
47using OpenSim.Region.Framework.Interfaces; 48using OpenSim.Region.Framework.Interfaces;
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs
index aa4a757..136ca92 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs
@@ -25,14 +25,23 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28
29using System; 28using System;
29using OpenSim.Framework;
30 30
31namespace OpenSim.Region.Framework.Interfaces 31namespace OpenSim.Region.Framework.Interfaces
32{ 32{
33 public interface IRegionReadyModule 33 public interface IRegionReadyModule
34 { 34 {
35 void OarLoadingAlert(string msg); 35 void OarLoadingAlert(string msg);
36
37 /// <summary>
38 /// Trigger region ready status manually.
39 /// </summary>
40 /// <remarks>
41 /// This should be called by the scene if the IRegionReadyModule has set Scene.LoginLock == true
42 /// </remarks>
43 /// <param name='scene'></param>
44 void TriggerRegionReady(IScene scene);
36 } 45 }
37} 46}
38 47
diff --git a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
index 3f68ee0..0fe681f 100644
--- a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
@@ -40,8 +40,6 @@ namespace OpenSim.Region.Framework.Interfaces
40 /// </remarks> 40 /// </remarks>
41 public interface IScenePresence : ISceneAgent 41 public interface IScenePresence : ISceneAgent
42 { 42 {
43 PresenceType PresenceType { get; }
44
45 /// <summary> 43 /// <summary>
46 /// Copy of the script states while the agent is in transit. This state may 44 /// Copy of the script states while the agent is in transit. This state may
47 /// need to be placed back in case of transfer fail. 45 /// need to be placed back in case of transfer fail.
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
index bfe1e8d..ed71a95 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs
@@ -67,6 +67,10 @@ namespace OpenSim.Region.Framework.Interfaces
67 /// <param name="key"></param> 67 /// <param name="key"></param>
68 void DispatchReply(UUID scriptId, int code, string text, string key); 68 void DispatchReply(UUID scriptId, int code, string text, string key);
69 69
70 /// For constants
71 void RegisterConstant(string cname, object value);
72 object LookupModConstant(string cname);
73
70 // For use ONLY by the script API 74 // For use ONLY by the script API
71 void RaiseEvent(UUID script, string id, string module, string command, string key); 75 void RaiseEvent(UUID script, string id, string module, string command, string key);
72 } 76 }
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 9ddac19..50a176b 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -551,11 +551,5 @@ namespace OpenSim.Region.Framework.Scenes.Animation
551 551
552 SendAnimPack(animIDs, sequenceNums, objectIDs); 552 SendAnimPack(animIDs, sequenceNums, objectIDs);
553 } 553 }
554
555 public void Close()
556 {
557 m_animations = null;
558 m_scenePresence = null;
559 }
560 } 554 }
561} 555} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index d783e57..7cb3811 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -500,15 +500,24 @@ namespace OpenSim.Region.Framework.Scenes
500 public delegate void RegionHeartbeatEnd(Scene scene); 500 public delegate void RegionHeartbeatEnd(Scene scene);
501 public event RegionHeartbeatEnd OnRegionHeartbeatEnd; 501 public event RegionHeartbeatEnd OnRegionHeartbeatEnd;
502 502
503 public delegate void LoginsEnabled(string regionName); 503 /// <summary>
504 /// Fired when logins to a region are enabled or disabled.
505 /// </summary>
506 /// <remarks>
507 ///
508 /// </remarks>
509 /// Fired
510 public event RegionLoginsStatusChange OnRegionLoginsStatusChange;
511 public delegate void RegionLoginsStatusChange(IScene scene);
504 512
505 /// <summary> 513 /// <summary>
506 /// This should only fire in all circumstances if the RegionReady module is active. 514 /// Fired when a region is considered ready for use.
507 /// </summary> 515 /// </summary>
508 /// <remarks> 516 /// <remarks>
509 /// TODO: Fire this even when the RegionReady module is not active. 517 /// A region is considered ready when startup operations such as loading of scripts already on the region
518 /// have been completed.
510 /// </remarks> 519 /// </remarks>
511 public event LoginsEnabled OnLoginsEnabled; 520 public event Action<IScene> OnRegionReadyStatusChange;
512 521
513 public delegate void PrimsLoaded(Scene s); 522 public delegate void PrimsLoaded(Scene s);
514 public event PrimsLoaded OnPrimsLoaded; 523 public event PrimsLoaded OnPrimsLoaded;
@@ -2502,21 +2511,42 @@ namespace OpenSim.Region.Framework.Scenes
2502 } 2511 }
2503 } 2512 }
2504 2513
2505 public void TriggerLoginsEnabled (string regionName) 2514 public void TriggerRegionLoginsStatusChange(IScene scene)
2506 { 2515 {
2507 LoginsEnabled handler = OnLoginsEnabled; 2516 RegionLoginsStatusChange handler = OnRegionLoginsStatusChange;
2508 2517
2509 if ( handler != null) 2518 if (handler != null)
2510 { 2519 {
2511 foreach (LoginsEnabled d in handler.GetInvocationList()) 2520 foreach (RegionLoginsStatusChange d in handler.GetInvocationList())
2512 { 2521 {
2513 try 2522 try
2514 { 2523 {
2515 d(regionName); 2524 d(scene);
2525 }
2526 catch (Exception e)
2527 {
2528 m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionLoginsStatusChange failed - continuing {0} - {1}",
2529 e.Message, e.StackTrace);
2530 }
2531 }
2532 }
2533 }
2534
2535 public void TriggerRegionReadyStatusChange(IScene scene)
2536 {
2537 Action<IScene> handler = OnRegionReadyStatusChange;
2538
2539 if (handler != null)
2540 {
2541 foreach (Action<IScene> d in handler.GetInvocationList())
2542 {
2543 try
2544 {
2545 d(scene);
2516 } 2546 }
2517 catch (Exception e) 2547 catch (Exception e)
2518 { 2548 {
2519 m_log.ErrorFormat("[EVENT MANAGER]: Delegate for LoginsEnabled failed - continuing {0} - {1}", 2549 m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionReadyStatusChange failed - continuing {0} - {1}",
2520 e.Message, e.StackTrace); 2550 e.Message, e.StackTrace);
2521 } 2551 }
2522 } 2552 }
diff --git a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
index 1365831..c11174d 100644
--- a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
+++ b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs
@@ -39,7 +39,7 @@ using OpenSim.Framework.Communications;
39using OpenSim.Framework.Console; 39using OpenSim.Framework.Console;
40using OpenSim.Framework.Servers; 40using OpenSim.Framework.Servers;
41using OpenSim.Framework.Servers.HttpServer; 41using OpenSim.Framework.Servers.HttpServer;
42using OpenSim.Framework.Statistics; 42using OpenSim.Framework.Monitoring;
43using OpenSim.Region.Framework; 43using OpenSim.Region.Framework;
44using OpenSim.Region.Framework.Interfaces; 44using OpenSim.Region.Framework.Interfaces;
45using OpenSim.Region.Framework.Scenes; 45using OpenSim.Region.Framework.Scenes;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 98b8fcc..672d95a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -811,16 +811,20 @@ namespace OpenSim.Region.Framework.Scenes
811 && oldAgentID == LibraryService.LibraryRootFolder.Owner)) 811 && oldAgentID == LibraryService.LibraryRootFolder.Owner))
812 { 812 {
813 CreateNewInventoryItem( 813 CreateNewInventoryItem(
814 remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Flags, callbackID, asset, (sbyte)item.InvType, 814 remoteClient, item.CreatorId, item.CreatorData, newFolderID,
815 item.BasePermissions, item.CurrentPermissions, item.EveryOnePermissions, item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch()); 815 newName, item.Description, item.Flags, callbackID, asset, (sbyte)item.InvType,
816 item.BasePermissions, item.CurrentPermissions, item.EveryOnePermissions,
817 item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch());
816 } 818 }
817 else 819 else
818 { 820 {
819 // If item is transfer or permissions are off or calling agent is allowed to copy item owner's inventory item. 821 // If item is transfer or permissions are off or calling agent is allowed to copy item owner's inventory item.
820 if (((item.CurrentPermissions & (uint)PermissionMask.Transfer) != 0) && (m_permissions.BypassPermissions() || m_permissions.CanCopyUserInventory(remoteClient.AgentId, oldItemID))) 822 if (((item.CurrentPermissions & (uint)PermissionMask.Transfer) != 0)
823 && (m_permissions.BypassPermissions()
824 || m_permissions.CanCopyUserInventory(remoteClient.AgentId, oldItemID)))
821 { 825 {
822 CreateNewInventoryItem( 826 CreateNewInventoryItem(
823 remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Flags, callbackID, 827 remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Description, item.Flags, callbackID,
824 asset, (sbyte) item.InvType, 828 asset, (sbyte) item.InvType,
825 item.NextPermissions, item.NextPermissions, item.EveryOnePermissions & item.NextPermissions, 829 item.NextPermissions, item.NextPermissions, item.EveryOnePermissions & item.NextPermissions,
826 item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch()); 830 item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch());
@@ -885,32 +889,50 @@ namespace OpenSim.Region.Framework.Scenes
885 /// <summary> 889 /// <summary>
886 /// Create a new inventory item. 890 /// Create a new inventory item.
887 /// </summary> 891 /// </summary>
888 /// <param name="remoteClient"></param> 892 /// <param name="remoteClient">Client creating this inventory item.</param>
889 /// <param name="folderID"></param> 893 /// <param name="creatorID"></param>
890 /// <param name="callbackID"></param> 894 /// <param name="creatorData"></param>
891 /// <param name="asset"></param> 895 /// <param name="folderID">UUID of folder in which this item should be placed.</param>
892 /// <param name="invType"></param> 896 /// <param name="name">Item name.</para>
893 /// <param name="nextOwnerMask"></param> 897 /// <param name="description">Item description.</param>
894 public void CreateNewInventoryItem(IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, 898 /// <param name="flags">Item flags</param>
895 AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate) 899 /// <param name="callbackID">Generated by the client.</para>
900 /// <param name="asset">Asset to which this item refers.</param>
901 /// <param name="invType">Type of inventory item.</param>
902 /// <param name="nextOwnerMask">Next owner pemrissions mask.</param>
903 /// <param name="creationDate">Unix timestamp at which this item was created.</param>
904 public void CreateNewInventoryItem(
905 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
906 string name, string description, uint flags, uint callbackID,
907 AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate)
896 { 908 {
897 CreateNewInventoryItem( 909 CreateNewInventoryItem(
898 remoteClient, creatorID, creatorData, folderID, name, flags, callbackID, asset, invType, 910 remoteClient, creatorID, creatorData, folderID, name, description, flags, callbackID, asset, invType,
899 (uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate); 911 (uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate);
900 } 912 }
901 913
902 /// <summary> 914 /// <summary>
903 /// Create a new Inventory Item 915 /// Create a new Inventory Item
904 /// </summary> 916 /// </summary>
905 /// <param name="remoteClient"></param> 917 /// <param name="remoteClient">Client creating this inventory item.</param>
906 /// <param name="folderID"></param> 918 /// <param name="creatorID"></param>
907 /// <param name="callbackID"></param> 919 /// <param name="creatorData"></param>
908 /// <param name="asset"></param> 920 /// <param name="folderID">UUID of folder in which this item should be placed.</param>
909 /// <param name="invType"></param> 921 /// <param name="name">Item name.</para>
910 /// <param name="nextOwnerMask"></param> 922 /// <param name="description">Item description.</param>
911 /// <param name="creationDate"></param> 923 /// <param name="flags">Item flags</param>
924 /// <param name="callbackID">Generated by the client.</para>
925 /// <param name="asset">Asset to which this item refers.</param>
926 /// <param name="invType">Type of inventory item.</param>
927 /// <param name="baseMask">Base permissions mask.</param>
928 /// <param name="currentMask">Current permissions mask.</param>
929 /// <param name="everyoneMask">Everyone permissions mask.</param>
930 /// <param name="nextOwnerMask">Next owner pemrissions mask.</param>
931 /// <param name="groupMask">Group permissions mask.</param>
932 /// <param name="creationDate">Unix timestamp at which this item was created.</param>
912 private void CreateNewInventoryItem( 933 private void CreateNewInventoryItem(
913 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, AssetBase asset, sbyte invType, 934 IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID,
935 string name, string description, uint flags, uint callbackID, AssetBase asset, sbyte invType,
914 uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate) 936 uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate)
915 { 937 {
916 InventoryItemBase item = new InventoryItemBase(); 938 InventoryItemBase item = new InventoryItemBase();
@@ -919,8 +941,8 @@ namespace OpenSim.Region.Framework.Scenes
919 item.CreatorData = creatorData; 941 item.CreatorData = creatorData;
920 item.ID = UUID.Random(); 942 item.ID = UUID.Random();
921 item.AssetID = asset.FullID; 943 item.AssetID = asset.FullID;
922 item.Description = asset.Description;
923 item.Name = name; 944 item.Name = name;
945 item.Description = description;
924 item.Flags = flags; 946 item.Flags = flags;
925 item.AssetType = asset.Type; 947 item.AssetType = asset.Type;
926 item.InvType = invType; 948 item.InvType = invType;
@@ -1002,7 +1024,8 @@ namespace OpenSim.Region.Framework.Scenes
1002 asset.Description = description; 1024 asset.Description = description;
1003 1025
1004 CreateNewInventoryItem( 1026 CreateNewInventoryItem(
1005 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, name, 0, callbackID, asset, invType, 1027 remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID,
1028 name, description, 0, callbackID, asset, invType,
1006 (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All, 1029 (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All,
1007 (uint)PermissionMask.All, (uint)PermissionMask.All, Util.UnixTimeSinceEpoch()); 1030 (uint)PermissionMask.All, (uint)PermissionMask.All, Util.UnixTimeSinceEpoch());
1008 } 1031 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index ad9e91d..3a28d42 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -40,6 +40,7 @@ using OpenMetaverse;
40using OpenMetaverse.Packets; 40using OpenMetaverse.Packets;
41using OpenMetaverse.Imaging; 41using OpenMetaverse.Imaging;
42using OpenSim.Framework; 42using OpenSim.Framework;
43using OpenSim.Framework.Monitoring;
43using OpenSim.Services.Interfaces; 44using OpenSim.Services.Interfaces;
44using OpenSim.Framework.Communications; 45using OpenSim.Framework.Communications;
45using OpenSim.Framework.Console; 46using OpenSim.Framework.Console;
@@ -129,9 +130,10 @@ namespace OpenSim.Region.Framework.Scenes
129 public bool m_strictAccessControl = true; 130 public bool m_strictAccessControl = true;
130 public bool m_seeIntoBannedRegion = false; 131 public bool m_seeIntoBannedRegion = false;
131 public int MaxUndoCount = 5; 132 public int MaxUndoCount = 5;
133
132 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 134 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
133 public bool LoginLock = false; 135 public bool LoginLock = false;
134 public bool LoginsDisabled = true; 136
135 public bool StartDisabled = false; 137 public bool StartDisabled = false;
136 public bool LoadingPrims; 138 public bool LoadingPrims;
137 public IXfer XferManager; 139 public IXfer XferManager;
@@ -727,6 +729,8 @@ namespace OpenSim.Region.Framework.Scenes
727 { 729 {
728 IConfig startupConfig = m_config.Configs["Startup"]; 730 IConfig startupConfig = m_config.Configs["Startup"];
729 731
732 StartDisabled = startupConfig.GetBoolean("StartDisabled", false);
733
730 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); 734 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance);
731 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup); 735 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
732 if (!m_useBackup) 736 if (!m_useBackup)
@@ -1229,15 +1233,17 @@ namespace OpenSim.Region.Framework.Scenes
1229 avatar.ControllingClient.SendShutdownConnectionNotice(); 1233 avatar.ControllingClient.SendShutdownConnectionNotice();
1230 }); 1234 });
1231 1235
1236 // Stop updating the scene objects and agents.
1237 m_shuttingDown = true;
1238
1232 // Wait here, or the kick messages won't actually get to the agents before the scene terminates. 1239 // Wait here, or the kick messages won't actually get to the agents before the scene terminates.
1240 // We also need to wait to avoid a race condition with the scene update loop which might not yet
1241 // have checked ShuttingDown.
1233 Thread.Sleep(500); 1242 Thread.Sleep(500);
1234 1243
1235 // Stop all client threads. 1244 // Stop all client threads.
1236 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); 1245 ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); });
1237 1246
1238 // Stop updating the scene objects and agents.
1239 m_shuttingDown = true;
1240
1241 m_log.Debug("[SCENE]: Persisting changed objects"); 1247 m_log.Debug("[SCENE]: Persisting changed objects");
1242 EventManager.TriggerSceneShuttingDown(this); 1248 EventManager.TriggerSceneShuttingDown(this);
1243 1249
@@ -1252,6 +1258,15 @@ namespace OpenSim.Region.Framework.Scenes
1252 1258
1253 m_sceneGraph.Close(); 1259 m_sceneGraph.Close();
1254 1260
1261 if (PhysicsScene != null)
1262 {
1263 PhysicsScene phys = PhysicsScene;
1264 // remove the physics engine from both Scene and SceneGraph
1265 PhysicsScene = null;
1266 phys.Dispose();
1267 phys = null;
1268 }
1269
1255 if (!GridService.DeregisterRegion(RegionInfo.RegionID)) 1270 if (!GridService.DeregisterRegion(RegionInfo.RegionID))
1256 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); 1271 m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name);
1257 1272
@@ -1530,7 +1545,7 @@ namespace OpenSim.Region.Framework.Scenes
1530 // landMS = Util.EnvironmentTickCountSubtract(ldMS); 1545 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1531 //} 1546 //}
1532 1547
1533 if (LoginsDisabled && Frame == 20) 1548 if (!LoginsEnabled && Frame == 20)
1534 { 1549 {
1535 // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock); 1550 // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock);
1536 1551
@@ -1538,31 +1553,34 @@ namespace OpenSim.Region.Framework.Scenes
1538 // this is a rare case where we know we have just went through a long cycle of heap 1553 // this is a rare case where we know we have just went through a long cycle of heap
1539 // allocations, and there is no more work to be done until someone logs in 1554 // allocations, and there is no more work to be done until someone logs in
1540 GC.Collect(); 1555 GC.Collect();
1541 1556
1542 IConfig startupConfig = m_config.Configs["Startup"]; 1557 if (!LoginLock)
1543 if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false))
1544 { 1558 {
1545 // This handles a case of a region having no scripts for the RegionReady module 1559 if (!StartDisabled)
1546 if (m_sceneGraph.GetActiveScriptsCount() == 0)
1547 {
1548 // need to be able to tell these have changed in RegionReady
1549 LoginLock = false;
1550 EventManager.TriggerLoginsEnabled(RegionInfo.RegionName);
1551 }
1552
1553 // For RegionReady lockouts
1554 if (!LoginLock)
1555 { 1560 {
1556 m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); 1561 m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName);
1557 LoginsDisabled = false; 1562 LoginsEnabled = true;
1558 } 1563 }
1559 1564
1560 m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo); 1565 m_sceneGridService.InformNeighborsThatRegionisUp(
1566 RequestModuleInterface<INeighbourService>(), RegionInfo);
1567
1568 // Region ready should always be set
1569 Ready = true;
1561 } 1570 }
1562 else 1571 else
1563 { 1572 {
1564 StartDisabled = true; 1573 // This handles a case of a region having no scripts for the RegionReady module
1565 LoginsDisabled = true; 1574 if (m_sceneGraph.GetActiveScriptsCount() == 0)
1575 {
1576 // In this case, we leave it to the IRegionReadyModule to enable logins
1577
1578 // LoginLock can currently only be set by a region module implementation.
1579 // If somehow this hasn't been done then the quickest way to bugfix is to see the
1580 // NullReferenceException
1581 IRegionReadyModule rrm = RequestModuleInterface<IRegionReadyModule>();
1582 rrm.TriggerRegionReady(this);
1583 }
1566 } 1584 }
1567 } 1585 }
1568 } 1586 }
@@ -3477,25 +3495,31 @@ namespace OpenSim.Region.Framework.Scenes
3477 if (AgentTransactionsModule != null) 3495 if (AgentTransactionsModule != null)
3478 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); 3496 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3479 3497
3480 avatar.Close();
3481
3482 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3498 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3483 m_log.Debug("[Scene] The avatar has left the building"); 3499 m_log.Debug("[Scene] The avatar has left the building");
3484 } 3500 }
3485 catch (Exception e) 3501 catch (Exception e)
3486 { 3502 {
3487 m_log.Error( 3503 m_log.Error(
3488 string.Format("[SCENE]: Exception removing {0} from {1}, ", avatar.Name, RegionInfo.RegionName), e); 3504 string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e);
3489 } 3505 }
3490 finally 3506 finally
3491 { 3507 {
3492 // Always clean these structures up so that any failure above doesn't cause them to remain in the 3508 try
3493 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering 3509 {
3494 // the same cleanup exception continually. 3510 // Always clean these structures up so that any failure above doesn't cause them to remain in the
3495 // TODO: This should probably extend to the whole method, but we don't want to also catch the NRE 3511 // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering
3496 // since this would hide the underlying failure and other associated problems. 3512 // the same cleanup exception continually.
3497 m_sceneGraph.RemoveScenePresence(agentID); 3513 m_sceneGraph.RemoveScenePresence(agentID);
3498 m_clientManager.Remove(agentID); 3514 m_clientManager.Remove(agentID);
3515
3516 avatar.Close();
3517 }
3518 catch (Exception e)
3519 {
3520 m_log.Error(
3521 string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e);
3522 }
3499 } 3523 }
3500 3524
3501 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3525 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
@@ -3609,7 +3633,7 @@ namespace OpenSim.Region.Framework.Scenes
3609 agent.startpos 3633 agent.startpos
3610 ); 3634 );
3611 3635
3612 if (LoginsDisabled) 3636 if (!LoginsEnabled)
3613 { 3637 {
3614 reason = "Logins Disabled"; 3638 reason = "Logins Disabled";
3615 return false; 3639 return false;
@@ -3666,8 +3690,8 @@ namespace OpenSim.Region.Framework.Scenes
3666 // We have a zombie from a crashed session. 3690 // We have a zombie from a crashed session.
3667 // Or the same user is trying to be root twice here, won't work. 3691 // Or the same user is trying to be root twice here, won't work.
3668 // Kill it. 3692 // Kill it.
3669 m_log.DebugFormat( 3693 m_log.WarnFormat(
3670 "[SCENE]: Zombie scene presence detected for {0} {1} in {2}", 3694 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3671 sp.Name, sp.UUID, RegionInfo.RegionName); 3695 sp.Name, sp.UUID, RegionInfo.RegionName);
3672 3696
3673 sp.ControllingClient.Close(); 3697 sp.ControllingClient.Close();
@@ -4658,6 +4682,23 @@ namespace OpenSim.Region.Framework.Scenes
4658 } 4682 }
4659 4683
4660 /// <summary> 4684 /// <summary>
4685 /// Gets all the scene presences in this scene.
4686 /// </summary>
4687 /// <remarks>
4688 /// This method will return both root and child scene presences.
4689 ///
4690 /// Consider using ForEachScenePresence() or ForEachRootScenePresence() if possible since these will not
4691 /// involving creating a new List object.
4692 /// </remarks>
4693 /// <returns>
4694 /// A list of the scene presences. Adding or removing from the list will not affect the presences in the scene.
4695 /// </returns>
4696 public List<ScenePresence> GetScenePresences()
4697 {
4698 return new List<ScenePresence>(m_sceneGraph.GetScenePresences());
4699 }
4700
4701 /// <summary>
4661 /// Performs action on all avatars in the scene (root scene presences) 4702 /// Performs action on all avatars in the scene (root scene presences)
4662 /// Avatars may be an NPC or a 'real' client. 4703 /// Avatars may be an NPC or a 'real' client.
4663 /// </summary> 4704 /// </summary>
@@ -5775,5 +5816,21 @@ Environment.Exit(1);
5775 { 5816 {
5776 GC.Collect(); 5817 GC.Collect();
5777 } 5818 }
5819
5820 // Wrappers to get physics modules retrieve assets. Has to be done this way
5821 // because we can't assign the asset service to physics directly - at the
5822 // time physics are instantiated it's not registered but it will be by
5823 // the time the first prim exists.
5824 public void PhysicsRequestAsset(UUID assetID, AssetReceivedDelegate callback)
5825 {
5826 AssetService.Get(assetID.ToString(), callback, PhysicsAssetReceived);
5827 }
5828
5829 private void PhysicsAssetReceived(string id, Object sender, AssetBase asset)
5830 {
5831 AssetReceivedDelegate callback = (AssetReceivedDelegate)sender;
5832
5833 callback(asset);
5834 }
5778 } 5835 }
5779} 5836}
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 8db4397..7c8bd88 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -106,6 +106,42 @@ namespace OpenSim.Region.Framework.Scenes
106 106
107 protected readonly ClientManager m_clientManager = new ClientManager(); 107 protected readonly ClientManager m_clientManager = new ClientManager();
108 108
109 public bool LoginsEnabled
110 {
111 get
112 {
113 return m_loginsEnabled;
114 }
115
116 set
117 {
118 if (m_loginsEnabled != value)
119 {
120 m_loginsEnabled = value;
121 EventManager.TriggerRegionLoginsStatusChange(this);
122 }
123 }
124 }
125 private bool m_loginsEnabled;
126
127 public bool Ready
128 {
129 get
130 {
131 return m_ready;
132 }
133
134 set
135 {
136 if (m_ready != value)
137 {
138 m_ready = value;
139 EventManager.TriggerRegionReadyStatusChange(this);
140 }
141 }
142 }
143 private bool m_ready;
144
109 public float TimeDilation 145 public float TimeDilation
110 { 146 {
111 get { return 1.0f; } 147 get { return 1.0f; }
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index c3d66eb..e0260e2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -848,7 +848,7 @@ namespace OpenSim.Region.Framework.Scenes
848 /// pass a delegate to ForEachScenePresence. 848 /// pass a delegate to ForEachScenePresence.
849 /// </summary> 849 /// </summary>
850 /// <returns></returns> 850 /// <returns></returns>
851 private List<ScenePresence> GetScenePresences() 851 protected internal List<ScenePresence> GetScenePresences()
852 { 852 {
853 return m_scenePresenceArray; 853 return m_scenePresenceArray;
854 } 854 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index e3fed49..f1b09ca 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -47,6 +47,48 @@ namespace OpenSim.Region.Framework.Scenes
47 47
48 public event RestartSim OnRestartSim; 48 public event RestartSim OnRestartSim;
49 49
50 /// <summary>
51 /// Fired when either all regions are ready for use or at least one region has become unready for use where
52 /// previously all regions were ready.
53 /// </summary>
54 public event Action<SceneManager> OnRegionsReadyStatusChange;
55
56 /// <summary>
57 /// Are all regions ready for use?
58 /// </summary>
59 public bool AllRegionsReady
60 {
61 get
62 {
63 return m_allRegionsReady;
64 }
65
66 private set
67 {
68 if (m_allRegionsReady != value)
69 {
70 m_allRegionsReady = value;
71 Action<SceneManager> handler = OnRegionsReadyStatusChange;
72 if (handler != null)
73 {
74 foreach (Action<SceneManager> d in handler.GetInvocationList())
75 {
76 try
77 {
78 d(this);
79 }
80 catch (Exception e)
81 {
82 m_log.ErrorFormat("[SCENE MANAGER]: Delegate for OnRegionsReadyStatusChange failed - continuing {0} - {1}",
83 e.Message, e.StackTrace);
84 }
85 }
86 }
87 }
88 }
89 }
90 private bool m_allRegionsReady;
91
50 private static SceneManager m_instance = null; 92 private static SceneManager m_instance = null;
51 public static SceneManager Instance 93 public static SceneManager Instance
52 { 94 {
@@ -128,9 +170,11 @@ namespace OpenSim.Region.Framework.Scenes
128 170
129 public void Add(Scene scene) 171 public void Add(Scene scene)
130 { 172 {
131 scene.OnRestart += HandleRestart; 173 lock (m_localScenes)
174 m_localScenes.Add(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, scene);
132 175
133 m_localScenes.Add(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, scene); 176 scene.OnRestart += HandleRestart;
177 scene.EventManager.OnRegionReadyStatusChange += HandleRegionReadyStatusChange;
134 } 178 }
135 179
136 public void HandleRestart(RegionInfo rdata) 180 public void HandleRestart(RegionInfo rdata)
@@ -138,12 +182,19 @@ namespace OpenSim.Region.Framework.Scenes
138 m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main"); 182 m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main");
139 int RegionSceneElement = -1; 183 int RegionSceneElement = -1;
140 184
141 m_localScenes.Remove(rdata.RegionID); 185 lock (m_localScenes)
186 m_localScenes.Remove(rdata.RegionID);
142 187
143 // Send signal to main that we're restarting this sim. 188 // Send signal to main that we're restarting this sim.
144 OnRestartSim(rdata); 189 OnRestartSim(rdata);
145 } 190 }
146 191
192 private void HandleRegionReadyStatusChange(IScene scene)
193 {
194 lock (m_localScenes)
195 AllRegionsReady = m_localScenes.FindAll(s => !s.Ready).Count == 0;
196 }
197
147 public void SendSimOnlineNotification(ulong regionHandle) 198 public void SendSimOnlineNotification(ulong regionHandle)
148 { 199 {
149 RegionInfo Result = null; 200 RegionInfo Result = null;
@@ -483,7 +534,8 @@ namespace OpenSim.Region.Framework.Scenes
483 534
484 public void CloseScene(Scene scene) 535 public void CloseScene(Scene scene)
485 { 536 {
486 m_localScenes.Remove(scene.RegionInfo.RegionID); 537 lock (m_localScenes)
538 m_localScenes.Remove(scene.RegionInfo.RegionID);
487 539
488 scene.Close(); 540 scene.Close();
489 } 541 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 6ab0027..08c7a58 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1991,7 +1991,7 @@ namespace OpenSim.Region.Framework.Scenes
1991 try 1991 try
1992 { 1992 {
1993 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart 1993 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1994 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things 1994 !m_scene.LoginsEnabled || // We're starting up or doing maintenance, don't mess with things
1995 m_scene.LoadingPrims) // Land may not be valid yet 1995 m_scene.LoadingPrims) // Land may not be valid yet
1996 1996
1997 { 1997 {
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cdabd45..4d3ab51 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -110,15 +110,10 @@ namespace OpenSim.Region.Framework.Scenes
110 110
111 public UUID currentParcelUUID = UUID.Zero; 111 public UUID currentParcelUUID = UUID.Zero;
112 112
113 protected ScenePresenceAnimator m_animator;
114 /// <value> 113 /// <value>
115 /// The animator for this avatar 114 /// The animator for this avatar
116 /// </value> 115 /// </value>
117 public ScenePresenceAnimator Animator 116 public ScenePresenceAnimator Animator { get; private set; }
118 {
119 get { return m_animator; }
120 private set { m_animator = value; }
121 }
122 117
123 /// <summary> 118 /// <summary>
124 /// Attachments recorded on this avatar. 119 /// Attachments recorded on this avatar.
@@ -2763,8 +2758,7 @@ namespace OpenSim.Region.Framework.Scenes
2763 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); 2758 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
2764 2759
2765 avatar.ControllingClient.SendAvatarDataImmediate(this); 2760 avatar.ControllingClient.SendAvatarDataImmediate(this);
2766 if (Animator != null) 2761 Animator.SendAnimPackToClient(avatar.ControllingClient);
2767 Animator.SendAnimPackToClient(avatar.ControllingClient);
2768 } 2762 }
2769 2763
2770 /// <summary> 2764 /// <summary>
@@ -3440,6 +3434,16 @@ namespace OpenSim.Region.Framework.Scenes
3440 if (IsChildAgent) 3434 if (IsChildAgent)
3441 return; 3435 return;
3442 3436
3437 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
3438 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
3439 // as of this comment the interval is set in AddToPhysicalScene
3440
3441// if (m_updateCount > 0)
3442// {
3443 Animator.UpdateMovementAnimations();
3444// m_updateCount--;
3445// }
3446
3443 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3447 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3444 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3448 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3445 3449
@@ -3453,7 +3457,7 @@ namespace OpenSim.Region.Framework.Scenes
3453// m_lastColCount = coldata.Count; 3457// m_lastColCount = coldata.Count;
3454// } 3458// }
3455 3459
3456 if (coldata.Count != 0 && Animator != null) 3460 if (coldata.Count != 0)
3457 { 3461 {
3458 switch (Animator.CurrentMovementAnimation) 3462 switch (Animator.CurrentMovementAnimation)
3459 { 3463 {
@@ -3565,7 +3569,7 @@ namespace OpenSim.Region.Framework.Scenes
3565 ControllingClient.SendHealth(Health); 3569 ControllingClient.SendHealth(Health);
3566 } 3570 }
3567 3571
3568 public void Close() 3572 protected internal void Close()
3569 { 3573 {
3570 // Clear known regions 3574 // Clear known regions
3571 KnownRegions = new Dictionary<ulong, string>(); 3575 KnownRegions = new Dictionary<ulong, string>();
@@ -3581,9 +3585,6 @@ namespace OpenSim.Region.Framework.Scenes
3581 // m_reprioritizationTimer.Dispose(); 3585 // m_reprioritizationTimer.Dispose();
3582 3586
3583 RemoveFromPhysicalScene(); 3587 RemoveFromPhysicalScene();
3584 if(Animator != null)
3585 Animator.Close();
3586 Animator = null;
3587 } 3588 }
3588 3589
3589 public void AddAttachment(SceneObjectGroup gobj) 3590 public void AddAttachment(SceneObjectGroup gobj)
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index d6ff5a2..20919a1 100644
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -30,7 +30,7 @@ using System.Collections.Generic;
30using System.Timers; 30using System.Timers;
31using OpenMetaverse.Packets; 31using OpenMetaverse.Packets;
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Framework.Statistics; 33using OpenSim.Framework.Monitoring;
34using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
35 35
36namespace OpenSim.Region.Framework.Scenes 36namespace OpenSim.Region.Framework.Scenes
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index 02c45ef..5758869 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -53,62 +53,94 @@ namespace OpenSim.Region.Framework.Scenes.Tests
53 /// Scene presence tests 53 /// Scene presence tests
54 /// </summary> 54 /// </summary>
55 [TestFixture] 55 [TestFixture]
56 public class ScenePresenceAgentTests 56 public class ScenePresenceAgentTests : OpenSimTestCase
57 { 57 {
58 public Scene scene, scene2, scene3; 58// public Scene scene, scene2, scene3;
59 public UUID agent1, agent2, agent3; 59// public UUID agent1, agent2, agent3;
60 public static Random random; 60// public static Random random;
61 public ulong region1,region2,region3; 61// public ulong region1, region2, region3;
62 public AgentCircuitData acd1; 62// public AgentCircuitData acd1;
63 public SceneObjectGroup sog1, sog2, sog3; 63// public TestClient testclient;
64 public TestClient testclient; 64
65 65// [TestFixtureSetUp]
66 [TestFixtureSetUp] 66// public void Init()
67 public void Init() 67// {
68//// TestHelpers.InMethod();
69////
70//// SceneHelpers sh = new SceneHelpers();
71////
72//// scene = sh.SetupScene("Neighbour x", UUID.Random(), 1000, 1000);
73//// scene2 = sh.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000);
74//// scene3 = sh.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000);
75////
76//// ISharedRegionModule interregionComms = new LocalSimulationConnectorModule();
77//// interregionComms.Initialise(new IniConfigSource());
78//// interregionComms.PostInitialise();
79//// SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), interregionComms);
80//// SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), interregionComms);
81//// SceneHelpers.SetupSceneModules(scene3, new IniConfigSource(), interregionComms);
82//
83//// agent1 = UUID.Random();
84//// agent2 = UUID.Random();
85//// agent3 = UUID.Random();
86//
87//// region1 = scene.RegionInfo.RegionHandle;
88//// region2 = scene2.RegionInfo.RegionHandle;
89//// region3 = scene3.RegionInfo.RegionHandle;
90// }
91
92 [Test]
93 public void TestCreateRootScenePresence()
68 { 94 {
69 TestHelpers.InMethod(); 95 TestHelpers.InMethod();
96// TestHelpers.EnableLogging();
97
98 UUID spUuid = TestHelpers.ParseTail(0x1);
70 99
71 SceneHelpers sh = new SceneHelpers(); 100 TestScene scene = new SceneHelpers().SetupScene();
72 101 SceneHelpers.AddScenePresence(scene, spUuid);
73 scene = sh.SetupScene("Neighbour x", UUID.Random(), 1000, 1000); 102
74 scene2 = sh.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000); 103 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null);
75 scene3 = sh.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000); 104 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
76 105
77 ISharedRegionModule interregionComms = new LocalSimulationConnectorModule(); 106 ScenePresence sp = scene.GetScenePresence(spUuid);
78 interregionComms.Initialise(new IniConfigSource()); 107 Assert.That(sp, Is.Not.Null);
79 interregionComms.PostInitialise(); 108 Assert.That(sp.IsChildAgent, Is.False);
80 SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), interregionComms); 109 Assert.That(sp.UUID, Is.EqualTo(spUuid));
81 SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), interregionComms); 110
82 SceneHelpers.SetupSceneModules(scene3, new IniConfigSource(), interregionComms); 111 Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1));
83
84 agent1 = UUID.Random();
85 agent2 = UUID.Random();
86 agent3 = UUID.Random();
87 random = new Random();
88 sog1 = SceneHelpers.CreateSceneObject(1, agent1);
89 scene.AddSceneObject(sog1);
90 sog2 = SceneHelpers.CreateSceneObject(1, agent1);
91 scene.AddSceneObject(sog2);
92 sog3 = SceneHelpers.CreateSceneObject(1, agent1);
93 scene.AddSceneObject(sog3);
94
95 region1 = scene.RegionInfo.RegionHandle;
96 region2 = scene2.RegionInfo.RegionHandle;
97 region3 = scene3.RegionInfo.RegionHandle;
98 } 112 }
99 113
100 [Test] 114 [Test]
101 public void TestCloseAgent() 115 public void TestCreateDuplicateRootScenePresence()
102 { 116 {
103 TestHelpers.InMethod(); 117 TestHelpers.InMethod();
104// TestHelpers.EnableLogging(); 118// TestHelpers.EnableLogging();
105 119
120 UUID spUuid = TestHelpers.ParseTail(0x1);
121
106 TestScene scene = new SceneHelpers().SetupScene(); 122 TestScene scene = new SceneHelpers().SetupScene();
107 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 123 SceneHelpers.AddScenePresence(scene, spUuid);
124 SceneHelpers.AddScenePresence(scene, spUuid);
108 125
109 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Not.Null); 126 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null);
110 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); 127 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
111 128
129 ScenePresence sp = scene.GetScenePresence(spUuid);
130 Assert.That(sp, Is.Not.Null);
131 Assert.That(sp.IsChildAgent, Is.False);
132 Assert.That(sp.UUID, Is.EqualTo(spUuid));
133 }
134
135 [Test]
136 public void TestCloseAgent()
137 {
138 TestHelpers.InMethod();
139// TestHelpers.EnableLogging();
140
141 TestScene scene = new SceneHelpers().SetupScene();
142 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
143
112 scene.IncomingCloseAgent(sp.UUID); 144 scene.IncomingCloseAgent(sp.UUID);
113 145
114 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); 146 Assert.That(scene.GetScenePresence(sp.UUID), Is.Null);
@@ -266,99 +298,99 @@ namespace OpenSim.Region.Framework.Scenes.Tests
266 // but things are synchronous among them. So there should be 298 // but things are synchronous among them. So there should be
267 // 3 threads in here. 299 // 3 threads in here.
268 //[Test] 300 //[Test]
269 public void T021_TestCrossToNewRegion() 301// public void T021_TestCrossToNewRegion()
270 { 302// {
271 TestHelpers.InMethod(); 303// TestHelpers.InMethod();
272 304//
273 scene.RegisterRegionWithGrid(); 305// scene.RegisterRegionWithGrid();
274 scene2.RegisterRegionWithGrid(); 306// scene2.RegisterRegionWithGrid();
275 307//
276 // Adding child agent to region 1001 308// // Adding child agent to region 1001
277 string reason; 309// string reason;
278 scene2.NewUserConnection(acd1,0, out reason); 310// scene2.NewUserConnection(acd1,0, out reason);
279 scene2.AddNewClient(testclient, PresenceType.User); 311// scene2.AddNewClient(testclient, PresenceType.User);
280 312//
281 ScenePresence presence = scene.GetScenePresence(agent1); 313// ScenePresence presence = scene.GetScenePresence(agent1);
282 presence.MakeRootAgent(new Vector3(0,unchecked(Constants.RegionSize-1),0), true); 314// presence.MakeRootAgent(new Vector3(0,unchecked(Constants.RegionSize-1),0), true);
283 315//
284 ScenePresence presence2 = scene2.GetScenePresence(agent1); 316// ScenePresence presence2 = scene2.GetScenePresence(agent1);
285 317//
286 // Adding neighbour region caps info to presence2 318// // Adding neighbour region caps info to presence2
287 319//
288 string cap = presence.ControllingClient.RequestClientInfo().CapsPath; 320// string cap = presence.ControllingClient.RequestClientInfo().CapsPath;
289 presence2.AddNeighbourRegion(region1, cap); 321// presence2.AddNeighbourRegion(region1, cap);
290 322//
291 Assert.That(presence.IsChildAgent, Is.False, "Did not start root in origin region."); 323// Assert.That(presence.IsChildAgent, Is.False, "Did not start root in origin region.");
292 Assert.That(presence2.IsChildAgent, Is.True, "Is not a child on destination region."); 324// Assert.That(presence2.IsChildAgent, Is.True, "Is not a child on destination region.");
293 325//
294 // Cross to x+1 326// // Cross to x+1
295 presence.AbsolutePosition = new Vector3(Constants.RegionSize+1,3,100); 327// presence.AbsolutePosition = new Vector3(Constants.RegionSize+1,3,100);
296 presence.Update(); 328// presence.Update();
297 329//
298 EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing"); 330// EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing");
299 331//
300 // Mimicking communication between client and server, by waiting OK from client 332// // Mimicking communication between client and server, by waiting OK from client
301 // sent by TestClient.CrossRegion call. Originally, this is network comm. 333// // sent by TestClient.CrossRegion call. Originally, this is network comm.
302 if (!wh.WaitOne(5000,false)) 334// if (!wh.WaitOne(5000,false))
303 { 335// {
304 presence.Update(); 336// presence.Update();
305 if (!wh.WaitOne(8000,false)) 337// if (!wh.WaitOne(8000,false))
306 throw new ArgumentException("1 - Timeout waiting for signal/variable."); 338// throw new ArgumentException("1 - Timeout waiting for signal/variable.");
307 } 339// }
308 340//
309 // This is a TestClient specific method that fires OnCompleteMovementToRegion event, which 341// // This is a TestClient specific method that fires OnCompleteMovementToRegion event, which
310 // would normally be fired after receiving the reply packet from comm. done on the last line. 342// // would normally be fired after receiving the reply packet from comm. done on the last line.
311 testclient.CompleteMovement(); 343// testclient.CompleteMovement();
312 344//
313 // Crossings are asynchronous 345// // Crossings are asynchronous
314 int timer = 10; 346// int timer = 10;
315 347//
316 // Make sure cross hasn't already finished 348// // Make sure cross hasn't already finished
317 if (!presence.IsInTransit && !presence.IsChildAgent) 349// if (!presence.IsInTransit && !presence.IsChildAgent)
318 { 350// {
319 // If not and not in transit yet, give it some more time 351// // If not and not in transit yet, give it some more time
320 Thread.Sleep(5000); 352// Thread.Sleep(5000);
321 } 353// }
322 354//
323 // Enough time, should at least be in transit by now. 355// // Enough time, should at least be in transit by now.
324 while (presence.IsInTransit && timer > 0) 356// while (presence.IsInTransit && timer > 0)
325 { 357// {
326 Thread.Sleep(1000); 358// Thread.Sleep(1000);
327 timer-=1; 359// timer-=1;
328 } 360// }
329 361//
330 Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 2->1."); 362// Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 2->1.");
331 Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected."); 363// Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected.");
332 Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent."); 364// Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent.");
333 365//
334 // Cross Back 366// // Cross Back
335 presence2.AbsolutePosition = new Vector3(-10, 3, 100); 367// presence2.AbsolutePosition = new Vector3(-10, 3, 100);
336 presence2.Update(); 368// presence2.Update();
337 369//
338 if (!wh.WaitOne(5000,false)) 370// if (!wh.WaitOne(5000,false))
339 { 371// {
340 presence2.Update(); 372// presence2.Update();
341 if (!wh.WaitOne(8000,false)) 373// if (!wh.WaitOne(8000,false))
342 throw new ArgumentException("2 - Timeout waiting for signal/variable."); 374// throw new ArgumentException("2 - Timeout waiting for signal/variable.");
343 } 375// }
344 testclient.CompleteMovement(); 376// testclient.CompleteMovement();
345 377//
346 if (!presence2.IsInTransit && !presence2.IsChildAgent) 378// if (!presence2.IsInTransit && !presence2.IsChildAgent)
347 { 379// {
348 // If not and not in transit yet, give it some more time 380// // If not and not in transit yet, give it some more time
349 Thread.Sleep(5000); 381// Thread.Sleep(5000);
350 } 382// }
351 383//
352 // Enough time, should at least be in transit by now. 384// // Enough time, should at least be in transit by now.
353 while (presence2.IsInTransit && timer > 0) 385// while (presence2.IsInTransit && timer > 0)
354 { 386// {
355 Thread.Sleep(1000); 387// Thread.Sleep(1000);
356 timer-=1; 388// timer-=1;
357 } 389// }
358 390//
359 Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 1->2."); 391// Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 1->2.");
360 Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected."); 392// Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected.");
361 Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again."); 393// Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again.");
362 } 394// }
363 } 395 }
364} \ No newline at end of file 396} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
index a407f01..37b5184 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
@@ -301,7 +301,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
301 sp.AbsolutePosition = preTeleportPosition; 301 sp.AbsolutePosition = preTeleportPosition;
302 302
303 // Make sceneB refuse CreateAgent 303 // Make sceneB refuse CreateAgent
304 sceneB.LoginsDisabled = true; 304 sceneB.LoginsEnabled = false;
305 305
306 sceneA.RequestTeleportLocation( 306 sceneA.RequestTeleportLocation(
307 sp.ControllingClient, 307 sp.ControllingClient,
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 86f33eb..3b83e58 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -38,6 +38,7 @@ using OpenMetaverse;
38using OpenMetaverse.Packets; 38using OpenMetaverse.Packets;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Client; 40using OpenSim.Framework.Client;
41using OpenSim.Framework.Monitoring;
41using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
42 43
43namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server 44namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs
index a7c5020..9d27386 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs
@@ -34,6 +34,7 @@ using System.Text;
34using System.Threading; 34using System.Threading;
35using log4net; 35using log4net;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Framework.Monitoring;
37using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
38 39
39namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server 40namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
index a7ebecc..5fe5948 100644
--- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
@@ -35,7 +35,7 @@ using Nini.Config;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using OpenSim.Framework.Console; 37using OpenSim.Framework.Console;
38using OpenSim.Framework.Statistics; 38using OpenSim.Framework.Monitoring;
39using OpenSim.Region.ClientStack.LindenUDP; 39using OpenSim.Region.ClientStack.LindenUDP;
40using OpenSim.Region.Framework.Interfaces; 40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
@@ -82,18 +82,6 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
82 m_scenes[scene.RegionInfo.RegionID] = scene; 82 m_scenes[scene.RegionInfo.RegionID] = scene;
83 83
84 scene.AddCommand( 84 scene.AddCommand(
85 "Comms", this, "image queues clear",
86 "image queues clear <first-name> <last-name>",
87 "Clear the image queues (textures downloaded via UDP) for a particular client.",
88 (mod, cmd) => MainConsole.Instance.Output(HandleImageQueuesClear(cmd)));
89
90 scene.AddCommand(
91 "Comms", this, "image queues show",
92 "image queues show <first-name> <last-name>",
93 "Show the image queues (textures downloaded via UDP) for a particular client.",
94 (mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd)));
95
96 scene.AddCommand(
97 "Comms", this, "show pqueues", 85 "Comms", this, "show pqueues",
98 "show pqueues [full]", 86 "show pqueues [full]",
99 "Show priority queue data for each client", 87 "Show priority queue data for each client",
@@ -105,8 +93,15 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
105 "Comms", this, "show queues", 93 "Comms", this, "show queues",
106 "show queues [full]", 94 "show queues [full]",
107 "Show queue data for each client", 95 "Show queue data for each client",
108 "Without the 'full' option, only root agents are shown." 96 "Without the 'full' option, only root agents are shown.\n"
109 + " With the 'full' option child agents are also shown.", 97 + "With the 'full' option child agents are also shown.\n\n"
98 + "Type - Rt is a root (avatar) client whilst cd is a child (neighbour interacting) client.\n"
99 + "Since Last In - Time in milliseconds since last packet received.\n"
100 + "Pkts In - Number of packets processed from the client.\n"
101 + "Pkts Out - Number of packets sent to the client.\n"
102 + "Pkts Resent - Number of packets resent to the client.\n"
103 + "Bytes Unacked - Number of bytes transferred to the client that are awaiting acknowledgement.\n"
104 + "Q Pkts * - Number of packets of various types (land, wind, etc.) to be sent to the client that are waiting for available bandwidth.\n",
110 (mod, cmd) => MainConsole.Instance.Output(GetQueuesReport(cmd))); 105 (mod, cmd) => MainConsole.Instance.Output(GetQueuesReport(cmd)));
111 106
112 scene.AddCommand( 107 scene.AddCommand(
@@ -114,6 +109,12 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
114 "show image queues <first-name> <last-name>", 109 "show image queues <first-name> <last-name>",
115 "Show the image queues (textures downloaded via UDP) for a particular client.", 110 "Show the image queues (textures downloaded via UDP) for a particular client.",
116 (mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd))); 111 (mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd)));
112
113 scene.AddCommand(
114 "Comms", this, "clear image queues",
115 "clear image queues <first-name> <last-name>",
116 "Clear the image queues (textures downloaded via UDP) for a particular client.",
117 (mod, cmd) => MainConsole.Instance.Output(HandleImageQueuesClear(cmd)));
117 118
118 scene.AddCommand( 119 scene.AddCommand(
119 "Comms", this, "show throttles", 120 "Comms", this, "show throttles",
@@ -373,17 +374,22 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
373 int maxNameLength = 18; 374 int maxNameLength = 18;
374 int maxRegionNameLength = 14; 375 int maxRegionNameLength = 14;
375 int maxTypeLength = 4; 376 int maxTypeLength = 4;
376 int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding; 377
378 int totalInfoFieldsLength
379 = maxNameLength + columnPadding
380 + maxRegionNameLength + columnPadding
381 + maxTypeLength + columnPadding;
377 382
378 report.Append(GetColumnEntry("User", maxNameLength, columnPadding)); 383 report.Append(GetColumnEntry("User", maxNameLength, columnPadding));
379 report.Append(GetColumnEntry("Region", maxRegionNameLength, columnPadding)); 384 report.Append(GetColumnEntry("Region", maxRegionNameLength, columnPadding));
380 report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding)); 385 report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding));
381 386
382 report.AppendFormat( 387 report.AppendFormat(
383 "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}\n", 388 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n",
389 "Since",
390 "Pkts",
384 "Pkts", 391 "Pkts",
385 "Pkts", 392 "Pkts",
386 "Pkts",
387 "Bytes", 393 "Bytes",
388 "Q Pkts", 394 "Q Pkts",
389 "Q Pkts", 395 "Q Pkts",
@@ -396,7 +402,8 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
396 402
397 report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", ""); 403 report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", "");
398 report.AppendFormat( 404 report.AppendFormat(
399 "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}\n", 405 "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n",
406 "Last In",
400 "In", 407 "In",
401 "Out", 408 "Out",
402 "Resent", 409 "Resent",
@@ -417,22 +424,22 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
417 scene.ForEachClient( 424 scene.ForEachClient(
418 delegate(IClientAPI client) 425 delegate(IClientAPI client)
419 { 426 {
420 if (client is IStatsCollector) 427 bool isChild = client.SceneAgent.IsChildAgent;
421 { 428 if (isChild && !showChildren)
422 bool isChild = client.SceneAgent.IsChildAgent; 429 return;
423 if (isChild && !showChildren) 430
424 return; 431 string name = client.Name;
425 432 if (pname != "" && name != pname)
426 string name = client.Name; 433 return;
427 if (pname != "" && name != pname)
428 return;
429 434
430 string regionName = scene.RegionInfo.RegionName; 435 string regionName = scene.RegionInfo.RegionName;
431 436
432 report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); 437 report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
433 report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding)); 438 report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
434 report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding)); 439 report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
435 440
441 if (client is IStatsCollector)
442 {
436 IStatsCollector stats = (IStatsCollector)client; 443 IStatsCollector stats = (IStatsCollector)client;
437 444
438 report.AppendLine(stats.Report()); 445 report.AppendLine(stats.Report());
diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
index 6bb6729..d718a2f 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs
@@ -36,7 +36,7 @@ using Nini.Config;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Framework.Console; 38using OpenSim.Framework.Console;
39using OpenSim.Framework.Statistics; 39using OpenSim.Framework.Monitoring;
40using OpenSim.Region.ClientStack.LindenUDP; 40using OpenSim.Region.ClientStack.LindenUDP;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
index 1b9e3ac..d68aabc 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs
@@ -36,7 +36,7 @@ using Nini.Config;
36using OpenMetaverse; 36using OpenMetaverse;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Framework.Console; 38using OpenSim.Framework.Console;
39using OpenSim.Framework.Statistics; 39using OpenSim.Framework.Monitoring;
40using OpenSim.Region.ClientStack.LindenUDP; 40using OpenSim.Region.ClientStack.LindenUDP;
41using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
42using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
index cd401a6..ca956fb 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs
@@ -37,6 +37,7 @@ using OpenMetaverse;
37using log4net; 37using log4net;
38using Nini.Config; 38using Nini.Config;
39using OpenSim.Framework; 39using OpenSim.Framework;
40using OpenSim.Framework.Monitoring;
40using OpenSim.Region.Framework.Interfaces; 41using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes; 42using OpenSim.Region.Framework.Scenes;
42 43
diff --git a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
index 2602050..4e84364 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs
@@ -37,7 +37,7 @@ using Nini.Config;
37using OpenMetaverse; 37using OpenMetaverse;
38using OpenSim.Framework; 38using OpenSim.Framework;
39using OpenSim.Framework.Console; 39using OpenSim.Framework.Console;
40using OpenSim.Framework.Statistics; 40using OpenSim.Framework.Monitoring;
41using OpenSim.Region.ClientStack.LindenUDP; 41using OpenSim.Region.ClientStack.LindenUDP;
42using OpenSim.Region.CoreModules.Avatar.Friends; 42using OpenSim.Region.CoreModules.Avatar.Friends;
43using OpenSim.Region.Framework.Interfaces; 43using OpenSim.Region.Framework.Interfaces;
diff --git a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
index e452124..40f7fbc 100755
--- a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
+++ b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PhysicsParameters")] 47 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PhysicsParameters")]
48 public class PhysicsParameters : ISharedRegionModule 48 public class PhysicsParameters : ISharedRegionModule
49 { 49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51// private static string LogHeader = "[PHYSICS PARAMETERS]"; 51// private static string LogHeader = "[PHYSICS PARAMETERS]";
52 52
53 private List<Scene> m_scenes = new List<Scene>(); 53 private List<Scene> m_scenes = new List<Scene>();
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
index 600cafb..fff3a32 100644
--- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs
@@ -31,16 +31,14 @@ using System.Reflection;
31using System.Net; 31using System.Net;
32using System.IO; 32using System.IO;
33using System.Text; 33using System.Text;
34
35using log4net; 34using log4net;
36using Nini.Config; 35using Nini.Config;
37using OpenMetaverse; 36using OpenMetaverse;
38using OpenMetaverse.StructuredData; 37using OpenMetaverse.StructuredData;
39using OpenSim.Services.Interfaces;
40
41using OpenSim.Framework; 38using OpenSim.Framework;
42using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
43using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
41using OpenSim.Services.Interfaces;
44 42
45namespace OpenSim.Region.OptionalModules.Scripting.RegionReady 43namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
46{ 44{
@@ -50,16 +48,15 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
50 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 49
52 private IConfig m_config = null; 50 private IConfig m_config = null;
53 private bool m_ScriptRez;
54 private bool m_firstEmptyCompileQueue; 51 private bool m_firstEmptyCompileQueue;
55 private bool m_oarFileLoading; 52 private bool m_oarFileLoading;
56 private bool m_lastOarLoadedOk; 53 private bool m_lastOarLoadedOk;
57 private int m_channelNotify = -1000; 54 private int m_channelNotify = -1000;
58 private bool m_enabled = false; 55 private bool m_enabled = false;
59 private bool m_disable_logins = false; 56 private bool m_disable_logins;
60 private string m_uri = string.Empty; 57 private string m_uri = string.Empty;
61 58
62 Scene m_scene = null; 59 Scene m_scene;
63 60
64 #region INonSharedRegionModule interface 61 #region INonSharedRegionModule interface
65 62
@@ -93,53 +90,40 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
93 90
94 m_scene.RegisterModuleInterface<IRegionReadyModule>(this); 91 m_scene.RegisterModuleInterface<IRegionReadyModule>(this);
95 92
96 m_ScriptRez = false;
97 m_firstEmptyCompileQueue = true; 93 m_firstEmptyCompileQueue = true;
98 m_oarFileLoading = false; 94 m_oarFileLoading = false;
99 m_lastOarLoadedOk = true; 95 m_lastOarLoadedOk = true;
100 96
101 m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; 97 m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded;
102 m_scene.EventManager.OnRezScript += OnRezScript;
103 m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled;
104 98
105 m_log.DebugFormat("[RegionReady]: Enabled for region {0}", scene.RegionInfo.RegionName); 99 m_log.DebugFormat("[RegionReady]: Enabled for region {0}", scene.RegionInfo.RegionName);
106 100
107 if (m_disable_logins == true) 101 if (m_disable_logins)
108 { 102 {
109 scene.LoginLock = true; 103 m_scene.LoginLock = true;
110 scene.LoginsDisabled = true; 104 m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue;
111 m_log.InfoFormat("[RegionReady]: Region {0} - logins disabled during initialization.",m_scene.RegionInfo.RegionName); 105
106 m_log.InfoFormat("[RegionReady]: Region {0} - LOGINS DISABLED DURING INITIALIZATION.", m_scene.Name);
112 107
113 if(m_uri != string.Empty) 108 if (m_uri != string.Empty)
114 { 109 {
115 RRAlert("disabled"); 110 RRAlert("disabled");
116 } 111 }
117 } 112 }
118 } 113 }
119 114
120 void OnRezScript (uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource)
121 {
122 if (!m_ScriptRez)
123 {
124 m_ScriptRez = true;
125 m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue;
126 m_scene.EventManager.OnRezScript -= OnRezScript;
127 }
128 }
129
130 public void RemoveRegion(Scene scene) 115 public void RemoveRegion(Scene scene)
131 { 116 {
132 if (!m_enabled) 117 if (!m_enabled)
133 return; 118 return;
134 119
135 m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue;
136 m_scene.EventManager.OnOarFileLoaded -= OnOarFileLoaded; 120 m_scene.EventManager.OnOarFileLoaded -= OnOarFileLoaded;
137 m_scene.EventManager.OnLoginsEnabled -= OnLoginsEnabled;
138 121
139 if(m_uri != string.Empty) 122 if (m_disable_logins)
140 { 123 m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue;
124
125 if (m_uri != string.Empty)
141 RRAlert("shutdown"); 126 RRAlert("shutdown");
142 }
143 127
144 m_scene = null; 128 m_scene = null;
145 } 129 }
@@ -159,7 +143,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
159 143
160 #endregion 144 #endregion
161 145
162
163 void OnEmptyScriptCompileQueue(int numScriptsFailed, string message) 146 void OnEmptyScriptCompileQueue(int numScriptsFailed, string message)
164 { 147 {
165 m_log.DebugFormat("[RegionReady]: Script compile queue empty!"); 148 m_log.DebugFormat("[RegionReady]: Script compile queue empty!");
@@ -193,75 +176,80 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady
193 m_scene.RegionInfo.RegionName, c.Message, m_channelNotify); 176 m_scene.RegionInfo.RegionName, c.Message, m_channelNotify);
194 177
195 m_scene.EventManager.TriggerOnChatBroadcast(this, c); 178 m_scene.EventManager.TriggerOnChatBroadcast(this, c);
196 m_scene.EventManager.TriggerLoginsEnabled(m_scene.RegionInfo.RegionName); 179
197 m_scene.SceneGridService.InformNeighborsThatRegionisUp(m_scene.RequestModuleInterface<INeighbourService>(), m_scene.RegionInfo); 180 TriggerRegionReady(m_scene);
198 } 181 }
199 } 182 }
200 183
201 void OnOarFileLoaded(Guid requestId, string message) 184 void OnOarFileLoaded(Guid requestId, string message)
202 { 185 {
203 m_oarFileLoading = true; 186 m_oarFileLoading = true;
187
204 if (message==String.Empty) 188 if (message==String.Empty)
205 { 189 {
206 m_lastOarLoadedOk = true; 190 m_lastOarLoadedOk = true;
207 } else { 191 }
192 else
193 {
208 m_log.WarnFormat("[RegionReady]: Oar file load errors: {0}", message); 194 m_log.WarnFormat("[RegionReady]: Oar file load errors: {0}", message);
209 m_lastOarLoadedOk = false; 195 m_lastOarLoadedOk = false;
210 } 196 }
211 } 197 }
212 198
213 // This will be triggerd by Scene if we have no scripts 199 /// <summary>
214 // m_ScriptsRezzing will be false if there were none 200 /// This will be triggered by Scene directly if it contains no scripts on startup. Otherwise it is triggered
215 // else it will be true and we should wait on the 201 /// when the script compile queue is empty after initial region startup.
216 // empty compile queue 202 /// </summary>
217 void OnLoginsEnabled(string regionName) 203 /// <param name='scene'></param>
204 public void TriggerRegionReady(IScene scene)
218 { 205 {
219 if (m_disable_logins == true) 206 m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue;
207 m_scene.LoginLock = false;
208
209 if (!m_scene.StartDisabled)
220 { 210 {
221 if (m_scene.StartDisabled == false) 211 m_scene.LoginsEnabled = true;
222 {
223 m_scene.LoginsDisabled = false;
224 m_scene.LoginLock = false;
225 212
226 m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; 213 // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}",
214 // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString());
227 215
228 // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", 216 m_log.InfoFormat(
229 // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); 217 "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name);
218 }
230 219
231 m_log.InfoFormat( 220 m_scene.SceneGridService.InformNeighborsThatRegionisUp(
232 "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); 221 m_scene.RequestModuleInterface<INeighbourService>(), m_scene.RegionInfo);
233 222
234 if (m_uri != string.Empty) 223 if (m_uri != string.Empty)
235 { 224 {
236 RRAlert("enabled"); 225 RRAlert("enabled");
237 }
238 }
239 } 226 }
227
228 m_scene.Ready = true;
240 } 229 }
241 230
242 public void OarLoadingAlert(string msg) 231 public void OarLoadingAlert(string msg)
243 { 232 {
244 // Let's bypass this for now until some better feedback can be established 233 // Let's bypass this for now until some better feedback can be established
245 // 234 //
246 return;
247 235
248 if (msg == "load") 236// if (msg == "load")
249 { 237// {
250 m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; 238// m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue;
251 m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; 239// m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded;
252 m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; 240// m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled;
253 m_scene.EventManager.OnRezScript += OnRezScript; 241// m_scene.EventManager.OnRezScript += OnRezScript;
254 m_oarFileLoading = true; 242// m_oarFileLoading = true;
255 m_firstEmptyCompileQueue = true; 243// m_firstEmptyCompileQueue = true;
256 244//
257 m_scene.LoginsDisabled = true; 245// m_scene.LoginsDisabled = true;
258 m_scene.LoginLock = true; 246// m_scene.LoginLock = true;
259 if ( m_uri != string.Empty ) 247// if ( m_uri != string.Empty )
260 { 248// {
261 RRAlert("loading oar"); 249// RRAlert("loading oar");
262 RRAlert("disabled"); 250// RRAlert("disabled");
263 } 251// }
264 } 252// }
265 } 253 }
266 254
267 public void RRAlert(string status) 255 public void RRAlert(string status)
diff --git a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index 74a85e2..705a847 100644
--- a/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -46,6 +46,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
46 private static readonly ILog m_log = 46 private static readonly ILog m_log =
47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 47 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private Dictionary<string,object> m_constants = new Dictionary<string,object>();
50
49#region ScriptInvocation 51#region ScriptInvocation
50 protected class ScriptInvocationData 52 protected class ScriptInvocationData
51 { 53 {
@@ -269,6 +271,37 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
269 Delegate fn = LookupScriptInvocation(fname); 271 Delegate fn = LookupScriptInvocation(fname);
270 return fn.DynamicInvoke(olist.ToArray()); 272 return fn.DynamicInvoke(olist.ToArray());
271 } 273 }
274
275 /// <summary>
276 /// Operation to for a region module to register a constant to be used
277 /// by the script engine
278 /// </summary>
279 public void RegisterConstant(string cname, object value)
280 {
281 m_log.DebugFormat("[MODULE COMMANDS] register constant <{0}> with value {1}",cname,value.ToString());
282 lock (m_constants)
283 {
284 m_constants.Add(cname,value);
285 }
286 }
287
288 /// <summary>
289 /// Operation to check for a registered constant
290 /// </summary>
291 public object LookupModConstant(string cname)
292 {
293 // m_log.DebugFormat("[MODULE COMMANDS] lookup constant <{0}>",cname);
294
295 lock (m_constants)
296 {
297 object value = null;
298 if (m_constants.TryGetValue(cname,out value))
299 return value;
300 }
301
302 return null;
303 }
304
272#endregion 305#endregion
273 306
274 } 307 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index dc0c008..09e1f0c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -41,7 +41,7 @@ public class BSCharacter : PhysicsActor
41 41
42 private BSScene _scene; 42 private BSScene _scene;
43 private String _avName; 43 private String _avName;
44 private bool _stopped; 44 // private bool _stopped;
45 private Vector3 _size; 45 private Vector3 _size;
46 private Vector3 _scale; 46 private Vector3 _scale;
47 private PrimitiveBaseShape _pbs; 47 private PrimitiveBaseShape _pbs;
@@ -134,9 +134,9 @@ public class BSCharacter : PhysicsActor
134 { 134 {
135 base.RequestPhysicsterseUpdate(); 135 base.RequestPhysicsterseUpdate();
136 } 136 }
137 137 // No one calls this method so I don't know what it could possibly mean
138 public override bool Stopped { 138 public override bool Stopped {
139 get { return _stopped; } 139 get { return false; }
140 } 140 }
141 public override Vector3 Size { 141 public override Vector3 Size {
142 get { return _size; } 142 get { return _size; }
@@ -391,52 +391,47 @@ public class BSCharacter : PhysicsActor
391 _mass = _density * _avatarVolume; 391 _mass = _density * _avatarVolume;
392 } 392 }
393 393
394 // Set to 'true' if the individual changed items should be checked
395 // (someday RequestPhysicsTerseUpdate() will take a bitmap of changed properties)
396 const bool SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES = false;
397
398 // The physics engine says that properties have updated. Update same and inform 394 // The physics engine says that properties have updated. Update same and inform
399 // the world that things have changed. 395 // the world that things have changed.
400 public void UpdateProperties(EntityProperties entprop) 396 public void UpdateProperties(EntityProperties entprop)
401 { 397 {
398 /*
402 bool changed = false; 399 bool changed = false;
403 if (SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES) { 400 // we assign to the local variables so the normal set action does not happen
404 // we assign to the local variables so the normal set action does not happen 401 if (_position != entprop.Position) {
405 if (_position != entprop.Position) {
406 _position = entprop.Position;
407 changed = true;
408 }
409 if (_orientation != entprop.Rotation) {
410 _orientation = entprop.Rotation;
411 changed = true;
412 }
413 if (_velocity != entprop.Velocity) {
414 _velocity = entprop.Velocity;
415 changed = true;
416 }
417 if (_acceleration != entprop.Acceleration) {
418 _acceleration = entprop.Acceleration;
419 changed = true;
420 }
421 if (_rotationalVelocity != entprop.RotationalVelocity) {
422 _rotationalVelocity = entprop.RotationalVelocity;
423 changed = true;
424 }
425 if (changed) {
426 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
427 // Avatar movement is not done by generating this event. There is code in the heartbeat
428 // loop that updates avatars.
429 // base.RequestPhysicsterseUpdate();
430 }
431 }
432 else {
433 _position = entprop.Position; 402 _position = entprop.Position;
403 changed = true;
404 }
405 if (_orientation != entprop.Rotation) {
434 _orientation = entprop.Rotation; 406 _orientation = entprop.Rotation;
407 changed = true;
408 }
409 if (_velocity != entprop.Velocity) {
435 _velocity = entprop.Velocity; 410 _velocity = entprop.Velocity;
411 changed = true;
412 }
413 if (_acceleration != entprop.Acceleration) {
436 _acceleration = entprop.Acceleration; 414 _acceleration = entprop.Acceleration;
415 changed = true;
416 }
417 if (_rotationalVelocity != entprop.RotationalVelocity) {
437 _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.
438 // base.RequestPhysicsterseUpdate(); 425 // base.RequestPhysicsterseUpdate();
439 } 426 }
427 */
428 _position = entprop.Position;
429 _orientation = entprop.Rotation;
430 _velocity = entprop.Velocity;
431 _acceleration = entprop.Acceleration;
432 _rotationalVelocity = entprop.RotationalVelocity;
433 // Avatars don't report theirr changes the usual way. Changes are checked for in the heartbeat loop.
434 // base.RequestPhysicsterseUpdate();
440 } 435 }
441 436
442 // Called by the scene when a collision with this object is reported 437 // Called by the scene when a collision with this object is reported
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
new file mode 100755
index 0000000..ea3093a
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs
@@ -0,0 +1,125 @@
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 BSConstraint : IDisposable
36{
37 private BulletSim m_world;
38 private BulletBody m_body1;
39 private BulletBody m_body2;
40 private BulletConstraint m_constraint;
41 private bool m_enabled = false;
42
43 public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
44 Vector3 frame1, Quaternion frame1rot,
45 Vector3 frame2, Quaternion frame2rot
46 )
47 {
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 }
57
58 public void Dispose()
59 {
60 if (m_enabled)
61 {
62 // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
63 BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
64 m_enabled = false;
65 }
66 }
67
68 public BulletBody Body1 { get { return m_body1; } }
69 public BulletBody Body2 { get { return m_body2; } }
70
71 public bool SetLinearLimits(Vector3 low, Vector3 high)
72 {
73 bool ret = false;
74 if (m_enabled)
75 ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high);
76 return ret;
77 }
78
79 public bool SetAngularLimits(Vector3 low, Vector3 high)
80 {
81 bool ret = false;
82 if (m_enabled)
83 ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high);
84 return ret;
85 }
86
87 public bool SetCFMAndERP(float cfm, float erp)
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 {
107 bool ret = false;
108 float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
109 if (m_enabled)
110 ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
111 return ret;
112 }
113
114 public bool CalculateTransforms()
115 {
116 bool ret = false;
117 if (m_enabled)
118 {
119 BulletSimAPI.CalculateTransforms2(m_constraint.Ptr);
120 ret = true;
121 }
122 return ret;
123 }
124}
125}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
new file mode 100755
index 0000000..c88e645
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs
@@ -0,0 +1,184 @@
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 log4net;
31using OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35
36public class BSConstraintCollection : IDisposable
37{
38 // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
39 // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]";
40
41 delegate bool ConstraintAction(BSConstraint constrain);
42
43 private List<BSConstraint> m_constraints;
44 private BulletSim m_world;
45
46 public BSConstraintCollection(BulletSim world)
47 {
48 m_world = world;
49 m_constraints = new List<BSConstraint>();
50 }
51
52 public void Dispose()
53 {
54 this.Clear();
55 }
56
57 public void Clear()
58 {
59 foreach (BSConstraint cons in m_constraints)
60 {
61 cons.Dispose();
62 }
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 }
75
76 public bool AddConstraint(BSConstraint cons)
77 {
78 // There is only one constraint between any bodies. Remove any old just to make sure.
79 RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
80
81 m_constraints.Add(cons);
82
83 return true;
84 }
85
86 // Get the constraint between two bodies. There can be only one.
87 // Return 'true' if a constraint was found.
88 public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint)
89 {
90 bool found = false;
91 BSConstraint foundConstraint = null;
92
93 uint lookingID1 = body1.ID;
94 uint lookingID2 = body2.ID;
95 ForEachConstraint(delegate(BSConstraint constrain)
96 {
97 if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
98 || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
99 {
100 foundConstraint = constrain;
101 found = true;
102 }
103 return found;
104 });
105 returnConstraint = foundConstraint;
106 return found;
107 }
108
109 // Remove any constraint between the passed bodies.
110 // Presumed there is only one such constraint possible.
111 // Return 'true' if a constraint was found and destroyed.
112 public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2)
113 {
114 // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID);
115
116 bool ret = false;
117 BSConstraint constrain;
118
119 if (this.TryGetConstraint(body1, body2, out constrain))
120 {
121 // remove the constraint from our collection
122 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 }
128
129 return ret;
130 }
131
132 // Remove all constraints that reference the passed body.
133 // Return 'true' if any constraints were destroyed.
134 public bool RemoveAndDestroyConstraint(BulletBody body1)
135 {
136 // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID);
137
138 List<BSConstraint> toRemove = new List<BSConstraint>();
139 uint lookingID = body1.ID;
140 ForEachConstraint(delegate(BSConstraint constrain)
141 {
142 if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
143 {
144 toRemove.Add(constrain);
145 }
146 return false;
147 });
148 lock (m_constraints)
149 {
150 foreach (BSConstraint constrain in toRemove)
151 {
152 m_constraints.Remove(constrain);
153 constrain.Dispose();
154 }
155 }
156 return (toRemove.Count > 0);
157 }
158
159 public bool RecalculateAllConstraints()
160 {
161 foreach (BSConstraint constrain in m_constraints)
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)
173 {
174 foreach (BSConstraint constrain in m_constraints)
175 {
176 if (action(constrain))
177 break;
178 }
179 }
180 }
181
182
183}
184}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index eb20eb3..c197e61 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -57,7 +57,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
57 private int frcount = 0; // Used to limit dynamics debug output to 57 private int frcount = 0; // Used to limit dynamics debug output to
58 // every 100th frame 58 // every 100th frame
59 59
60 // private BSScene m_parentScene = null;
61 private BSPrim m_prim; // the prim this dynamic controller belongs to 60 private BSPrim m_prim; // the prim this dynamic controller belongs to
62 61
63 // Vehicle properties 62 // Vehicle properties
@@ -131,8 +130,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
131 m_type = Vehicle.TYPE_NONE; 130 m_type = Vehicle.TYPE_NONE;
132 } 131 }
133 132
134 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) 133 internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep)
135 { 134 {
135 DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
136 switch (pParam) 136 switch (pParam)
137 { 137 {
138 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: 138 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
@@ -229,8 +229,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
229 } 229 }
230 }//end ProcessFloatVehicleParam 230 }//end ProcessFloatVehicleParam
231 231
232 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) 232 internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep)
233 { 233 {
234 DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
234 switch (pParam) 235 switch (pParam)
235 { 236 {
236 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 237 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
@@ -265,6 +266,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
265 266
266 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) 267 internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
267 { 268 {
269 DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
268 switch (pParam) 270 switch (pParam)
269 { 271 {
270 case Vehicle.REFERENCE_FRAME: 272 case Vehicle.REFERENCE_FRAME:
@@ -278,6 +280,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
278 280
279 internal void ProcessVehicleFlags(int pParam, bool remove) 281 internal void ProcessVehicleFlags(int pParam, bool remove)
280 { 282 {
283 DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove);
281 if (remove) 284 if (remove)
282 { 285 {
283 if (pParam == -1) 286 if (pParam == -1)
@@ -434,6 +437,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
434 437
435 internal void ProcessTypeChange(Vehicle pType) 438 internal void ProcessTypeChange(Vehicle pType)
436 { 439 {
440 DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType);
437 // Set Defaults For Type 441 // Set Defaults For Type
438 m_type = pType; 442 m_type = pType;
439 switch (pType) 443 switch (pType)
@@ -594,11 +598,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
594 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); 598 m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
595 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); 599 m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT);
596 break; 600 break;
597
598 } 601 }
599 }//end SetDefaultsForType 602 }//end SetDefaultsForType
600 603
601 internal void Step(float pTimestep, BSScene pParentScene) 604 internal void Step(float pTimestep)
602 { 605 {
603 if (m_type == Vehicle.TYPE_NONE) return; 606 if (m_type == Vehicle.TYPE_NONE) return;
604 607
@@ -606,21 +609,34 @@ namespace OpenSim.Region.Physics.BulletSPlugin
606 if (frcount > 100) 609 if (frcount > 100)
607 frcount = 0; 610 frcount = 0;
608 611
609 MoveLinear(pTimestep, pParentScene); 612 MoveLinear(pTimestep);
610 MoveAngular(pTimestep); 613 MoveAngular(pTimestep);
611 LimitRotation(pTimestep); 614 LimitRotation(pTimestep);
615
616 DetailLog("{0},Dynamics,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);
612 }// end Step 618 }// end Step
613 619
614 private void MoveLinear(float pTimestep, BSScene _pParentScene) 620 private void MoveLinear(float pTimestep)
615 { 621 {
616 if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant 622 // requested m_linearMotorDirection is significant
623 // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f))
624 if (m_linearMotorDirection.LengthSquared() > 0.0001f)
617 { 625 {
626 Vector3 origDir = m_linearMotorDirection;
627 Vector3 origVel = m_lastLinearVelocityVector;
628
618 // add drive to body 629 // add drive to body
619 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); 630 // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep);
620 m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? 631 Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale);
632 // lastLinearVelocityVector is the current body velocity vector?
633 // RA: Not sure what the *10 is for. A correction for pTimestep?
634 // m_lastLinearVelocityVector += (addAmount*10);
635 m_lastLinearVelocityVector += addAmount;
621 636
622 // This will work temporarily, but we really need to compare speed on an axis 637 // This will work temporarily, but we really need to compare speed on an axis
623 // KF: Limit body velocity to applied velocity? 638 // KF: Limit body velocity to applied velocity?
639 // Limit the velocity vector to less than the last set linear motor direction
624 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) 640 if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X))
625 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; 641 m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X;
626 if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) 642 if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y))
@@ -630,76 +646,93 @@ namespace OpenSim.Region.Physics.BulletSPlugin
630 646
631 // decay applied velocity 647 // decay applied velocity
632 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); 648 Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep)));
633 //Console.WriteLine("decay: " + decayfraction);
634 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; 649 m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f;
635 //Console.WriteLine("actual: " + m_linearMotorDirection); 650
651 /*
652 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale;
653 m_lastLinearVelocityVector += addAmount;
654
655 float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale);
656 m_linearMotorDirection *= decayfraction;
657
658 */
659
660 DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}",
661 m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector);
636 } 662 }
637 else 663 else
638 { // requested is not significant 664 {
639 // if what remains of applied is small, zero it. 665 // if what remains of applied is small, zero it.
640 if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) 666 // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f))
641 m_lastLinearVelocityVector = Vector3.Zero; 667 // m_lastLinearVelocityVector = Vector3.Zero;
668 m_linearMotorDirection = Vector3.Zero;
669 m_lastLinearVelocityVector = Vector3.Zero;
642 } 670 }
643 671
644 // convert requested object velocity to world-referenced vector 672 // convert requested object velocity to world-referenced vector
645 m_dir = m_lastLinearVelocityVector; 673 Quaternion rotq = m_prim.Orientation;
646 Quaternion rot = m_prim.Orientation; 674 m_dir = m_lastLinearVelocityVector * rotq;
647 Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object 675
648 m_dir *= rotq; // apply obj rotation to velocity vector 676 // Add the various forces into m_dir which will be our new direction vector (velocity)
649 677
650 // add Gravity andBuoyancy 678 // add Gravity and Buoyancy
651 // KF: So far I have found no good method to combine a script-requested 679 // KF: So far I have found no good method to combine a script-requested
652 // .Z velocity and gravity. Therefore only 0g will used script-requested 680 // .Z velocity and gravity. Therefore only 0g will used script-requested
653 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. 681 // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only.
654 Vector3 grav = Vector3.Zero; 682 Vector3 grav = Vector3.Zero;
655 // There is some gravity, make a gravity force vector 683 // There is some gravity, make a gravity force vector that is applied after object velocity.
656 // that is applied after object velocity.
657 float objMass = m_prim.Mass;
658 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 684 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
659 grav.Z = _pParentScene.DefaultGravity.Z * objMass * (1f - m_VehicleBuoyancy); 685 grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy);
660 // Preserve the current Z velocity 686 // Preserve the current Z velocity
661 Vector3 vel_now = m_prim.Velocity; 687 Vector3 vel_now = m_prim.Velocity;
662 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity 688 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
663 689
664 Vector3 pos = m_prim.Position; 690 Vector3 pos = m_prim.Position;
691 Vector3 posChange = pos;
665// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); 692// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f);
666 Vector3 posChange = new Vector3();
667 posChange.X = pos.X - m_lastPositionVector.X;
668 posChange.Y = pos.Y - m_lastPositionVector.Y;
669 posChange.Z = pos.Z - m_lastPositionVector.Z;
670 double Zchange = Math.Abs(posChange.Z); 693 double Zchange = Math.Abs(posChange.Z);
671 if (m_BlockingEndPoint != Vector3.Zero) 694 if (m_BlockingEndPoint != Vector3.Zero)
672 { 695 {
696 bool changed = false;
673 if (pos.X >= (m_BlockingEndPoint.X - (float)1)) 697 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
674 { 698 {
675 pos.X -= posChange.X + 1; 699 pos.X -= posChange.X + 1;
676 m_prim.Position = pos; 700 changed = true;
677 } 701 }
678 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) 702 if (pos.Y >= (m_BlockingEndPoint.Y - (float)1))
679 { 703 {
680 pos.Y -= posChange.Y + 1; 704 pos.Y -= posChange.Y + 1;
681 m_prim.Position = pos; 705 changed = true;
682 } 706 }
683 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) 707 if (pos.Z >= (m_BlockingEndPoint.Z - (float)1))
684 { 708 {
685 pos.Z -= posChange.Z + 1; 709 pos.Z -= posChange.Z + 1;
686 m_prim.Position = pos; 710 changed = true;
687 } 711 }
688 if (pos.X <= 0) 712 if (pos.X <= 0)
689 { 713 {
690 pos.X += posChange.X + 1; 714 pos.X += posChange.X + 1;
691 m_prim.Position = pos; 715 changed = true;
692 } 716 }
693 if (pos.Y <= 0) 717 if (pos.Y <= 0)
694 { 718 {
695 pos.Y += posChange.Y + 1; 719 pos.Y += posChange.Y + 1;
720 changed = true;
721 }
722 if (changed)
723 {
696 m_prim.Position = pos; 724 m_prim.Position = pos;
725 DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
726 m_prim.LocalID, m_BlockingEndPoint, posChange, pos);
697 } 727 }
698 } 728 }
699 if (pos.Z < _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y)) 729
730 // If below the terrain, move us above the ground a little.
731 if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos))
700 { 732 {
701 pos.Z = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + 2; 733 pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2;
702 m_prim.Position = pos; 734 m_prim.Position = pos;
735 DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos);
703 } 736 }
704 737
705 // Check if hovering 738 // Check if hovering
@@ -708,11 +741,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
708 // We should hover, get the target height 741 // We should hover, get the target height
709 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) 742 if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0)
710 { 743 {
711 m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight; 744 m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight;
712 } 745 }
713 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) 746 if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
714 { 747 {
715 m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; 748 m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
716 } 749 }
717 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) 750 if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
718 { 751 {
@@ -746,6 +779,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
746 } 779 }
747 } 780 }
748 781
782 DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight);
783
749// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped 784// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
750// m_VhoverTimescale = 0f; // time to acheive height 785// m_VhoverTimescale = 0f; // time to acheive height
751// pTimestep is time since last frame,in secs 786// pTimestep is time since last frame,in secs
@@ -774,12 +809,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
774 { 809 {
775 grav.Z = (float)(grav.Z * 1.125); 810 grav.Z = (float)(grav.Z * 1.125);
776 } 811 }
777 float terraintemp = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y); 812 float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos);
778 float postemp = (pos.Z - terraintemp); 813 float postemp = (pos.Z - terraintemp);
779 if (postemp > 2.5f) 814 if (postemp > 2.5f)
780 { 815 {
781 grav.Z = (float)(grav.Z * 1.037125); 816 grav.Z = (float)(grav.Z * 1.037125);
782 } 817 }
818 DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
783 //End Experimental Values 819 //End Experimental Values
784 } 820 }
785 if ((m_flags & (VehicleFlag.NO_X)) != 0) 821 if ((m_flags & (VehicleFlag.NO_X)) != 0)
@@ -800,32 +836,39 @@ namespace OpenSim.Region.Physics.BulletSPlugin
800 // Apply velocity 836 // Apply velocity
801 m_prim.Velocity = m_dir; 837 m_prim.Velocity = m_dir;
802 // apply gravity force 838 // apply gravity force
803 m_prim.Force = grav; 839 // Why is this set here? The physics engine already does gravity.
804 840 // m_prim.AddForce(grav, false);
841 // m_prim.Force = grav;
805 842
806 // apply friction 843 // Apply friction
807 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); 844 Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
808 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; 845 m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
846
847 DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}",
848 m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount);
849
809 } // end MoveLinear() 850 } // end MoveLinear()
810 851
811 private void MoveAngular(float pTimestep) 852 private void MoveAngular(float pTimestep)
812 { 853 {
813 /* 854 // m_angularMotorDirection // angular velocity requested by LSL motor
814 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor 855 // m_angularMotorApply // application frame counter
815 private int m_angularMotorApply = 0; // application frame counter 856 // m_angularMotorVelocity // current angular motor velocity (ramps up and down)
816 private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down) 857 // m_angularMotorTimescale // motor angular velocity ramp up rate
817 private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate 858 // m_angularMotorDecayTimescale // motor angular velocity decay rate
818 private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate 859 // m_angularFrictionTimescale // body angular velocity decay rate
819 private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate 860 // m_lastAngularVelocity // what was last applied to body
820 private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body
821 */
822 861
823 // Get what the body is doing, this includes 'external' influences 862 // Get what the body is doing, this includes 'external' influences
824 Vector3 angularVelocity = m_prim.RotationalVelocity; 863 Vector3 angularVelocity = m_prim.RotationalVelocity;
825 // Vector3 angularVelocity = Vector3.Zero;
826 864
827 if (m_angularMotorApply > 0) 865 if (m_angularMotorApply > 0)
828 { 866 {
867 // Rather than snapping the angular motor velocity from the old value to
868 // a newly set velocity, this routine steps the value from the previous
869 // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection).
870 // There are m_angularMotorApply steps.
871 Vector3 origAngularVelocity = m_angularMotorVelocity;
829 // ramp up to new value 872 // ramp up to new value
830 // current velocity += error / (time to get there / step interval) 873 // current velocity += error / (time to get there / step interval)
831 // requested speed - last motor speed 874 // requested speed - last motor speed
@@ -833,23 +876,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin
833 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); 876 m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
834 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); 877 m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
835 878
879 DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}",
880 m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
881
836 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected 882 m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected
837 // velocity may still be acheived. 883 // velocity may still be acheived.
838 } 884 }
839 else 885 else
840 { 886 {
841 // no motor recently applied, keep the body velocity 887 // No motor recently applied, keep the body velocity
842 /* m_angularMotorVelocity.X = angularVelocity.X;
843 m_angularMotorVelocity.Y = angularVelocity.Y;
844 m_angularMotorVelocity.Z = angularVelocity.Z; */
845
846 // and decay the velocity 888 // and decay the velocity
847 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); 889 m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep);
848 } // end motor section 890 } // end motor section
849 891
850 // Vertical attractor section 892 // Vertical attractor section
851 Vector3 vertattr = Vector3.Zero; 893 Vector3 vertattr = Vector3.Zero;
852
853 if (m_verticalAttractionTimescale < 300) 894 if (m_verticalAttractionTimescale < 300)
854 { 895 {
855 float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); 896 float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep);
@@ -871,7 +912,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
871 // Error is 0 (no error) to +/- 2 (max error) 912 // Error is 0 (no error) to +/- 2 (max error)
872 // scale it by VAservo 913 // scale it by VAservo
873 verterr = verterr * VAservo; 914 verterr = verterr * VAservo;
874//if (frcount == 0) Console.WriteLine("VAerr=" + verterr);
875 915
876 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so 916 // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so
877 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. 917 // Change Body angular velocity X based on Y, and Y based on X. Z is not changed.
@@ -884,11 +924,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin
884 vertattr.X += bounce * angularVelocity.X; 924 vertattr.X += bounce * angularVelocity.X;
885 vertattr.Y += bounce * angularVelocity.Y; 925 vertattr.Y += bounce * angularVelocity.Y;
886 926
927 DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}",
928 m_prim.LocalID, verterr, bounce, vertattr);
929
887 } // else vertical attractor is off 930 } // else vertical attractor is off
888 931
889 // m_lastVertAttractor = vertattr; 932 // m_lastVertAttractor = vertattr;
890 933
891 // Bank section tba 934 // Bank section tba
935
892 // Deflection section tba 936 // Deflection section tba
893 937
894 // Sum velocities 938 // Sum velocities
@@ -898,11 +942,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
898 { 942 {
899 m_lastAngularVelocity.X = 0; 943 m_lastAngularVelocity.X = 0;
900 m_lastAngularVelocity.Y = 0; 944 m_lastAngularVelocity.Y = 0;
945 DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
901 } 946 }
902 947
903 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) 948 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
904 { 949 {
905 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. 950 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
951 DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
906 } 952 }
907 953
908 // apply friction 954 // apply friction
@@ -912,10 +958,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
912 // Apply to the body 958 // Apply to the body
913 m_prim.RotationalVelocity = m_lastAngularVelocity; 959 m_prim.RotationalVelocity = m_lastAngularVelocity;
914 960
961 DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity);
915 } //end MoveAngular 962 } //end MoveAngular
963
916 internal void LimitRotation(float timestep) 964 internal void LimitRotation(float timestep)
917 { 965 {
918 Quaternion rotq = m_prim.Orientation; // rotq = rotation of object 966 Quaternion rotq = m_prim.Orientation;
919 Quaternion m_rot = rotq; 967 Quaternion m_rot = rotq;
920 bool changed = false; 968 bool changed = false;
921 if (m_RollreferenceFrame != Quaternion.Identity) 969 if (m_RollreferenceFrame != Quaternion.Identity)
@@ -923,18 +971,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin
923 if (rotq.X >= m_RollreferenceFrame.X) 971 if (rotq.X >= m_RollreferenceFrame.X)
924 { 972 {
925 m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); 973 m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2);
974 changed = true;
926 } 975 }
927 if (rotq.Y >= m_RollreferenceFrame.Y) 976 if (rotq.Y >= m_RollreferenceFrame.Y)
928 { 977 {
929 m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); 978 m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2);
979 changed = true;
930 } 980 }
931 if (rotq.X <= -m_RollreferenceFrame.X) 981 if (rotq.X <= -m_RollreferenceFrame.X)
932 { 982 {
933 m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); 983 m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2);
984 changed = true;
934 } 985 }
935 if (rotq.Y <= -m_RollreferenceFrame.Y) 986 if (rotq.Y <= -m_RollreferenceFrame.Y)
936 { 987 {
937 m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); 988 m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2);
989 changed = true;
938 } 990 }
939 changed = true; 991 changed = true;
940 } 992 }
@@ -944,8 +996,23 @@ namespace OpenSim.Region.Physics.BulletSPlugin
944 m_rot.Y = 0; 996 m_rot.Y = 0;
945 changed = true; 997 changed = true;
946 } 998 }
999 if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0)
1000 {
1001 m_rot.X = 0;
1002 m_rot.Y = 0;
1003 changed = true;
1004 }
947 if (changed) 1005 if (changed)
948 m_prim.Orientation = m_rot; 1006 m_prim.Orientation = m_rot;
1007
1008 DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot);
1009 }
1010
1011 // Invoke the detailed logger and output something if it's enabled.
1012 private void DetailLog(string msg, params Object[] args)
1013 {
1014 if (m_prim.Scene.VehicleLoggingEnabled)
1015 m_prim.Scene.PhysicsLogging.Write(msg, args);
949 } 1016 }
950 } 1017 }
951} 1018}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
new file mode 100755
index 0000000..6f8430c
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -0,0 +1,352 @@
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;
30
31using OMV = OpenMetaverse;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35public class BSLinkset
36{
37 private static string LogHeader = "[BULLETSIM LINKSET]";
38
39 private BSPrim m_linksetRoot;
40 public BSPrim Root { get { return m_linksetRoot; } }
41
42 private BSScene m_scene;
43
44 private List<BSPrim> m_children;
45
46 // We lock the diddling of linkset classes to prevent any badness.
47 // This locks the modification of the instances of this class. Changes
48 // to the physical representation is done via the tainting mechenism.
49 private object m_linksetActivityLock = new Object();
50
51 // We keep the prim's mass in the linkset structure since it could be dependent on other prims
52 private float m_mass;
53 public float LinksetMass
54 {
55 get
56 {
57 m_mass = ComputeLinksetMass();
58 return m_mass;
59 }
60 }
61
62 public OMV.Vector3 CenterOfMass
63 {
64 get { return ComputeLinksetCenterOfMass(); }
65 }
66
67 public OMV.Vector3 GeometricCenter
68 {
69 get { return ComputeLinksetGeometricCenter(); }
70 }
71
72 public BSLinkset(BSScene scene, BSPrim parent)
73 {
74 // A simple linkset of one (no children)
75 m_scene = scene;
76 m_linksetRoot = parent;
77 m_children = new List<BSPrim>();
78 m_mass = parent.MassRaw;
79 }
80
81 // Link to a linkset where the child knows the parent.
82 // 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.
84 public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent)
85 {
86 lock (m_linksetActivityLock)
87 {
88 parent.Linkset.AddChildToLinkset(child);
89 }
90 return parent.Linkset;
91 }
92
93 public BSLinkset RemoveMeFromLinkset(BSPrim child)
94 {
95 lock (m_linksetActivityLock)
96 {
97 if (IsRoot(child))
98 {
99 // if root of linkset, take the linkset apart
100 while (m_children.Count > 0)
101 {
102 // Note that we don't do a foreach because the remove routine
103 // takes it out of the list.
104 RemoveChildFromLinkset(m_children[0]);
105 }
106 m_children.Clear(); // just to make sure
107 }
108 else
109 {
110 // Just removing a child from an existing linkset
111 RemoveChildFromLinkset(child);
112 }
113 }
114
115 // The child is down to a linkset of just itself
116 return new BSLinkset(m_scene, child);
117 }
118
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
168 public bool IsRoot(BSPrim requestor)
169 {
170 return (requestor.LocalID == m_linksetRoot.LocalID);
171 }
172
173 // Return 'true' if this linkset has any children (more than the root member)
174 public bool HasAnyChildren { get { return (m_children.Count > 0); } }
175
176 // Return 'true' if this child is in this linkset
177 public bool HasChild(BSPrim child)
178 {
179 bool ret = false;
180 foreach (BSPrim bp in m_children)
181 {
182 if (child.LocalID == bp.LocalID)
183 {
184 ret = true;
185 break;
186 }
187 }
188 return ret;
189 }
190
191 private float ComputeLinksetMass()
192 {
193 float mass = m_linksetRoot.MassRaw;
194 foreach (BSPrim bp in m_children)
195 {
196 mass += bp.MassRaw;
197 }
198 return mass;
199 }
200
201 private OMV.Vector3 ComputeLinksetCenterOfMass()
202 {
203 OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw;
204 float totalMass = m_linksetRoot.MassRaw;
205
206 foreach (BSPrim bp in m_children)
207 {
208 com += bp.Position * bp.MassRaw;
209 totalMass += bp.MassRaw;
210 }
211 com /= totalMass;
212
213 return com;
214 }
215
216 private OMV.Vector3 ComputeLinksetGeometricCenter()
217 {
218 OMV.Vector3 com = m_linksetRoot.Position;
219
220 foreach (BSPrim bp in m_children)
221 {
222 com += bp.Position * bp.MassRaw;
223 }
224 com /= m_children.Count + 1;
225
226 return com;
227 }
228
229 // I am the root of a linkset and a new child is being added
230 public void AddChildToLinkset(BSPrim pchild)
231 {
232 BSPrim child = pchild;
233 if (!HasChild(child))
234 {
235 m_children.Add(child);
236
237 m_scene.TaintedObject(delegate()
238 {
239 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);
241 PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child
242 });
243 }
244 return;
245 }
246
247 // 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.
249 public void RemoveChildFromLinkset(BSPrim pchild)
250 {
251 BSPrim child = pchild;
252
253 if (m_children.Remove(child))
254 {
255 m_scene.TaintedObject(delegate()
256 {
257 DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
258 DetailLog("{0},RemoveChildFromLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID);
259
260 if (m_children.Count == 0)
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 });
270 }
271 else
272 {
273 // 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);
275 }
276 return;
277 }
278
279 // Create a constraint between me (root of linkset) and the passed prim (the child).
280 // Called at taint time!
281 private void PhysicallyLinkAChildToRoot(BSPrim childPrim)
282 {
283 // Zero motion for children so they don't interpolate
284 childPrim.ZeroMotion();
285
286 // relative position normalized to the root prim
287 OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation);
288 OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation;
289
290 // relative rotation of the child to the parent
291 OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
292
293 // create a constraint that allows no freedom of movement between the two objects
294 // 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);
296 DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID);
297 BSConstraint constrain = m_scene.Constraints.CreateConstraint(
298 m_scene.World, m_linksetRoot.Body, childPrim.Body,
299 // childRelativePosition,
300 // childRelativeRotation,
301 OMV.Vector3.Zero,
302 OMV.Quaternion.Identity,
303 OMV.Vector3.Zero,
304 OMV.Quaternion.Identity
305 );
306 constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
307 constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
308
309 // tweek the constraint to increase stability
310 constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset));
311 constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor),
312 m_scene.Params.linkConstraintTransMotorMaxVel,
313 m_scene.Params.linkConstraintTransMotorMaxForce);
314 constrain.SetCFMAndERP(m_scene.Params.linkConstraintCFM, m_scene.Params.linkConstraintERP);
315
316 }
317
318 // Remove linkage between myself and a particular child
319 // Called at taint time!
320 private void PhysicallyUnlinkAChildFromRoot(BSPrim childPrim)
321 {
322 DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
323 LogHeader, m_linksetRoot.LocalID, childPrim.LocalID);
324 DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID);
325 // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID);
326 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body, childPrim.Body);
327 }
328
329 // Remove linkage between myself and any possible children I might have
330 // Called at taint time!
331 private void PhysicallyUnlinkAllChildrenFromRoot()
332 {
333 // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
334 DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID);
335 m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body);
336 // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
337 }
338
339 // Invoke the detailed logger and output something if it's enabled.
340 private void DebugLog(string msg, params Object[] args)
341 {
342 m_scene.Logger.DebugFormat(msg, args);
343 }
344
345 // Invoke the detailed logger and output something if it's enabled.
346 private void DetailLog(string msg, params Object[] args)
347 {
348 m_scene.PhysicsLogging.Write(msg, args);
349 }
350
351}
352}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 130f1ca..a4ab702 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -42,6 +42,8 @@ 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); }
46
45 private IMesh _mesh; 47 private IMesh _mesh;
46 private PrimitiveBaseShape _pbs; 48 private PrimitiveBaseShape _pbs;
47 private ShapeData.PhysicsShapeType _shapeType; 49 private ShapeData.PhysicsShapeType _shapeType;
@@ -50,6 +52,7 @@ public sealed class BSPrim : PhysicsActor
50 private List<ConvexResult> _hulls; 52 private List<ConvexResult> _hulls;
51 53
52 private BSScene _scene; 54 private BSScene _scene;
55 public BSScene Scene { get { return _scene; } }
53 private String _avName; 56 private String _avName;
54 private uint _localID = 0; 57 private uint _localID = 0;
55 58
@@ -63,7 +66,7 @@ public sealed class BSPrim : PhysicsActor
63 private bool _isSelected; 66 private bool _isSelected;
64 private bool _isVolumeDetect; 67 private bool _isVolumeDetect;
65 private OMV.Vector3 _position; 68 private OMV.Vector3 _position;
66 private float _mass; 69 private float _mass; // the mass of this object
67 private float _density; 70 private float _density;
68 private OMV.Vector3 _force; 71 private OMV.Vector3 _force;
69 private OMV.Vector3 _velocity; 72 private OMV.Vector3 _velocity;
@@ -86,14 +89,25 @@ public sealed class BSPrim : PhysicsActor
86 private bool _kinematic; 89 private bool _kinematic;
87 private float _buoyancy; 90 private float _buoyancy;
88 91
89 private List<BSPrim> _childrenPrims; 92 // Membership in a linkset is controlled by this class.
90 private BSPrim _parentPrim; 93 private BSLinkset _linkset;
94 public BSLinkset Linkset
95 {
96 get { return _linkset; }
97 set { _linkset = value; }
98 }
91 99
92 private int _subscribedEventsMs = 0; 100 private int _subscribedEventsMs = 0;
93 private int _nextCollisionOkTime = 0; 101 private int _nextCollisionOkTime = 0;
94 long _collidingStep; 102 long _collidingStep;
95 long _collidingGroundStep; 103 long _collidingGroundStep;
96 104
105 private BulletBody m_body;
106 public BulletBody Body {
107 get { return m_body; }
108 set { m_body = value; }
109 }
110
97 private BSDynamics _vehicle; 111 private BSDynamics _vehicle;
98 112
99 private OMV.Vector3 _PIDTarget; 113 private OMV.Vector3 _PIDTarget;
@@ -127,17 +141,18 @@ public sealed class BSPrim : PhysicsActor
127 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material 141 _friction = _scene.Params.defaultFriction; // TODO: compute based on object material
128 _density = _scene.Params.defaultDensity; // TODO: compute based on object material 142 _density = _scene.Params.defaultDensity; // TODO: compute based on object material
129 _restitution = _scene.Params.defaultRestitution; 143 _restitution = _scene.Params.defaultRestitution;
130 _parentPrim = null; // not a child or a parent 144 _linkset = new BSLinkset(_scene, this); // a linkset of one
131 _vehicle = new BSDynamics(this); // add vehicleness 145 _vehicle = new BSDynamics(this); // add vehicleness
132 _childrenPrims = new List<BSPrim>(); 146 _mass = CalculateMass();
133 if (_isPhysical)
134 _mass = CalculateMass();
135 else
136 _mass = 0f;
137 // do the actual object creation at taint time 147 // do the actual object creation at taint time
138 _scene.TaintedObject(delegate() 148 _scene.TaintedObject(delegate()
139 { 149 {
140 RecreateGeomAndObject(); 150 RecreateGeomAndObject();
151
152 // Get the pointer to the physical body for this object.
153 // At the moment, we're still letting BulletSim manage the creation and destruction
154 // of the object. Someday we'll move that into the C# code.
155 m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
141 }); 156 });
142 } 157 }
143 158
@@ -145,13 +160,19 @@ public sealed class BSPrim : PhysicsActor
145 public void Destroy() 160 public void Destroy()
146 { 161 {
147 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); 162 // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
163 // DetailLog("{0},Destroy", LocalID);
164
148 // Undo any vehicle properties 165 // Undo any vehicle properties
149 _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); 166 _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE);
150 _scene.RemoveVehiclePrim(this); // just to make sure 167 _scene.RemoveVehiclePrim(this); // just to make sure
168
151 _scene.TaintedObject(delegate() 169 _scene.TaintedObject(delegate()
152 { 170 {
171 // Undo any links between me and any other object
172 _linkset = _linkset.RemoveMeFromLinkset(this);
173
153 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. 174 // everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
154 BulletSimAPI.DestroyObject(_scene.WorldID, _localID); 175 BulletSimAPI.DestroyObject(_scene.WorldID, LocalID);
155 }); 176 });
156 } 177 }
157 178
@@ -164,8 +185,9 @@ public sealed class BSPrim : PhysicsActor
164 _size = value; 185 _size = value;
165 _scene.TaintedObject(delegate() 186 _scene.TaintedObject(delegate()
166 { 187 {
167 if (_isPhysical) _mass = CalculateMass(); // changing size changes the mass 188 _mass = CalculateMass(); // changing size changes the mass
168 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, _mass, _isPhysical); 189 BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical);
190 DetailLog("{0}: setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical);
169 RecreateGeomAndObject(); 191 RecreateGeomAndObject();
170 }); 192 });
171 } 193 }
@@ -175,7 +197,7 @@ public sealed class BSPrim : PhysicsActor
175 _pbs = value; 197 _pbs = value;
176 _scene.TaintedObject(delegate() 198 _scene.TaintedObject(delegate()
177 { 199 {
178 if (_isPhysical) _mass = CalculateMass(); // changing the shape changes the mass 200 _mass = CalculateMass(); // changing the shape changes the mass
179 RecreateGeomAndObject(); 201 RecreateGeomAndObject();
180 }); 202 });
181 } 203 }
@@ -202,33 +224,10 @@ public sealed class BSPrim : PhysicsActor
202 // link me to the specified parent 224 // link me to the specified parent
203 public override void link(PhysicsActor obj) { 225 public override void link(PhysicsActor obj) {
204 BSPrim parent = obj as BSPrim; 226 BSPrim parent = obj as BSPrim;
205 // m_log.DebugFormat("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); 227 DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID);
206 // TODO: decide if this parent checking needs to happen at taint time 228 DetailLog("{0},link,parent={1}", LocalID, obj.LocalID);
207 if (_parentPrim == null) 229
208 { 230 _linkset = _linkset.AddMeToLinkset(this, parent);
209 if (parent != null)
210 {
211 // I don't have a parent so I am joining a linkset
212 parent.AddChildToLinkset(this);
213 }
214 }
215 else
216 {
217 // I already have a parent, is parenting changing?
218 if (parent != _parentPrim)
219 {
220 if (parent == null)
221 {
222 // we are being removed from a linkset
223 _parentPrim.RemoveChildFromLinkset(this);
224 }
225 else
226 {
227 // asking to reparent a prim should not happen
228 m_log.ErrorFormat("{0}: Reparenting a prim. ", LogHeader);
229 }
230 }
231 }
232 return; 231 return;
233 } 232 }
234 233
@@ -236,101 +235,92 @@ public sealed class BSPrim : PhysicsActor
236 public override void delink() { 235 public override void delink() {
237 // TODO: decide if this parent checking needs to happen at taint time 236 // TODO: decide if this parent checking needs to happen at taint time
238 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen 237 // Race condition here: if link() and delink() in same simulation tick, the delink will not happen
239 // m_log.DebugFormat("{0}: delink {1}/{2}", LogHeader, _avName, _localID); 238 DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
240 if (_parentPrim != null) 239 _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString());
241 { 240 DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString());
242 _parentPrim.RemoveChildFromLinkset(this);
243 }
244 return;
245 }
246
247 // I am the root of a linkset and a new child is being added
248 public void AddChildToLinkset(BSPrim pchild)
249 {
250 BSPrim child = pchild;
251 _scene.TaintedObject(delegate()
252 {
253 if (!_childrenPrims.Contains(child))
254 {
255 _childrenPrims.Add(child);
256 child.ParentPrim = this; // the child has gained a parent
257 RecreateGeomAndObject(); // rebuild my shape with the new child added
258 }
259 });
260 return;
261 }
262
263 // I am the root of a linkset and one of my children is being removed.
264 // Safe to call even if the child is not really in my linkset.
265 public void RemoveChildFromLinkset(BSPrim pchild)
266 {
267 BSPrim child = pchild;
268 _scene.TaintedObject(delegate()
269 {
270 if (_childrenPrims.Contains(child))
271 {
272 BulletSimAPI.RemoveConstraint(_scene.WorldID, child.LocalID, this.LocalID);
273 _childrenPrims.Remove(child);
274 child.ParentPrim = null; // the child has lost its parent
275 RecreateGeomAndObject(); // rebuild my shape with the child removed
276 }
277 else
278 {
279 m_log.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset");
280 }
281 });
282 return;
283 }
284
285 public BSPrim ParentPrim
286 {
287 set { _parentPrim = value; }
288 }
289 241
290 // return true if we are the root of a linkset (there are children to manage) 242 _linkset.RemoveMeFromLinkset(this);
291 public bool IsRootOfLinkset 243 return;
292 {
293 get { return (_parentPrim == null && _childrenPrims.Count != 0); }
294 } 244 }
295 245
296 // Set motion values to zero. 246 // Set motion values to zero.
297 // Do it to the properties so the values get set in the physics engine. 247 // Do it to the properties so the values get set in the physics engine.
298 // Push the setting of the values to the viewer. 248 // Push the setting of the values to the viewer.
299 private void ZeroMotion() 249 // Called at taint time!
250 public void ZeroMotion()
300 { 251 {
301 Velocity = OMV.Vector3.Zero; 252 _velocity = OMV.Vector3.Zero;
302 _acceleration = OMV.Vector3.Zero; 253 _acceleration = OMV.Vector3.Zero;
303 RotationalVelocity = OMV.Vector3.Zero; 254 _rotationalVelocity = OMV.Vector3.Zero;
304 base.RequestPhysicsterseUpdate(); 255
256 // Zero some other properties directly into the physics engine
257 BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero);
258 BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero);
259 BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero);
260 BulletSimAPI.ClearForces2(Body.Ptr);
305 } 261 }
306 262
307 public override void LockAngularMotion(OMV.Vector3 axis) { return; } 263 public override void LockAngularMotion(OMV.Vector3 axis)
264 {
265 DetailLog("{0},LockAngularMotion,call,axis={1}", LocalID, axis);
266 return;
267 }
308 268
309 public override OMV.Vector3 Position { 269 public override OMV.Vector3 Position {
310 get { 270 get {
311 // don't do the following GetObjectPosition because this function is called a zillion times 271 if (!_linkset.IsRoot(this))
272 // child prims move around based on their parent. Need to get the latest location
273 _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
274
275 // don't do the GetObjectPosition for root elements because this function is called a zillion times
312 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 276 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
313 return _position; 277 return _position;
314 } 278 }
315 set { 279 set {
316 _position = value; 280 _position = value;
281 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
317 _scene.TaintedObject(delegate() 282 _scene.TaintedObject(delegate()
318 { 283 {
284 DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
319 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 285 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
320 // m_log.DebugFormat("{0}: setPosition: id={1}, position={2}", LogHeader, _localID, _position);
321 }); 286 });
322 } 287 }
323 } 288 }
324 public override float Mass { 289
325 get { return _mass; } 290 // Return the effective mass of the object.
291 // If there are multiple items in the linkset, add them together for the root
292 public override float Mass
293 {
294 get
295 {
296 return _linkset.LinksetMass;
297 }
298 }
299
300 // used when we only want this prim's mass and not the linkset thing
301 public float MassRaw { get { return _mass; } }
302
303 // Is this used?
304 public override OMV.Vector3 CenterOfMass
305 {
306 get { return _linkset.CenterOfMass; }
307 }
308
309 // Is this used?
310 public override OMV.Vector3 GeometricCenter
311 {
312 get { return _linkset.GeometricCenter; }
326 } 313 }
314
327 public override OMV.Vector3 Force { 315 public override OMV.Vector3 Force {
328 get { return _force; } 316 get { return _force; }
329 set { 317 set {
330 _force = value; 318 _force = value;
331 _scene.TaintedObject(delegate() 319 _scene.TaintedObject(delegate()
332 { 320 {
333 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 321 DetailLog("{0},SetForce,taint,force={1}", LocalID, _force);
322 // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
323 BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
334 }); 324 });
335 } 325 }
336 } 326 }
@@ -341,15 +331,22 @@ public sealed class BSPrim : PhysicsActor
341 } 331 }
342 set { 332 set {
343 Vehicle type = (Vehicle)value; 333 Vehicle type = (Vehicle)value;
344 _vehicle.ProcessTypeChange(type);
345 _scene.TaintedObject(delegate() 334 _scene.TaintedObject(delegate()
346 { 335 {
336 DetailLog("{0},SetVehicleType,taint,type={1}", LocalID, type);
337 _vehicle.ProcessTypeChange(type);
347 if (type == Vehicle.TYPE_NONE) 338 if (type == Vehicle.TYPE_NONE)
348 { 339 {
349 _scene.RemoveVehiclePrim(this); 340 _scene.RemoveVehiclePrim(this);
350 } 341 }
351 else 342 else
352 { 343 {
344 _scene.TaintedObject(delegate()
345 {
346 // Tell the physics engine to clear state
347 BulletSimAPI.ClearForces2(this.Body.Ptr);
348 });
349
353 // make it so the scene will call us each tick to do vehicle things 350 // make it so the scene will call us each tick to do vehicle things
354 _scene.AddVehiclePrim(this); 351 _scene.AddVehiclePrim(this);
355 } 352 }
@@ -359,47 +356,59 @@ public sealed class BSPrim : PhysicsActor
359 } 356 }
360 public override void VehicleFloatParam(int param, float value) 357 public override void VehicleFloatParam(int param, float value)
361 { 358 {
362 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); 359 _scene.TaintedObject(delegate()
360 {
361 _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
362 });
363 } 363 }
364 public override void VehicleVectorParam(int param, OMV.Vector3 value) 364 public override void VehicleVectorParam(int param, OMV.Vector3 value)
365 { 365 {
366 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); 366 _scene.TaintedObject(delegate()
367 {
368 _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
369 });
367 } 370 }
368 public override void VehicleRotationParam(int param, OMV.Quaternion rotation) 371 public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
369 { 372 {
370 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); 373 _scene.TaintedObject(delegate()
374 {
375 _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
376 });
371 } 377 }
372 public override void VehicleFlags(int param, bool remove) 378 public override void VehicleFlags(int param, bool remove)
373 { 379 {
374 _vehicle.ProcessVehicleFlags(param, remove); 380 _scene.TaintedObject(delegate()
381 {
382 _vehicle.ProcessVehicleFlags(param, remove);
383 });
375 } 384 }
376 // Called each simulation step to advance vehicle characteristics 385
386 // Called each simulation step to advance vehicle characteristics.
387 // Called from Scene when doing simulation step so we're in taint processing time.
377 public void StepVehicle(float timeStep) 388 public void StepVehicle(float timeStep)
378 { 389 {
379 _vehicle.Step(timeStep, _scene); 390 if (IsPhysical)
391 _vehicle.Step(timeStep);
380 } 392 }
381 393
382 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more 394 // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more
383 public override void SetVolumeDetect(int param) { 395 public override void SetVolumeDetect(int param) {
384 bool newValue = (param != 0); 396 bool newValue = (param != 0);
385 if (_isVolumeDetect != newValue) 397 _isVolumeDetect = newValue;
398 _scene.TaintedObject(delegate()
386 { 399 {
387 _isVolumeDetect = newValue; 400 SetObjectDynamic();
388 _scene.TaintedObject(delegate() 401 });
389 {
390 SetObjectDynamic();
391 });
392 }
393 return; 402 return;
394 } 403 }
395 404
396 public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } }
397 public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } }
398 public override OMV.Vector3 Velocity { 405 public override OMV.Vector3 Velocity {
399 get { return _velocity; } 406 get { return _velocity; }
400 set { _velocity = value; 407 set {
408 _velocity = value;
401 _scene.TaintedObject(delegate() 409 _scene.TaintedObject(delegate()
402 { 410 {
411 DetailLog("{0},SetVelocity,taint,vel={1}", LocalID, _velocity);
403 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); 412 BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
404 }); 413 });
405 } 414 }
@@ -407,6 +416,7 @@ public sealed class BSPrim : PhysicsActor
407 public override OMV.Vector3 Torque { 416 public override OMV.Vector3 Torque {
408 get { return _torque; } 417 get { return _torque; }
409 set { _torque = value; 418 set { _torque = value;
419 DetailLog("{0},SetTorque,call,torque={1}", LocalID, _torque);
410 } 420 }
411 } 421 }
412 public override float CollisionScore { 422 public override float CollisionScore {
@@ -419,13 +429,21 @@ public sealed class BSPrim : PhysicsActor
419 set { _acceleration = value; } 429 set { _acceleration = value; }
420 } 430 }
421 public override OMV.Quaternion Orientation { 431 public override OMV.Quaternion Orientation {
422 get { return _orientation; } 432 get {
433 if (!_linkset.IsRoot(this))
434 {
435 // Children move around because tied to parent. Get a fresh value.
436 _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
437 }
438 return _orientation;
439 }
423 set { 440 set {
424 _orientation = value; 441 _orientation = value;
425 // m_log.DebugFormat("{0}: set orientation: id={1}, ori={2}", LogHeader, LocalID, _orientation); 442 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
426 _scene.TaintedObject(delegate() 443 _scene.TaintedObject(delegate()
427 { 444 {
428 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); 445 // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
446 DetailLog("{0},SetOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
429 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); 447 BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
430 }); 448 });
431 } 449 }
@@ -458,25 +476,24 @@ public sealed class BSPrim : PhysicsActor
458 get { return !IsPhantom && !_isVolumeDetect; } 476 get { return !IsPhantom && !_isVolumeDetect; }
459 } 477 }
460 478
461 // make gravity work if the object is physical and not selected 479 // Make gravity work if the object is physical and not selected
462 // no locking here because only called when it is safe 480 // No locking here because only called when it is safe
481 // Only called at taint time so it is save to call into Bullet.
463 private void SetObjectDynamic() 482 private void SetObjectDynamic()
464 { 483 {
465 // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid); 484 // RA: remove this for the moment.
466 // non-physical things work best with a mass of zero 485 // The problem is that dynamic objects are hulls so if we are becoming physical
467 if (IsStatic) 486 // the shape has to be checked and possibly built.
468 { 487 // Maybe a VerifyCorrectPhysicalShape() routine?
469 _mass = 0f; 488 // RecreateGeomAndObject();
470 }
471 else
472 {
473 _mass = CalculateMass();
474 // If it's dynamic, make sure the hull has been created for it
475 // This shouldn't do much work if the object had previously been built
476 RecreateGeomAndObject();
477 489
478 } 490 float mass = _mass;
479 BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), _mass); 491 // Bullet wants static objects have a mass of zero
492 if (IsStatic)
493 mass = 0f;
494
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);
480 } 497 }
481 498
482 // prims don't fly 499 // prims don't fly
@@ -516,11 +533,24 @@ public sealed class BSPrim : PhysicsActor
516 set { _floatOnWater = value; } 533 set { _floatOnWater = value; }
517 } 534 }
518 public override OMV.Vector3 RotationalVelocity { 535 public override OMV.Vector3 RotationalVelocity {
519 get { return _rotationalVelocity; } 536 get {
520 set { _rotationalVelocity = value; 537 /*
538 OMV.Vector3 pv = OMV.Vector3.Zero;
539 // if close to zero, report zero
540 // This is copied from ODE but I'm not sure why it returns zero but doesn't
541 // zero the property in the physics engine.
542 if (_rotationalVelocity.ApproxEquals(pv, 0.2f))
543 return pv;
544 */
545
546 return _rotationalVelocity;
547 }
548 set {
549 _rotationalVelocity = value;
521 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); 550 // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
522 _scene.TaintedObject(delegate() 551 _scene.TaintedObject(delegate()
523 { 552 {
553 DetailLog("{0},SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
524 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); 554 BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
525 }); 555 });
526 } 556 }
@@ -533,11 +563,13 @@ public sealed class BSPrim : PhysicsActor
533 } 563 }
534 public override float Buoyancy { 564 public override float Buoyancy {
535 get { return _buoyancy; } 565 get { return _buoyancy; }
536 set { _buoyancy = value; 566 set {
537 _scene.TaintedObject(delegate() 567 _buoyancy = value;
538 { 568 _scene.TaintedObject(delegate()
539 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); 569 {
540 }); 570 DetailLog("{0},SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
571 BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
572 });
541 } 573 }
542 } 574 }
543 575
@@ -573,27 +605,45 @@ public sealed class BSPrim : PhysicsActor
573 public override float APIDStrength { set { return; } } 605 public override float APIDStrength { set { return; } }
574 public override float APIDDamping { set { return; } } 606 public override float APIDDamping { set { return; } }
575 607
608 private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
576 public override void AddForce(OMV.Vector3 force, bool pushforce) { 609 public override void AddForce(OMV.Vector3 force, bool pushforce) {
577 if (force.IsFinite()) 610 if (force.IsFinite())
578 { 611 {
579 _force.X += force.X; 612 // _force += force;
580 _force.Y += force.Y; 613 lock (m_accumulatedForces)
581 _force.Z += force.Z; 614 m_accumulatedForces.Add(new OMV.Vector3(force));
582 } 615 }
583 else 616 else
584 { 617 {
585 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); 618 m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
619 return;
586 } 620 }
587 _scene.TaintedObject(delegate() 621 _scene.TaintedObject(delegate()
588 { 622 {
589 BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); 623 lock (m_accumulatedForces)
624 {
625 if (m_accumulatedForces.Count > 0)
626 {
627 OMV.Vector3 fSum = OMV.Vector3.Zero;
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 }
637 }
590 }); 638 });
591 } 639 }
592 640
593 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { 641 public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
642 DetailLog("{0},AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
594 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); 643 // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
595 } 644 }
596 public override void SetMomentum(OMV.Vector3 momentum) { 645 public override void SetMomentum(OMV.Vector3 momentum) {
646 DetailLog("{0},SetMomentum,call,mom={1}", LocalID, momentum);
597 } 647 }
598 public override void SubscribeEvents(int ms) { 648 public override void SubscribeEvents(int ms) {
599 _subscribedEventsMs = ms; 649 _subscribedEventsMs = ms;
@@ -885,6 +935,9 @@ public sealed class BSPrim : PhysicsActor
885 935
886 returnMass = _density * volume; 936 returnMass = _density * volume;
887 937
938 /*
939 * This change means each object keeps its own mass and the Mass property
940 * will return the sum if we're part of a linkset.
888 if (IsRootOfLinkset) 941 if (IsRootOfLinkset)
889 { 942 {
890 foreach (BSPrim prim in _childrenPrims) 943 foreach (BSPrim prim in _childrenPrims)
@@ -892,6 +945,7 @@ public sealed class BSPrim : PhysicsActor
892 returnMass += prim.CalculateMass(); 945 returnMass += prim.CalculateMass();
893 } 946 }
894 } 947 }
948 */
895 949
896 if (returnMass <= 0) 950 if (returnMass <= 0)
897 returnMass = 0.0001f; 951 returnMass = 0.0001f;
@@ -907,9 +961,11 @@ public sealed class BSPrim : PhysicsActor
907 // The objects needs a hull if it's physical otherwise a mesh is enough 961 // The objects needs a hull if it's physical otherwise a mesh is enough
908 // No locking here because this is done when we know physics is not simulating 962 // No locking here because this is done when we know physics is not simulating
909 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used 963 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used
910 private void CreateGeom(bool forceRebuild) 964 // Returns 'true' if the geometry was rebuilt
965 private bool CreateGeom(bool forceRebuild)
911 { 966 {
912 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. 967 // the mesher thought this was too simple to mesh. Use a native Bullet collision shape.
968 bool ret = false;
913 if (!_scene.NeedsMeshing(_pbs)) 969 if (!_scene.NeedsMeshing(_pbs))
914 { 970 {
915 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) 971 if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
@@ -917,16 +973,28 @@ public sealed class BSPrim : PhysicsActor
917 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) 973 if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
918 { 974 {
919 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); 975 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
920 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; 976 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
921 // Bullet native objects are scaled by the Bullet engine so pass the size in 977 {
922 _scale = _size; 978 DetailLog("{0},CreateGeom,sphere", LocalID);
979 _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
980 // Bullet native objects are scaled by the Bullet engine so pass the size in
981 _scale = _size;
982 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
983 ret = true;
984 }
923 } 985 }
924 } 986 }
925 else 987 else
926 { 988 {
927 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size); 989 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
928 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; 990 if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
929 _scale = _size; 991 {
992 DetailLog("{0},CreateGeom,box", LocalID);
993 _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
994 _scale = _size;
995 // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
996 ret = true;
997 }
930 } 998 }
931 } 999 }
932 else 1000 else
@@ -938,6 +1006,7 @@ public sealed class BSPrim : PhysicsActor
938 // physical objects require a hull for interaction. 1006 // physical objects require a hull for interaction.
939 // This will create the mesh if it doesn't already exist 1007 // This will create the mesh if it doesn't already exist
940 CreateGeomHull(); 1008 CreateGeomHull();
1009 ret = true;
941 } 1010 }
942 } 1011 }
943 else 1012 else
@@ -946,9 +1015,11 @@ public sealed class BSPrim : PhysicsActor
946 { 1015 {
947 // Static (non-physical) objects only need a mesh for bumping into 1016 // Static (non-physical) objects only need a mesh for bumping into
948 CreateGeomMesh(); 1017 CreateGeomMesh();
1018 ret = true;
949 } 1019 }
950 } 1020 }
951 } 1021 }
1022 return ret;
952 } 1023 }
953 1024
954 // No locking here because this is done when we know physics is not simulating 1025 // No locking here because this is done when we know physics is not simulating
@@ -961,10 +1032,12 @@ public sealed class BSPrim : PhysicsActor
961 // if this new shape is the same as last time, don't recreate the mesh 1032 // if this new shape is the same as last time, don't recreate the mesh
962 if (_meshKey == newMeshKey) return; 1033 if (_meshKey == newMeshKey) return;
963 1034
1035 DetailLog("{0},CreateGeomMesh,create,key={1}", LocalID, _meshKey);
964 // Since we're recreating new, get rid of any previously generated shape 1036 // Since we're recreating new, get rid of any previously generated shape
965 if (_meshKey != 0) 1037 if (_meshKey != 0)
966 { 1038 {
967 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); 1039 // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
1040 DetailLog("{0},CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
968 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1041 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
969 _mesh = null; 1042 _mesh = null;
970 _meshKey = 0; 1043 _meshKey = 0;
@@ -981,7 +1054,6 @@ public sealed class BSPrim : PhysicsActor
981 int vi = 0; 1054 int vi = 0;
982 foreach (OMV.Vector3 vv in vertices) 1055 foreach (OMV.Vector3 vv in vertices)
983 { 1056 {
984 // m_log.DebugFormat("{0}: {1}: <{2:0.00}, {3:0.00}, {4:0.00}>", LogHeader, vi / 3, vv.X, vv.Y, vv.Z);
985 verticesAsFloats[vi++] = vv.X; 1057 verticesAsFloats[vi++] = vv.X;
986 verticesAsFloats[vi++] = vv.Y; 1058 verticesAsFloats[vi++] = vv.Y;
987 verticesAsFloats[vi++] = vv.Z; 1059 verticesAsFloats[vi++] = vv.Z;
@@ -995,6 +1067,7 @@ public sealed class BSPrim : PhysicsActor
995 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; 1067 _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
996 // meshes are already scaled by the meshmerizer 1068 // meshes are already scaled by the meshmerizer
997 _scale = new OMV.Vector3(1f, 1f, 1f); 1069 _scale = new OMV.Vector3(1f, 1f, 1f);
1070 DetailLog("{0},CreateGeomMesh,done", LocalID);
998 return; 1071 return;
999 } 1072 }
1000 1073
@@ -1008,13 +1081,17 @@ public sealed class BSPrim : PhysicsActor
1008 // if the hull hasn't changed, don't rebuild it 1081 // if the hull hasn't changed, don't rebuild it
1009 if (newHullKey == _hullKey) return; 1082 if (newHullKey == _hullKey) return;
1010 1083
1084 DetailLog("{0},CreateGeomHull,create,key={1}", LocalID, _meshKey);
1085
1011 // Since we're recreating new, get rid of any previously generated shape 1086 // Since we're recreating new, get rid of any previously generated shape
1012 if (_hullKey != 0) 1087 if (_hullKey != 0)
1013 { 1088 {
1014 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); 1089 // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey);
1090 DetailLog("{0},CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey);
1015 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); 1091 BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
1016 _hullKey = 0; 1092 _hullKey = 0;
1017 _hulls.Clear(); 1093 _hulls.Clear();
1094 DetailLog("{0},CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey);
1018 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); 1095 BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
1019 _mesh = null; // the mesh cannot match either 1096 _mesh = null; // the mesh cannot match either
1020 _meshKey = 0; 1097 _meshKey = 0;
@@ -1111,6 +1188,7 @@ public sealed class BSPrim : PhysicsActor
1111 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; 1188 _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
1112 // meshes are already scaled by the meshmerizer 1189 // meshes are already scaled by the meshmerizer
1113 _scale = new OMV.Vector3(1f, 1f, 1f); 1190 _scale = new OMV.Vector3(1f, 1f, 1f);
1191 DetailLog("{0},CreateGeomHull,done", LocalID);
1114 return; 1192 return;
1115 } 1193 }
1116 1194
@@ -1124,47 +1202,21 @@ public sealed class BSPrim : PhysicsActor
1124 1202
1125 // Create an object in Bullet if it has not already been created 1203 // Create an object in Bullet if it has not already been created
1126 // No locking here because this is done when the physics engine is not simulating 1204 // No locking here because this is done when the physics engine is not simulating
1127 private void CreateObject() 1205 // Returns 'true' if an object was actually created.
1206 private bool CreateObject()
1128 { 1207 {
1129 if (IsRootOfLinkset) 1208 // this routine is called when objects are rebuilt.
1130 {
1131 // Create a linkset around this object
1132 // CreateLinksetWithCompoundHull();
1133 CreateLinksetWithConstraints();
1134 }
1135 else
1136 {
1137 // simple object
1138 // the mesh or hull must have already been created in Bullet
1139 ShapeData shape;
1140 FillShapeInfo(out shape);
1141 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1142 BulletSimAPI.CreateObject(_scene.WorldID, shape);
1143 }
1144 }
1145 1209
1146 // Create a linkset by creating a compound hull at the root prim that consists of all 1210 // the mesh or hull must have already been created in Bullet
1147 // the children. 1211 ShapeData shape;
1148 // NOTE: This does not allow proper collisions with the children prims so it is not a workable solution 1212 FillShapeInfo(out shape);
1149 void CreateLinksetWithCompoundHull() 1213 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type);
1150 { 1214 bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
1151 // If I am the root prim of a linkset, replace my physical shape with all the 1215
1152 // pieces of the children. 1216 // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
1153 // All of the children should have called CreateGeom so they have a hull 1217 m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID);
1154 // in the physics engine already. Here we pull together all of those hulls 1218
1155 // into one shape. 1219 return ret;
1156 int totalPrimsInLinkset = _childrenPrims.Count + 1;
1157 // m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, totalPrimsInLinkset);
1158 ShapeData[] shapes = new ShapeData[totalPrimsInLinkset];
1159 FillShapeInfo(out shapes[0]);
1160 int ii = 1;
1161 foreach (BSPrim prim in _childrenPrims)
1162 {
1163 // m_log.DebugFormat("{0}: CreateLinkset: adding prim {1}", LogHeader, prim.LocalID);
1164 prim.FillShapeInfo(out shapes[ii]);
1165 ii++;
1166 }
1167 BulletSimAPI.CreateLinkset(_scene.WorldID, totalPrimsInLinkset, shapes);
1168 } 1220 }
1169 1221
1170 // Copy prim's info into the BulletSim shape description structure 1222 // Copy prim's info into the BulletSim shape description structure
@@ -1186,44 +1238,6 @@ public sealed class BSPrim : PhysicsActor
1186 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; 1238 shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue;
1187 } 1239 }
1188 1240
1189 // Create the linkset by putting constraints between the objects of the set so they cannot move
1190 // relative to each other.
1191 // TODO: make this more effeicient: a large linkset gets rebuilt over and over and prims are added
1192 void CreateLinksetWithConstraints()
1193 {
1194 // m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1);
1195
1196 // remove any constraints that might be in place
1197 foreach (BSPrim prim in _childrenPrims)
1198 {
1199 // m_log.DebugFormat("{0}: CreateLinkset: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
1200 BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, prim.LocalID);
1201 }
1202 // create constraints between the root prim and each of the children
1203 foreach (BSPrim prim in _childrenPrims)
1204 {
1205 // m_log.DebugFormat("{0}: CreateLinkset: AddConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID);
1206
1207 // Zero motion for children so they don't interpolate
1208 prim.ZeroMotion();
1209
1210 // relative position normalized to the root prim
1211 OMV.Vector3 childRelativePosition = (prim._position - this._position) * OMV.Quaternion.Inverse(this._orientation);
1212
1213 // relative rotation of the child to the parent
1214 OMV.Quaternion relativeRotation = OMV.Quaternion.Inverse(prim._orientation) * this._orientation;
1215
1216 // this is a constraint that allows no freedom of movement between the two objects
1217 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
1218 BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID,
1219 childRelativePosition,
1220 relativeRotation,
1221 OMV.Vector3.Zero,
1222 OMV.Quaternion.Identity,
1223 OMV.Vector3.Zero, OMV.Vector3.Zero,
1224 OMV.Vector3.Zero, OMV.Vector3.Zero);
1225 }
1226 }
1227 1241
1228 // Rebuild the geometry and object. 1242 // Rebuild the geometry and object.
1229 // This is called when the shape changes so we need to recreate the mesh/hull. 1243 // This is called when the shape changes so we need to recreate the mesh/hull.
@@ -1231,8 +1245,8 @@ public sealed class BSPrim : PhysicsActor
1231 private void RecreateGeomAndObject() 1245 private void RecreateGeomAndObject()
1232 { 1246 {
1233 // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); 1247 // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID);
1234 CreateGeom(true); 1248 if (CreateGeom(true))
1235 CreateObject(); 1249 CreateObject();
1236 return; 1250 return;
1237 } 1251 }
1238 1252
@@ -1252,78 +1266,78 @@ public sealed class BSPrim : PhysicsActor
1252 const float POSITION_TOLERANCE = 0.05f; 1266 const float POSITION_TOLERANCE = 0.05f;
1253 const float ACCELERATION_TOLERANCE = 0.01f; 1267 const float ACCELERATION_TOLERANCE = 0.01f;
1254 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; 1268 const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
1255 const bool SHOULD_DAMP_UPDATES = false;
1256 1269
1257 public void UpdateProperties(EntityProperties entprop) 1270 public void UpdateProperties(EntityProperties entprop)
1258 { 1271 {
1272 /*
1259 UpdatedProperties changed = 0; 1273 UpdatedProperties changed = 0;
1260 if (SHOULD_DAMP_UPDATES) 1274 // assign to the local variables so the normal set action does not happen
1275 // if (_position != entprop.Position)
1276 if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
1261 { 1277 {
1262 // assign to the local variables so the normal set action does not happen 1278 _position = entprop.Position;
1263 // if (_position != entprop.Position) 1279 changed |= UpdatedProperties.Position;
1264 if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
1265 {
1266 _position = entprop.Position;
1267 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, pos = {2}", LogHeader, LocalID, _position);
1268 changed |= UpdatedProperties.Position;
1269 }
1270 // if (_orientation != entprop.Rotation)
1271 if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
1272 {
1273 _orientation = entprop.Rotation;
1274 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, rot = {2}", LogHeader, LocalID, _orientation);
1275 changed |= UpdatedProperties.Rotation;
1276 }
1277 // if (_velocity != entprop.Velocity)
1278 if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
1279 {
1280 _velocity = entprop.Velocity;
1281 // m_log.DebugFormat("{0}: UpdateProperties: velocity = {1}", LogHeader, _velocity);
1282 changed |= UpdatedProperties.Velocity;
1283 }
1284 // if (_acceleration != entprop.Acceleration)
1285 if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
1286 {
1287 _acceleration = entprop.Acceleration;
1288 // m_log.DebugFormat("{0}: UpdateProperties: acceleration = {1}", LogHeader, _acceleration);
1289 changed |= UpdatedProperties.Acceleration;
1290 }
1291 // if (_rotationalVelocity != entprop.RotationalVelocity)
1292 if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
1293 {
1294 _rotationalVelocity = entprop.RotationalVelocity;
1295 // m_log.DebugFormat("{0}: UpdateProperties: rotationalVelocity = {1}", LogHeader, _rotationalVelocity);
1296 changed |= UpdatedProperties.RotationalVel;
1297 }
1298 if (changed != 0)
1299 {
1300 // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
1301 // Only update the position of single objects and linkset roots
1302 if (this._parentPrim == null)
1303 {
1304 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
1305 base.RequestPhysicsterseUpdate();
1306 }
1307 }
1308 } 1280 }
1309 else 1281 // if (_orientation != entprop.Rotation)
1282 if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
1310 { 1283 {
1311 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. 1284 _orientation = entprop.Rotation;
1312 1285 changed |= UpdatedProperties.Rotation;
1313 // Only updates only for individual prims and for the root object of a linkset. 1286 }
1287 // if (_velocity != entprop.Velocity)
1288 if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
1289 {
1290 _velocity = entprop.Velocity;
1291 changed |= UpdatedProperties.Velocity;
1292 }
1293 // if (_acceleration != entprop.Acceleration)
1294 if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
1295 {
1296 _acceleration = entprop.Acceleration;
1297 changed |= UpdatedProperties.Acceleration;
1298 }
1299 // if (_rotationalVelocity != entprop.RotationalVelocity)
1300 if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
1301 {
1302 _rotationalVelocity = entprop.RotationalVelocity;
1303 changed |= UpdatedProperties.RotationalVel;
1304 }
1305 if (changed != 0)
1306 {
1307 // Only update the position of single objects and linkset roots
1314 if (this._parentPrim == null) 1308 if (this._parentPrim == null)
1315 { 1309 {
1316 // Assign to the local variables so the normal set action does not happen
1317 _position = entprop.Position;
1318 _orientation = entprop.Rotation;
1319 _velocity = entprop.Velocity;
1320 _acceleration = entprop.Acceleration;
1321 _rotationalVelocity = entprop.RotationalVelocity;
1322 // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
1323 // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1324 base.RequestPhysicsterseUpdate(); 1310 base.RequestPhysicsterseUpdate();
1325 } 1311 }
1326 } 1312 }
1313 */
1314
1315 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
1316
1317 // Updates only for individual prims and for the root object of a linkset.
1318 if (_linkset.IsRoot(this))
1319 {
1320 // Assign to the local variables so the normal set action does not happen
1321 _position = entprop.Position;
1322 _orientation = entprop.Rotation;
1323 _velocity = entprop.Velocity;
1324 _acceleration = entprop.Acceleration;
1325 _rotationalVelocity = entprop.RotationalVelocity;
1326
1327 // 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);
1329 DetailLog("{0},UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1330 LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
1331
1332 base.RequestPhysicsterseUpdate();
1333 }
1334 else
1335 {
1336 // For debugging, we can also report the movement of children
1337 DetailLog("{0},UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
1338 LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
1339 entprop.Acceleration, entprop.RotationalVelocity);
1340 }
1327 } 1341 }
1328 1342
1329 // I've collided with something 1343 // I've collided with something
@@ -1362,5 +1376,11 @@ public sealed class BSPrim : PhysicsActor
1362 collisionCollection.Clear(); 1376 collisionCollection.Clear();
1363 } 1377 }
1364 } 1378 }
1379
1380 // Invoke the detailed logger and output something if it's enabled.
1381 private void DetailLog(string msg, params Object[] args)
1382 {
1383 Scene.PhysicsLogging.Write(msg, args);
1384 }
1365} 1385}
1366} 1386}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 417cb5f..28d5cb5 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -29,12 +29,14 @@ using System.Collections.Generic;
29using System.Runtime.InteropServices; 29using System.Runtime.InteropServices;
30using System.Text; 30using System.Text;
31using System.Threading; 31using System.Threading;
32using Nini.Config;
33using log4net;
34using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Framework;
34using OpenSim.Region.CoreModules;
35using Logging = OpenSim.Region.CoreModules.Framework.Statistics.Logging;
35using OpenSim.Region.Physics.Manager; 36using OpenSim.Region.Physics.Manager;
37using Nini.Config;
38using log4net;
36using OpenMetaverse; 39using OpenMetaverse;
37using OpenSim.Region.Framework;
38 40
39// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) 41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
40// Debug linkset 42// Debug linkset
@@ -44,15 +46,17 @@ using OpenSim.Region.Framework;
44// Compute physics FPS reasonably 46// Compute physics FPS reasonably
45// Based on material, set density and friction 47// Based on material, set density and friction
46// More efficient memory usage when passing hull information from BSPrim to BulletSim 48// More efficient memory usage when passing hull information from BSPrim to BulletSim
49// Move all logic out of the C++ code and into the C# code for easier future modifications.
47// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? 50// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly?
48// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) 51// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground)
49// At the moment, physical and phantom causes object to drop through the terrain 52// At the moment, physical and phantom causes object to drop through the terrain
50// Physical phantom objects and related typing (collision options ) 53// Physical phantom objects and related typing (collision options )
54// Use collision masks for collision with terrain and phantom objects
51// Check out llVolumeDetect. Must do something for that. 55// Check out llVolumeDetect. Must do something for that.
52// Should prim.link() and prim.delink() membership checking happen at taint time? 56// Should prim.link() and prim.delink() membership checking happen at taint time?
57// changing the position and orientation of a linked prim must rebuild the constraint with the root.
53// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once 58// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
54// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 59// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
55// Use collision masks for collision with terrain and phantom objects
56// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) 60// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
57// Implement LockAngularMotion 61// Implement LockAngularMotion
58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 62// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
@@ -60,9 +64,6 @@ using OpenSim.Region.Framework;
60// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. 64// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet.
61// Add PID movement operations. What does ScenePresence.MoveToTarget do? 65// Add PID movement operations. What does ScenePresence.MoveToTarget do?
62// Check terrain size. 128 or 127? 66// Check terrain size. 128 or 127?
63// Multiple contact points on collision?
64// See code in ode::near... calls to collision_accounting_events()
65// (This might not be a problem. ODE collects all the collisions with one object in one tick.)
66// Raycast 67// Raycast
67// 68//
68namespace OpenSim.Region.Physics.BulletSPlugin 69namespace OpenSim.Region.Physics.BulletSPlugin
@@ -72,6 +73,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
72 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);
73 private static readonly string LogHeader = "[BULLETS SCENE]"; 74 private static readonly string LogHeader = "[BULLETS SCENE]";
74 75
76 public void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); }
77
75 public string BulletSimVersion = "?"; 78 public string BulletSimVersion = "?";
76 79
77 private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); 80 private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>();
@@ -84,6 +87,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
84 private uint m_worldID; 87 private uint m_worldID;
85 public uint WorldID { get { return m_worldID; } } 88 public uint WorldID { get { return m_worldID; } }
86 89
90 // let my minuions use my logger
91 public ILog Logger { get { return m_log; } }
92
87 private bool m_initialized = false; 93 private bool m_initialized = false;
88 94
89 private int m_detailedStatsStep = 0; 95 private int m_detailedStatsStep = 0;
@@ -100,11 +106,24 @@ public class BSScene : PhysicsScene, IPhysicsParameters
100 get { return m_sculptLOD; } 106 get { return m_sculptLOD; }
101 } 107 }
102 108
109 private BulletSim m_worldSim;
110 public BulletSim World
111 {
112 get { return m_worldSim; }
113 }
114 private BSConstraintCollection m_constraintCollection;
115 public BSConstraintCollection Constraints
116 {
117 get { return m_constraintCollection; }
118 }
119
103 private int m_maxSubSteps; 120 private int m_maxSubSteps;
104 private float m_fixedTimeStep; 121 private float m_fixedTimeStep;
105 private long m_simulationStep = 0; 122 private long m_simulationStep = 0;
106 public long SimulationStep { get { return m_simulationStep; } } 123 public long SimulationStep { get { return m_simulationStep; } }
107 124
125 public float LastSimulatedTimestep { get; private set; }
126
108 // A value of the time now so all the collision and update routines do not have to get their own 127 // A value of the time now so all the collision and update routines do not have to get their own
109 // Set to 'now' just before all the prims and actors are called for collisions and updates 128 // Set to 'now' just before all the prims and actors are called for collisions and updates
110 private int m_simulationNowTime; 129 private int m_simulationNowTime;
@@ -121,6 +140,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
121 private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed 140 private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed
122 private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes 141 private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes
123 142
143 public float PID_D { get; private set; } // derivative
144 public float PID_P { get; private set; } // proportional
145
124 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero 146 public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
125 public const uint GROUNDPLANE_ID = 1; 147 public const uint GROUNDPLANE_ID = 1;
126 148
@@ -147,8 +169,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters
147 ConfigurationParameters[] m_params; 169 ConfigurationParameters[] m_params;
148 GCHandle m_paramsHandle; 170 GCHandle m_paramsHandle;
149 171
172 public bool shouldDebugLog { get; private set; }
173
150 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; 174 private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
151 175
176 // Sometimes you just have to log everything.
177 public Logging.LogWriter PhysicsLogging;
178 private bool m_physicsLoggingEnabled;
179 private string m_physicsLoggingDir;
180 private string m_physicsLoggingPrefix;
181 private int m_physicsLoggingFileMinutes;
182
183 private bool m_vehicleLoggingEnabled;
184 public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } }
185
152 public BSScene(string identifier) 186 public BSScene(string identifier)
153 { 187 {
154 m_initialized = false; 188 m_initialized = false;
@@ -169,17 +203,32 @@ public class BSScene : PhysicsScene, IPhysicsParameters
169 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; 203 m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
170 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); 204 m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
171 205
206 // Enable very detailed logging.
207 // By creating an empty logger when not logging, the log message invocation code
208 // can be left in and every call doesn't have to check for null.
209 if (m_physicsLoggingEnabled)
210 {
211 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes);
212 }
213 else
214 {
215 PhysicsLogging = new Logging.LogWriter();
216 }
217
172 // Get the version of the DLL 218 // Get the version of the DLL
173 // TODO: this doesn't work yet. Something wrong with marshaling the returned string. 219 // TODO: this doesn't work yet. Something wrong with marshaling the returned string.
174 // BulletSimVersion = BulletSimAPI.GetVersion(); 220 // BulletSimVersion = BulletSimAPI.GetVersion();
175 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); 221 // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
176 222
177 // if Debug, enable logging from the unmanaged code 223 // if Debug, enable logging from the unmanaged code
178 if (m_log.IsDebugEnabled) 224 if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
179 { 225 {
180 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); 226 m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
181 // the handle is saved to it doesn't get freed after this call 227 if (PhysicsLogging.Enabled)
182 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); 228 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
229 else
230 m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
231 // the handle is saved in a variable to make sure it doesn't get freed after this call
183 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); 232 BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
184 } 233 }
185 234
@@ -194,6 +243,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
194 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), 243 m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
195 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); 244 m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
196 245
246 // 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.
248 m_worldSim = new BulletSim(m_worldID, BulletSimAPI.GetSimHandle2(m_worldID));
249 m_constraintCollection = new BSConstraintCollection(World);
250
197 m_initialized = true; 251 m_initialized = true;
198 } 252 }
199 253
@@ -202,110 +256,27 @@ public class BSScene : PhysicsScene, IPhysicsParameters
202 private void GetInitialParameterValues(IConfigSource config) 256 private void GetInitialParameterValues(IConfigSource config)
203 { 257 {
204 ConfigurationParameters parms = new ConfigurationParameters(); 258 ConfigurationParameters parms = new ConfigurationParameters();
259 m_params[0] = parms;
205 260
206 _meshSculptedPrim = true; // mesh sculpted prims 261 SetParameterDefaultValues();
207 _forceSimplePrimMeshing = false; // use complex meshing if called for
208
209 m_meshLOD = 8f;
210 m_sculptLOD = 32f;
211
212 m_detailedStatsStep = 0; // disabled
213
214 m_maxSubSteps = 10;
215 m_fixedTimeStep = 1f / 60f;
216 m_maxCollisionsPerFrame = 2048;
217 m_maxUpdatesPerFrame = 2048;
218 m_maximumObjectMass = 10000.01f;
219
220 parms.defaultFriction = 0.5f;
221 parms.defaultDensity = 10.000006836f; // Aluminum g/cm3
222 parms.defaultRestitution = 0f;
223 parms.collisionMargin = 0.0f;
224 parms.gravity = -9.80665f;
225
226 parms.linearDamping = 0.0f;
227 parms.angularDamping = 0.0f;
228 parms.deactivationTime = 0.2f;
229 parms.linearSleepingThreshold = 0.8f;
230 parms.angularSleepingThreshold = 1.0f;
231 parms.ccdMotionThreshold = 0.0f; // set to zero to disable
232 parms.ccdSweptSphereRadius = 0.0f;
233 parms.contactProcessingThreshold = 0.1f;
234
235 parms.terrainFriction = 0.5f;
236 parms.terrainHitFraction = 0.8f;
237 parms.terrainRestitution = 0f;
238 parms.avatarFriction = 0.5f;
239 parms.avatarRestitution = 0.0f;
240 parms.avatarDensity = 60f;
241 parms.avatarCapsuleRadius = 0.37f;
242 parms.avatarCapsuleHeight = 1.5f; // 2.140599f
243 parms.avatarContactProcessingThreshold = 0.1f;
244
245 parms.maxPersistantManifoldPoolSize = 0f;
246 parms.shouldDisableContactPoolDynamicAllocation = ConfigurationParameters.numericTrue;
247 parms.shouldForceUpdateAllAabbs = ConfigurationParameters.numericFalse;
248 parms.shouldRandomizeSolverOrder = ConfigurationParameters.numericFalse;
249 parms.shouldSplitSimulationIslands = ConfigurationParameters.numericFalse;
250 parms.shouldEnableFrictionCaching = ConfigurationParameters.numericFalse;
251 parms.numberOfSolverIterations = 0f; // means use default
252 262
253 if (config != null) 263 if (config != null)
254 { 264 {
255 // If there are specifications in the ini file, use those values 265 // If there are specifications in the ini file, use those values
256 // WHEN ADDING OR UPDATING THIS SECTION, BE SURE TO UPDATE OpenSimDefaults.ini
257 // ALSO REMEMBER TO UPDATE THE RUNTIME SETTING OF THE PARAMETERS.
258 IConfig pConfig = config.Configs["BulletSim"]; 266 IConfig pConfig = config.Configs["BulletSim"];
259 if (pConfig != null) 267 if (pConfig != null)
260 { 268 {
261 _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); 269 SetParameterConfigurationValues(pConfig);
262 _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing); 270
263 271 // Very detailed logging for physics debugging
264 m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep); 272 m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
265 m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD); 273 m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
266 m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD); 274 m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-");
267 275 m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
268 m_maxSubSteps = pConfig.GetInt("MaxSubSteps", m_maxSubSteps); 276 // Very detailed logging for vehicle debugging
269 m_fixedTimeStep = pConfig.GetFloat("FixedTimeStep", m_fixedTimeStep); 277 m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
270 m_maxCollisionsPerFrame = pConfig.GetInt("MaxCollisionsPerFrame", m_maxCollisionsPerFrame);
271 m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame);
272 m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass);
273
274 parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction);
275 parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity);
276 parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution);
277 parms.collisionMargin = pConfig.GetFloat("CollisionMargin", parms.collisionMargin);
278 parms.gravity = pConfig.GetFloat("Gravity", parms.gravity);
279
280 parms.linearDamping = pConfig.GetFloat("LinearDamping", parms.linearDamping);
281 parms.angularDamping = pConfig.GetFloat("AngularDamping", parms.angularDamping);
282 parms.deactivationTime = pConfig.GetFloat("DeactivationTime", parms.deactivationTime);
283 parms.linearSleepingThreshold = pConfig.GetFloat("LinearSleepingThreshold", parms.linearSleepingThreshold);
284 parms.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", parms.angularSleepingThreshold);
285 parms.ccdMotionThreshold = pConfig.GetFloat("CcdMotionThreshold", parms.ccdMotionThreshold);
286 parms.ccdSweptSphereRadius = pConfig.GetFloat("CcdSweptSphereRadius", parms.ccdSweptSphereRadius);
287 parms.contactProcessingThreshold = pConfig.GetFloat("ContactProcessingThreshold", parms.contactProcessingThreshold);
288
289 parms.terrainFriction = pConfig.GetFloat("TerrainFriction", parms.terrainFriction);
290 parms.terrainHitFraction = pConfig.GetFloat("TerrainHitFraction", parms.terrainHitFraction);
291 parms.terrainRestitution = pConfig.GetFloat("TerrainRestitution", parms.terrainRestitution);
292 parms.avatarFriction = pConfig.GetFloat("AvatarFriction", parms.avatarFriction);
293 parms.avatarRestitution = pConfig.GetFloat("AvatarRestitution", parms.avatarRestitution);
294 parms.avatarDensity = pConfig.GetFloat("AvatarDensity", parms.avatarDensity);
295 parms.avatarCapsuleRadius = pConfig.GetFloat("AvatarCapsuleRadius", parms.avatarCapsuleRadius);
296 parms.avatarCapsuleHeight = pConfig.GetFloat("AvatarCapsuleHeight", parms.avatarCapsuleHeight);
297 parms.avatarContactProcessingThreshold = pConfig.GetFloat("AvatarContactProcessingThreshold", parms.avatarContactProcessingThreshold);
298
299 parms.maxPersistantManifoldPoolSize = pConfig.GetFloat("MaxPersistantManifoldPoolSize", parms.maxPersistantManifoldPoolSize);
300 parms.shouldDisableContactPoolDynamicAllocation = ParamBoolean(pConfig, "ShouldDisableContactPoolDynamicAllocation", parms.shouldDisableContactPoolDynamicAllocation);
301 parms.shouldForceUpdateAllAabbs = ParamBoolean(pConfig, "ShouldForceUpdateAllAabbs", parms.shouldForceUpdateAllAabbs);
302 parms.shouldRandomizeSolverOrder = ParamBoolean(pConfig, "ShouldRandomizeSolverOrder", parms.shouldRandomizeSolverOrder);
303 parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands);
304 parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching);
305 parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations);
306 } 278 }
307 } 279 }
308 m_params[0] = parms;
309 } 280 }
310 281
311 // A helper function that handles a true/false parameter and returns the proper float number encoding 282 // A helper function that handles a true/false parameter and returns the proper float number encoding
@@ -323,12 +294,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
323 return ret; 294 return ret;
324 } 295 }
325 296
326
327 // Called directly from unmanaged code so don't do much 297 // Called directly from unmanaged code so don't do much
328 private void BulletLogger(string msg) 298 private void BulletLogger(string msg)
329 { 299 {
330 m_log.Debug("[BULLETS UNMANAGED]:" + msg); 300 m_log.Debug("[BULLETS UNMANAGED]:" + msg);
331 } 301 }
302
303 // Called directly from unmanaged code so don't do much
304 private void BulletLoggerPhysLog(string msg)
305 {
306 PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
307 }
332 308
333 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) 309 public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
334 { 310 {
@@ -339,6 +315,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
339 public override PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, bool isFlying) 315 public override PhysicsActor AddAvatar(uint localID, string avName, Vector3 position, Vector3 size, bool isFlying)
340 { 316 {
341 // m_log.DebugFormat("{0}: AddAvatar: {1}", LogHeader, avName); 317 // m_log.DebugFormat("{0}: AddAvatar: {1}", LogHeader, avName);
318
319 if (!m_initialized) return null;
320
342 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); 321 BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
343 lock (m_avatars) m_avatars.Add(localID, actor); 322 lock (m_avatars) m_avatars.Add(localID, actor);
344 return actor; 323 return actor;
@@ -347,34 +326,47 @@ public class BSScene : PhysicsScene, IPhysicsParameters
347 public override void RemoveAvatar(PhysicsActor actor) 326 public override void RemoveAvatar(PhysicsActor actor)
348 { 327 {
349 // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader); 328 // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader);
350 if (actor is BSCharacter) 329
351 { 330 if (!m_initialized) return;
352 ((BSCharacter)actor).Destroy(); 331
353 } 332 BSCharacter bsactor = actor as BSCharacter;
354 try 333 if (bsactor != null)
355 {
356 lock (m_avatars) m_avatars.Remove(actor.LocalID);
357 }
358 catch (Exception e)
359 { 334 {
360 m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e); 335 try
336 {
337 lock (m_avatars) m_avatars.Remove(actor.LocalID);
338 }
339 catch (Exception e)
340 {
341 m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e);
342 }
343 bsactor.Destroy();
344 // bsactor.dispose();
361 } 345 }
362 } 346 }
363 347
364 public override void RemovePrim(PhysicsActor prim) 348 public override void RemovePrim(PhysicsActor prim)
365 { 349 {
366 // m_log.DebugFormat("{0}: RemovePrim", LogHeader); 350 if (!m_initialized) return;
367 if (prim is BSPrim) 351
368 { 352 BSPrim bsprim = prim as BSPrim;
369 ((BSPrim)prim).Destroy(); 353 if (bsprim != null)
370 }
371 try
372 { 354 {
373 lock (m_prims) m_prims.Remove(prim.LocalID); 355 m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
356 try
357 {
358 lock (m_prims) m_prims.Remove(bsprim.LocalID);
359 }
360 catch (Exception e)
361 {
362 m_log.ErrorFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e);
363 }
364 bsprim.Destroy();
365 // bsprim.dispose();
374 } 366 }
375 catch (Exception e) 367 else
376 { 368 {
377 m_log.WarnFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e); 369 m_log.ErrorFormat("{0}: Attempt to remove prim that is not a BSPrim type.", LogHeader);
378 } 370 }
379 } 371 }
380 372
@@ -382,6 +374,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
382 Vector3 size, Quaternion rotation, bool isPhysical, uint localID) 374 Vector3 size, Quaternion rotation, bool isPhysical, uint localID)
383 { 375 {
384 // m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName); 376 // m_log.DebugFormat("{0}: AddPrimShape2: {1}", LogHeader, primName);
377
378 if (!m_initialized) return null;
379
385 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); 380 BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
386 lock (m_prims) m_prims.Add(localID, prim); 381 lock (m_prims) m_prims.Add(localID, prim);
387 return prim; 382 return prim;
@@ -400,6 +395,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
400 int collidersCount; 395 int collidersCount;
401 IntPtr collidersPtr; 396 IntPtr collidersPtr;
402 397
398 LastSimulatedTimestep = timeStep;
399
403 // prevent simulation until we've been initialized 400 // prevent simulation until we've been initialized
404 if (!m_initialized) return 10.0f; 401 if (!m_initialized) return 10.0f;
405 402
@@ -459,7 +456,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
459 for (int ii = 0; ii < updatedEntityCount; ii++) 456 for (int ii = 0; ii < updatedEntityCount; ii++)
460 { 457 {
461 EntityProperties entprop = m_updateArray[ii]; 458 EntityProperties entprop = m_updateArray[ii];
462 // m_log.DebugFormat("{0}: entprop[{1}]: id={2}, pos={3}", LogHeader, ii, entprop.ID, entprop.Position);
463 BSPrim prim; 459 BSPrim prim;
464 if (m_prims.TryGetValue(entprop.ID, out prim)) 460 if (m_prims.TryGetValue(entprop.ID, out prim))
465 { 461 {
@@ -532,8 +528,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters
532 }); 528 });
533 } 529 }
534 530
531 // Someday we will have complex terrain with caves and tunnels
532 // For the moment, it's flat and convex
533 public float GetTerrainHeightAtXYZ(Vector3 loc)
534 {
535 return GetTerrainHeightAtXY(loc.X, loc.Y);
536 }
537
535 public float GetTerrainHeightAtXY(float tX, float tY) 538 public float GetTerrainHeightAtXY(float tX, float tY)
536 { 539 {
540 if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize)
541 return 30;
537 return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)]; 542 return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)];
538 } 543 }
539 544
@@ -555,6 +560,33 @@ public class BSScene : PhysicsScene, IPhysicsParameters
555 public override void Dispose() 560 public override void Dispose()
556 { 561 {
557 // m_log.DebugFormat("{0}: Dispose()", LogHeader); 562 // m_log.DebugFormat("{0}: Dispose()", LogHeader);
563
564 // make sure no stepping happens while we're deleting stuff
565 m_initialized = false;
566
567 if (m_constraintCollection != null)
568 {
569 m_constraintCollection.Dispose();
570 m_constraintCollection = null;
571 }
572
573 foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
574 {
575 kvp.Value.Destroy();
576 }
577 m_avatars.Clear();
578
579 foreach (KeyValuePair<uint, BSPrim> kvp in m_prims)
580 {
581 kvp.Value.Destroy();
582 }
583 m_prims.Clear();
584
585 // Anything left in the unmanaged code should be cleaned out
586 BulletSimAPI.Shutdown(WorldID);
587
588 // Not logging any more
589 PhysicsLogging.Close();
558 } 590 }
559 591
560 public override Dictionary<uint, float> GetTopColliders() 592 public override Dictionary<uint, float> GetTopColliders()
@@ -680,10 +712,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
680 } 712 }
681 713
682 // The calls to the PhysicsActors can't directly call into the physics engine 714 // The calls to the PhysicsActors can't directly call into the physics engine
683 // because it might be busy. We we delay changes to a known time. 715 // because it might be busy. We delay changes to a known time.
684 // We rely on C#'s closure to save and restore the context for the delegate. 716 // We rely on C#'s closure to save and restore the context for the delegate.
685 public void TaintedObject(TaintCallback callback) 717 public void TaintedObject(TaintCallback callback)
686 { 718 {
719 if (!m_initialized) return;
720
687 lock (_taintLock) 721 lock (_taintLock)
688 _taintedObjects.Add(callback); 722 _taintedObjects.Add(callback);
689 return; 723 return;
@@ -757,61 +791,392 @@ public class BSScene : PhysicsScene, IPhysicsParameters
757 } 791 }
758 #endregion Vehicles 792 #endregion Vehicles
759 793
760 #region Runtime settable parameters 794 #region Parameters
761 public static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[] 795
762 { 796 delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
763 new PhysParameterEntry("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)"), 797 delegate float ParamGet(BSScene scene);
764 new PhysParameterEntry("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)"), 798 delegate void ParamSet(BSScene scene, string paramName, uint localID, float val);
765 new PhysParameterEntry("MaxSubStep", "In simulation step, maximum number of substeps"), 799
766 new PhysParameterEntry("FixedTimeStep", "In simulation step, seconds of one substep (1/60)"), 800 private struct ParameterDefn
767 new PhysParameterEntry("MaxObjectMass", "Maximum object mass (10000.01)"), 801 {
768 new PhysParameterEntry("DetailedStats", "Frames between outputting detailed phys stats. Zero is off"), 802 public string name;
769 803 public string desc;
770 new PhysParameterEntry("DefaultFriction", "Friction factor used on new objects"), 804 public float defaultValue;
771 new PhysParameterEntry("DefaultDensity", "Density for new objects" ), 805 public ParamUser userParam;
772 new PhysParameterEntry("DefaultRestitution", "Bouncyness of an object" ), 806 public ParamGet getter;
773 // new PhysParameterEntry("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!!)" ), 807 public ParamSet setter;
774 new PhysParameterEntry("Gravity", "Vertical force of gravity (negative means down)" ), 808 public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
775 809 {
776 new PhysParameterEntry("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)" ), 810 name = n;
777 new PhysParameterEntry("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)" ), 811 desc = d;
778 new PhysParameterEntry("DeactivationTime", "Seconds before considering an object potentially static" ), 812 defaultValue = v;
779 new PhysParameterEntry("LinearSleepingThreshold", "Seconds to measure linear movement before considering static" ), 813 userParam = u;
780 new PhysParameterEntry("AngularSleepingThreshold", "Seconds to measure angular movement before considering static" ), 814 getter = g;
781 new PhysParameterEntry("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ), 815 setter = s;
782 new PhysParameterEntry("CcdSweptSphereRadius", "Continuious collision detection test radius" ), 816 }
783 new PhysParameterEntry("ContactProcessingThreshold", "Distance between contacts before doing collision check" ), 817 }
784 // Can only change the following at initialization time. Change the INI file and reboot. 818
785 new PhysParameterEntry("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)"), 819 // List of all of the externally visible parameters.
786 new PhysParameterEntry("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count"), 820 // For each parameter, this table maps a text name to getter and setters.
787 new PhysParameterEntry("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step"), 821 // To add a new externally referencable/settable parameter, add the paramter storage
788 new PhysParameterEntry("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction"), 822 // location somewhere in the program and make an entry in this table with the
789 new PhysParameterEntry("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands"), 823 // getters and setters.
790 new PhysParameterEntry("ShouldEnableFrictionCaching", "Enable friction computation caching"), 824 // To add a new variable, it is easiest to find an existing definition and copy it.
791 new PhysParameterEntry("NumberOfSolverIterations", "Number of internal iterations (0 means default)"), 825 // Parameter values are floats. Booleans are converted to a floating value.
792 826 //
793 new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ), 827 // A ParameterDefn() takes the following parameters:
794 new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ), 828 // -- the text name of the parameter. This is used for console input and ini file.
795 829 // -- a short text description of the parameter. This shows up in the console listing.
796 new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ), 830 // -- a delegate for fetching the parameter from the ini file.
797 new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ), 831 // Should handle fetching the right type from the ini file and converting it.
798 832 // -- a delegate for getting the value as a float
799 new PhysParameterEntry("TerrainFriction", "Factor to reduce movement against terrain surface" ), 833 // -- a delegate for setting the value from a float
800 new PhysParameterEntry("TerrainHitFraction", "Distance to measure hit collisions" ), 834 //
801 new PhysParameterEntry("TerrainRestitution", "Bouncyness" ), 835 // The single letter parameters for the delegates are:
802 new PhysParameterEntry("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation." ), 836 // s = BSScene
803 new PhysParameterEntry("AvatarDensity", "Density of an avatar. Changed on avatar recreation." ), 837 // p = string parameter name
804 new PhysParameterEntry("AvatarRestitution", "Bouncyness. Changed on avatar recreation." ), 838 // l = localID of referenced object
805 new PhysParameterEntry("AvatarCapsuleRadius", "Radius of space around an avatar" ), 839 // v = float value
806 new PhysParameterEntry("AvatarCapsuleHeight", "Default height of space around avatar" ), 840 // cf = parameter configuration class (for fetching values from ini file)
807 new PhysParameterEntry("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions") 841 private ParameterDefn[] ParameterDefinitions =
842 {
843 new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties",
844 ConfigurationParameters.numericTrue,
845 (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); },
846 (s) => { return s.NumericBool(s._meshSculptedPrim); },
847 (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ),
848 new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects",
849 ConfigurationParameters.numericFalse,
850 (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); },
851 (s) => { return s.NumericBool(s._forceSimplePrimMeshing); },
852 (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ),
853
854 new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
855 8f,
856 (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); },
857 (s) => { return (float)s.m_meshLOD; },
858 (s,p,l,v) => { s.m_meshLOD = (int)v; } ),
859 new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
860 32,
861 (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); },
862 (s) => { return (float)s.m_sculptLOD; },
863 (s,p,l,v) => { s.m_sculptLOD = (int)v; } ),
864
865 new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
866 10f,
867 (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); },
868 (s) => { return (float)s.m_maxSubSteps; },
869 (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ),
870 new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)",
871 1f / 60f,
872 (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); },
873 (s) => { return (float)s.m_fixedTimeStep; },
874 (s,p,l,v) => { s.m_fixedTimeStep = v; } ),
875 new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame",
876 2048f,
877 (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); },
878 (s) => { return (float)s.m_maxCollisionsPerFrame; },
879 (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ),
880 new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame",
881 8000f,
882 (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); },
883 (s) => { return (float)s.m_maxUpdatesPerFrame; },
884 (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
885 new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
886 10000.01f,
887 (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); },
888 (s) => { return (float)s.m_maximumObjectMass; },
889 (s,p,l,v) => { s.m_maximumObjectMass = v; } ),
890
891 new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
892 2200f,
893 (s,cf,p,v) => { s.PID_D = cf.GetFloat(p, v); },
894 (s) => { return (float)s.PID_D; },
895 (s,p,l,v) => { s.PID_D = v; } ),
896 new ParameterDefn("PID_P", "Parameteric factor for motion smoothing",
897 900f,
898 (s,cf,p,v) => { s.PID_P = cf.GetFloat(p, v); },
899 (s) => { return (float)s.PID_P; },
900 (s,p,l,v) => { s.PID_P = v; } ),
901
902 new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
903 0.5f,
904 (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); },
905 (s) => { return s.m_params[0].defaultFriction; },
906 (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ),
907 new ParameterDefn("DefaultDensity", "Density for new objects" ,
908 10.000006836f, // Aluminum g/cm3
909 (s,cf,p,v) => { s.m_params[0].defaultDensity = cf.GetFloat(p, v); },
910 (s) => { return s.m_params[0].defaultDensity; },
911 (s,p,l,v) => { s.m_params[0].defaultDensity = v; } ),
912 new ParameterDefn("DefaultRestitution", "Bouncyness of an object" ,
913 0f,
914 (s,cf,p,v) => { s.m_params[0].defaultRestitution = cf.GetFloat(p, v); },
915 (s) => { return s.m_params[0].defaultRestitution; },
916 (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ),
917 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
918 0f,
919 (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); },
920 (s) => { return s.m_params[0].collisionMargin; },
921 (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ),
922 new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)",
923 -9.80665f,
924 (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); },
925 (s) => { return s.m_params[0].gravity; },
926 (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ),
927
928
929 new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)",
930 0f,
931 (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
932 (s) => { return s.m_params[0].linearDamping; },
933 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ),
934 new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
935 0f,
936 (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
937 (s) => { return s.m_params[0].angularDamping; },
938 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ),
939 new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
940 0.2f,
941 (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
942 (s) => { return s.m_params[0].deactivationTime; },
943 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ),
944 new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
945 0.8f,
946 (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
947 (s) => { return s.m_params[0].linearSleepingThreshold; },
948 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
949 new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
950 1.0f,
951 (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
952 (s) => { return s.m_params[0].angularSleepingThreshold; },
953 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
954 new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
955 0f, // set to zero to disable
956 (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
957 (s) => { return s.m_params[0].ccdMotionThreshold; },
958 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
959 new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
960 0f,
961 (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
962 (s) => { return s.m_params[0].ccdSweptSphereRadius; },
963 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
964 new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
965 0.1f,
966 (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
967 (s) => { return s.m_params[0].contactProcessingThreshold; },
968 (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
969
970 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
971 0.5f,
972 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
973 (s) => { return s.m_params[0].terrainFriction; },
974 (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ),
975 new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" ,
976 0.8f,
977 (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); },
978 (s) => { return s.m_params[0].terrainHitFraction; },
979 (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ),
980 new ParameterDefn("TerrainRestitution", "Bouncyness" ,
981 0f,
982 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
983 (s) => { return s.m_params[0].terrainRestitution; },
984 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
985 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
986 0.5f,
987 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
988 (s) => { return s.m_params[0].avatarFriction; },
989 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ),
990 new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
991 60f,
992 (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
993 (s) => { return s.m_params[0].avatarDensity; },
994 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ),
995 new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
996 0f,
997 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
998 (s) => { return s.m_params[0].avatarRestitution; },
999 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ),
1000 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
1001 0.37f,
1002 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
1003 (s) => { return s.m_params[0].avatarCapsuleRadius; },
1004 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
1005 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
1006 1.5f,
1007 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
1008 (s) => { return s.m_params[0].avatarCapsuleHeight; },
1009 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
1010 new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
1011 0.1f,
1012 (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
1013 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
1014 (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1015
1016
1017 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)",
1018 0f, // zero to disable
1019 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
1020 (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
1021 (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
1022 new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
1023 ConfigurationParameters.numericTrue,
1024 (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1025 (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; },
1026 (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ),
1027 new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
1028 ConfigurationParameters.numericFalse,
1029 (s,cf,p,v) => { s.m_params[0].shouldForceUpdateAllAabbs = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1030 (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; },
1031 (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ),
1032 new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction",
1033 ConfigurationParameters.numericFalse,
1034 (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1035 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
1036 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
1037 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
1038 ConfigurationParameters.numericFalse,
1039 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1040 (s) => { return s.m_params[0].shouldSplitSimulationIslands; },
1041 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ),
1042 new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching",
1043 ConfigurationParameters.numericFalse,
1044 (s,cf,p,v) => { s.m_params[0].shouldEnableFrictionCaching = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1045 (s) => { return s.m_params[0].shouldEnableFrictionCaching; },
1046 (s,p,l,v) => { s.m_params[0].shouldEnableFrictionCaching = v; } ),
1047 new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)",
1048 0f, // zero says use Bullet default
1049 (s,cf,p,v) => { s.m_params[0].numberOfSolverIterations = cf.GetFloat(p, v); },
1050 (s) => { return s.m_params[0].numberOfSolverIterations; },
1051 (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ),
1052
1053 new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.",
1054 ConfigurationParameters.numericFalse,
1055 (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1056 (s) => { return s.m_params[0].linkConstraintUseFrameOffset; },
1057 (s,p,l,v) => { s.m_params[0].linkConstraintUseFrameOffset = v; } ),
1058 new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints",
1059 ConfigurationParameters.numericTrue,
1060 (s,cf,p,v) => { s.m_params[0].linkConstraintEnableTransMotor = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1061 (s) => { return s.m_params[0].linkConstraintEnableTransMotor; },
1062 (s,p,l,v) => { s.m_params[0].linkConstraintEnableTransMotor = v; } ),
1063 new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints",
1064 5.0f,
1065 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = cf.GetFloat(p, v); },
1066 (s) => { return s.m_params[0].linkConstraintTransMotorMaxVel; },
1067 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = v; } ),
1068 new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints",
1069 0.1f,
1070 (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); },
1071 (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; },
1072 (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ),
1073 new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0",
1074 0.0f,
1075 (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); },
1076 (s) => { return s.m_params[0].linkConstraintCFM; },
1077 (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ),
1078 new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2",
1079 0.2f,
1080 (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); },
1081 (s) => { return s.m_params[0].linkConstraintERP; },
1082 (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ),
1083
1084 new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)",
1085 0f,
1086 (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); },
1087 (s) => { return (float)s.m_detailedStatsStep; },
1088 (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
1089 new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
1090 ConfigurationParameters.numericFalse,
1091 (s,cf,p,v) => { s.shouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
1092 (s) => { return s.NumericBool(s.shouldDebugLog); },
1093 (s,p,l,v) => { s.shouldDebugLog = s.BoolNumeric(v); } ),
808 1094
809 }; 1095 };
810 1096
1097 // Convert a boolean to our numeric true and false values
1098 public float NumericBool(bool b)
1099 {
1100 return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse);
1101 }
1102
1103 // Convert numeric true and false values to a boolean
1104 public bool BoolNumeric(float b)
1105 {
1106 return (b == ConfigurationParameters.numericTrue ? true : false);
1107 }
1108
1109 // Search through the parameter definitions and return the matching
1110 // ParameterDefn structure.
1111 // Case does not matter as names are compared after converting to lower case.
1112 // Returns 'false' if the parameter is not found.
1113 private bool TryGetParameter(string paramName, out ParameterDefn defn)
1114 {
1115 bool ret = false;
1116 ParameterDefn foundDefn = new ParameterDefn();
1117 string pName = paramName.ToLower();
1118
1119 foreach (ParameterDefn parm in ParameterDefinitions)
1120 {
1121 if (pName == parm.name.ToLower())
1122 {
1123 foundDefn = parm;
1124 ret = true;
1125 break;
1126 }
1127 }
1128 defn = foundDefn;
1129 return ret;
1130 }
1131
1132 // Pass through the settable parameters and set the default values
1133 private void SetParameterDefaultValues()
1134 {
1135 foreach (ParameterDefn parm in ParameterDefinitions)
1136 {
1137 parm.setter(this, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue);
1138 }
1139 }
1140
1141 // Get user set values out of the ini file.
1142 private void SetParameterConfigurationValues(IConfig cfg)
1143 {
1144 foreach (ParameterDefn parm in ParameterDefinitions)
1145 {
1146 parm.userParam(this, cfg, parm.name, parm.defaultValue);
1147 }
1148 }
1149
1150 private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
1151
1152 private void BuildParameterTable()
1153 {
1154 if (SettableParameters.Length < ParameterDefinitions.Length)
1155 {
1156
1157 List<PhysParameterEntry> entries = new List<PhysParameterEntry>();
1158 for (int ii = 0; ii < ParameterDefinitions.Length; ii++)
1159 {
1160 ParameterDefn pd = ParameterDefinitions[ii];
1161 entries.Add(new PhysParameterEntry(pd.name, pd.desc));
1162 }
1163
1164 // make the list in alphabetical order for estetic reasons
1165 entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2)
1166 {
1167 return ppe1.name.CompareTo(ppe2.name);
1168 });
1169
1170 SettableParameters = entries.ToArray();
1171 }
1172 }
1173
1174
811 #region IPhysicsParameters 1175 #region IPhysicsParameters
812 // Get the list of parameters this physics engine supports 1176 // Get the list of parameters this physics engine supports
813 public PhysParameterEntry[] GetParameterList() 1177 public PhysParameterEntry[] GetParameterList()
814 { 1178 {
1179 BuildParameterTable();
815 return SettableParameters; 1180 return SettableParameters;
816 } 1181 }
817 1182
@@ -823,63 +1188,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
823 // value activated ('terrainFriction' for instance). 1188 // value activated ('terrainFriction' for instance).
824 public bool SetPhysicsParameter(string parm, float val, uint localID) 1189 public bool SetPhysicsParameter(string parm, float val, uint localID)
825 { 1190 {
826 bool ret = true; 1191 bool ret = false;
827 string lparm = parm.ToLower(); 1192 ParameterDefn theParam;
828 switch (lparm) 1193 if (TryGetParameter(parm, out theParam))
829 { 1194 {
830 case "detailedstats": m_detailedStatsStep = (int)val; break; 1195 theParam.setter(this, parm, localID, val);
831 1196 ret = true;
832 case "meshlod": m_meshLOD = (int)val; break;
833 case "sculptlod": m_sculptLOD = (int)val; break;
834 case "maxsubstep": m_maxSubSteps = (int)val; break;
835 case "fixedtimestep": m_fixedTimeStep = val; break;
836 case "maxobjectmass": m_maximumObjectMass = val; break;
837
838 case "defaultfriction": m_params[0].defaultFriction = val; break;
839 case "defaultdensity": m_params[0].defaultDensity = val; break;
840 case "defaultrestitution": m_params[0].defaultRestitution = val; break;
841 case "collisionmargin": m_params[0].collisionMargin = val; break;
842 case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, localID, val); break;
843
844 case "lineardamping": UpdateParameterPrims(ref m_params[0].linearDamping, lparm, localID, val); break;
845 case "angulardamping": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break;
846 case "deactivationtime": UpdateParameterPrims(ref m_params[0].deactivationTime, lparm, localID, val); break;
847 case "linearsleepingthreshold": UpdateParameterPrims(ref m_params[0].linearSleepingThreshold, lparm, localID, val); break;
848 case "angularsleepingthreshold": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break;
849 case "ccdmotionthreshold": UpdateParameterPrims(ref m_params[0].ccdMotionThreshold, lparm, localID, val); break;
850 case "ccdsweptsphereradius": UpdateParameterPrims(ref m_params[0].ccdSweptSphereRadius, lparm, localID, val); break;
851 case "contactprocessingthreshold": UpdateParameterPrims(ref m_params[0].contactProcessingThreshold, lparm, localID, val); break;
852 // the following are used only at initialization time so setting them makes no sense
853 // case "maxPersistantmanifoldpoolSize": m_params[0].maxPersistantManifoldPoolSize = val; break;
854 // case "shoulddisablecontactpooldynamicallocation": m_params[0].shouldDisableContactPoolDynamicAllocation = val; break;
855 // case "shouldforceupdateallaabbs": m_params[0].shouldForceUpdateAllAabbs = val; break;
856 // case "shouldrandomizesolverorder": m_params[0].shouldRandomizeSolverOrder = val; break;
857 // case "shouldsplitsimulationislands": m_params[0].shouldSplitSimulationIslands = val; break;
858 // case "shouldenablefrictioncaching": m_params[0].shouldEnableFrictionCaching = val; break;
859 // case "numberofsolveriterations": m_params[0].numberOfSolverIterations = val; break;
860
861 case "friction": TaintedUpdateParameter(lparm, localID, val); break;
862 case "restitution": TaintedUpdateParameter(lparm, localID, val); break;
863
864 // set a terrain physical feature and cause terrain to be recalculated
865 case "terrainfriction": m_params[0].terrainFriction = val; TaintedUpdateParameter("terrain", 0, val); break;
866 case "terrainhitfraction": m_params[0].terrainHitFraction = val; TaintedUpdateParameter("terrain", 0, val); break;
867 case "terrainrestitution": m_params[0].terrainRestitution = val; TaintedUpdateParameter("terrain", 0, val); break;
868 // set an avatar physical feature and cause avatar(s) to be recalculated
869 case "avatarfriction": UpdateParameterAvatars(ref m_params[0].avatarFriction, "avatar", localID, val); break;
870 case "avatardensity": UpdateParameterAvatars(ref m_params[0].avatarDensity, "avatar", localID, val); break;
871 case "avatarrestitution": UpdateParameterAvatars(ref m_params[0].avatarRestitution, "avatar", localID, val); break;
872 case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break;
873 case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break;
874 case "avatarcontactprocessingthreshold": UpdateParameterAvatars(ref m_params[0].avatarContactProcessingThreshold, "avatar", localID, val); break;
875
876 default: ret = false; break;
877 } 1197 }
878 return ret; 1198 return ret;
879 } 1199 }
880 1200
881 // check to see if we are updating a parameter for a particular or all of the prims 1201 // check to see if we are updating a parameter for a particular or all of the prims
882 private void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) 1202 protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val)
883 { 1203 {
884 List<uint> operateOn; 1204 List<uint> operateOn;
885 lock (m_prims) operateOn = new List<uint>(m_prims.Keys); 1205 lock (m_prims) operateOn = new List<uint>(m_prims.Keys);
@@ -887,7 +1207,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
887 } 1207 }
888 1208
889 // check to see if we are updating a parameter for a particular or all of the avatars 1209 // check to see if we are updating a parameter for a particular or all of the avatars
890 private void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val) 1210 protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
891 { 1211 {
892 List<uint> operateOn; 1212 List<uint> operateOn;
893 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys); 1213 lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys);
@@ -898,7 +1218,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
898 // If the local ID is APPLY_TO_NONE, just change the default value 1218 // If the local ID is APPLY_TO_NONE, just change the default value
899 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs 1219 // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs
900 // If the localID is a specific object, apply the parameter change to only that object 1220 // If the localID is a specific object, apply the parameter change to only that object
901 private void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val) 1221 protected void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val)
902 { 1222 {
903 switch (localID) 1223 switch (localID)
904 { 1224 {
@@ -925,7 +1245,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
925 } 1245 }
926 1246
927 // schedule the actual updating of the paramter to when the phys engine is not busy 1247 // schedule the actual updating of the paramter to when the phys engine is not busy
928 private void TaintedUpdateParameter(string parm, uint localID, float val) 1248 protected void TaintedUpdateParameter(string parm, uint localID, float val)
929 { 1249 {
930 uint xlocalID = localID; 1250 uint xlocalID = localID;
931 string xparm = parm.ToLower(); 1251 string xparm = parm.ToLower();
@@ -940,50 +1260,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
940 public bool GetPhysicsParameter(string parm, out float value) 1260 public bool GetPhysicsParameter(string parm, out float value)
941 { 1261 {
942 float val = 0f; 1262 float val = 0f;
943 bool ret = true; 1263 bool ret = false;
944 switch (parm.ToLower()) 1264 ParameterDefn theParam;
945 { 1265 if (TryGetParameter(parm, out theParam))
946 case "detailedstats": val = (int)m_detailedStatsStep; break; 1266 {
947 case "meshlod": val = (float)m_meshLOD; break; 1267 val = theParam.getter(this);
948 case "sculptlod": val = (float)m_sculptLOD; break; 1268 ret = true;
949 case "maxsubstep": val = (float)m_maxSubSteps; break;
950 case "fixedtimestep": val = m_fixedTimeStep; break;
951 case "maxobjectmass": val = m_maximumObjectMass; break;
952
953 case "defaultfriction": val = m_params[0].defaultFriction; break;
954 case "defaultdensity": val = m_params[0].defaultDensity; break;
955 case "defaultrestitution": val = m_params[0].defaultRestitution; break;
956 case "collisionmargin": val = m_params[0].collisionMargin; break;
957 case "gravity": val = m_params[0].gravity; break;
958
959 case "lineardamping": val = m_params[0].linearDamping; break;
960 case "angulardamping": val = m_params[0].angularDamping; break;
961 case "deactivationtime": val = m_params[0].deactivationTime; break;
962 case "linearsleepingthreshold": val = m_params[0].linearSleepingThreshold; break;
963 case "angularsleepingthreshold": val = m_params[0].angularDamping; break;
964 case "ccdmotionthreshold": val = m_params[0].ccdMotionThreshold; break;
965 case "ccdsweptsphereradius": val = m_params[0].ccdSweptSphereRadius; break;
966 case "contactprocessingthreshold": val = m_params[0].contactProcessingThreshold; break;
967 case "maxPersistantmanifoldpoolSize": val = m_params[0].maxPersistantManifoldPoolSize; break;
968 case "shoulddisablecontactpooldynamicallocation": val = m_params[0].shouldDisableContactPoolDynamicAllocation; break;
969 case "shouldforceupdateallaabbs": val = m_params[0].shouldForceUpdateAllAabbs; break;
970 case "shouldrandomizesolverorder": val = m_params[0].shouldRandomizeSolverOrder; break;
971 case "shouldsplitsimulationislands": val = m_params[0].shouldSplitSimulationIslands; break;
972 case "shouldenablefrictioncaching": val = m_params[0].shouldEnableFrictionCaching; break;
973 case "numberofsolveriterations": val = m_params[0].numberOfSolverIterations; break;
974
975 case "terrainfriction": val = m_params[0].terrainFriction; break;
976 case "terrainhitfraction": val = m_params[0].terrainHitFraction; break;
977 case "terrainrestitution": val = m_params[0].terrainRestitution; break;
978
979 case "avatarfriction": val = m_params[0].avatarFriction; break;
980 case "avatardensity": val = m_params[0].avatarDensity; break;
981 case "avatarrestitution": val = m_params[0].avatarRestitution; break;
982 case "avatarcapsuleradius": val = m_params[0].avatarCapsuleRadius; break;
983 case "avatarcapsuleheight": val = m_params[0].avatarCapsuleHeight; break;
984 case "avatarcontactprocessingthreshold": val = m_params[0].avatarContactProcessingThreshold; break;
985 default: ret = false; break;
986
987 } 1269 }
988 value = val; 1270 value = val;
989 return ret; 1271 return ret;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 086f0dc..0ffbc94 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -32,6 +32,28 @@ using OpenMetaverse;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin { 33namespace OpenSim.Region.Physics.BulletSPlugin {
34 34
35// Classes to allow some type checking for the API
36public struct BulletSim
37{
38 public BulletSim(uint id, IntPtr xx) { ID = id; Ptr = xx; }
39 public IntPtr Ptr;
40 public uint ID;
41}
42
43public struct BulletBody
44{
45 public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; }
46 public IntPtr Ptr;
47 public uint ID;
48}
49
50public struct BulletConstraint
51{
52 public BulletConstraint(IntPtr xx) { Ptr = xx; }
53 public IntPtr Ptr;
54}
55
56// ===============================================================================
35[StructLayout(LayoutKind.Sequential)] 57[StructLayout(LayoutKind.Sequential)]
36public struct ConvexHull 58public struct ConvexHull
37{ 59{
@@ -44,13 +66,14 @@ public struct ShapeData
44{ 66{
45 public enum PhysicsShapeType 67 public enum PhysicsShapeType
46 { 68 {
47 SHAPE_AVATAR = 0, 69 SHAPE_UNKNOWN = 0,
48 SHAPE_BOX = 1, 70 SHAPE_AVATAR = 1,
49 SHAPE_CONE = 2, 71 SHAPE_BOX = 2,
50 SHAPE_CYLINDER = 3, 72 SHAPE_CONE = 3,
51 SHAPE_SPHERE = 4, 73 SHAPE_CYLINDER = 4,
52 SHAPE_MESH = 5, 74 SHAPE_SPHERE = 5,
53 SHAPE_HULL = 6 75 SHAPE_MESH = 6,
76 SHAPE_HULL = 7
54 }; 77 };
55 public uint ID; 78 public uint ID;
56 public PhysicsShapeType Type; 79 public PhysicsShapeType Type;
@@ -64,12 +87,12 @@ public struct ShapeData
64 public System.UInt64 MeshKey; 87 public System.UInt64 MeshKey;
65 public float Friction; 88 public float Friction;
66 public float Restitution; 89 public float Restitution;
67 public int Collidable; 90 public float Collidable; // true of things bump into this
68 public int Static; // true if a static object. Otherwise gravity, etc. 91 public float Static; // true if a static object. Otherwise gravity, etc.
69 92
70 // note that bools are passed as ints since bool size changes by language and architecture 93 // note that bools are passed as floats since bool size changes by language and architecture
71 public const int numericTrue = 1; 94 public const float numericTrue = 1f;
72 public const int numericFalse = 0; 95 public const float numericFalse = 0f;
73} 96}
74[StructLayout(LayoutKind.Sequential)] 97[StructLayout(LayoutKind.Sequential)]
75public struct SweepHit 98public struct SweepHit
@@ -142,10 +165,56 @@ public struct ConfigurationParameters
142 public float shouldEnableFrictionCaching; 165 public float shouldEnableFrictionCaching;
143 public float numberOfSolverIterations; 166 public float numberOfSolverIterations;
144 167
168 public float linkConstraintUseFrameOffset;
169 public float linkConstraintEnableTransMotor;
170 public float linkConstraintTransMotorMaxVel;
171 public float linkConstraintTransMotorMaxForce;
172 public float linkConstraintERP;
173 public float linkConstraintCFM;
174
145 public const float numericTrue = 1f; 175 public const float numericTrue = 1f;
146 public const float numericFalse = 0f; 176 public const float numericFalse = 0f;
147} 177}
148 178
179// Values used by Bullet and BulletSim to control collisions
180public enum CollisionFlags : uint
181{
182 STATIC_OBJECT = 1 << 0,
183 KINEMATIC_OBJECT = 1 << 1,
184 NO_CONTACT_RESPONSE = 1 << 2,
185 CUSTOM_MATERIAL_CALLBACK = 1 << 3,
186 CHARACTER_OBJECT = 1 << 4,
187 DISABLE_VISUALIZE_OBJECT = 1 << 5,
188 DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
189 // Following used by BulletSim to control collisions
190 VOLUME_DETECT_OBJECT = 1 << 10,
191 PHANTOM_OBJECT = 1 << 11,
192 PHYSICAL_OBJECT = 1 << 12,
193};
194
195// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
196// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2.
197public enum ConstraintParams : int
198{
199 BT_CONSTRAINT_ERP = 1, // this one is not used in Bullet as of 20120730
200 BT_CONSTRAINT_STOP_ERP,
201 BT_CONSTRAINT_CFM,
202 BT_CONSTRAINT_STOP_CFM,
203};
204public enum ConstraintParamAxis : int
205{
206 AXIS_LINEAR_X = 0,
207 AXIS_LINEAR_Y,
208 AXIS_LINEAR_Z,
209 AXIS_ANGULAR_X,
210 AXIS_ANGULAR_Y,
211 AXIS_ANGULAR_Z,
212 AXIS_LINEAR_ALL = 20, // these last three added by BulletSim so we don't have to do zillions of calls
213 AXIS_ANGULAR_ALL,
214 AXIS_ALL
215};
216
217// ===============================================================================
149static class BulletSimAPI { 218static class BulletSimAPI {
150 219
151[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 220[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -195,6 +264,7 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey);
195[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 264[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
196public static extern bool CreateObject(uint worldID, ShapeData shapeData); 265public static extern bool CreateObject(uint worldID, ShapeData shapeData);
197 266
267/* Remove old functionality
198[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 268[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
199public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); 269public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas);
200 270
@@ -209,11 +279,15 @@ public static extern bool RemoveConstraintByID(uint worldID, uint id1);
209 279
210[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 280[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
211public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); 281public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2);
282 */
212 283
213[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 284[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
214public static extern Vector3 GetObjectPosition(uint WorldID, uint id); 285public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
215 286
216[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 287[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
288public static extern Quaternion GetObjectOrientation(uint WorldID, uint id);
289
290[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
217public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation); 291public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation);
218 292
219[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 293[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -268,5 +342,179 @@ public static extern void DumpBulletStatistics();
268public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); 342public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
269[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 343[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
270public static extern void SetDebugLogCallback(DebugLogCallback callback); 344public static extern void SetDebugLogCallback(DebugLogCallback callback);
345
346// ===============================================================================
347// ===============================================================================
348// ===============================================================================
349// A new version of the API that enables moving all the logic out of the C++ code and into
350// the C# code. This will make modifications easier for the next person.
351// This interface passes the actual pointers to the objects in the unmanaged
352// address space. All the management (calls for creation/destruction/lookup)
353// is done in the C# code.
354// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt
355// and the old code is removed.
356
357[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
358public static extern IntPtr GetSimHandle2(uint worldID);
359
360[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
361public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
362
363[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
364public static extern IntPtr GetBodyHandle2(IntPtr sim, uint id);
365
366// ===============================================================================
367[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
368public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
369 int maxCollisions, IntPtr collisionArray,
370 int maxUpdates, IntPtr updateArray);
371
372[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
373public static extern bool UpdateParameter2(IntPtr sim, uint localID, String parm, float value);
374
375[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
376public static extern void SetHeightmap2(IntPtr sim, float[] heightmap);
377
378[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
379public static extern void Shutdown2(IntPtr sim);
380
381[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
382public static extern int PhysicsStep2(IntPtr sim, float timeStep, int maxSubSteps, float fixedTimeStep,
383 out int updatedEntityCount,
384 out IntPtr updatedEntitiesPtr,
385 out int collidersCount,
386 out IntPtr collidersPtr);
387
388/*
389[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
390public static extern IntPtr CreateMesh2(IntPtr sim, int indicesCount, int* indices, int verticesCount, float* vertices );
391
392[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
393public static extern bool BuildHull2(IntPtr sim, IntPtr mesh);
394
395[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
396public static extern bool ReleaseHull2(IntPtr sim, IntPtr mesh);
397
398[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
399public static extern bool DestroyMesh2(IntPtr sim, IntPtr mesh);
400
401[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
402public static extern IntPtr CreateObject2(IntPtr sim, ShapeData shapeData);
403*/
404
405[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
406public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2,
407 Vector3 frame1loc, Quaternion frame1rot,
408 Vector3 frame2loc, Quaternion frame2rot,
409 bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
410
411[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
412public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
413
414[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
415public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
416
417[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
418public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
419
420[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
421public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
422
423[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
424public static extern bool CalculateTransforms2(IntPtr constrain);
425
426[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
427public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
428
429[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
430public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain);
431
432[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
433public static extern Vector3 GetPosition2(IntPtr obj);
434
435[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
436public static extern Quaternion GetOrientation2(IntPtr obj);
437
438[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
439public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation);
440
441[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
442public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity);
443
444[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
445public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity);
446
447[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
448public static extern bool SetObjectForce2(IntPtr obj, Vector3 force);
449
450[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
451public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val);
452
453[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
454public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val);
455
456[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
457public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping);
458
459[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
460public static extern bool SetDeactivationTime2(IntPtr obj, float val);
461
462[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
463public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold);
464
465[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
466public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val);
467
468[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
469public static extern bool SetFriction2(IntPtr obj, float val);
470
471[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
472public static extern bool SetRestitution2(IntPtr obj, float val);
473
474[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
475public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val);
476
477[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
478public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang);
479
480[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
481public static extern IntPtr SetCollisionFlags2(IntPtr obj, uint flags);
482
483[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
484public static extern IntPtr AddToCollisionFlags2(IntPtr obj, uint flags);
485
486[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
487public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, uint flags);
488
489[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
490public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
491
492[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
493public static extern bool UpdateInertiaTensor2(IntPtr obj);
494
495[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
496public static extern bool SetGravity2(IntPtr obj, Vector3 val);
497
498[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
499public static extern IntPtr ClearForces2(IntPtr obj);
500
501[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
502public static extern bool SetMargin2(IntPtr obj, float val);
503
504[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
505public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
506
507[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
508public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
509
510[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
511public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
512
513[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
514public static extern bool DestroyObject2(IntPtr world, uint id);
515
516[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
517public static extern void DumpPhysicsStatistics2(IntPtr sim);
518
271} 519}
272} 520}
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index cfede55..5274f3b 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -71,6 +71,9 @@ namespace OpenSim.Region.Physics.Manager
71 All = 0x3f 71 All = 0x3f
72 } 72 }
73 73
74 public delegate void RequestAssetDelegate(UUID assetID, AssetReceivedDelegate callback);
75 public delegate void AssetReceivedDelegate(AssetBase asset);
76
74 /// <summary> 77 /// <summary>
75 /// Contact result from a raycast. 78 /// Contact result from a raycast.
76 /// </summary> 79 /// </summary>
@@ -103,6 +106,8 @@ namespace OpenSim.Region.Physics.Manager
103 get { return new NullPhysicsScene(); } 106 get { return new NullPhysicsScene(); }
104 } 107 }
105 108
109 public RequestAssetDelegate RequestAssetMethod { private get; set; }
110
106 public virtual void TriggerPhysicsBasedRestart() 111 public virtual void TriggerPhysicsBasedRestart()
107 { 112 {
108 physicsCrash handler = OnPhysicsCrash; 113 physicsCrash handler = OnPhysicsCrash;
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index 32e81e2..929b019 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -290,7 +290,6 @@ namespace OpenSim.Region.Physics.OdePlugin
290 290
291 private readonly IntPtr contactgroup; 291 private readonly IntPtr contactgroup;
292 292
293 internal IntPtr LandGeom;
294 internal IntPtr WaterGeom; 293 internal IntPtr WaterGeom;
295 294
296 private float nmTerrainContactFriction = 255.0f; 295 private float nmTerrainContactFriction = 255.0f;
@@ -489,6 +488,8 @@ namespace OpenSim.Region.Physics.OdePlugin
489 /// </summary> 488 /// </summary>
490 internal Object OdeLock = new Object(); 489 internal Object OdeLock = new Object();
491 490
491 private bool _worldInitialized = false;
492
492 public IMesher mesher; 493 public IMesher mesher;
493 494
494 private IConfigSource m_config; 495 private IConfigSource m_config;
@@ -875,6 +876,8 @@ namespace OpenSim.Region.Physics.OdePlugin
875 staticPrimspace[i, j] = IntPtr.Zero; 876 staticPrimspace[i, j] = IntPtr.Zero;
876 } 877 }
877 } 878 }
879
880 _worldInitialized = true;
878 } 881 }
879 882
880// internal void waitForSpaceUnlock(IntPtr space) 883// internal void waitForSpaceUnlock(IntPtr space)
@@ -1508,8 +1511,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1508 { 1511 {
1509 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) 1512 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f)
1510 && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) 1513 && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f)
1511 && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) 1514 && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)))
1512 && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
1513 { 1515 {
1514 if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f) 1516 if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f)
1515 { 1517 {
@@ -1538,7 +1540,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1538 //d.GeomGetAABB(contactGeom.g2, out aabb2); 1540 //d.GeomGetAABB(contactGeom.g2, out aabb2);
1539 //d.GeomGetAABB(contactGeom.g1, out aabb1); 1541 //d.GeomGetAABB(contactGeom.g1, out aabb1);
1540 //aabb1. 1542 //aabb1.
1541 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) 1543 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)))
1542 { 1544 {
1543 if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z) 1545 if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z)
1544 { 1546 {
@@ -2896,6 +2898,8 @@ namespace OpenSim.Region.Physics.OdePlugin
2896 /// <returns>The number of frames simulated over that period.</returns> 2898 /// <returns>The number of frames simulated over that period.</returns>
2897 public override float Simulate(float timeStep) 2899 public override float Simulate(float timeStep)
2898 { 2900 {
2901 if (!_worldInitialized) return 11f;
2902
2899 int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0; 2903 int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0;
2900 int tempTick = 0, tempTick2 = 0; 2904 int tempTick = 0, tempTick2 = 0;
2901 2905
@@ -4017,6 +4021,8 @@ namespace OpenSim.Region.Physics.OdePlugin
4017 4021
4018 public override void Dispose() 4022 public override void Dispose()
4019 { 4023 {
4024 _worldInitialized = false;
4025
4020 m_rayCastManager.Dispose(); 4026 m_rayCastManager.Dispose();
4021 m_rayCastManager = null; 4027 m_rayCastManager = null;
4022 4028
@@ -4037,6 +4043,7 @@ namespace OpenSim.Region.Physics.OdePlugin
4037 d.WorldDestroy(world); 4043 d.WorldDestroy(world);
4038 //d.CloseODE(); 4044 //d.CloseODE();
4039 } 4045 }
4046
4040 } 4047 }
4041 4048
4042 public override Dictionary<uint, float> GetTopColliders() 4049 public override Dictionary<uint, float> GetTopColliders()
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 204c4ff..3144d76 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -99,6 +99,8 @@ namespace OpenSim.Region.RegionCombinerModule
99 99
100 public void RemoveRegion(Scene scene) 100 public void RemoveRegion(Scene scene)
101 { 101 {
102 lock (m_startingScenes)
103 m_startingScenes.Remove(scene.RegionInfo.originRegionID);
102 } 104 }
103 105
104 public void RegionLoaded(Scene scene) 106 public void RegionLoaded(Scene scene)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index 693992a..94fd940 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Threading; 31using System.Threading;
32using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Framework; 33using OpenSim.Framework;
34using OpenSim.Framework.Monitoring;
34using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
35using OpenSim.Region.ScriptEngine.Interfaces; 36using OpenSim.Region.ScriptEngine.Interfaces;
36using OpenSim.Region.ScriptEngine.Shared; 37using OpenSim.Region.ScriptEngine.Shared;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index cd72dc2..ce1c364 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -6885,22 +6885,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6885 if (folderID == UUID.Zero) 6885 if (folderID == UUID.Zero)
6886 return; 6886 return;
6887 6887
6888 byte[] bucket = new byte[1];
6889 bucket[0] = (byte)AssetType.Folder;
6890 //byte[] objBytes = folderID.GetBytes();
6891 //Array.Copy(objBytes, 0, bucket, 1, 16);
6892
6893 GridInstantMessage msg = new GridInstantMessage(World,
6894 m_host.OwnerID, m_host.Name, destID,
6895 (byte)InstantMessageDialog.TaskInventoryOffered,
6896 false, category+". "+m_host.Name+" is located at "+
6897 World.RegionInfo.RegionName+" "+
6898 m_host.AbsolutePosition.ToString(),
6899 folderID, true, m_host.AbsolutePosition,
6900 bucket);
6901
6902 if (m_TransferModule != null) 6888 if (m_TransferModule != null)
6889 {
6890 byte[] bucket = new byte[] { (byte)AssetType.Folder };
6891
6892 GridInstantMessage msg = new GridInstantMessage(World,
6893 m_host.UUID, m_host.Name + ", an object owned by " +
6894 resolveName(m_host.OwnerID) + ",", destID,
6895 (byte)InstantMessageDialog.TaskInventoryOffered,
6896 false, category + "\n" + m_host.Name + " is located at " +
6897 World.RegionInfo.RegionName + " " +
6898 m_host.AbsolutePosition.ToString(),
6899 folderID, true, m_host.AbsolutePosition,
6900 bucket);
6901
6903 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 6902 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
6903 }
6904 } 6904 }
6905 6905
6906 public void llSetVehicleType(int type) 6906 public void llSetVehicleType(int type)
@@ -11847,7 +11847,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11847 break; 11847 break;
11848 case ScriptBaseClass.OBJECT_ROT: 11848 case ScriptBaseClass.OBJECT_ROT:
11849 { 11849 {
11850 Quaternion rot = Quaternion.Identity; 11850 Quaternion rot = Quaternion.Identity;
11851 11851
11852 if (obj.ParentGroup.RootPart == obj) 11852 if (obj.ParentGroup.RootPart == obj)
11853 rot = obj.ParentGroup.GroupRotation; 11853 rot = obj.ParentGroup.GroupRotation;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index 4bd3dff..7844c75 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -200,24 +200,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
200 for (int i = 0; i < result.Length; i++) 200 for (int i = 0; i < result.Length; i++)
201 { 201 {
202 if (result[i] is string) 202 if (result[i] is string)
203 {
203 llist[i] = new LSL_String((string)result[i]); 204 llist[i] = new LSL_String((string)result[i]);
205 }
204 else if (result[i] is int) 206 else if (result[i] is int)
207 {
205 llist[i] = new LSL_Integer((int)result[i]); 208 llist[i] = new LSL_Integer((int)result[i]);
209 }
206 else if (result[i] is float) 210 else if (result[i] is float)
211 {
207 llist[i] = new LSL_Float((float)result[i]); 212 llist[i] = new LSL_Float((float)result[i]);
213 }
214 else if (result[i] is UUID)
215 {
216 llist[i] = new LSL_Key(result[i].ToString());
217 }
208 else if (result[i] is OpenMetaverse.Vector3) 218 else if (result[i] is OpenMetaverse.Vector3)
209 { 219 {
210 OpenMetaverse.Vector3 vresult = (OpenMetaverse.Vector3)result[i]; 220 OpenMetaverse.Vector3 vresult = (OpenMetaverse.Vector3)result[i];
211 llist[i] = new LSL_Vector(vresult.X,vresult.Y,vresult.Z); 221 llist[i] = new LSL_Vector(vresult.X, vresult.Y, vresult.Z);
212 } 222 }
213 else if (result[i] is OpenMetaverse.Quaternion) 223 else if (result[i] is OpenMetaverse.Quaternion)
214 { 224 {
215 OpenMetaverse.Quaternion qresult = (OpenMetaverse.Quaternion)result[i]; 225 OpenMetaverse.Quaternion qresult = (OpenMetaverse.Quaternion)result[i];
216 llist[i] = new LSL_Rotation(qresult.X,qresult.Y,qresult.Z,qresult.W); 226 llist[i] = new LSL_Rotation(qresult.X, qresult.Y, qresult.Z, qresult.W);
217 } 227 }
218 else 228 else
219 { 229 {
220 MODError(String.Format("unknown list element returned by {0}",fname)); 230 MODError(String.Format("unknown list element {1} returned by {0}", fname, result[i].GetType().Name));
221 } 231 }
222 } 232 }
223 233
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 29d0342..1181c10 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -3290,8 +3290,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3290 ((LSL_Api)m_LSL_Api).llSay(0, string.Format("Unable to attach, item '{0}' is not an object.", itemName)); 3290 ((LSL_Api)m_LSL_Api).llSay(0, string.Format("Unable to attach, item '{0}' is not an object.", itemName));
3291 3291
3292 throw new Exception(String.Format("The inventory item '{0}' is not an object", itemName)); 3292 throw new Exception(String.Format("The inventory item '{0}' is not an object", itemName));
3293
3294 return;
3295 } 3293 }
3296 3294
3297 ScenePresence sp = World.GetScenePresence(avatarId); 3295 ScenePresence sp = World.GetScenePresence(avatarId);
@@ -3322,5 +3320,47 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3322 InitLSL(); 3320 InitLSL();
3323 ((LSL_Api)m_LSL_Api).DetachFromAvatar(); 3321 ((LSL_Api)m_LSL_Api).DetachFromAvatar();
3324 } 3322 }
3323
3324 /// <summary>
3325 /// Checks if thing is a UUID.
3326 /// </summary>
3327 /// <param name="thing"></param>
3328 /// <returns>1 if thing is a valid UUID, 0 otherwise</returns>
3329 public LSL_Integer osIsUUID(string thing)
3330 {
3331 CheckThreatLevel(ThreatLevel.None, "osIsUUID");
3332 m_host.AddScriptLPS(1);
3333
3334 UUID test;
3335 return UUID.TryParse(thing, out test) ? 1 : 0;
3336 }
3337
3338 /// <summary>
3339 /// Wraps to Math.Min()
3340 /// </summary>
3341 /// <param name="a"></param>
3342 /// <param name="b"></param>
3343 /// <returns></returns>
3344 public LSL_Float osMin(double a, double b)
3345 {
3346 CheckThreatLevel(ThreatLevel.None, "osMin");
3347 m_host.AddScriptLPS(1);
3348
3349 return Math.Min(a, b);
3350 }
3351
3352 /// <summary>
3353 /// Wraps to Math.max()
3354 /// </summary>
3355 /// <param name="a"></param>
3356 /// <param name="b"></param>
3357 /// <returns></returns>
3358 public LSL_Float osMax(double a, double b)
3359 {
3360 CheckThreatLevel(ThreatLevel.None, "osMax");
3361 m_host.AddScriptLPS(1);
3362
3363 return Math.Max(a, b);
3364 }
3325 } 3365 }
3326} 3366}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index 19f3ce1..678f9d5 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -51,8 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
51 { 51 {
52 get 52 get
53 { 53 {
54 lock (SenseRepeatListLock) 54 return SenseRepeaters.Count;
55 return SenseRepeaters.Count;
56 } 55 }
57 } 56 }
58 57
@@ -61,8 +60,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
61 m_CmdManager = CmdManager; 60 m_CmdManager = CmdManager;
62 maximumRange = CmdManager.m_ScriptEngine.Config.GetDouble("SensorMaxRange", 96.0d); 61 maximumRange = CmdManager.m_ScriptEngine.Config.GetDouble("SensorMaxRange", 96.0d);
63 maximumToReturn = CmdManager.m_ScriptEngine.Config.GetInt("SensorMaxResults", 16); 62 maximumToReturn = CmdManager.m_ScriptEngine.Config.GetInt("SensorMaxResults", 16);
63 m_npcModule = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<INPCModule>();
64 } 64 }
65 65
66 private INPCModule m_npcModule;
67
66 private Object SenseLock = new Object(); 68 private Object SenseLock = new Object();
67 69
68 private const int AGENT = 1; 70 private const int AGENT = 1;
@@ -115,6 +117,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
115 public double distance; 117 public double distance;
116 } 118 }
117 119
120 /// <summary>
121 /// Sensors to process.
122 /// </summary>
123 /// <remarks>
124 /// Do not add or remove sensors from this list directly. Instead, copy the list and substitute the updated
125 /// copy. This is to avoid locking the list for the duration of the sensor sweep, which increases the danger
126 /// of deadlocks with future code updates.
127 ///
128 /// Always lock SenseRepeatListLock when updating this list.
129 /// </remarks>
118 private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>(); 130 private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>();
119 private object SenseRepeatListLock = new object(); 131 private object SenseRepeatListLock = new object();
120 132
@@ -124,6 +136,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
124 { 136 {
125 // Always remove first, in case this is a re-set 137 // Always remove first, in case this is a re-set
126 UnSetSenseRepeaterEvents(m_localID, m_itemID); 138 UnSetSenseRepeaterEvents(m_localID, m_itemID);
139
127 if (sec == 0) // Disabling timer 140 if (sec == 0) // Disabling timer
128 return; 141 return;
129 142
@@ -143,9 +156,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
143 ts.host = host; 156 ts.host = host;
144 157
145 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); 158 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
159
160 AddSenseRepeater(ts);
161 }
162
163 private void AddSenseRepeater(SenseRepeatClass senseRepeater)
164 {
146 lock (SenseRepeatListLock) 165 lock (SenseRepeatListLock)
147 { 166 {
148 SenseRepeaters.Add(ts); 167 List<SenseRepeatClass> newSenseRepeaters = new List<SenseRepeatClass>(SenseRepeaters);
168 newSenseRepeaters.Add(senseRepeater);
169 SenseRepeaters = newSenseRepeaters;
149 } 170 }
150 } 171 }
151 172
@@ -154,39 +175,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
154 // Remove from timer 175 // Remove from timer
155 lock (SenseRepeatListLock) 176 lock (SenseRepeatListLock)
156 { 177 {
157 List<SenseRepeatClass> NewSensors = new List<SenseRepeatClass>(); 178 List<SenseRepeatClass> newSenseRepeaters = new List<SenseRepeatClass>();
158 foreach (SenseRepeatClass ts in SenseRepeaters) 179 foreach (SenseRepeatClass ts in SenseRepeaters)
159 { 180 {
160 if (ts.localID != m_localID || ts.itemID != m_itemID) 181 if (ts.localID != m_localID || ts.itemID != m_itemID)
161 { 182 {
162 NewSensors.Add(ts); 183 newSenseRepeaters.Add(ts);
163 } 184 }
164 } 185 }
165 SenseRepeaters.Clear(); 186
166 SenseRepeaters = NewSensors; 187 SenseRepeaters = newSenseRepeaters;
167 } 188 }
168 } 189 }
169 190
170 public void CheckSenseRepeaterEvents() 191 public void CheckSenseRepeaterEvents()
171 { 192 {
172 lock (SenseRepeatListLock) 193 // Go through all timers
194 foreach (SenseRepeatClass ts in SenseRepeaters)
173 { 195 {
174 // Nothing to do here? 196 // Time has passed?
175 if (SenseRepeaters.Count == 0) 197 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
176 return;
177
178 // Go through all timers
179 foreach (SenseRepeatClass ts in SenseRepeaters)
180 { 198 {
181 // Time has passed? 199 SensorSweep(ts);
182 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) 200 // set next interval
183 { 201 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
184 SensorSweep(ts);
185 // set next interval
186 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
187 }
188 } 202 }
189 } // lock 203 }
190 } 204 }
191 205
192 public void SenseOnce(uint m_localID, UUID m_itemID, 206 public void SenseOnce(uint m_localID, UUID m_itemID,
@@ -440,8 +454,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
440 454
441 private List<SensedEntity> doAgentSensor(SenseRepeatClass ts) 455 private List<SensedEntity> doAgentSensor(SenseRepeatClass ts)
442 { 456 {
443 INPCModule npcModule = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<INPCModule>();
444
445 List<SensedEntity> sensedEntities = new List<SensedEntity>(); 457 List<SensedEntity> sensedEntities = new List<SensedEntity>();
446 458
447 // If nobody about quit fast 459 // If nobody about quit fast
@@ -477,7 +489,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
477 bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0); 489 bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0);
478 Vector3 toRegionPos; 490 Vector3 toRegionPos;
479 double dis; 491 double dis;
480 492
481 Action<ScenePresence> senseEntity = new Action<ScenePresence>(presence => 493 Action<ScenePresence> senseEntity = new Action<ScenePresence>(presence =>
482 { 494 {
483// m_log.DebugFormat( 495// m_log.DebugFormat(
@@ -486,7 +498,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
486 498
487 if ((ts.type & NPC) == 0 && presence.PresenceType == PresenceType.Npc) 499 if ((ts.type & NPC) == 0 && presence.PresenceType == PresenceType.Npc)
488 { 500 {
489 INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene); 501 INPC npcData = m_npcModule.GetNPC(presence.UUID, presence.Scene);
490 if (npcData == null || !npcData.SenseAsAgent) 502 if (npcData == null || !npcData.SenseAsAgent)
491 { 503 {
492// m_log.DebugFormat( 504// m_log.DebugFormat(
@@ -504,7 +516,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
504 } 516 }
505 else 517 else
506 { 518 {
507 INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene); 519 INPC npcData = m_npcModule.GetNPC(presence.UUID, presence.Scene);
508 if (npcData != null && npcData.SenseAsAgent) 520 if (npcData != null && npcData.SenseAsAgent)
509 { 521 {
510// m_log.DebugFormat( 522// m_log.DebugFormat(
@@ -619,21 +631,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
619 { 631 {
620 List<Object> data = new List<Object>(); 632 List<Object> data = new List<Object>();
621 633
622 lock (SenseRepeatListLock) 634 foreach (SenseRepeatClass ts in SenseRepeaters)
623 { 635 {
624 foreach (SenseRepeatClass ts in SenseRepeaters) 636 if (ts.itemID == itemID)
625 { 637 {
626 if (ts.itemID == itemID) 638 data.Add(ts.interval);
627 { 639 data.Add(ts.name);
628 data.Add(ts.interval); 640 data.Add(ts.keyID);
629 data.Add(ts.name); 641 data.Add(ts.type);
630 data.Add(ts.keyID); 642 data.Add(ts.range);
631 data.Add(ts.type); 643 data.Add(ts.arc);
632 data.Add(ts.range);
633 data.Add(ts.arc);
634 }
635 } 644 }
636 } 645 }
646
637 return data.ToArray(); 647 return data.ToArray();
638 } 648 }
639 649
@@ -667,8 +677,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
667 ts.next = 677 ts.next =
668 DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); 678 DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
669 679
670 lock (SenseRepeatListLock) 680 AddSenseRepeater(ts);
671 SenseRepeaters.Add(ts);
672 681
673 idx += 6; 682 idx += 6;
674 } 683 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 1facc96..aba66d3 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -276,5 +276,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
276 276
277 void osSetTerrainTexture(int level, LSL_Key texture); 277 void osSetTerrainTexture(int level, LSL_Key texture);
278 void osSetTerrainTextureHeight(int corner, double low, double high); 278 void osSetTerrainTextureHeight(int corner, double low, double high);
279
280 /// <summary>
281 /// Checks if thing is a UUID.
282 /// </summary>
283 /// <param name="thing"></param>
284 /// <returns>1 if thing is a valid UUID, 0 otherwise</returns>
285 LSL_Integer osIsUUID(string thing);
286
287 /// <summary>
288 /// Wraps to Math.Min()
289 /// </summary>
290 /// <param name="a"></param>
291 /// <param name="b"></param>
292 /// <returns></returns>
293 LSL_Float osMin(double a, double b);
294
295 /// <summary>
296 /// Wraps to Math.max()
297 /// </summary>
298 /// <param name="a"></param>
299 /// <param name="b"></param>
300 /// <returns></returns>
301 LSL_Float osMax(double a, double b);
279 } 302 }
280} 303}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index b40bdf0..53daa13 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -930,5 +930,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
930 { 930 {
931 m_OSSL_Functions.osSetTerrainTextureHeight(corner, low, high); 931 m_OSSL_Functions.osSetTerrainTextureHeight(corner, low, high);
932 } 932 }
933
934 public LSL_Integer osIsUUID(string thing)
935 {
936 return m_OSSL_Functions.osIsUUID(thing);
937 }
938
939 public LSL_Float osMin(double a, double b)
940 {
941 return m_OSSL_Functions.osMin(a, b);
942 }
943
944 public LSL_Float osMax(double a, double b)
945 {
946 return m_OSSL_Functions.osMax(a, b);
947 }
933 } 948 }
934} 949}
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
index b24f016..97dd0f6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
@@ -38,7 +38,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
38{ 38{
39 public class CSCodeGenerator : ICodeConverter 39 public class CSCodeGenerator : ICodeConverter
40 { 40 {
41// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 41// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
42 42
43 private SYMBOL m_astRoot = null; 43 private SYMBOL m_astRoot = null;
44 private Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> m_positionMap; 44 private Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> m_positionMap;
@@ -255,7 +255,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
255 else if (s is IdentDotExpression) 255 else if (s is IdentDotExpression)
256 retstr += Generate(CheckName(((IdentDotExpression) s).Name) + "." + ((IdentDotExpression) s).Member, s); 256 retstr += Generate(CheckName(((IdentDotExpression) s).Name) + "." + ((IdentDotExpression) s).Member, s);
257 else if (s is IdentExpression) 257 else if (s is IdentExpression)
258 retstr += Generate(CheckName(((IdentExpression) s).Name), s); 258 retstr += GenerateIdentifier(((IdentExpression) s).Name, s);
259 else if (s is IDENT) 259 else if (s is IDENT)
260 retstr += Generate(CheckName(((TOKEN) s).yytext), s); 260 retstr += Generate(CheckName(((TOKEN) s).yytext), s);
261 else 261 else
@@ -868,6 +868,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
868 } 868 }
869 869
870 /// <summary> 870 /// <summary>
871 /// Generates the code for an identifier
872 /// </summary>
873 /// <param name="id">The symbol name</param>
874 /// <param name="s">The Symbol node.</param>
875 /// <returns>String containing C# code for identifier reference.</returns>
876 private string GenerateIdentifier(string id, SYMBOL s)
877 {
878 if (m_comms != null)
879 {
880 object value = m_comms.LookupModConstant(id);
881 if (value != null)
882 {
883 string retval = null;
884 if (value is int)
885 retval = ((int)value).ToString();
886 else if (value is float)
887 retval = String.Format("new LSL_Types.LSLFloat({0})",((float)value).ToString());
888 else if (value is string)
889 retval = String.Format("new LSL_Types.LSLString(\"{0}\")",((string)value));
890 else if (value is OpenMetaverse.UUID)
891 retval = String.Format("new LSL_Types.key(\"{0}\")",((OpenMetaverse.UUID)value).ToString());
892 else if (value is OpenMetaverse.Vector3)
893 retval = String.Format("new LSL_Types.Vector3(\"{0}\")",((OpenMetaverse.Vector3)value).ToString());
894 else if (value is OpenMetaverse.Quaternion)
895 retval = String.Format("new LSL_Types.Quaternion(\"{0}\")",((OpenMetaverse.Quaternion)value).ToString());
896 else retval = id;
897
898 return Generate(retval, s);
899 }
900 }
901
902 return Generate(CheckName(id), s);
903 }
904
905 /// <summary>
871 /// Generates the code for a FunctionCall node. 906 /// Generates the code for a FunctionCall node.
872 /// </summary> 907 /// </summary>
873 /// <param name="fc">The FunctionCall node.</param> 908 /// <param name="fc">The FunctionCall node.</param>
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
index 5c9d30f..9e5fb24 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs
@@ -36,6 +36,7 @@ using OpenSim.Framework;
36using OpenSim.Region.CoreModules; 36using OpenSim.Region.CoreModules;
37using OpenSim.Region.Framework.Scenes; 37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Services.Interfaces; 38using OpenSim.Services.Interfaces;
39using OpenSim.Region.Framework.Interfaces;
39 40
40namespace OpenSim.Region.ScriptEngine.Shared 41namespace OpenSim.Region.ScriptEngine.Shared
41{ 42{
@@ -83,6 +84,12 @@ namespace OpenSim.Region.ScriptEngine.Shared
83 84
84 public class DetectParams 85 public class DetectParams
85 { 86 {
87 public const int AGENT = 1;
88 public const int ACTIVE = 2;
89 public const int PASSIVE = 4;
90 public const int SCRIPTED = 8;
91 public const int OS_NPC = 0x01000000;
92
86 public DetectParams() 93 public DetectParams()
87 { 94 {
88 Key = UUID.Zero; 95 Key = UUID.Zero;
@@ -199,8 +206,27 @@ namespace OpenSim.Region.ScriptEngine.Shared
199 Type = 0x01; // Avatar 206 Type = 0x01; // Avatar
200 if (presence.PresenceType == PresenceType.Npc) 207 if (presence.PresenceType == PresenceType.Npc)
201 Type = 0x20; 208 Type = 0x20;
209
210 // Cope Impl. We don't use OS_NPC.
211 //if (presence.PresenceType != PresenceType.Npc)
212 //{
213 // Type = AGENT;
214 //}
215 //else
216 //{
217 // Type = OS_NPC;
218
219 // INPCModule npcModule = scene.RequestModuleInterface<INPCModule>();
220 // INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene);
221
222 // if (npcData.SenseAsAgent)
223 // {
224 // Type |= AGENT;
225 // }
226 //}
227
202 if (presence.Velocity != Vector3.Zero) 228 if (presence.Velocity != Vector3.Zero)
203 Type |= 0x02; // Active 229 Type |= ACTIVE;
204 230
205 Group = presence.ControllingClient.ActiveGroupId; 231 Group = presence.ControllingClient.ActiveGroupId;
206 232
@@ -215,15 +241,15 @@ namespace OpenSim.Region.ScriptEngine.Shared
215 Name = part.Name; 241 Name = part.Name;
216 Owner = part.OwnerID; 242 Owner = part.OwnerID;
217 if (part.Velocity == Vector3.Zero) 243 if (part.Velocity == Vector3.Zero)
218 Type = 0x04; // Passive 244 Type = PASSIVE;
219 else 245 else
220 Type = 0x02; // Passive 246 Type = ACTIVE;
221 247
222 foreach (SceneObjectPart p in part.ParentGroup.Parts) 248 foreach (SceneObjectPart p in part.ParentGroup.Parts)
223 { 249 {
224 if (p.Inventory.ContainsScripts()) 250 if (p.Inventory.ContainsScripts())
225 { 251 {
226 Type |= 0x08; // Scripted 252 Type |= SCRIPTED; // Scripted
227 break; 253 break;
228 } 254 }
229 } 255 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 983eed2..771db0c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -312,11 +312,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
312 part.SetScriptEvents(ItemID, 312 part.SetScriptEvents(ItemID,
313 (int)m_Script.GetStateEventFlags(State)); 313 (int)m_Script.GetStateEventFlags(State));
314 314
315 Running = false; 315 if (!Running)
316
317 if (ShuttingDown)
318 m_startOnInit = false; 316 m_startOnInit = false;
319 317
318 Running = false;
319
320 // we get new rez events on sim restart, too 320 // we get new rez events on sim restart, too
321 // but if there is state, then we fire the change 321 // but if there is state, then we fire the change
322 // event 322 // event
@@ -352,12 +352,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
352 352
353 public void Init() 353 public void Init()
354 { 354 {
355 if (!m_startOnInit) 355 if (ShuttingDown)
356 return; 356 return;
357 357
358 if (m_startedFromSavedState) 358 if (m_startedFromSavedState)
359 { 359 {
360 Start(); 360 if (m_startOnInit)
361 Start();
361 if (m_postOnRez) 362 if (m_postOnRez)
362 { 363 {
363 PostEvent(new EventParams("on_rez", 364 PostEvent(new EventParams("on_rez",
@@ -389,7 +390,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
389 } 390 }
390 else 391 else
391 { 392 {
392 Start(); 393 if (m_startOnInit)
394 Start();
393 PostEvent(new EventParams("state_entry", 395 PostEvent(new EventParams("state_entry",
394 new Object[0], new DetectParams[0])); 396 new Object[0], new DetectParams[0]));
395 if (m_postOnRez) 397 if (m_postOnRez)
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 35a0200..f6cb7df 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -109,6 +109,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
109 private bool m_KillTimedOutScripts; 109 private bool m_KillTimedOutScripts;
110 private string m_ScriptEnginesPath = null; 110 private string m_ScriptEnginesPath = null;
111 111
112 private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>();
113
112 /// <summary> 114 /// <summary>
113 /// Is the entire simulator in the process of shutting down? 115 /// Is the entire simulator in the process of shutting down?
114 /// </summary> 116 /// </summary>
@@ -715,6 +717,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
715 m_Scene.EventManager.OnGetScriptRunning += OnGetScriptRunning; 717 m_Scene.EventManager.OnGetScriptRunning += OnGetScriptRunning;
716 m_Scene.EventManager.OnShutdown += OnShutdown; 718 m_Scene.EventManager.OnShutdown += OnShutdown;
717 719
720 // If region ready has been triggered, then the region had no scripts to compile and completed its other
721 // work.
722 m_Scene.EventManager.OnRegionReadyStatusChange += s => { if (s.Ready) m_InitialStartup = false; };
723
718 if (m_SleepTime > 0) 724 if (m_SleepTime > 0)
719 { 725 {
720 m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoMaintenance), 726 m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoMaintenance),
@@ -1269,7 +1275,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1269 1275
1270 if (instance!=null) 1276 if (instance!=null)
1271 instance.Init(); 1277 instance.Init();
1272 1278
1279 bool runIt;
1280 if (m_runFlags.TryGetValue(itemID, out runIt))
1281 {
1282 if (!runIt)
1283 StopScript(itemID);
1284 m_runFlags.Remove(itemID);
1285 }
1286
1273 return true; 1287 return true;
1274 } 1288 }
1275 1289
@@ -1660,6 +1674,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1660 IScriptInstance instance = GetInstance(itemID); 1674 IScriptInstance instance = GetInstance(itemID);
1661 if (instance != null) 1675 if (instance != null)
1662 instance.Start(); 1676 instance.Start();
1677 else
1678 m_runFlags.AddOrUpdate(itemID, true, 240);
1663 } 1679 }
1664 1680
1665 public void StopScript(UUID itemID) 1681 public void StopScript(UUID itemID)
@@ -1671,6 +1687,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1671 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort. 1687 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
1672 instance.Stop(1000); 1688 instance.Stop(1000);
1673 } 1689 }
1690 else
1691 {
1692 m_runFlags.AddOrUpdate(itemID, false, 240);
1693 }
1674 } 1694 }
1675 1695
1676 public DetectParams GetDetectParams(UUID itemID, int idx) 1696 public DetectParams GetDetectParams(UUID itemID, int idx)
diff --git a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
index dcbd717..3243a9a 100644
--- a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
+++ b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs
@@ -34,7 +34,7 @@ using Mono.Data.SqliteClient;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Framework.Statistics; 37using OpenSim.Framework.Monitoring;
38 38
39namespace OpenSim.Region.UserStatistics 39namespace OpenSim.Region.UserStatistics
40{ 40{
diff --git a/OpenSim/Region/UserStatistics/Default_Report.cs b/OpenSim/Region/UserStatistics/Default_Report.cs
index 0e17630..cdc615c 100644
--- a/OpenSim/Region/UserStatistics/Default_Report.cs
+++ b/OpenSim/Region/UserStatistics/Default_Report.cs
@@ -33,7 +33,7 @@ using System.Text;
33using Mono.Data.SqliteClient; 33using Mono.Data.SqliteClient;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Framework.Statistics; 36using OpenSim.Framework.Monitoring;
37 37
38 38
39namespace OpenSim.Region.UserStatistics 39namespace OpenSim.Region.UserStatistics
diff --git a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
index 811baba..74de46b 100644
--- a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
+++ b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs
@@ -34,7 +34,7 @@ using System.Text.RegularExpressions;
34using Mono.Data.SqliteClient; 34using Mono.Data.SqliteClient;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Framework.Statistics; 37using OpenSim.Framework.Monitoring;
38 38
39namespace OpenSim.Region.UserStatistics 39namespace OpenSim.Region.UserStatistics
40{ 40{
diff --git a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
index 8c04e71..28051fb 100644
--- a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
+++ b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs
@@ -33,7 +33,7 @@ using System.Text;
33using Mono.Data.SqliteClient; 33using Mono.Data.SqliteClient;
34using OpenMetaverse; 34using OpenMetaverse;
35using OpenSim.Region.Framework.Scenes; 35using OpenSim.Region.Framework.Scenes;
36using OpenSim.Framework.Statistics; 36using OpenSim.Framework.Monitoring;
37 37
38namespace OpenSim.Region.UserStatistics 38namespace OpenSim.Region.UserStatistics
39{ 39{