aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorDiva Canto2012-11-27 14:43:01 -0800
committerDiva Canto2012-11-27 14:43:01 -0800
commita82f699f4348ea1ab139ab338973c9cee04df712 (patch)
treed1bf4948670e1d207fe4f6c60f6b7771e1625839 /OpenSim/Region
parentPrevent the core Groups module from being enabled when its name doesn't match... (diff)
parentBulletSim: reorganize linear movement routine into separate subroutines enabl... (diff)
downloadopensim-SC_OLD-a82f699f4348ea1ab139ab338973c9cee04df712.zip
opensim-SC_OLD-a82f699f4348ea1ab139ab338973c9cee04df712.tar.gz
opensim-SC_OLD-a82f699f4348ea1ab139ab338973c9cee04df712.tar.bz2
opensim-SC_OLD-a82f699f4348ea1ab139ab338973c9cee04df712.tar.xz
Merge branch 'master' of ssh://opensimulator.org/var/git/opensim
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Application/ConfigurationLoader.cs1
-rw-r--r--OpenSim/Region/Application/OpenSim.cs205
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs78
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs2
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs137
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs113
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs89
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs25
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs317
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs128
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs5
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs13
-rw-r--r--OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Region/RestartModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Sound/SoundModule.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs3
-rw-r--r--OpenSim/Region/CoreModules/World/Wind/WindModule.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs53
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs58
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs101
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs83
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs15
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs127
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs2
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs39
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs579
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs4
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs6
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs191
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSMotors.cs273
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs9
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs120
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs80
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs75
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapes.cs421
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs170
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs339
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs262
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs220
-rw-r--r--OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs3
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs2
80 files changed, 2502 insertions, 1991 deletions
diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs
index 8d95c41..fc3999f 100644
--- a/OpenSim/Region/Application/ConfigurationLoader.cs
+++ b/OpenSim/Region/Application/ConfigurationLoader.cs
@@ -188,7 +188,6 @@ namespace OpenSim
188 // Make sure command line options take precedence 188 // Make sure command line options take precedence
189 m_config.Source.Merge(argvSource); 189 m_config.Source.Merge(argvSource);
190 190
191
192 IConfig enVars = m_config.Source.Configs["Environment"]; 191 IConfig enVars = m_config.Source.Configs["Environment"];
193 192
194 if( enVars != null ) 193 if( enVars != null )
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index 47252f6..cffbb3b 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -82,8 +82,8 @@ namespace OpenSim
82 { 82 {
83 base.ReadExtraConfigSettings(); 83 base.ReadExtraConfigSettings();
84 84
85 IConfig startupConfig = m_config.Source.Configs["Startup"]; 85 IConfig startupConfig = Config.Configs["Startup"];
86 IConfig networkConfig = m_config.Source.Configs["Network"]; 86 IConfig networkConfig = Config.Configs["Network"];
87 87
88 int stpMaxThreads = 15; 88 int stpMaxThreads = 15;
89 89
@@ -106,22 +106,6 @@ namespace OpenSim
106 m_timeInterval = startupConfig.GetInt("timer_Interval", 1200); 106 m_timeInterval = startupConfig.GetInt("timer_Interval", 1200);
107 } 107 }
108 108
109 if (m_logFileAppender != null)
110 {
111 if (m_logFileAppender is log4net.Appender.FileAppender)
112 {
113 log4net.Appender.FileAppender appender =
114 (log4net.Appender.FileAppender)m_logFileAppender;
115 string fileName = startupConfig.GetString("LogFile", String.Empty);
116 if (fileName != String.Empty)
117 {
118 appender.File = fileName;
119 appender.ActivateOptions();
120 }
121 m_log.InfoFormat("[LOGGING]: Logging started to file {0}", appender.File);
122 }
123 }
124
125 string asyncCallMethodStr = startupConfig.GetString("async_call_method", String.Empty); 109 string asyncCallMethodStr = startupConfig.GetString("async_call_method", String.Empty);
126 FireAndForgetMethod asyncCallMethod; 110 FireAndForgetMethod asyncCallMethod;
127 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod)) 111 if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod))
@@ -164,7 +148,7 @@ namespace OpenSim
164 break; 148 break;
165 case "rest": 149 case "rest":
166 m_console = new RemoteConsole("Region"); 150 m_console = new RemoteConsole("Region");
167 ((RemoteConsole)m_console).ReadConfig(m_config.Source); 151 ((RemoteConsole)m_console).ReadConfig(Config);
168 break; 152 break;
169 default: 153 default:
170 m_console = new LocalConsole("Region"); 154 m_console = new LocalConsole("Region");
@@ -174,6 +158,7 @@ namespace OpenSim
174 158
175 MainConsole.Instance = m_console; 159 MainConsole.Instance = m_console;
176 160
161 RegisterCommonAppenders(Config.Configs["Startup"]);
177 RegisterConsoleCommands(); 162 RegisterConsoleCommands();
178 163
179 base.StartupSpecific(); 164 base.StartupSpecific();
@@ -372,26 +357,6 @@ namespace OpenSim
372 "restart", 357 "restart",
373 "Restart all sims in this instance", RunCommand); 358 "Restart all sims in this instance", RunCommand);
374 359
375 m_console.Commands.AddCommand("General", false, "config set",
376 "config set <section> <key> <value>",
377 "Set a config option. In most cases this is not useful since changed parameters are not dynamically reloaded. Neither do changed parameters persist - you will have to change a config file manually and restart.", HandleConfig);
378
379 m_console.Commands.AddCommand("General", false, "config get",
380 "config get [<section>] [<key>]",
381 "Synonym for config show",
382 HandleConfig);
383
384 m_console.Commands.AddCommand("General", false, "config show",
385 "config show [<section>] [<key>]",
386 "Show config information",
387 "If neither section nor field are specified, then the whole current configuration is printed." + Environment.NewLine
388 + "If a section is given but not a field, then all fields in that section are printed.",
389 HandleConfig);
390
391 m_console.Commands.AddCommand("General", false, "config save",
392 "config save <path>",
393 "Save current configuration to a file at the given path", HandleConfig);
394
395 m_console.Commands.AddCommand("General", false, "command-script", 360 m_console.Commands.AddCommand("General", false, "command-script",
396 "command-script <script>", 361 "command-script <script>",
397 "Run a command script from file", RunCommand); 362 "Run a command script from file", RunCommand);
@@ -502,35 +467,6 @@ namespace OpenSim
502 } 467 }
503 468
504 /// <summary> 469 /// <summary>
505 /// Run an optional startup list of commands
506 /// </summary>
507 /// <param name="fileName"></param>
508 private void RunCommandScript(string fileName)
509 {
510 if (File.Exists(fileName))
511 {
512 m_log.Info("[COMMANDFILE]: Running " + fileName);
513
514 using (StreamReader readFile = File.OpenText(fileName))
515 {
516 string currentCommand;
517 while ((currentCommand = readFile.ReadLine()) != null)
518 {
519 currentCommand = currentCommand.Trim();
520 if (!(currentCommand == ""
521 || currentCommand.StartsWith(";")
522 || currentCommand.StartsWith("//")
523 || currentCommand.StartsWith("#")))
524 {
525 m_log.Info("[COMMANDFILE]: Running '" + currentCommand + "'");
526 m_console.RunCommand(currentCommand);
527 }
528 }
529 }
530 }
531 }
532
533 /// <summary>
534 /// Opens a file and uses it as input to the console command parser. 470 /// Opens a file and uses it as input to the console command parser.
535 /// </summary> 471 /// </summary>
536 /// <param name="fileName">name of file to use as input to the console</param> 472 /// <param name="fileName">name of file to use as input to the console</param>
@@ -634,111 +570,9 @@ namespace OpenSim
634 bool changed = PopulateRegionEstateInfo(regInfo); 570 bool changed = PopulateRegionEstateInfo(regInfo);
635 IScene scene; 571 IScene scene;
636 CreateRegion(regInfo, true, out scene); 572 CreateRegion(regInfo, true, out scene);
637 if (changed)
638 regInfo.EstateSettings.Save();
639 }
640 573
641 /// <summary> 574 if (changed)
642 /// Change and load configuration file data. 575 regInfo.EstateSettings.Save();
643 /// </summary>
644 /// <param name="module"></param>
645 /// <param name="cmd"></param>
646 private void HandleConfig(string module, string[] cmd)
647 {
648 List<string> args = new List<string>(cmd);
649 args.RemoveAt(0);
650 string[] cmdparams = args.ToArray();
651
652 if (cmdparams.Length > 0)
653 {
654 string firstParam = cmdparams[0].ToLower();
655
656 switch (firstParam)
657 {
658 case "set":
659 if (cmdparams.Length < 4)
660 {
661 Notice("Syntax: config set <section> <key> <value>");
662 Notice("Example: config set ScriptEngine.DotNetEngine NumberOfScriptThreads 5");
663 }
664 else
665 {
666 IConfig c;
667 IConfigSource source = new IniConfigSource();
668 c = source.AddConfig(cmdparams[1]);
669 if (c != null)
670 {
671 string _value = String.Join(" ", cmdparams, 3, cmdparams.Length - 3);
672 c.Set(cmdparams[2], _value);
673 m_config.Source.Merge(source);
674
675 Notice("In section [{0}], set {1} = {2}", c.Name, cmdparams[2], _value);
676 }
677 }
678 break;
679
680 case "get":
681 case "show":
682 if (cmdparams.Length == 1)
683 {
684 foreach (IConfig config in m_config.Source.Configs)
685 {
686 Notice("[{0}]", config.Name);
687 string[] keys = config.GetKeys();
688 foreach (string key in keys)
689 Notice(" {0} = {1}", key, config.GetString(key));
690 }
691 }
692 else if (cmdparams.Length == 2 || cmdparams.Length == 3)
693 {
694 IConfig config = m_config.Source.Configs[cmdparams[1]];
695 if (config == null)
696 {
697 Notice("Section \"{0}\" does not exist.",cmdparams[1]);
698 break;
699 }
700 else
701 {
702 if (cmdparams.Length == 2)
703 {
704 Notice("[{0}]", config.Name);
705 foreach (string key in config.GetKeys())
706 Notice(" {0} = {1}", key, config.GetString(key));
707 }
708 else
709 {
710 Notice(
711 "config get {0} {1} : {2}",
712 cmdparams[1], cmdparams[2], config.GetString(cmdparams[2]));
713 }
714 }
715 }
716 else
717 {
718 Notice("Syntax: config {0} [<section>] [<key>]", firstParam);
719 Notice("Example: config {0} ScriptEngine.DotNetEngine NumberOfScriptThreads", firstParam);
720 }
721
722 break;
723
724 case "save":
725 if (cmdparams.Length < 2)
726 {
727 Notice("Syntax: config save <path>");
728 return;
729 }
730
731 if (Application.iniFilePath == cmdparams[1])
732 {
733 Notice("Path can not be " + Application.iniFilePath);
734 return;
735 }
736
737 Notice("Saving configuration file: " + cmdparams[1]);
738 m_config.Save(cmdparams[1]);
739 break;
740 }
741 }
742 } 576 }
743 577
744 /// <summary> 578 /// <summary>
@@ -787,13 +621,6 @@ namespace OpenSim
787 621
788 switch (command) 622 switch (command)
789 { 623 {
790 case "command-script":
791 if (cmdparams.Length > 0)
792 {
793 RunCommandScript(cmdparams[0]);
794 }
795 break;
796
797 case "backup": 624 case "backup":
798 MainConsole.Instance.Output("Triggering save of pending object updates to persistent store"); 625 MainConsole.Instance.Output("Triggering save of pending object updates to persistent store");
799 SceneManager.BackupCurrentScene(); 626 SceneManager.BackupCurrentScene();
@@ -837,12 +664,20 @@ namespace OpenSim
837 664
838 if (!SceneManager.TrySetCurrentScene(newRegionName)) 665 if (!SceneManager.TrySetCurrentScene(newRegionName))
839 MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName)); 666 MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName));
667 else
668 RefreshPrompt();
840 } 669 }
841 else 670 else
842 { 671 {
843 MainConsole.Instance.Output("Usage: change region <region name>"); 672 MainConsole.Instance.Output("Usage: change region <region name>");
844 } 673 }
674 }
845 675
676 /// <summary>
677 /// Refreshs prompt with the current selection details.
678 /// </summary>
679 private void RefreshPrompt()
680 {
846 string regionName = (SceneManager.CurrentScene == null ? "root" : SceneManager.CurrentScene.RegionInfo.RegionName); 681 string regionName = (SceneManager.CurrentScene == null ? "root" : SceneManager.CurrentScene.RegionInfo.RegionName);
847 MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName)); 682 MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName));
848 683
@@ -864,6 +699,18 @@ namespace OpenSim
864 m_console.ConsoleScene = SceneManager.CurrentScene; 699 m_console.ConsoleScene = SceneManager.CurrentScene;
865 } 700 }
866 701
702 protected override void HandleRestartRegion(RegionInfo whichRegion)
703 {
704 base.HandleRestartRegion(whichRegion);
705
706 // Where we are restarting multiple scenes at once, a previous call to RefreshPrompt may have set the
707 // m_console.ConsoleScene to null (indicating all scenes).
708 if (m_console.ConsoleScene != null && whichRegion.RegionName == ((Scene)m_console.ConsoleScene).Name)
709 SceneManager.TrySetCurrentScene(whichRegion.RegionName);
710
711 RefreshPrompt();
712 }
713
867 /// <summary> 714 /// <summary>
868 /// Turn on some debugging values for OpenSim. 715 /// Turn on some debugging values for OpenSim.
869 /// </summary> 716 /// </summary>
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 808c760..c3c87e7 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -100,13 +100,7 @@ namespace OpenSim
100 /// <value> 100 /// <value>
101 /// The config information passed into the OpenSimulator region server. 101 /// The config information passed into the OpenSimulator region server.
102 /// </value> 102 /// </value>
103 public OpenSimConfigSource ConfigSource 103 public OpenSimConfigSource ConfigSource { get; private set; }
104 {
105 get { return m_config; }
106 set { m_config = value; }
107 }
108
109 protected OpenSimConfigSource m_config;
110 104
111 public List<IClientNetworkServer> ClientServers 105 public List<IClientNetworkServer> ClientServers
112 { 106 {
@@ -146,13 +140,14 @@ namespace OpenSim
146 protected virtual void LoadConfigSettings(IConfigSource configSource) 140 protected virtual void LoadConfigSettings(IConfigSource configSource)
147 { 141 {
148 m_configLoader = new ConfigurationLoader(); 142 m_configLoader = new ConfigurationLoader();
149 m_config = m_configLoader.LoadConfigSettings(configSource, envConfigSource, out m_configSettings, out m_networkServersInfo); 143 ConfigSource = m_configLoader.LoadConfigSettings(configSource, envConfigSource, out m_configSettings, out m_networkServersInfo);
144 Config = ConfigSource.Source;
150 ReadExtraConfigSettings(); 145 ReadExtraConfigSettings();
151 } 146 }
152 147
153 protected virtual void ReadExtraConfigSettings() 148 protected virtual void ReadExtraConfigSettings()
154 { 149 {
155 IConfig networkConfig = m_config.Source.Configs["Network"]; 150 IConfig networkConfig = Config.Configs["Network"];
156 if (networkConfig != null) 151 if (networkConfig != null)
157 { 152 {
158 proxyUrl = networkConfig.GetString("proxy_url", ""); 153 proxyUrl = networkConfig.GetString("proxy_url", "");
@@ -185,7 +180,7 @@ namespace OpenSim
185 /// </summary> 180 /// </summary>
186 protected override void StartupSpecific() 181 protected override void StartupSpecific()
187 { 182 {
188 IConfig startupConfig = m_config.Source.Configs["Startup"]; 183 IConfig startupConfig = Config.Configs["Startup"];
189 if (startupConfig != null) 184 if (startupConfig != null)
190 { 185 {
191 string pidFile = startupConfig.GetString("PIDFile", String.Empty); 186 string pidFile = startupConfig.GetString("PIDFile", String.Empty);
@@ -196,7 +191,7 @@ namespace OpenSim
196 } 191 }
197 192
198 // Load the simulation data service 193 // Load the simulation data service
199 IConfig simDataConfig = m_config.Source.Configs["SimulationDataStore"]; 194 IConfig simDataConfig = Config.Configs["SimulationDataStore"];
200 if (simDataConfig == null) 195 if (simDataConfig == null)
201 throw new Exception("Configuration file is missing the [SimulationDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?"); 196 throw new Exception("Configuration file is missing the [SimulationDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?");
202 197
@@ -204,7 +199,7 @@ namespace OpenSim
204 if (String.IsNullOrEmpty(module)) 199 if (String.IsNullOrEmpty(module))
205 throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [SimulationDataStore] section."); 200 throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [SimulationDataStore] section.");
206 201
207 m_simulationDataService = ServerUtils.LoadPlugin<ISimulationDataService>(module, new object[] { m_config.Source }); 202 m_simulationDataService = ServerUtils.LoadPlugin<ISimulationDataService>(module, new object[] { Config });
208 if (m_simulationDataService == null) 203 if (m_simulationDataService == null)
209 throw new Exception( 204 throw new Exception(
210 string.Format( 205 string.Format(
@@ -212,7 +207,7 @@ namespace OpenSim
212 module)); 207 module));
213 208
214 // Load the estate data service 209 // Load the estate data service
215 IConfig estateDataConfig = m_config.Source.Configs["EstateDataStore"]; 210 IConfig estateDataConfig = Config.Configs["EstateDataStore"];
216 if (estateDataConfig == null) 211 if (estateDataConfig == null)
217 throw new Exception("Configuration file is missing the [EstateDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?"); 212 throw new Exception("Configuration file is missing the [EstateDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?");
218 213
@@ -220,7 +215,7 @@ namespace OpenSim
220 if (String.IsNullOrEmpty(module)) 215 if (String.IsNullOrEmpty(module))
221 throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [EstateDataStore] section"); 216 throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [EstateDataStore] section");
222 217
223 m_estateDataService = ServerUtils.LoadPlugin<IEstateDataService>(module, new object[] { m_config.Source }); 218 m_estateDataService = ServerUtils.LoadPlugin<IEstateDataService>(module, new object[] { Config });
224 if (m_estateDataService == null) 219 if (m_estateDataService == null)
225 throw new Exception( 220 throw new Exception(
226 string.Format( 221 string.Format(
@@ -242,7 +237,7 @@ namespace OpenSim
242 } 237 }
243 } 238 }
244 239
245 protected virtual void AddPluginCommands(CommandConsole console) 240 protected virtual void AddPluginCommands(ICommandConsole console)
246 { 241 {
247 List<string> topics = GetHelpTopics(); 242 List<string> topics = GetHelpTopics();
248 243
@@ -304,7 +299,7 @@ namespace OpenSim
304 // Called from base.StartUp() 299 // Called from base.StartUp()
305 300
306 m_httpServerPort = m_networkServersInfo.HttpListenerPort; 301 m_httpServerPort = m_networkServersInfo.HttpListenerPort;
307 SceneManager.OnRestartSim += handleRestartRegion; 302 SceneManager.OnRestartSim += HandleRestartRegion;
308 303
309 // Only enable the watchdogs when all regions are ready. Otherwise we get false positives when cpu is 304 // Only enable the watchdogs when all regions are ready. Otherwise we get false positives when cpu is
310 // heavily used during initial startup. 305 // heavily used during initial startup.
@@ -369,7 +364,7 @@ namespace OpenSim
369 } 364 }
370 365
371 IClientNetworkServer clientServer; 366 IClientNetworkServer clientServer;
372 Scene scene = SetupScene(regionInfo, proxyOffset, m_config.Source, out clientServer); 367 Scene scene = SetupScene(regionInfo, proxyOffset, Config, out clientServer);
373 368
374 m_log.Info("[MODULES]: Loading Region's modules (old style)"); 369 m_log.Info("[MODULES]: Loading Region's modules (old style)");
375 370
@@ -451,10 +446,10 @@ namespace OpenSim
451 string estateOwnerPassword = null; 446 string estateOwnerPassword = null;
452 string rawEstateOwnerUuid = null; 447 string rawEstateOwnerUuid = null;
453 448
454 if (m_config.Source.Configs[ESTATE_SECTION_NAME] != null) 449 if (Config.Configs[ESTATE_SECTION_NAME] != null)
455 { 450 {
456 string defaultEstateOwnerName 451 string defaultEstateOwnerName
457 = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerName", "").Trim(); 452 = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerName", "").Trim();
458 string[] ownerNames = defaultEstateOwnerName.Split(' '); 453 string[] ownerNames = defaultEstateOwnerName.Split(' ');
459 454
460 if (ownerNames.Length >= 2) 455 if (ownerNames.Length >= 2)
@@ -464,9 +459,9 @@ namespace OpenSim
464 } 459 }
465 460
466 // Info to be used only on Standalone Mode 461 // Info to be used only on Standalone Mode
467 rawEstateOwnerUuid = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerUUID", null); 462 rawEstateOwnerUuid = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerUUID", null);
468 estateOwnerEMail = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerEMail", null); 463 estateOwnerEMail = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerEMail", null);
469 estateOwnerPassword = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerPassword", null); 464 estateOwnerPassword = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateOwnerPassword", null);
470 } 465 }
471 466
472 MainConsole.Instance.OutputFormat("Estate {0} has no owner set.", regionInfo.EstateSettings.EstateName); 467 MainConsole.Instance.OutputFormat("Estate {0} has no owner set.", regionInfo.EstateSettings.EstateName);
@@ -713,7 +708,7 @@ namespace OpenSim
713 return new Scene( 708 return new Scene(
714 regionInfo, circuitManager, sceneGridService, 709 regionInfo, circuitManager, sceneGridService,
715 simDataService, estateDataService, false, 710 simDataService, estateDataService, false,
716 m_config.Source, m_version); 711 Config, m_version);
717 } 712 }
718 713
719 protected void ShutdownClientServer(RegionInfo whichRegion) 714 protected void ShutdownClientServer(RegionInfo whichRegion)
@@ -740,9 +735,11 @@ namespace OpenSim
740 } 735 }
741 } 736 }
742 737
743 public void handleRestartRegion(RegionInfo whichRegion) 738 protected virtual void HandleRestartRegion(RegionInfo whichRegion)
744 { 739 {
745 m_log.Info("[OPENSIM]: Got restart signal from SceneManager"); 740 m_log.InfoFormat(
741 "[OPENSIM]: Got restart signal from SceneManager for region {0} ({1},{2})",
742 whichRegion.RegionName, whichRegion.RegionLocX, whichRegion.RegionLocY);
746 743
747 ShutdownClientServer(whichRegion); 744 ShutdownClientServer(whichRegion);
748 IScene scene; 745 IScene scene;
@@ -754,7 +751,7 @@ namespace OpenSim
754 protected override PhysicsScene GetPhysicsScene(string osSceneIdentifier) 751 protected override PhysicsScene GetPhysicsScene(string osSceneIdentifier)
755 { 752 {
756 return GetPhysicsScene( 753 return GetPhysicsScene(
757 m_configSettings.PhysicsEngine, m_configSettings.MeshEngineName, m_config.Source, osSceneIdentifier); 754 m_configSettings.PhysicsEngine, m_configSettings.MeshEngineName, Config, osSceneIdentifier);
758 } 755 }
759 756
760 /// <summary> 757 /// <summary>
@@ -888,7 +885,6 @@ namespace OpenSim
888 m_log.Info("[SHUTDOWN]: Closing all threads"); 885 m_log.Info("[SHUTDOWN]: Closing all threads");
889 m_log.Info("[SHUTDOWN]: Killing listener thread"); 886 m_log.Info("[SHUTDOWN]: Killing listener thread");
890 m_log.Info("[SHUTDOWN]: Killing clients"); 887 m_log.Info("[SHUTDOWN]: Killing clients");
891 // TODO: implement this
892 m_log.Info("[SHUTDOWN]: Closing console and terminating"); 888 m_log.Info("[SHUTDOWN]: Closing console and terminating");
893 889
894 try 890 try
@@ -897,7 +893,7 @@ namespace OpenSim
897 } 893 }
898 catch (Exception e) 894 catch (Exception e)
899 { 895 {
900 m_log.ErrorFormat("[SHUTDOWN]: Ignoring failure during shutdown - {0}", e); 896 m_log.Error("[SHUTDOWN]: Ignoring failure during shutdown - ", e);
901 } 897 }
902 } 898 }
903 899
@@ -991,9 +987,9 @@ namespace OpenSim
991 987
992 string defaultEstateName = null; 988 string defaultEstateName = null;
993 989
994 if (m_config.Source.Configs[ESTATE_SECTION_NAME] != null) 990 if (Config.Configs[ESTATE_SECTION_NAME] != null)
995 { 991 {
996 defaultEstateName = m_config.Source.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateName", null); 992 defaultEstateName = Config.Configs[ESTATE_SECTION_NAME].GetString("DefaultEstateName", null);
997 993
998 if (defaultEstateName != null) 994 if (defaultEstateName != null)
999 { 995 {
@@ -1076,28 +1072,14 @@ namespace OpenSim
1076 MainConsole.Instance.Output("Joining the estate failed. Please try again."); 1072 MainConsole.Instance.Output("Joining the estate failed. Please try again.");
1077 } 1073 }
1078 } 1074 }
1079 } 1075 }
1080 1076
1081 return true; // need to update the database 1077 return true; // need to update the database
1082 } 1078 }
1083 } 1079 }
1084 1080
1085 public class OpenSimConfigSource 1081 public class OpenSimConfigSource
1086 { 1082 {
1087 public IConfigSource Source; 1083 public IConfigSource Source;
1088
1089 public void Save(string path)
1090 {
1091 if (Source is IniConfigSource)
1092 {
1093 IniConfigSource iniCon = (IniConfigSource) Source;
1094 iniCon.Save(path);
1095 }
1096 else if (Source is XmlConfigSource)
1097 {
1098 XmlConfigSource xmlCon = (XmlConfigSource) Source;
1099 xmlCon.Save(path);
1100 }
1101 }
1102 } 1084 }
1103} 1085} \ No newline at end of file
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index d604cf6..ed8ec16 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -44,7 +44,7 @@ using OpenSim.Tests.Common.Mock;
44namespace OpenSim.Region.ClientStack.Linden.Tests 44namespace OpenSim.Region.ClientStack.Linden.Tests
45{ 45{
46 [TestFixture] 46 [TestFixture]
47 public class EventQueueTests 47 public class EventQueueTests : OpenSimTestCase
48 { 48 {
49 private TestScene m_scene; 49 private TestScene m_scene;
50 50
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
index 5fcf376..7d9f581 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs
@@ -43,7 +43,7 @@ using OpenSim.Tests.Common.Mock;
43namespace OpenSim.Region.ClientStack.LindenUDP.Tests 43namespace OpenSim.Region.ClientStack.LindenUDP.Tests
44{ 44{
45 [TestFixture] 45 [TestFixture]
46 public class LLImageManagerTests 46 public class LLImageManagerTests : OpenSimTestCase
47 { 47 {
48 private AssetBase m_testImageAsset; 48 private AssetBase m_testImageAsset;
49 private Scene scene; 49 private Scene scene;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs
index 0f88ec6..5f73a94 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/PacketHandlerTests.cs
@@ -39,7 +39,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
39 /// Tests for the LL packet handler 39 /// Tests for the LL packet handler
40 /// </summary> 40 /// </summary>
41 [TestFixture] 41 [TestFixture]
42 public class PacketHandlerTests 42 public class PacketHandlerTests : OpenSimTestCase
43 { 43 {
44// [Test] 44// [Test]
45// /// <summary> 45// /// <summary>
diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
index 1c2bfd0..0872cc8 100644
--- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
+++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs
@@ -47,7 +47,7 @@ namespace OpenSim.Region.CoreModules.Asset.Tests
47 /// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness. 47 /// At the moment we're only test the in-memory part of the FlotsamAssetCache. This is a considerable weakness.
48 /// </summary> 48 /// </summary>
49 [TestFixture] 49 [TestFixture]
50 public class FlotsamAssetCacheTests 50 public class FlotsamAssetCacheTests : OpenSimTestCase
51 { 51 {
52 protected TestScene m_scene; 52 protected TestScene m_scene;
53 protected FlotsamAssetCache m_cache; 53 protected FlotsamAssetCache m_cache;
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
index 848b3bf..1830d41 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs
@@ -39,7 +39,7 @@ using OpenSim.Tests.Common.Mock;
39namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory 39namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
40{ 40{
41 [TestFixture] 41 [TestFixture]
42 public class AvatarFactoryModuleTests 42 public class AvatarFactoryModuleTests : OpenSimTestCase
43 { 43 {
44 /// <summary> 44 /// <summary>
45 /// Only partial right now since we don't yet test that it's ended up in the avatar appearance service. 45 /// Only partial right now since we don't yet test that it's ended up in the avatar appearance service.
diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
index 7a197f7..961117e 100644
--- a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs
@@ -40,7 +40,7 @@ using OpenSim.Tests.Common.Mock;
40namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests 40namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class FriendsModuleTests 43 public class FriendsModuleTests : OpenSimTestCase
44 { 44 {
45 private FriendsModule m_fm; 45 private FriendsModule m_fm;
46 private TestScene m_scene; 46 private TestScene m_scene;
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
index 21d8bd7..b768257 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/Tests/InventoryAccessModuleTests.cs
@@ -49,7 +49,7 @@ using OpenSim.Tests.Common.Mock;
49namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests 49namespace OpenSim.Region.CoreModules.Framework.InventoryAccess.Tests
50{ 50{
51 [TestFixture] 51 [TestFixture]
52 public class InventoryAccessModuleTests 52 public class InventoryAccessModuleTests : OpenSimTestCase
53 { 53 {
54 protected TestScene m_scene; 54 protected TestScene m_scene;
55 protected BasicInventoryAccessModule m_iam; 55 protected BasicInventoryAccessModule m_iam;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs
new file mode 100644
index 0000000..fdbe10a
--- /dev/null
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/BasePresenceServiceConnector.cs
@@ -0,0 +1,137 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
32using Mono.Addins;
33using Nini.Config;
34using OpenMetaverse;
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Server.Base;
38using OpenSim.Services.Interfaces;
39using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
40
41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
42{
43 public class BasePresenceServiceConnector : IPresenceService
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47 protected bool m_Enabled;
48
49 protected PresenceDetector m_PresenceDetector;
50
51 /// <summary>
52 /// Underlying presence service. Do not use directly.
53 /// </summary>
54 public IPresenceService m_PresenceService;
55
56 public Type ReplaceableInterface
57 {
58 get { return null; }
59 }
60
61 public void AddRegion(Scene scene)
62 {
63 if (!m_Enabled)
64 return;
65
66 // m_log.DebugFormat(
67 // "[LOCAL PRESENCE CONNECTOR]: Registering IPresenceService to scene {0}", scene.RegionInfo.RegionName);
68
69 scene.RegisterModuleInterface<IPresenceService>(this);
70 m_PresenceDetector.AddRegion(scene);
71
72 m_log.InfoFormat("[BASE PRESENCE SERVICE CONNECTOR]: Enabled for region {0}", scene.Name);
73 }
74
75 public void RemoveRegion(Scene scene)
76 {
77 if (!m_Enabled)
78 return;
79
80 m_PresenceDetector.RemoveRegion(scene);
81 }
82
83 public void RegionLoaded(Scene scene)
84 {
85 if (!m_Enabled)
86 return;
87
88 }
89
90 public void PostInitialise()
91 {
92 }
93
94 public void Close()
95 {
96 }
97
98 #region IPresenceService
99
100 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
101 {
102 m_log.Warn("[BASE PRESENCE SERVICE CONNECTOR]: LoginAgent connector not implemented at the simulators");
103 return false;
104 }
105
106 public bool LogoutAgent(UUID sessionID)
107 {
108 return m_PresenceService.LogoutAgent(sessionID);
109 }
110
111 public bool LogoutRegionAgents(UUID regionID)
112 {
113 return m_PresenceService.LogoutRegionAgents(regionID);
114 }
115
116 public bool ReportAgent(UUID sessionID, UUID regionID)
117 {
118 return m_PresenceService.ReportAgent(sessionID, regionID);
119 }
120
121 public PresenceInfo GetAgent(UUID sessionID)
122 {
123 return m_PresenceService.GetAgent(sessionID);
124 }
125
126 public PresenceInfo[] GetAgents(string[] userIDs)
127 {
128 // Don't bother potentially making a useless network call if we not going to ask for any users anyway.
129 if (userIDs.Length == 0)
130 return new PresenceInfo[0];
131
132 return m_PresenceService.GetAgents(userIDs);
133 }
134
135 #endregion
136 }
137} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs
index d8bed1b..db5c520 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs
@@ -24,53 +24,29 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27
27using System; 28using System;
28using System.Collections.Generic; 29using System.Collections.Generic;
29using System.Reflection; 30using System.Reflection;
30 31using log4net;
32using Mono.Addins;
33using Nini.Config;
34using OpenMetaverse;
31using OpenSim.Region.Framework.Interfaces; 35using OpenSim.Region.Framework.Interfaces;
32using OpenSim.Region.Framework.Scenes; 36using OpenSim.Region.Framework.Scenes;
33using OpenSim.Server.Base; 37using OpenSim.Server.Base;
34using OpenSim.Services.Interfaces; 38using OpenSim.Services.Interfaces;
35using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; 39using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
36 40
37using OpenMetaverse;
38using log4net;
39using Mono.Addins;
40using Nini.Config;
41
42namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence 41namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
43{ 42{
44 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalPresenceServicesConnector")] 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalPresenceServicesConnector")]
45 public class LocalPresenceServicesConnector : ISharedRegionModule, IPresenceService 44 public class LocalPresenceServicesConnector : BasePresenceServiceConnector, ISharedRegionModule, IPresenceService
46 { 45 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 47
49 private bool m_Enabled = false;
50
51 private PresenceDetector m_PresenceDetector;
52
53 /// <summary>
54 /// Underlying presence service. Do not use directly.
55 /// </summary>
56 public IPresenceService m_PresenceService;
57
58 public LocalPresenceServicesConnector()
59 {
60 }
61
62 public LocalPresenceServicesConnector(IConfigSource source)
63 {
64 Initialise(source);
65 }
66
67 #region ISharedRegionModule 48 #region ISharedRegionModule
68 49
69 public Type ReplaceableInterface
70 {
71 get { return null; }
72 }
73
74 public string Name 50 public string Name
75 { 51 {
76 get { return "LocalPresenceServicesConnector"; } 52 get { return "LocalPresenceServicesConnector"; }
@@ -121,81 +97,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
121 } 97 }
122 } 98 }
123 99
124 public void PostInitialise()
125 {
126 }
127
128 public void Close()
129 {
130 }
131
132 public void AddRegion(Scene scene)
133 {
134 if (!m_Enabled)
135 return;
136
137 // m_log.DebugFormat(
138 // "[LOCAL PRESENCE CONNECTOR]: Registering IPresenceService to scene {0}", scene.RegionInfo.RegionName);
139
140 scene.RegisterModuleInterface<IPresenceService>(this);
141 m_PresenceDetector.AddRegion(scene);
142
143 m_log.InfoFormat("[LOCAL PRESENCE CONNECTOR]: Enabled local presence for region {0}", scene.RegionInfo.RegionName);
144
145 }
146
147 public void RemoveRegion(Scene scene)
148 {
149 if (!m_Enabled)
150 return;
151
152 m_PresenceDetector.RemoveRegion(scene);
153 }
154
155 public void RegionLoaded(Scene scene)
156 {
157 if (!m_Enabled)
158 return;
159
160 }
161
162 #endregion 100 #endregion
163
164 #region IPresenceService
165
166 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
167 {
168 m_log.Warn("[LOCAL PRESENCE CONNECTOR]: LoginAgent connector not implemented at the simulators");
169 return false;
170 }
171
172 public bool LogoutAgent(UUID sessionID)
173 {
174 return m_PresenceService.LogoutAgent(sessionID);
175 }
176
177
178 public bool LogoutRegionAgents(UUID regionID)
179 {
180 return m_PresenceService.LogoutRegionAgents(regionID);
181 }
182
183 public bool ReportAgent(UUID sessionID, UUID regionID)
184 {
185 return m_PresenceService.ReportAgent(sessionID, regionID);
186 }
187
188 public PresenceInfo GetAgent(UUID sessionID)
189 {
190 return m_PresenceService.GetAgent(sessionID);
191 }
192
193 public PresenceInfo[] GetAgents(string[] userIDs)
194 {
195 return m_PresenceService.GetAgents(userIDs);
196 }
197
198 #endregion
199
200 } 101 }
201} 102} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs
index be73932..6ca5c28 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/RemotePresenceServiceConnector.cs
@@ -43,22 +43,12 @@ using Nini.Config;
43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence 43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
44{ 44{
45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemotePresenceServicesConnector")] 45 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemotePresenceServicesConnector")]
46 public class RemotePresenceServicesConnector : ISharedRegionModule, IPresenceService 46 public class RemotePresenceServicesConnector : BasePresenceServiceConnector, ISharedRegionModule
47 { 47 {
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 49
50 #region ISharedRegionModule 50 #region ISharedRegionModule
51 51
52 private bool m_Enabled = false;
53
54 private PresenceDetector m_PresenceDetector;
55 private IPresenceService m_RemoteConnector;
56
57 public Type ReplaceableInterface
58 {
59 get { return null; }
60 }
61
62 public string Name 52 public string Name
63 { 53 {
64 get { return "RemotePresenceServicesConnector"; } 54 get { return "RemotePresenceServicesConnector"; }
@@ -72,7 +62,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
72 string name = moduleConfig.GetString("PresenceServices", ""); 62 string name = moduleConfig.GetString("PresenceServices", "");
73 if (name == Name) 63 if (name == Name)
74 { 64 {
75 m_RemoteConnector = new PresenceServicesConnector(source); 65 m_PresenceService = new PresenceServicesConnector(source);
76 66
77 m_Enabled = true; 67 m_Enabled = true;
78 68
@@ -81,81 +71,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence
81 m_log.Info("[REMOTE PRESENCE CONNECTOR]: Remote presence enabled"); 71 m_log.Info("[REMOTE PRESENCE CONNECTOR]: Remote presence enabled");
82 } 72 }
83 } 73 }
84
85 }
86
87 public void PostInitialise()
88 {
89 }
90
91 public void Close()
92 {
93 }
94
95 public void AddRegion(Scene scene)
96 {
97 if (!m_Enabled)
98 return;
99
100 scene.RegisterModuleInterface<IPresenceService>(this);
101 m_PresenceDetector.AddRegion(scene);
102
103 m_log.InfoFormat("[REMOTE PRESENCE CONNECTOR]: Enabled remote presence for region {0}", scene.RegionInfo.RegionName);
104
105 }
106
107 public void RemoveRegion(Scene scene)
108 {
109 if (!m_Enabled)
110 return;
111
112 m_PresenceDetector.RemoveRegion(scene);
113 }
114
115 public void RegionLoaded(Scene scene)
116 {
117 if (!m_Enabled)
118 return;
119
120 }
121
122 #endregion
123
124 #region IPresenceService
125
126 public bool LoginAgent(string userID, UUID sessionID, UUID secureSessionID)
127 {
128 m_log.Warn("[REMOTE PRESENCE CONNECTOR]: LoginAgent connector not implemented at the simulators");
129 return false;
130 }
131
132 public bool LogoutAgent(UUID sessionID)
133 {
134 return m_RemoteConnector.LogoutAgent(sessionID);
135 }
136
137
138 public bool LogoutRegionAgents(UUID regionID)
139 {
140 return m_RemoteConnector.LogoutRegionAgents(regionID);
141 }
142
143 public bool ReportAgent(UUID sessionID, UUID regionID)
144 {
145 return m_RemoteConnector.ReportAgent(sessionID, regionID);
146 }
147
148 public PresenceInfo GetAgent(UUID sessionID)
149 {
150 return m_RemoteConnector.GetAgent(sessionID);
151 }
152
153 public PresenceInfo[] GetAgents(string[] userIDs)
154 {
155 return m_RemoteConnector.GetAgents(userIDs);
156 } 74 }
157 75
158 #endregion 76 #endregion
159
160 } 77 }
161} 78} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
index 4556df3..7e365ca 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs
@@ -35,7 +35,6 @@ using NUnit.Framework;
35using OpenMetaverse; 35using OpenMetaverse;
36using OpenSim.Framework; 36using OpenSim.Framework;
37using Nini.Config; 37using Nini.Config;
38
39using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence; 38using OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence;
40using OpenSim.Region.Framework.Scenes; 39using OpenSim.Region.Framework.Scenes;
41using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; 40using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
@@ -44,7 +43,7 @@ using OpenSim.Tests.Common;
44namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests 43namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests
45{ 44{
46 [TestFixture] 45 [TestFixture]
47 public class PresenceConnectorsTests 46 public class PresenceConnectorsTests : OpenSimTestCase
48 { 47 {
49 LocalPresenceServicesConnector m_LocalConnector; 48 LocalPresenceServicesConnector m_LocalConnector;
50 private void SetUp() 49 private void SetUp()
@@ -56,7 +55,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests
56 config.Configs["PresenceService"].Set("LocalServiceModule", "OpenSim.Services.PresenceService.dll:PresenceService"); 55 config.Configs["PresenceService"].Set("LocalServiceModule", "OpenSim.Services.PresenceService.dll:PresenceService");
57 config.Configs["PresenceService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); 56 config.Configs["PresenceService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
58 57
59 m_LocalConnector = new LocalPresenceServicesConnector(config); 58 m_LocalConnector = new LocalPresenceServicesConnector();
59 m_LocalConnector.Initialise(config);
60 60
61 // Let's stick in a test presence 61 // Let's stick in a test presence
62 m_LocalConnector.m_PresenceService.LoginAgent(UUID.Zero.ToString(), UUID.Zero, UUID.Zero); 62 m_LocalConnector.m_PresenceService.LoginAgent(UUID.Zero.ToString(), UUID.Zero, UUID.Zero);
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index ea806ec..c810242 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
@@ -552,13 +552,22 @@ namespace OpenSim.Region.CoreModules.World.Archiver
552 552
553 // Validate User and Group UUID's 553 // Validate User and Group UUID's
554 554
555 if (!ResolveUserUuid(scene, parcel.OwnerID)) 555 if (parcel.IsGroupOwned)
556 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
557
558 if (!ResolveGroupUuid(parcel.GroupID))
559 { 556 {
560 parcel.GroupID = UUID.Zero; 557 if (!ResolveGroupUuid(parcel.GroupID))
561 parcel.IsGroupOwned = false; 558 {
559 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
560 parcel.GroupID = UUID.Zero;
561 parcel.IsGroupOwned = false;
562 }
563 }
564 else
565 {
566 if (!ResolveUserUuid(scene, parcel.OwnerID))
567 parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner;
568
569 if (!ResolveGroupUuid(parcel.GroupID))
570 parcel.GroupID = UUID.Zero;
562 } 571 }
563 572
564 List<LandAccessEntry> accessList = new List<LandAccessEntry>(); 573 List<LandAccessEntry> accessList = new List<LandAccessEntry>();
@@ -571,8 +580,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
571 parcel.ParcelAccessList = accessList; 580 parcel.ParcelAccessList = accessList;
572 581
573// m_log.DebugFormat( 582// m_log.DebugFormat(
574// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", 583// "[ARCHIVER]: Adding parcel {0}, local id {1}, owner {2}, group {3}, isGroupOwned {4}, area {5}",
575// parcel.Name, parcel.LocalID, parcel.Area); 584// parcel.Name, parcel.LocalID, parcel.OwnerID, parcel.GroupID, parcel.IsGroupOwned, parcel.Area);
576 585
577 landData.Add(parcel); 586 landData.Add(parcel);
578 } 587 }
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
index d751b1c..7bdd65c 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs
@@ -167,7 +167,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
167 } 167 }
168 scenesGroup.CalcSceneLocations(); 168 scenesGroup.CalcSceneLocations();
169 169
170
171 m_archiveWriter = new TarArchiveWriter(m_saveStream); 170 m_archiveWriter = new TarArchiveWriter(m_saveStream);
172 171
173 try 172 try
@@ -216,7 +215,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
216 } 215 }
217 } 216 }
218 217
219
220 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids) 218 private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary<UUID, AssetType> assetUuids)
221 { 219 {
222 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); 220 m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName);
@@ -540,7 +538,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
540 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); 538 xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y));
541 } 539 }
542 540
543
544 protected void Save(Scene scene, List<SceneObjectGroup> sceneObjects, string regionDir) 541 protected void Save(Scene scene, List<SceneObjectGroup> sceneObjects, string regionDir)
545 { 542 {
546 if (regionDir != string.Empty) 543 if (regionDir != string.Empty)
@@ -560,8 +557,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
560 foreach (ILandObject lo in landObjects) 557 foreach (ILandObject lo in landObjects)
561 { 558 {
562 LandData landData = lo.LandData; 559 LandData landData = lo.LandData;
563 string landDataPath = String.Format("{0}{1}{2}.xml", 560 string landDataPath
564 regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString()); 561 = String.Format("{0}{1}", regionDir, ArchiveConstants.CreateOarLandDataPath(landData));
565 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); 562 m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
566 } 563 }
567 564
@@ -604,7 +601,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver
604 601
605 CloseArchive(String.Empty); 602 CloseArchive(String.Empty);
606 } 603 }
607
608 604
609 /// <summary> 605 /// <summary>
610 /// Closes the archive and notifies that we're done. 606 /// Closes the archive and notifies that we're done.
@@ -629,6 +625,5 @@ namespace OpenSim.Region.CoreModules.World.Archiver
629 625
630 m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage); 626 m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage);
631 } 627 }
632
633 } 628 }
634} 629} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
index 82f49b0..eec1cec 100644
--- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
+++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs
@@ -31,16 +31,19 @@ using System.IO;
31using System.Reflection; 31using System.Reflection;
32using System.Threading; 32using System.Threading;
33using log4net.Config; 33using log4net.Config;
34using Nini.Config;
34using NUnit.Framework; 35using NUnit.Framework;
35using OpenMetaverse; 36using OpenMetaverse;
36using OpenMetaverse.Assets; 37using OpenMetaverse.Assets;
37using OpenSim.Framework; 38using OpenSim.Framework;
38using OpenSim.Framework.Serialization; 39using OpenSim.Framework.Serialization;
39using OpenSim.Framework.Serialization.External; 40using OpenSim.Framework.Serialization.External;
41using OpenSim.Region.CoreModules.World.Land;
40using OpenSim.Region.CoreModules.World.Serialiser; 42using OpenSim.Region.CoreModules.World.Serialiser;
41using OpenSim.Region.CoreModules.World.Terrain; 43using OpenSim.Region.CoreModules.World.Terrain;
42using OpenSim.Region.Framework.Scenes; 44using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.Framework.Scenes.Serialization; 45using OpenSim.Region.Framework.Scenes.Serialization;
46using OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups;
44using OpenSim.Tests.Common; 47using OpenSim.Tests.Common;
45using OpenSim.Tests.Common.Mock; 48using OpenSim.Tests.Common.Mock;
46using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants; 49using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants;
@@ -69,9 +72,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
69 { 72 {
70 base.SetUp(); 73 base.SetUp();
71 74
72 // FIXME: Do something about this - relying on statics in unit tests causes trouble sooner or later
73 new SceneManager();
74
75 m_archiverModule = new ArchiverModule(); 75 m_archiverModule = new ArchiverModule();
76 m_serialiserModule = new SerialiserModule(); 76 m_serialiserModule = new SerialiserModule();
77 TerrainModule terrainModule = new TerrainModule(); 77 TerrainModule terrainModule = new TerrainModule();
@@ -127,6 +127,53 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
127 127
128 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName }; 128 return new SceneObjectPart(ownerId, shape, groupPosition, rotationOffset, offsetPosition) { Name = partName };
129 } 129 }
130
131 private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid)
132 {
133 SceneObjectPart part1 = CreateSceneObjectPart1();
134 sog1 = new SceneObjectGroup(part1);
135 scene.AddNewSceneObject(sog1, false);
136
137 AssetNotecard nc = new AssetNotecard();
138 nc.BodyText = "Hello World!";
139 nc.Encode();
140 ncAssetUuid = UUID.Random();
141 UUID ncItemUuid = UUID.Random();
142 AssetBase ncAsset
143 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
144 m_scene.AssetService.Store(ncAsset);
145
146 TaskInventoryItem ncItem
147 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
148 SceneObjectPart part2 = CreateSceneObjectPart2();
149 sog2 = new SceneObjectGroup(part2);
150 part2.Inventory.AddInventoryItem(ncItem, true);
151
152 scene.AddNewSceneObject(sog2, false);
153 }
154
155 private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid)
156 {
157 using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName))
158 {
159 using (BinaryReader br = new BinaryReader(resource))
160 {
161 // FIXME: Use the inspector instead
162 soundData = br.ReadBytes(99999999);
163 soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
164 string soundAssetFileName
165 = ArchiveConstants.ASSETS_PATH + soundUuid
166 + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
167 tar.WriteFile(soundAssetFileName, soundData);
168
169 /*
170 AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
171 scene.AssetService.Store(soundAsset);
172 asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
173 */
174 }
175 }
176 }
130 177
131 /// <summary> 178 /// <summary>
132 /// Test saving an OpenSim Region Archive. 179 /// Test saving an OpenSim Region Archive.
@@ -204,30 +251,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
204 // TODO: Test presence of more files and contents of files. 251 // TODO: Test presence of more files and contents of files.
205 } 252 }
206 253
207 private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid)
208 {
209 SceneObjectPart part1 = CreateSceneObjectPart1();
210 sog1 = new SceneObjectGroup(part1);
211 scene.AddNewSceneObject(sog1, false);
212
213 AssetNotecard nc = new AssetNotecard();
214 nc.BodyText = "Hello World!";
215 nc.Encode();
216 ncAssetUuid = UUID.Random();
217 UUID ncItemUuid = UUID.Random();
218 AssetBase ncAsset
219 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
220 m_scene.AssetService.Store(ncAsset);
221
222 TaskInventoryItem ncItem
223 = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid };
224 SceneObjectPart part2 = CreateSceneObjectPart2();
225 sog2 = new SceneObjectGroup(part2);
226 part2.Inventory.AddInventoryItem(ncItem, true);
227
228 scene.AddNewSceneObject(sog2, false);
229 }
230
231 /// <summary> 254 /// <summary>
232 /// Test saving an OpenSim Region Archive with the no assets option 255 /// Test saving an OpenSim Region Archive with the no assets option
233 /// </summary> 256 /// </summary>
@@ -309,59 +332,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
309 } 332 }
310 333
311 /// <summary> 334 /// <summary>
312 /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g.
313 /// 2 can come after 3).
314 /// </summary>
315 [Test]
316 public void TestLoadOarUnorderedParts()
317 {
318 TestHelpers.InMethod();
319
320 UUID ownerId = TestHelpers.ParseTail(0xaaaa);
321
322 MemoryStream archiveWriteStream = new MemoryStream();
323 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
324
325 tar.WriteFile(
326 ArchiveConstants.CONTROL_FILE_PATH,
327 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
328
329 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11);
330 SceneObjectPart sop2
331 = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId);
332 SceneObjectPart sop3
333 = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId);
334
335 // Add the parts so they will be written out in reverse order to the oar
336 sog1.AddPart(sop3);
337 sop3.LinkNum = 3;
338 sog1.AddPart(sop2);
339 sop2.LinkNum = 2;
340
341 tar.WriteFile(
342 ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition),
343 SceneObjectSerializer.ToXml2Format(sog1));
344
345 tar.Close();
346
347 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
348
349 lock (this)
350 {
351 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
352 m_archiverModule.DearchiveRegion(archiveReadStream);
353 }
354
355 Assert.That(m_lastErrorMessage, Is.Null);
356
357 SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2");
358 Assert.That(part2.LinkNum, Is.EqualTo(2));
359
360 SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3");
361 Assert.That(part3.LinkNum, Is.EqualTo(3));
362 }
363
364 /// <summary>
365 /// Test loading an OpenSim Region Archive. 335 /// Test loading an OpenSim Region Archive.
366 /// </summary> 336 /// </summary>
367 [Test] 337 [Test]
@@ -435,50 +405,57 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
435 TestLoadedRegion(part1, soundItemName, soundData); 405 TestLoadedRegion(part1, soundItemName, soundData);
436 } 406 }
437 407
438 private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid) 408 /// <summary>
409 /// Test loading an OpenSim Region Archive where the scene object parts are not ordered by link number (e.g.
410 /// 2 can come after 3).
411 /// </summary>
412 [Test]
413 public void TestLoadOarUnorderedParts()
439 { 414 {
440 using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) 415 TestHelpers.InMethod();
441 {
442 using (BinaryReader br = new BinaryReader(resource))
443 {
444 // FIXME: Use the inspector instead
445 soundData = br.ReadBytes(99999999);
446 soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001");
447 string soundAssetFileName
448 = ArchiveConstants.ASSETS_PATH + soundUuid
449 + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV];
450 tar.WriteFile(soundAssetFileName, soundData);
451 416
452 /* 417 UUID ownerId = TestHelpers.ParseTail(0xaaaa);
453 AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData);
454 scene.AssetService.Store(soundAsset);
455 asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav";
456 */
457 }
458 }
459 }
460 418
461 private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData) 419 MemoryStream archiveWriteStream = new MemoryStream();
462 { 420 TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream);
463 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name);
464 421
465 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); 422 tar.WriteFile(
466 Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical"); 423 ArchiveConstants.CONTROL_FILE_PATH,
467 Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal"); 424 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
468 Assert.That(
469 object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal");
470 Assert.That(
471 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal");
472 Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation));
473 Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition));
474 425
475 TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0]; 426 SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11);
476 Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null"); 427 SceneObjectPart sop2
477 AssetBase loadedSoundAsset = m_scene.AssetService.Get(loadedSoundItem.AssetID.ToString()); 428 = SceneHelpers.CreateSceneObjectPart("obj1-Part2", TestHelpers.ParseTail(0x12), ownerId);
478 Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null"); 429 SceneObjectPart sop3
479 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); 430 = SceneHelpers.CreateSceneObjectPart("obj1-Part3", TestHelpers.ParseTail(0x13), ownerId);
480 431
481 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); 432 // Add the parts so they will be written out in reverse order to the oar
433 sog1.AddPart(sop3);
434 sop3.LinkNum = 3;
435 sog1.AddPart(sop2);
436 sop2.LinkNum = 2;
437
438 tar.WriteFile(
439 ArchiveConstants.CreateOarObjectPath(sog1.Name, sog1.UUID, sog1.AbsolutePosition),
440 SceneObjectSerializer.ToXml2Format(sog1));
441
442 tar.Close();
443
444 MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray());
445
446 lock (this)
447 {
448 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
449 m_archiverModule.DearchiveRegion(archiveReadStream);
450 }
451
452 Assert.That(m_lastErrorMessage, Is.Null);
453
454 SceneObjectPart part2 = m_scene.GetSceneObjectPart("obj1-Part2");
455 Assert.That(part2.LinkNum, Is.EqualTo(2));
456
457 SceneObjectPart part3 = m_scene.GetSceneObjectPart("obj1-Part3");
458 Assert.That(part3.LinkNum, Is.EqualTo(3));
482 } 459 }
483 460
484 /// <summary> 461 /// <summary>
@@ -538,8 +515,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
538 SerialiserModule serialiserModule = new SerialiserModule(); 515 SerialiserModule serialiserModule = new SerialiserModule();
539 TerrainModule terrainModule = new TerrainModule(); 516 TerrainModule terrainModule = new TerrainModule();
540 517
541 m_sceneHelpers = new SceneHelpers(); 518 SceneHelpers m_sceneHelpers2 = new SceneHelpers();
542 TestScene scene2 = m_sceneHelpers.SetupScene(); 519 TestScene scene2 = m_sceneHelpers2.SetupScene();
543 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); 520 SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule);
544 521
545 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is 522 // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is
@@ -563,6 +540,71 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
563 } 540 }
564 541
565 /// <summary> 542 /// <summary>
543 /// Test OAR loading where the land parcel is group deeded.
544 /// </summary>
545 /// <remarks>
546 /// In this situation, the owner ID is set to the group ID.
547 /// </remarks>
548 [Test]
549 public void TestLoadOarDeededLand()
550 {
551 TestHelpers.InMethod();
552// TestHelpers.EnableLogging();
553
554 UUID landID = TestHelpers.ParseTail(0x10);
555
556 MockGroupsServicesConnector groupsService = new MockGroupsServicesConnector();
557
558 IConfigSource configSource = new IniConfigSource();
559 IConfig config = configSource.AddConfig("Groups");
560 config.Set("Enabled", true);
561 config.Set("Module", "GroupsModule");
562 config.Set("DebugEnabled", true);
563 SceneHelpers.SetupSceneModules(
564 m_scene, configSource, new object[] { new GroupsModule(), groupsService, new LandManagementModule() });
565
566 // Create group in scene for loading
567 // FIXME: For now we'll put up with the issue that we'll get a group ID that varies across tests.
568 UUID groupID
569 = groupsService.CreateGroup(UUID.Zero, "group1", "", true, UUID.Zero, 3, true, true, true, UUID.Zero);
570
571 // Construct OAR
572 MemoryStream oarStream = new MemoryStream();
573 TarArchiveWriter tar = new TarArchiveWriter(oarStream);
574
575 tar.WriteDir(ArchiveConstants.LANDDATA_PATH);
576 tar.WriteFile(
577 ArchiveConstants.CONTROL_FILE_PATH,
578 new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup()));
579
580 LandObject lo = new LandObject(groupID, true, null);
581 lo.SetLandBitmap(lo.BasicFullRegionLandBitmap());
582 LandData ld = lo.LandData;
583 ld.GlobalID = landID;
584
585 string ldPath = ArchiveConstants.CreateOarLandDataPath(ld);
586 tar.WriteFile(ldPath, LandDataSerializer.Serialize(ld, null));
587 tar.Close();
588
589 oarStream = new MemoryStream(oarStream.ToArray());
590
591 // Load OAR
592 lock (this)
593 {
594 m_scene.EventManager.OnOarFileLoaded += LoadCompleted;
595 m_archiverModule.DearchiveRegion(oarStream);
596 }
597
598 ILandObject rLo = m_scene.LandChannel.GetLandObject(16, 16);
599 LandData rLd = rLo.LandData;
600
601 Assert.That(rLd.GlobalID, Is.EqualTo(landID));
602 Assert.That(rLd.OwnerID, Is.EqualTo(groupID));
603 Assert.That(rLd.GroupID, Is.EqualTo(groupID));
604 Assert.That(rLd.IsGroupOwned, Is.EqualTo(true));
605 }
606
607 /// <summary>
566 /// Test loading the region settings of an OpenSim Region Archive. 608 /// Test loading the region settings of an OpenSim Region Archive.
567 /// </summary> 609 /// </summary>
568 [Test] 610 [Test]
@@ -781,9 +823,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
781 } 823 }
782 } 824 }
783 825
784
785 // Save OAR 826 // Save OAR
786
787 MemoryStream archiveWriteStream = new MemoryStream(); 827 MemoryStream archiveWriteStream = new MemoryStream();
788 m_scene.EventManager.OnOarFileSaved += SaveCompleted; 828 m_scene.EventManager.OnOarFileSaved += SaveCompleted;
789 829
@@ -800,7 +840,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
800 840
801 841
802 // Check that the OAR contains the expected data 842 // Check that the OAR contains the expected data
803
804 Assert.That(m_lastRequestId, Is.EqualTo(requestId)); 843 Assert.That(m_lastRequestId, Is.EqualTo(requestId));
805 844
806 byte[] archive = archiveWriteStream.ToArray(); 845 byte[] archive = archiveWriteStream.ToArray();
@@ -892,7 +931,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
892 } 931 }
893 932
894 ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); 933 ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup();
895 SceneManager.Instance.ForEachScene(delegate(Scene scene) 934 m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene)
896 { 935 {
897 scenesGroup.AddScene(scene); 936 scenesGroup.AddScene(scene);
898 }); 937 });
@@ -950,13 +989,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
950 989
951 // Delete the current objects, to test that they're loaded from the OAR and didn't 990 // Delete the current objects, to test that they're loaded from the OAR and didn't
952 // just remain in the scene. 991 // just remain in the scene.
953 SceneManager.Instance.ForEachScene(delegate(Scene scene) 992 m_sceneHelpers.SceneManager.ForEachScene(delegate(Scene scene)
954 { 993 {
955 scene.DeleteAllSceneObjects(); 994 scene.DeleteAllSceneObjects();
956 }); 995 });
957 996
958 // Create a "hole", to test that that the corresponding region isn't loaded from the OAR 997 // Create a "hole", to test that that the corresponding region isn't loaded from the OAR
959 SceneManager.Instance.CloseScene(SceneManager.Instance.Scenes[1]); 998 m_sceneHelpers.SceneManager.CloseScene(SceneManager.Instance.Scenes[1]);
960 999
961 1000
962 // Check thay the OAR file contains the expected data 1001 // Check thay the OAR file contains the expected data
@@ -971,10 +1010,32 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
971 1010
972 Assert.That(m_lastErrorMessage, Is.Null); 1011 Assert.That(m_lastErrorMessage, Is.Null);
973 1012
974 Assert.AreEqual(3, SceneManager.Instance.Scenes.Count); 1013 Assert.AreEqual(3, m_sceneHelpers.SceneManager.Scenes.Count);
975 1014
976 TestLoadedRegion(part1, soundItemName, soundData); 1015 TestLoadedRegion(part1, soundItemName, soundData);
977 } 1016 }
978 1017
1018 private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData)
1019 {
1020 SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name);
1021
1022 Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded");
1023 Assert.That(object1PartLoaded.Name, Is.EqualTo(part1.Name), "object1 names not identical");
1024 Assert.That(object1PartLoaded.GroupPosition, Is.EqualTo(part1.GroupPosition), "object1 group position not equal");
1025 Assert.That(
1026 object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal");
1027 Assert.That(
1028 object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal");
1029 Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation));
1030 Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition));
1031
1032 TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0];
1033 Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null");
1034 AssetBase loadedSoundAsset = m_scene.AssetService.Get(loadedSoundItem.AssetID.ToString());
1035 Assert.That(loadedSoundAsset, Is.Not.Null, "loaded sound asset was null");
1036 Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match");
1037
1038 Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels");
1039 }
979 } 1040 }
980} 1041} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 39cc93d..eb06fcc 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -53,6 +53,11 @@ namespace OpenSim.Region.CoreModules.World.Estate
53 53
54 protected EstateManagementCommands m_commands; 54 protected EstateManagementCommands m_commands;
55 55
56 /// <summary>
57 /// If false, region restart requests from the client are blocked even if they are otherwise legitimate.
58 /// </summary>
59 public bool AllowRegionRestartFromClient { get; set; }
60
56 private EstateTerrainXferHandler TerrainUploader; 61 private EstateTerrainXferHandler TerrainUploader;
57 public TelehubManager m_Telehub; 62 public TelehubManager m_Telehub;
58 63
@@ -60,6 +65,53 @@ namespace OpenSim.Region.CoreModules.World.Estate
60 public event ChangeDelegate OnEstateInfoChange; 65 public event ChangeDelegate OnEstateInfoChange;
61 public event MessageDelegate OnEstateMessage; 66 public event MessageDelegate OnEstateMessage;
62 67
68 #region Region Module interface
69
70 public string Name { get { return "EstateManagementModule"; } }
71
72 public Type ReplaceableInterface { get { return null; } }
73
74 public void Initialise(IConfigSource source)
75 {
76 AllowRegionRestartFromClient = true;
77
78 IConfig config = source.Configs["EstateManagement"];
79
80 if (config != null)
81 AllowRegionRestartFromClient = config.GetBoolean("AllowRegionRestartFromClient", true);
82 }
83
84 public void AddRegion(Scene scene)
85 {
86 Scene = scene;
87 Scene.RegisterModuleInterface<IEstateModule>(this);
88 Scene.EventManager.OnNewClient += EventManager_OnNewClient;
89 Scene.EventManager.OnRequestChangeWaterHeight += changeWaterHeight;
90
91 m_Telehub = new TelehubManager(scene);
92
93 m_commands = new EstateManagementCommands(this);
94 m_commands.Initialise();
95 }
96
97 public void RemoveRegion(Scene scene) {}
98
99 public void RegionLoaded(Scene scene)
100 {
101 // Sets up the sun module based no the saved Estate and Region Settings
102 // DO NOT REMOVE or the sun will stop working
103 scene.TriggerEstateSunUpdate();
104
105 UserManager = scene.RequestModuleInterface<IUserManagement>();
106 }
107
108 public void Close()
109 {
110 m_commands.Close();
111 }
112
113 #endregion
114
63 #region Packet Data Responders 115 #region Packet Data Responders
64 116
65 private void sendDetailedEstateData(IClientAPI remote_client, UUID invoice) 117 private void sendDetailedEstateData(IClientAPI remote_client, UUID invoice)
@@ -184,6 +236,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
184 Scene.RegionInfo.RegionSettings.TerrainTexture4 = texture; 236 Scene.RegionInfo.RegionSettings.TerrainTexture4 = texture;
185 break; 237 break;
186 } 238 }
239
187 Scene.RegionInfo.RegionSettings.Save(); 240 Scene.RegionInfo.RegionSettings.Save();
188 TriggerRegionInfoChange(); 241 TriggerRegionInfoChange();
189 sendRegionInfoPacketToAll(); 242 sendRegionInfoPacketToAll();
@@ -215,6 +268,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
215 Scene.RegionInfo.RegionSettings.Elevation2NE = highValue; 268 Scene.RegionInfo.RegionSettings.Elevation2NE = highValue;
216 break; 269 break;
217 } 270 }
271
218 Scene.RegionInfo.RegionSettings.Save(); 272 Scene.RegionInfo.RegionSettings.Save();
219 TriggerRegionInfoChange(); 273 TriggerRegionInfoChange();
220 sendRegionHandshakeToAll(); 274 sendRegionHandshakeToAll();
@@ -255,6 +309,12 @@ namespace OpenSim.Region.CoreModules.World.Estate
255 309
256 private void handleEstateRestartSimRequest(IClientAPI remoteClient, int timeInSeconds) 310 private void handleEstateRestartSimRequest(IClientAPI remoteClient, int timeInSeconds)
257 { 311 {
312 if (!AllowRegionRestartFromClient)
313 {
314 remoteClient.SendAlertMessage("Region restart has been disabled on this simulator.");
315 return;
316 }
317
258 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>(); 318 IRestartModule restartModule = Scene.RequestModuleInterface<IRestartModule>();
259 if (restartModule != null) 319 if (restartModule != null)
260 { 320 {
@@ -271,6 +331,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
271 } 331 }
272 332
273 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true); 333 restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true);
334
335 m_log.InfoFormat(
336 "User {0} requested restart of region {1} in {2} seconds",
337 remoteClient.Name, Scene.Name, times.Count != 0 ? times[0] : 0);
274 } 338 }
275 } 339 }
276 340
@@ -295,7 +359,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
295 359
296 if ((estateAccessType & 4) != 0) // User add 360 if ((estateAccessType & 4) != 0) // User add
297 { 361 {
298 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 362 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
299 { 363 {
300 if ((estateAccessType & 1) != 0) // All estates 364 if ((estateAccessType & 1) != 0) // All estates
301 { 365 {
@@ -325,9 +389,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
325 } 389 }
326 390
327 } 391 }
392
328 if ((estateAccessType & 8) != 0) // User remove 393 if ((estateAccessType & 8) != 0) // User remove
329 { 394 {
330 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 395 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
331 { 396 {
332 if ((estateAccessType & 1) != 0) // All estates 397 if ((estateAccessType & 1) != 0) // All estates
333 { 398 {
@@ -356,9 +421,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
356 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 421 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
357 } 422 }
358 } 423 }
424
359 if ((estateAccessType & 16) != 0) // Group add 425 if ((estateAccessType & 16) != 0) // Group add
360 { 426 {
361 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 427 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
362 { 428 {
363 if ((estateAccessType & 1) != 0) // All estates 429 if ((estateAccessType & 1) != 0) // All estates
364 { 430 {
@@ -387,9 +453,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
387 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 453 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
388 } 454 }
389 } 455 }
456
390 if ((estateAccessType & 32) != 0) // Group remove 457 if ((estateAccessType & 32) != 0) // Group remove
391 { 458 {
392 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 459 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
393 { 460 {
394 if ((estateAccessType & 1) != 0) // All estates 461 if ((estateAccessType & 1) != 0) // All estates
395 { 462 {
@@ -418,9 +485,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
418 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 485 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
419 } 486 }
420 } 487 }
488
421 if ((estateAccessType & 64) != 0) // Ban add 489 if ((estateAccessType & 64) != 0) // Ban add
422 { 490 {
423 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || Scene.Permissions.BypassPermissions()) 491 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false))
424 { 492 {
425 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans; 493 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans;
426 494
@@ -495,9 +563,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
495 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 563 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
496 } 564 }
497 } 565 }
566
498 if ((estateAccessType & 128) != 0) // Ban remove 567 if ((estateAccessType & 128) != 0) // Ban remove
499 { 568 {
500 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false) || Scene.Permissions.BypassPermissions()) 569 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, false))
501 { 570 {
502 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans; 571 EstateBan[] banlistcheck = Scene.RegionInfo.EstateSettings.EstateBans;
503 572
@@ -550,9 +619,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
550 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 619 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
551 } 620 }
552 } 621 }
622
553 if ((estateAccessType & 256) != 0) // Manager add 623 if ((estateAccessType & 256) != 0) // Manager add
554 { 624 {
555 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 625 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
556 { 626 {
557 if ((estateAccessType & 1) != 0) // All estates 627 if ((estateAccessType & 1) != 0) // All estates
558 { 628 {
@@ -581,9 +651,10 @@ namespace OpenSim.Region.CoreModules.World.Estate
581 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions"); 651 remote_client.SendAlertMessage("Method EstateAccessDelta Failed, you don't have permissions");
582 } 652 }
583 } 653 }
654
584 if ((estateAccessType & 512) != 0) // Manager remove 655 if ((estateAccessType & 512) != 0) // Manager remove
585 { 656 {
586 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true) || Scene.Permissions.BypassPermissions()) 657 if (Scene.Permissions.CanIssueEstateCommand(remote_client.AgentId, true))
587 { 658 {
588 if ((estateAccessType & 1) != 0) // All estates 659 if ((estateAccessType & 1) != 0) // All estates
589 { 660 {
@@ -614,7 +685,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
614 } 685 }
615 } 686 }
616 687
617 public void handleOnEstateManageTelehub (IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1) 688 public void handleOnEstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1)
618 { 689 {
619 SceneObjectPart part; 690 SceneObjectPart part;
620 691
@@ -1072,45 +1143,6 @@ namespace OpenSim.Region.CoreModules.World.Estate
1072 1143
1073 #endregion 1144 #endregion
1074 1145
1075 #region Region Module interface
1076
1077 public string Name { get { return "EstateManagementModule"; } }
1078
1079 public Type ReplaceableInterface { get { return null; } }
1080
1081 public void Initialise(IConfigSource source) {}
1082
1083 public void AddRegion(Scene scene)
1084 {
1085 Scene = scene;
1086 Scene.RegisterModuleInterface<IEstateModule>(this);
1087 Scene.EventManager.OnNewClient += EventManager_OnNewClient;
1088 Scene.EventManager.OnRequestChangeWaterHeight += changeWaterHeight;
1089
1090 m_Telehub = new TelehubManager(scene);
1091
1092 m_commands = new EstateManagementCommands(this);
1093 m_commands.Initialise();
1094 }
1095
1096 public void RemoveRegion(Scene scene) {}
1097
1098 public void RegionLoaded(Scene scene)
1099 {
1100 // Sets up the sun module based no the saved Estate and Region Settings
1101 // DO NOT REMOVE or the sun will stop working
1102 scene.TriggerEstateSunUpdate();
1103
1104 UserManager = scene.RequestModuleInterface<IUserManagement>();
1105 }
1106
1107 public void Close()
1108 {
1109 m_commands.Close();
1110 }
1111
1112 #endregion
1113
1114 #region Other Functions 1146 #region Other Functions
1115 1147
1116 public void changeWaterHeight(float height) 1148 public void changeWaterHeight(float height)
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 8682798..7149aad 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -1378,10 +1378,11 @@ namespace OpenSim.Region.CoreModules.World.Land
1378 1378
1379 public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data) 1379 public void EventManagerOnIncomingLandDataFromStorage(List<LandData> data)
1380 { 1380 {
1381// m_log.DebugFormat(
1382// "[LAND MANAGMENT MODULE]: Processing {0} incoming parcels on {1}", data.Count, m_scene.Name);
1383
1381 for (int i = 0; i < data.Count; i++) 1384 for (int i = 0; i < data.Count; i++)
1382 {
1383 IncomingLandObjectFromStorage(data[i]); 1385 IncomingLandObjectFromStorage(data[i]);
1384 }
1385 } 1386 }
1386 1387
1387 public void IncomingLandObjectFromStorage(LandData data) 1388 public void IncomingLandObjectFromStorage(LandData data)
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 8829f27..5969d45 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -727,9 +727,10 @@ namespace OpenSim.Region.CoreModules.World.Land
727 int ty = min_y * 4; 727 int ty = min_y * 4;
728 if (ty > ((int)Constants.RegionSize - 1)) 728 if (ty > ((int)Constants.RegionSize - 1))
729 ty = ((int)Constants.RegionSize - 1); 729 ty = ((int)Constants.RegionSize - 1);
730
730 LandData.AABBMin = 731 LandData.AABBMin =
731 new Vector3((float) (min_x * 4), (float) (min_y * 4), 732 new Vector3(
732 (float) m_scene.Heightmap[tx, ty]); 733 (float)(min_x * 4), (float)(min_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
733 734
734 tx = max_x * 4; 735 tx = max_x * 4;
735 if (tx > ((int)Constants.RegionSize - 1)) 736 if (tx > ((int)Constants.RegionSize - 1))
@@ -737,9 +738,11 @@ namespace OpenSim.Region.CoreModules.World.Land
737 ty = max_y * 4; 738 ty = max_y * 4;
738 if (ty > ((int)Constants.RegionSize - 1)) 739 if (ty > ((int)Constants.RegionSize - 1))
739 ty = ((int)Constants.RegionSize - 1); 740 ty = ((int)Constants.RegionSize - 1);
740 LandData.AABBMax = 741
741 new Vector3((float) (max_x * 4), (float) (max_y * 4), 742 LandData.AABBMax
742 (float) m_scene.Heightmap[tx, ty]); 743 = new Vector3(
744 (float)(max_x * 4), (float)(max_y * 4), m_scene != null ? (float)m_scene.Heightmap[tx, ty] : 0);
745
743 LandData.Area = tempArea; 746 LandData.Area = tempArea;
744 } 747 }
745 748
diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
index b5ee4d2..14eca42 100644
--- a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
+++ b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
@@ -41,7 +41,7 @@ using OpenSim.Tests.Common.Mock;
41namespace OpenSim.Region.CoreModules.World.Land.Tests 41namespace OpenSim.Region.CoreModules.World.Land.Tests
42{ 42{
43 [TestFixture] 43 [TestFixture]
44 public class PrimCountModuleTests 44 public class PrimCountModuleTests : OpenSimTestCase
45 { 45 {
46 protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000"); 46 protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000");
47 protected UUID m_groupId = new UUID("00000000-0000-0000-8888-000000000000"); 47 protected UUID m_groupId = new UUID("00000000-0000-0000-8888-000000000000");
diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
index 396095a..ba4b041 100644
--- a/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
+++ b/OpenSim/Region/CoreModules/World/Media/Moap/Tests/MoapTests.cs
@@ -44,7 +44,7 @@ using OpenSim.Tests.Common.Mock;
44namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests 44namespace OpenSim.Region.CoreModules.World.Media.Moap.Tests
45{ 45{
46 [TestFixture] 46 [TestFixture]
47 public class MoapTests 47 public class MoapTests : OpenSimTestCase
48 { 48 {
49 protected TestScene m_scene; 49 protected TestScene m_scene;
50 protected MoapModule m_module; 50 protected MoapModule m_module;
diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
index fea4de0..249a40d 100644
--- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
+++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Linq;
29using System.Reflection; 30using System.Reflection;
30using System.Timers; 31using System.Timers;
31using System.Threading; 32using System.Threading;
@@ -264,7 +265,10 @@ namespace OpenSim.Region.CoreModules.World.Region
264 for (int i = 4 ; i < args.Length ; i++) 265 for (int i = 4 ; i < args.Length ; i++)
265 times.Add(Convert.ToInt32(args[i])); 266 times.Add(Convert.ToInt32(args[i]));
266 267
268 MainConsole.Instance.OutputFormat(
269 "Region {0} scheduled for restart in {1} seconds", m_Scene.Name, times.Sum());
270
267 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice); 271 ScheduleRestart(UUID.Zero, args[3], times.ToArray(), notice);
268 } 272 }
269 } 273 }
270} 274} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
index 7825e3e..bcb8e2f 100644
--- a/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
+++ b/OpenSim/Region/CoreModules/World/Serialiser/Tests/SerialiserTests.cs
@@ -39,7 +39,7 @@ using OpenSim.Tests.Common;
39namespace OpenSim.Region.CoreModules.World.Serialiser.Tests 39namespace OpenSim.Region.CoreModules.World.Serialiser.Tests
40{ 40{
41 [TestFixture] 41 [TestFixture]
42 public class SerialiserTests 42 public class SerialiserTests : OpenSimTestCase
43 { 43 {
44 private string xml = @" 44 private string xml = @"
45 <SceneObjectGroup> 45 <SceneObjectGroup>
diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
index 513a8f5..089fcda 100644
--- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
+++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs
@@ -43,8 +43,8 @@ namespace OpenSim.Region.CoreModules.World.Sound
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")] 43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")]
44 public class SoundModule : INonSharedRegionModule, ISoundModule 44 public class SoundModule : INonSharedRegionModule, ISoundModule
45 { 45 {
46 private static readonly ILog m_log = LogManager.GetLogger( 46// private static readonly ILog m_log = LogManager.GetLogger(
47 MethodBase.GetCurrentMethod().DeclaringType); 47// MethodBase.GetCurrentMethod().DeclaringType);
48 48
49 private Scene m_scene; 49 private Scene m_scene;
50 50
diff --git a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
index 3d4f762..be719ea 100644
--- a/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
+++ b/OpenSim/Region/CoreModules/World/Terrain/Tests/TerrainTest.cs
@@ -30,11 +30,12 @@ using NUnit.Framework;
30using OpenSim.Framework; 30using OpenSim.Framework;
31using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes; 31using OpenSim.Region.CoreModules.World.Terrain.PaintBrushes;
32using OpenSim.Region.Framework.Scenes; 32using OpenSim.Region.Framework.Scenes;
33using OpenSim.Tests.Common;
33 34
34namespace OpenSim.Region.CoreModules.World.Terrain.Tests 35namespace OpenSim.Region.CoreModules.World.Terrain.Tests
35{ 36{
36 [TestFixture] 37 [TestFixture]
37 public class TerrainTest 38 public class TerrainTest : OpenSimTestCase
38 { 39 {
39 [Test] 40 [Test]
40 public void BrushTest() 41 public void BrushTest()
diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
index fd8e2b4..9de588c 100644
--- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
+++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs
@@ -66,7 +66,7 @@ namespace OpenSim.Region.CoreModules
66 public void Initialise(IConfigSource config) 66 public void Initialise(IConfigSource config)
67 { 67 {
68 m_windConfig = config.Configs["Wind"]; 68 m_windConfig = config.Configs["Wind"];
69 string desiredWindPlugin = m_dWindPluginName; 69// string desiredWindPlugin = m_dWindPluginName;
70 70
71 if (m_windConfig != null) 71 if (m_windConfig != null)
72 { 72 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index db45d6b..1ad5edd 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -740,7 +740,12 @@ namespace OpenSim.Region.Framework.Scenes
740 // 740 //
741 // Out of memory 741 // Out of memory
742 // Operating system has killed the plugin 742 // Operating system has killed the plugin
743 m_sceneGraph.UnRecoverableError += RestartNow; 743 m_sceneGraph.UnRecoverableError
744 += () =>
745 {
746 m_log.ErrorFormat("[SCENE]: Restarting region {0} due to unrecoverable physics crash", Name);
747 RestartNow();
748 };
744 749
745 RegisterDefaultSceneEvents(); 750 RegisterDefaultSceneEvents();
746 751
@@ -1134,15 +1139,9 @@ namespace OpenSim.Region.Framework.Scenes
1134 } 1139 }
1135 } 1140 }
1136 1141
1137 m_log.Error("[REGION]: Closing"); 1142 m_log.InfoFormat("[REGION]: Restarting region {0}", Name);
1138 Close();
1139 1143
1140 if (PhysicsScene != null) 1144 Close();
1141 {
1142 PhysicsScene.Dispose();
1143 }
1144
1145 m_log.Error("[REGION]: Firing Region Restart Message");
1146 1145
1147 base.Restart(); 1146 base.Restart();
1148 } 1147 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index 9bd27d3..1e2e973 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -100,23 +100,25 @@ namespace OpenSim.Region.Framework.Scenes
100 } 100 }
101 101
102 private readonly List<Scene> m_localScenes = new List<Scene>(); 102 private readonly List<Scene> m_localScenes = new List<Scene>();
103 private Scene m_currentScene = null;
104 103
105 public List<Scene> Scenes 104 public List<Scene> Scenes
106 { 105 {
107 get { return new List<Scene>(m_localScenes); } 106 get { return new List<Scene>(m_localScenes); }
108 } 107 }
109 108
110 public Scene CurrentScene 109 /// <summary>
111 { 110 /// Scene selected from the console.
112 get { return m_currentScene; } 111 /// </summary>
113 } 112 /// <value>
113 /// If null, then all scenes are considered selected (signalled as "Root" on the console).
114 /// </value>
115 public Scene CurrentScene { get; private set; }
114 116
115 public Scene CurrentOrFirstScene 117 public Scene CurrentOrFirstScene
116 { 118 {
117 get 119 get
118 { 120 {
119 if (m_currentScene == null) 121 if (CurrentScene == null)
120 { 122 {
121 lock (m_localScenes) 123 lock (m_localScenes)
122 { 124 {
@@ -128,7 +130,7 @@ namespace OpenSim.Region.Framework.Scenes
128 } 130 }
129 else 131 else
130 { 132 {
131 return m_currentScene; 133 return CurrentScene;
132 } 134 }
133 } 135 }
134 } 136 }
@@ -141,6 +143,13 @@ namespace OpenSim.Region.Framework.Scenes
141 143
142 public void Close() 144 public void Close()
143 { 145 {
146 lock (m_localScenes)
147 {
148 for (int i = 0; i < m_localScenes.Count; i++)
149 {
150 m_localScenes[i].Close();
151 }
152 }
144 } 153 }
145 154
146 public void Close(Scene cscene) 155 public void Close(Scene cscene)
@@ -171,8 +180,7 @@ namespace OpenSim.Region.Framework.Scenes
171 180
172 public void HandleRestart(RegionInfo rdata) 181 public void HandleRestart(RegionInfo rdata)
173 { 182 {
174 m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main"); 183 Scene restartedScene = null;
175 int RegionSceneElement = -1;
176 184
177 lock (m_localScenes) 185 lock (m_localScenes)
178 { 186 {
@@ -180,19 +188,18 @@ namespace OpenSim.Region.Framework.Scenes
180 { 188 {
181 if (rdata.RegionName == m_localScenes[i].RegionInfo.RegionName) 189 if (rdata.RegionName == m_localScenes[i].RegionInfo.RegionName)
182 { 190 {
183 RegionSceneElement = i; 191 restartedScene = m_localScenes[i];
192 m_localScenes.RemoveAt(i);
193 break;
184 } 194 }
185 } 195 }
186
187 // Now we make sure the region is no longer known about by the SceneManager
188 // Prevents duplicates.
189
190 if (RegionSceneElement >= 0)
191 {
192 m_localScenes.RemoveAt(RegionSceneElement);
193 }
194 } 196 }
195 197
198 // If the currently selected scene has been restarted, then we can't reselect here since we the scene
199 // hasn't yet been recreated. We will have to leave this to the caller.
200 if (CurrentScene == restartedScene)
201 CurrentScene = null;
202
196 // Send signal to main that we're restarting this sim. 203 // Send signal to main that we're restarting this sim.
197 OnRestartSim(rdata); 204 OnRestartSim(rdata);
198 } 205 }
@@ -334,14 +341,14 @@ namespace OpenSim.Region.Framework.Scenes
334 341
335 private void ForEachCurrentScene(Action<Scene> func) 342 private void ForEachCurrentScene(Action<Scene> func)
336 { 343 {
337 if (m_currentScene == null) 344 if (CurrentScene == null)
338 { 345 {
339 lock (m_localScenes) 346 lock (m_localScenes)
340 m_localScenes.ForEach(func); 347 m_localScenes.ForEach(func);
341 } 348 }
342 else 349 else
343 { 350 {
344 func(m_currentScene); 351 func(CurrentScene);
345 } 352 }
346 } 353 }
347 354
@@ -361,7 +368,7 @@ namespace OpenSim.Region.Framework.Scenes
361 || (String.Compare(regionName, "..") == 0) 368 || (String.Compare(regionName, "..") == 0)
362 || (String.Compare(regionName, "/") == 0)) 369 || (String.Compare(regionName, "/") == 0))
363 { 370 {
364 m_currentScene = null; 371 CurrentScene = null;
365 return true; 372 return true;
366 } 373 }
367 else 374 else
@@ -372,7 +379,7 @@ namespace OpenSim.Region.Framework.Scenes
372 { 379 {
373 if (String.Compare(scene.RegionInfo.RegionName, regionName, true) == 0) 380 if (String.Compare(scene.RegionInfo.RegionName, regionName, true) == 0)
374 { 381 {
375 m_currentScene = scene; 382 CurrentScene = scene;
376 return true; 383 return true;
377 } 384 }
378 } 385 }
@@ -392,7 +399,7 @@ namespace OpenSim.Region.Framework.Scenes
392 { 399 {
393 if (scene.RegionInfo.RegionID == regionID) 400 if (scene.RegionInfo.RegionID == regionID)
394 { 401 {
395 m_currentScene = scene; 402 CurrentScene = scene;
396 return true; 403 return true;
397 } 404 }
398 } 405 }
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 96bca3e..6f36c0b 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1698,8 +1698,16 @@ namespace OpenSim.Region.Framework.Scenes
1698// "[SCENE PRESENCE]: Avatar {0} received request to move to position {1} in {2}", 1698// "[SCENE PRESENCE]: Avatar {0} received request to move to position {1} in {2}",
1699// Name, pos, m_scene.RegionInfo.RegionName); 1699// Name, pos, m_scene.RegionInfo.RegionName);
1700 1700
1701 if (pos.X < 0 || pos.X >= Constants.RegionSize 1701 // Allow move to another sub-region within a megaregion
1702 || pos.Y < 0 || pos.Y >= Constants.RegionSize 1702 Vector2 regionSize;
1703 IRegionCombinerModule regionCombinerModule = m_scene.RequestModuleInterface<IRegionCombinerModule>();
1704 if (regionCombinerModule != null)
1705 regionSize = regionCombinerModule.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID);
1706 else
1707 regionSize = new Vector2(Constants.RegionSize);
1708
1709 if (pos.X < 0 || pos.X >= regionSize.X
1710 || pos.Y < 0 || pos.Y >= regionSize.Y
1703 || pos.Z < 0) 1711 || pos.Z < 0)
1704 return; 1712 return;
1705 1713
@@ -1713,7 +1721,16 @@ namespace OpenSim.Region.Framework.Scenes
1713// pos.Z = AbsolutePosition.Z; 1721// pos.Z = AbsolutePosition.Z;
1714// } 1722// }
1715 1723
1716 float terrainHeight = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 1724 // Get terrain height for sub-region in a megaregion if necessary
1725 int X = (int)((m_scene.RegionInfo.RegionLocX * Constants.RegionSize) + pos.X);
1726 int Y = (int)((m_scene.RegionInfo.RegionLocY * Constants.RegionSize) + pos.Y);
1727 UUID target_regionID = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y).RegionID;
1728 Scene targetScene = m_scene;
1729
1730 if (!SceneManager.Instance.TryGetScene(target_regionID, out targetScene))
1731 targetScene = m_scene;
1732
1733 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % Constants.RegionSize), (int)(pos.Y % Constants.RegionSize)];
1717 pos.Z = Math.Max(terrainHeight, pos.Z); 1734 pos.Z = Math.Max(terrainHeight, pos.Z);
1718 1735
1719 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 1736 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
diff --git a/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs b/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs
index 4a21dc9..e209221 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/BorderTests.cs
@@ -37,7 +37,7 @@ using OpenSim.Tests.Common;
37namespace OpenSim.Region.Framework.Scenes.Tests 37namespace OpenSim.Region.Framework.Scenes.Tests
38{ 38{
39 [TestFixture] 39 [TestFixture]
40 public class BorderTests 40 public class BorderTests : OpenSimTestCase
41 { 41 {
42 [Test] 42 [Test]
43 public void TestCross() 43 public void TestCross()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
index ea9fc93..766ce83 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
@@ -41,7 +41,7 @@ using OpenSim.Tests.Common;
41namespace OpenSim.Region.Framework.Scenes.Tests 41namespace OpenSim.Region.Framework.Scenes.Tests
42{ 42{
43 [TestFixture, LongRunning] 43 [TestFixture, LongRunning]
44 public class EntityManagerTests 44 public class EntityManagerTests : OpenSimTestCase
45 { 45 {
46 static public Random random; 46 static public Random random;
47 SceneObjectGroup found; 47 SceneObjectGroup found;
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
index d23c965..575a081 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs
@@ -40,7 +40,7 @@ using OpenSim.Tests.Common.Mock;
40namespace OpenSim.Region.Framework.Scenes.Tests 40namespace OpenSim.Region.Framework.Scenes.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class SceneGraphTests 43 public class SceneGraphTests : OpenSimTestCase
44 { 44 {
45 [Test] 45 [Test]
46 public void TestDuplicateObject() 46 public void TestDuplicateObject()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs
new file mode 100644
index 0000000..2d831fa
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneManagerTests.cs
@@ -0,0 +1,58 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Threading;
32using NUnit.Framework;
33using OpenMetaverse;
34using OpenSim.Framework;
35using OpenSim.Framework.Communications;
36using OpenSim.Region.Framework.Scenes;
37using OpenSim.Services.Interfaces;
38using OpenSim.Tests.Common;
39using OpenSim.Tests.Common.Mock;
40
41namespace OpenSim.Region.Framework.Scenes.Tests
42{
43 [TestFixture]
44 public class SceneManagerTests : OpenSimTestCase
45 {
46 [Test]
47 public void TestClose()
48 {
49 TestHelpers.InMethod();
50
51 SceneHelpers sh = new SceneHelpers();
52 Scene scene = sh.SetupScene();
53
54 sh.SceneManager.Close();
55 Assert.That(scene.ShuttingDown, Is.True);
56 }
57 }
58} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
index 5b334c6..a07d64c 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Threading; 31using System.Threading;
32using Nini.Config;
32using NUnit.Framework; 33using NUnit.Framework;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
@@ -182,6 +183,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
182 /// <summary> 183 /// <summary>
183 /// Test deleting an object from a scene. 184 /// Test deleting an object from a scene.
184 /// </summary> 185 /// </summary>
186 /// <remarks>
187 /// This is the most basic form of delete. For all more sophisticated forms of derez (done asynchrnously
188 /// and where object can be taken to user inventory, etc.), see SceneObjectDeRezTests.
189 /// </remarks>
185 [Test] 190 [Test]
186 public void TestDeleteSceneObject() 191 public void TestDeleteSceneObject()
187 { 192 {
@@ -201,100 +206,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
201 } 206 }
202 207
203 /// <summary> 208 /// <summary>
204 /// Test deleting an object asynchronously
205 /// </summary>
206 [Test]
207 public void TestDeleteSceneObjectAsync()
208 {
209 TestHelpers.InMethod();
210 //log4net.Config.XmlConfigurator.Configure();
211
212 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001");
213
214 TestScene scene = new SceneHelpers().SetupScene();
215
216 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
217 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
218 sogd.Enabled = false;
219
220 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene);
221
222 IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient;
223 scene.DeRezObjects(client, new System.Collections.Generic.List<uint>() { so.LocalId }, UUID.Zero, DeRezAction.Delete, UUID.Zero);
224
225 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
226
227 Assert.That(retrievedPart, Is.Not.Null);
228
229 Assert.That(so.IsDeleted, Is.False);
230
231 sogd.InventoryDeQueueAndDelete();
232
233 Assert.That(so.IsDeleted, Is.True);
234
235 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
236 Assert.That(retrievedPart2, Is.Null);
237 }
238
239 /// <summary>
240 /// Test deleting an object asynchronously to user inventory.
241 /// </summary>
242// [Test]
243 public void TestDeleteSceneObjectAsyncToUserInventory()
244 {
245 TestHelpers.InMethod();
246 TestHelpers.EnableLogging();
247
248 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001");
249 string myObjectName = "Fred";
250
251 TestScene scene = new SceneHelpers().SetupScene();
252
253 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
254 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
255 sogd.Enabled = false;
256
257 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, myObjectName, agentId);
258
259// Assert.That(
260// scene.CommsManager.UserAdminService.AddUser(
261// "Bob", "Hoskins", "test", "test@test.com", 1000, 1000, agentId),
262// Is.EqualTo(agentId));
263
264 UserAccount ua = UserAccountHelpers.CreateUserWithInventory(scene, agentId);
265 InventoryFolderBase folder1
266 = UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, ua.PrincipalID, "folder1");
267
268 IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient;
269 scene.DeRezObjects(client, new List<uint>() { so.LocalId }, UUID.Zero, DeRezAction.Take, folder1.ID);
270
271 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
272
273 Assert.That(retrievedPart, Is.Not.Null);
274 Assert.That(so.IsDeleted, Is.False);
275
276 sogd.InventoryDeQueueAndDelete();
277
278 Assert.That(so.IsDeleted, Is.True);
279
280 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
281 Assert.That(retrievedPart2, Is.Null);
282
283// SceneSetupHelpers.DeleteSceneObjectAsync(scene, part, DeRezAction.Take, userInfo.RootFolder.ID, client);
284
285 InventoryItemBase retrievedItem
286 = UserInventoryHelpers.GetInventoryItem(
287 scene.InventoryService, ua.PrincipalID, "folder1/" + myObjectName);
288
289 // Check that we now have the taken part in our inventory
290 Assert.That(retrievedItem, Is.Not.Null);
291
292 // Check that the taken part has actually disappeared
293// SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
294// Assert.That(retrievedPart, Is.Null);
295 }
296
297 /// <summary>
298 /// Changing a scene object uuid changes the root part uuid. This is a valid operation if the object is not 209 /// Changing a scene object uuid changes the root part uuid. This is a valid operation if the object is not
299 /// in a scene and is useful if one wants to supply a UUID directly rather than use the one generated by 210 /// in a scene and is useful if one wants to supply a UUID directly rather than use the one generated by
300 /// OpenSim. 211 /// OpenSim.
@@ -329,4 +240,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
329 Assert.That(sog.Parts.Length, Is.EqualTo(2)); 240 Assert.That(sog.Parts.Length, Is.EqualTo(2));
330 } 241 }
331 } 242 }
332} 243} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
index 0076f41..c1522e7 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
@@ -33,22 +33,24 @@ using NUnit.Framework;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Framework.Communications; 35using OpenSim.Framework.Communications;
36using OpenSim.Region.CoreModules.Framework.InventoryAccess;
36using OpenSim.Region.CoreModules.World.Permissions; 37using OpenSim.Region.CoreModules.World.Permissions;
37using OpenSim.Region.Framework.Scenes; 38using OpenSim.Region.Framework.Scenes;
39using OpenSim.Services.Interfaces;
38using OpenSim.Tests.Common; 40using OpenSim.Tests.Common;
39using OpenSim.Tests.Common.Mock; 41using OpenSim.Tests.Common.Mock;
40 42
41namespace OpenSim.Region.Framework.Scenes.Tests 43namespace OpenSim.Region.Framework.Scenes.Tests
42{ 44{
43 /// <summary> 45 /// <summary>
44 /// Tests derez of scene objects by users. 46 /// Tests derez of scene objects.
45 /// </summary> 47 /// </summary>
46 /// <remarks> 48 /// <remarks>
47 /// This is at a level above the SceneObjectBasicTests, which act on the scene directly. 49 /// This is at a level above the SceneObjectBasicTests, which act on the scene directly.
48 /// TODO: These tests are very incomplete - they only test for a few conditions. 50 /// TODO: These tests are incomplete - need to test more kinds of derez (e.g. return object).
49 /// </remarks> 51 /// </remarks>
50 [TestFixture] 52 [TestFixture]
51 public class SceneObjectDeRezTests 53 public class SceneObjectDeRezTests : OpenSimTestCase
52 { 54 {
53 /// <summary> 55 /// <summary>
54 /// Test deleting an object from a scene. 56 /// Test deleting an object from a scene.
@@ -76,14 +78,20 @@ namespace OpenSim.Region.Framework.Scenes.Tests
76 = new SceneObjectPart(userId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero); 78 = new SceneObjectPart(userId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero);
77 part.Name = "obj1"; 79 part.Name = "obj1";
78 scene.AddNewSceneObject(new SceneObjectGroup(part), false); 80 scene.AddNewSceneObject(new SceneObjectGroup(part), false);
81
79 List<uint> localIds = new List<uint>(); 82 List<uint> localIds = new List<uint>();
80 localIds.Add(part.LocalId); 83 localIds.Add(part.LocalId);
81
82 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero); 84 scene.DeRezObjects(client, localIds, UUID.Zero, DeRezAction.Delete, UUID.Zero);
85
86 // Check that object isn't deleted until we crank the sogd handle.
87 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
88 Assert.That(retrievedPart, Is.Not.Null);
89 Assert.That(retrievedPart.ParentGroup.IsDeleted, Is.False);
90
83 sogd.InventoryDeQueueAndDelete(); 91 sogd.InventoryDeQueueAndDelete();
84 92
85 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); 93 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(part.LocalId);
86 Assert.That(retrievedPart, Is.Null); 94 Assert.That(retrievedPart2, Is.Null);
87 } 95 }
88 96
89 /// <summary> 97 /// <summary>
@@ -124,6 +132,67 @@ namespace OpenSim.Region.Framework.Scenes.Tests
124 // Object should still be in the scene. 132 // Object should still be in the scene.
125 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId); 133 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
126 Assert.That(retrievedPart.UUID, Is.EqualTo(part.UUID)); 134 Assert.That(retrievedPart.UUID, Is.EqualTo(part.UUID));
127 } 135 }
136
137 /// <summary>
138 /// Test deleting an object asynchronously to user inventory.
139 /// </summary>
140 [Test]
141 public void TestDeleteSceneObjectAsyncToUserInventory()
142 {
143 TestHelpers.InMethod();
144// TestHelpers.EnableLogging();
145
146 UUID agentId = UUID.Parse("00000000-0000-0000-0000-000000000001");
147 string myObjectName = "Fred";
148
149 TestScene scene = new SceneHelpers().SetupScene();
150
151 IConfigSource configSource = new IniConfigSource();
152 IConfig config = configSource.AddConfig("Modules");
153 config.Set("InventoryAccessModule", "BasicInventoryAccessModule");
154 SceneHelpers.SetupSceneModules(
155 scene, configSource, new object[] { new BasicInventoryAccessModule() });
156
157 SceneHelpers.SetupSceneModules(scene, new object[] { });
158
159 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
160 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
161 sogd.Enabled = false;
162
163 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, myObjectName, agentId);
164
165 UserAccount ua = UserAccountHelpers.CreateUserWithInventory(scene, agentId);
166 InventoryFolderBase folder1
167 = UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, ua.PrincipalID, "folder1");
168
169 IClientAPI client = SceneHelpers.AddScenePresence(scene, agentId).ControllingClient;
170 scene.DeRezObjects(client, new List<uint>() { so.LocalId }, UUID.Zero, DeRezAction.Take, folder1.ID);
171
172 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(so.LocalId);
173
174 Assert.That(retrievedPart, Is.Not.Null);
175 Assert.That(so.IsDeleted, Is.False);
176
177 sogd.InventoryDeQueueAndDelete();
178
179 Assert.That(so.IsDeleted, Is.True);
180
181 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
182 Assert.That(retrievedPart2, Is.Null);
183
184// SceneSetupHelpers.DeleteSceneObjectAsync(scene, part, DeRezAction.Take, userInfo.RootFolder.ID, client);
185
186 InventoryItemBase retrievedItem
187 = UserInventoryHelpers.GetInventoryItem(
188 scene.InventoryService, ua.PrincipalID, "folder1/" + myObjectName);
189
190 // Check that we now have the taken part in our inventory
191 Assert.That(retrievedItem, Is.Not.Null);
192
193 // Check that the taken part has actually disappeared
194// SceneObjectPart retrievedPart = scene.GetSceneObjectPart(part.LocalId);
195// Assert.That(retrievedPart, Is.Null);
196 }
128 } 197 }
129} \ No newline at end of file 198} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
index 0e525c9..9378e20 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectLinkingTests.cs
@@ -40,7 +40,7 @@ using log4net;
40namespace OpenSim.Region.Framework.Scenes.Tests 40namespace OpenSim.Region.Framework.Scenes.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class SceneObjectLinkingTests 43 public class SceneObjectLinkingTests : OpenSimTestCase
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
index 89647d6..c264433 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
41 /// Basic scene object resize tests 41 /// Basic scene object resize tests
42 /// </summary> 42 /// </summary>
43 [TestFixture] 43 [TestFixture]
44 public class SceneObjectResizeTests 44 public class SceneObjectResizeTests : OpenSimTestCase
45 { 45 {
46 /// <summary> 46 /// <summary>
47 /// Test resizing an object 47 /// Test resizing an object
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs
index d2361f8..a58e735 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs
@@ -40,7 +40,7 @@ using OpenSim.Tests.Common.Mock;
40namespace OpenSim.Region.Framework.Scenes.Tests 40namespace OpenSim.Region.Framework.Scenes.Tests
41{ 41{
42 [TestFixture] 42 [TestFixture]
43 public class SceneObjectScriptTests 43 public class SceneObjectScriptTests : OpenSimTestCase
44 { 44 {
45 [Test] 45 [Test]
46 public void TestAddScript() 46 public void TestAddScript()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
index 6d255aa..abaa1d1 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSpatialTests.cs
@@ -42,14 +42,16 @@ namespace OpenSim.Region.Framework.Scenes.Tests
42 /// Spatial scene object tests (will eventually cover root and child part position, rotation properties, etc.) 42 /// Spatial scene object tests (will eventually cover root and child part position, rotation properties, etc.)
43 /// </summary> 43 /// </summary>
44 [TestFixture] 44 [TestFixture]
45 public class SceneObjectSpatialTests 45 public class SceneObjectSpatialTests : OpenSimTestCase
46 { 46 {
47 TestScene m_scene; 47 TestScene m_scene;
48 UUID m_ownerId = TestHelpers.ParseTail(0x1); 48 UUID m_ownerId = TestHelpers.ParseTail(0x1);
49 49
50 [SetUp] 50 [SetUp]
51 public void SetUp() 51 public override void SetUp()
52 { 52 {
53 base.SetUp();
54
53 m_scene = new SceneHelpers().SetupScene(); 55 m_scene = new SceneHelpers().SetupScene();
54 } 56 }
55 57
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
index 742c769..093cbd2 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectStatusTests.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
42 /// Basic scene object status tests 42 /// Basic scene object status tests
43 /// </summary> 43 /// </summary>
44 [TestFixture] 44 [TestFixture]
45 public class SceneObjectStatusTests 45 public class SceneObjectStatusTests : OpenSimTestCase
46 { 46 {
47 private TestScene m_scene; 47 private TestScene m_scene;
48 private UUID m_ownerId = TestHelpers.ParseTail(0x1); 48 private UUID m_ownerId = TestHelpers.ParseTail(0x1);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
index 646e5fa..1cd8ae9 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
51 /// Scene presence animation tests 51 /// Scene presence animation tests
52 /// </summary> 52 /// </summary>
53 [TestFixture] 53 [TestFixture]
54 public class ScenePresenceAnimationTests 54 public class ScenePresenceAnimationTests : OpenSimTestCase
55 { 55 {
56 [Test] 56 [Test]
57 public void TestFlyingAnimation() 57 public void TestFlyingAnimation()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
index 1d1ff88..d80afd3 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAutopilotTests.cs
@@ -42,7 +42,7 @@ using OpenSim.Tests.Common.Mock;
42namespace OpenSim.Region.Framework.Scenes.Tests 42namespace OpenSim.Region.Framework.Scenes.Tests
43{ 43{
44 [TestFixture] 44 [TestFixture]
45 public class ScenePresenceAutopilotTests 45 public class ScenePresenceAutopilotTests : OpenSimTestCase
46 { 46 {
47 private TestScene m_scene; 47 private TestScene m_scene;
48 48
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
index 493ab70..acaeb90 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
@@ -43,7 +43,7 @@ using System.Threading;
43namespace OpenSim.Region.Framework.Scenes.Tests 43namespace OpenSim.Region.Framework.Scenes.Tests
44{ 44{
45 [TestFixture] 45 [TestFixture]
46 public class ScenePresenceSitTests 46 public class ScenePresenceSitTests : OpenSimTestCase
47 { 47 {
48 private TestScene m_scene; 48 private TestScene m_scene;
49 private ScenePresence m_sp; 49 private ScenePresence m_sp;
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
index 37b5184..8dd1f3d 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
49 /// Teleport tests in a standalone OpenSim 49 /// Teleport tests in a standalone OpenSim
50 /// </summary> 50 /// </summary>
51 [TestFixture] 51 [TestFixture]
52 public class ScenePresenceTeleportTests 52 public class ScenePresenceTeleportTests : OpenSimTestCase
53 { 53 {
54 [TestFixtureSetUp] 54 [TestFixtureSetUp]
55 public void FixtureInit() 55 public void FixtureInit()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
index ac3da1e..9d8eb0b 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs
@@ -50,7 +50,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
50 /// Scene presence tests 50 /// Scene presence tests
51 /// </summary> 51 /// </summary>
52 [TestFixture] 52 [TestFixture]
53 public class SceneTests 53 public class SceneTests : OpenSimTestCase
54 { 54 {
55 /// <summary> 55 /// <summary>
56 /// Very basic scene update test. Should become more elaborate with time. 56 /// Very basic scene update test. Should become more elaborate with time.
diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
index a51e4e3..0b461f5 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
@@ -50,7 +50,7 @@ using OpenSim.Tests.Common.Mock;
50namespace OpenSim.Region.Framework.Tests 50namespace OpenSim.Region.Framework.Tests
51{ 51{
52 [TestFixture] 52 [TestFixture]
53 public class TaskInventoryTests 53 public class TaskInventoryTests : OpenSimTestCase
54 { 54 {
55 [Test] 55 [Test]
56 public void TestAddTaskInventoryItem() 56 public void TestAddTaskInventoryItem()
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index 198e487..dd27294 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -38,7 +38,7 @@ using OpenSim.Tests.Common.Mock;
38namespace OpenSim.Region.Framework.Scenes.Tests 38namespace OpenSim.Region.Framework.Scenes.Tests
39{ 39{
40 [TestFixture] 40 [TestFixture]
41 public class UuidGathererTests 41 public class UuidGathererTests : OpenSimTestCase
42 { 42 {
43 protected IAssetService m_assetService; 43 protected IAssetService m_assetService;
44 protected UuidGatherer m_uuidGatherer; 44 protected UuidGatherer m_uuidGatherer;
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs
index 6d26075..6b5b40a 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/IGroupsServicesConnector.cs
@@ -36,7 +36,22 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
36 { 36 {
37 UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID); 37 UUID CreateGroup(UUID RequestingAgentID, string name, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish, UUID founderID);
38 void UpdateGroup(UUID RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish); 38 void UpdateGroup(UUID RequestingAgentID, UUID groupID, string charter, bool showInList, UUID insigniaID, int membershipFee, bool openEnrollment, bool allowPublish, bool maturePublish);
39
40 /// <summary>
41 /// Get the group record.
42 /// </summary>
43 /// <returns></returns>
44 /// <param name='RequestingAgentID'>The UUID of the user making the request.</param>
45 /// <param name='GroupID'>
46 /// The ID of the record to retrieve.
47 /// GroupName may be specified instead, in which case this parameter will be UUID.Zero
48 /// </param>
49 /// <param name='GroupName'>
50 /// The name of the group to retrieve.
51 /// GroupID may be specified instead, in which case this parmeter will be null.
52 /// </param>
39 GroupRecord GetGroupRecord(UUID RequestingAgentID, UUID GroupID, string GroupName); 53 GroupRecord GetGroupRecord(UUID RequestingAgentID, UUID GroupID, string GroupName);
54
40 List<DirGroupsReplyData> FindGroups(UUID RequestingAgentID, string search); 55 List<DirGroupsReplyData> FindGroups(UUID RequestingAgentID, string search);
41 List<GroupMembersData> GetGroupMembers(UUID RequestingAgentID, UUID GroupID); 56 List<GroupMembersData> GetGroupMembers(UUID RequestingAgentID, UUID GroupID);
42 57
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
index ac638f1..c1bdacb 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/Tests/GroupsModuleTests.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups.Tests
42 /// Basic groups module tests 42 /// Basic groups module tests
43 /// </summary> 43 /// </summary>
44 [TestFixture] 44 [TestFixture]
45 public class GroupsModuleTests 45 public class GroupsModuleTests : OpenSimTestCase
46 { 46 {
47 [Test] 47 [Test]
48 public void TestBasic() 48 public void TestBasic()
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
index d0c3ea5..1101851 100644
--- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/XmlRpcGroupsServicesConnectorModule.cs
@@ -54,13 +54,62 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
54 54
55 private bool m_debugEnabled = false; 55 private bool m_debugEnabled = false;
56 56
57 public const GroupPowers m_DefaultEveryonePowers = GroupPowers.AllowSetHome | 57 public const GroupPowers DefaultEveryonePowers
58 GroupPowers.Accountable | 58 = GroupPowers.AllowSetHome
59 GroupPowers.JoinChat | 59 | GroupPowers.Accountable
60 GroupPowers.AllowVoiceChat | 60 | GroupPowers.JoinChat
61 GroupPowers.ReceiveNotices | 61 | GroupPowers.AllowVoiceChat
62 GroupPowers.StartProposal | 62 | GroupPowers.ReceiveNotices
63 GroupPowers.VoteOnProposal; 63 | GroupPowers.StartProposal
64 | GroupPowers.VoteOnProposal;
65
66 // Would this be cleaner as (GroupPowers)ulong.MaxValue?
67 public const GroupPowers DefaultOwnerPowers
68 = GroupPowers.Accountable
69 | GroupPowers.AllowEditLand
70 | GroupPowers.AllowFly
71 | GroupPowers.AllowLandmark
72 | GroupPowers.AllowRez
73 | GroupPowers.AllowSetHome
74 | GroupPowers.AllowVoiceChat
75 | GroupPowers.AssignMember
76 | GroupPowers.AssignMemberLimited
77 | GroupPowers.ChangeActions
78 | GroupPowers.ChangeIdentity
79 | GroupPowers.ChangeMedia
80 | GroupPowers.ChangeOptions
81 | GroupPowers.CreateRole
82 | GroupPowers.DeedObject
83 | GroupPowers.DeleteRole
84 | GroupPowers.Eject
85 | GroupPowers.FindPlaces
86 | GroupPowers.Invite
87 | GroupPowers.JoinChat
88 | GroupPowers.LandChangeIdentity
89 | GroupPowers.LandDeed
90 | GroupPowers.LandDivideJoin
91 | GroupPowers.LandEdit
92 | GroupPowers.LandEjectAndFreeze
93 | GroupPowers.LandGardening
94 | GroupPowers.LandManageAllowed
95 | GroupPowers.LandManageBanned
96 | GroupPowers.LandManagePasses
97 | GroupPowers.LandOptions
98 | GroupPowers.LandRelease
99 | GroupPowers.LandSetSale
100 | GroupPowers.ModerateChat
101 | GroupPowers.ObjectManipulate
102 | GroupPowers.ObjectSetForSale
103 | GroupPowers.ReceiveNotices
104 | GroupPowers.RemoveMember
105 | GroupPowers.ReturnGroupOwned
106 | GroupPowers.ReturnGroupSet
107 | GroupPowers.ReturnNonGroup
108 | GroupPowers.RoleProperties
109 | GroupPowers.SendNotices
110 | GroupPowers.SetLandingPoint
111 | GroupPowers.StartProposal
112 | GroupPowers.VoteOnProposal;
64 113
65 private bool m_connectorEnabled = false; 114 private bool m_connectorEnabled = false;
66 115
@@ -219,59 +268,9 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
219 param["AllowPublish"] = allowPublish == true ? 1 : 0; 268 param["AllowPublish"] = allowPublish == true ? 1 : 0;
220 param["MaturePublish"] = maturePublish == true ? 1 : 0; 269 param["MaturePublish"] = maturePublish == true ? 1 : 0;
221 param["FounderID"] = founderID.ToString(); 270 param["FounderID"] = founderID.ToString();
222 param["EveryonePowers"] = ((ulong)m_DefaultEveryonePowers).ToString(); 271 param["EveryonePowers"] = ((ulong)DefaultEveryonePowers).ToString();
223 param["OwnerRoleID"] = OwnerRoleID.ToString(); 272 param["OwnerRoleID"] = OwnerRoleID.ToString();
224 273 param["OwnersPowers"] = ((ulong)DefaultOwnerPowers).ToString();
225 // Would this be cleaner as (GroupPowers)ulong.MaxValue;
226 GroupPowers OwnerPowers = GroupPowers.Accountable
227 | GroupPowers.AllowEditLand
228 | GroupPowers.AllowFly
229 | GroupPowers.AllowLandmark
230 | GroupPowers.AllowRez
231 | GroupPowers.AllowSetHome
232 | GroupPowers.AllowVoiceChat
233 | GroupPowers.AssignMember
234 | GroupPowers.AssignMemberLimited
235 | GroupPowers.ChangeActions
236 | GroupPowers.ChangeIdentity
237 | GroupPowers.ChangeMedia
238 | GroupPowers.ChangeOptions
239 | GroupPowers.CreateRole
240 | GroupPowers.DeedObject
241 | GroupPowers.DeleteRole
242 | GroupPowers.Eject
243 | GroupPowers.FindPlaces
244 | GroupPowers.Invite
245 | GroupPowers.JoinChat
246 | GroupPowers.LandChangeIdentity
247 | GroupPowers.LandDeed
248 | GroupPowers.LandDivideJoin
249 | GroupPowers.LandEdit
250 | GroupPowers.LandEjectAndFreeze
251 | GroupPowers.LandGardening
252 | GroupPowers.LandManageAllowed
253 | GroupPowers.LandManageBanned
254 | GroupPowers.LandManagePasses
255 | GroupPowers.LandOptions
256 | GroupPowers.LandRelease
257 | GroupPowers.LandSetSale
258 | GroupPowers.ModerateChat
259 | GroupPowers.ObjectManipulate
260 | GroupPowers.ObjectSetForSale
261 | GroupPowers.ReceiveNotices
262 | GroupPowers.RemoveMember
263 | GroupPowers.ReturnGroupOwned
264 | GroupPowers.ReturnGroupSet
265 | GroupPowers.ReturnNonGroup
266 | GroupPowers.RoleProperties
267 | GroupPowers.SendNotices
268 | GroupPowers.SetLandingPoint
269 | GroupPowers.StartProposal
270 | GroupPowers.VoteOnProposal;
271 param["OwnersPowers"] = ((ulong)OwnerPowers).ToString();
272
273
274
275 274
276 Hashtable respData = XmlRpcCall(requestingAgentID, "groups.createGroup", param); 275 Hashtable respData = XmlRpcCall(requestingAgentID, "groups.createGroup", param);
277 276
@@ -612,8 +611,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
612 } 611 }
613 612
614 return Roles; 613 return Roles;
615
616
617 } 614 }
618 615
619 public List<GroupRolesData> GetGroupRoles(UUID requestingAgentID, UUID GroupID) 616 public List<GroupRolesData> GetGroupRoles(UUID requestingAgentID, UUID GroupID)
@@ -676,7 +673,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
676 } 673 }
677 674
678 return members; 675 return members;
679
680 } 676 }
681 677
682 public List<GroupRoleMembersData> GetGroupRoleMembers(UUID requestingAgentID, UUID GroupID) 678 public List<GroupRoleMembersData> GetGroupRoleMembers(UUID requestingAgentID, UUID GroupID)
@@ -727,9 +723,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
727 values.Add(data); 723 values.Add(data);
728 } 724 }
729 } 725 }
730 return values;
731 726
727 return values;
732 } 728 }
729
733 public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID) 730 public GroupNoticeInfo GetGroupNotice(UUID requestingAgentID, UUID noticeID)
734 { 731 {
735 Hashtable param = new Hashtable(); 732 Hashtable param = new Hashtable();
@@ -737,7 +734,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
737 734
738 Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotice", param); 735 Hashtable respData = XmlRpcCall(requestingAgentID, "groups.getGroupNotice", param);
739 736
740
741 if (respData.Contains("error")) 737 if (respData.Contains("error"))
742 { 738 {
743 return null; 739 return null;
@@ -761,6 +757,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
761 757
762 return data; 758 return data;
763 } 759 }
760
764 public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket) 761 public void AddGroupNotice(UUID requestingAgentID, UUID groupID, UUID noticeID, string fromName, string subject, string message, byte[] binaryBucket)
765 { 762 {
766 string binBucket = OpenMetaverse.Utils.BytesToHexString(binaryBucket, ""); 763 string binBucket = OpenMetaverse.Utils.BytesToHexString(binaryBucket, "");
@@ -777,8 +774,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups
777 XmlRpcCall(requestingAgentID, "groups.addGroupNotice", param); 774 XmlRpcCall(requestingAgentID, "groups.addGroupNotice", param);
778 } 775 }
779 776
780
781
782 #endregion 777 #endregion
783 778
784 #region GroupSessionTracking 779 #region GroupSessionTracking
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index 52ed846..a522277 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -48,7 +48,7 @@ using OpenSim.Tests.Common.Mock;
48namespace OpenSim.Region.OptionalModules.World.NPC.Tests 48namespace OpenSim.Region.OptionalModules.World.NPC.Tests
49{ 49{
50 [TestFixture] 50 [TestFixture]
51 public class NPCModuleTests 51 public class NPCModuleTests : OpenSimTestCase
52 { 52 {
53 private TestScene m_scene; 53 private TestScene m_scene;
54 private AvatarFactoryModule m_afMod; 54 private AvatarFactoryModule m_afMod;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index f33c124..4c195e1 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -78,11 +78,17 @@ public sealed class BSCharacter : BSPhysObject
78 private float _PIDHoverTao; 78 private float _PIDHoverTao;
79 79
80 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) 80 public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying)
81 : base(parent_scene, localID, avName, "BSCharacter")
81 { 82 {
82 base.BaseInitialize(parent_scene, localID, avName, "BSCharacter");
83 _physicsActorType = (int)ActorTypes.Agent; 83 _physicsActorType = (int)ActorTypes.Agent;
84 _position = pos; 84 _position = pos;
85
86 // Old versions of ScenePresence passed only the height. If width and/or depth are zero,
87 // replace with the default values.
85 _size = size; 88 _size = size;
89 if (_size.X == 0f) _size.X = PhysicsScene.Params.avatarCapsuleDepth;
90 if (_size.Y == 0f) _size.Y = PhysicsScene.Params.avatarCapsuleWidth;
91
86 _flying = isFlying; 92 _flying = isFlying;
87 _orientation = OMV.Quaternion.Identity; 93 _orientation = OMV.Quaternion.Identity;
88 _velocity = OMV.Vector3.Zero; 94 _velocity = OMV.Vector3.Zero;
@@ -131,6 +137,10 @@ public sealed class BSCharacter : BSPhysObject
131 // Set the velocity and compute the proper friction 137 // Set the velocity and compute the proper friction
132 ForceVelocity = _velocity; 138 ForceVelocity = _velocity;
133 139
140 // This will enable or disable the flying buoyancy of the avatar.
141 // Needs to be reset especially when an avatar is recreated after crossing a region boundry.
142 Flying = _flying;
143
134 BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution); 144 BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution);
135 BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin); 145 BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin);
136 BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); 146 BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale);
@@ -171,8 +181,7 @@ public sealed class BSCharacter : BSPhysObject
171 get 181 get
172 { 182 {
173 // Avatar capsule size is kept in the scale parameter. 183 // Avatar capsule size is kept in the scale parameter.
174 // return _size; 184 return _size;
175 return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z);
176 } 185 }
177 186
178 set { 187 set {
@@ -180,8 +189,8 @@ public sealed class BSCharacter : BSPhysObject
180 _size = value; 189 _size = value;
181 ComputeAvatarScale(_size); 190 ComputeAvatarScale(_size);
182 ComputeAvatarVolumeAndMass(); 191 ComputeAvatarVolumeAndMass();
183 DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}", 192 DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
184 LocalID, Scale, _avatarDensity, _avatarVolume, RawMass); 193 LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
185 194
186 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() 195 PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
187 { 196 {
@@ -199,9 +208,9 @@ public sealed class BSCharacter : BSPhysObject
199 set { BaseShape = value; } 208 set { BaseShape = value; }
200 } 209 }
201 // I want the physics engine to make an avatar capsule 210 // I want the physics engine to make an avatar capsule
202 public override ShapeData.PhysicsShapeType PreferredPhysicalShape 211 public override BSPhysicsShapeType PreferredPhysicalShape
203 { 212 {
204 get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } 213 get {return BSPhysicsShapeType.SHAPE_CAPSULE; }
205 } 214 }
206 215
207 public override bool Grabbed { 216 public override bool Grabbed {
@@ -610,13 +619,19 @@ public sealed class BSCharacter : BSPhysObject
610 // The 'size' given by the simulator is the mid-point of the avatar 619 // The 'size' given by the simulator is the mid-point of the avatar
611 // and X and Y are unspecified. 620 // and X and Y are unspecified.
612 621
613 OMV.Vector3 newScale = OMV.Vector3.Zero; 622 OMV.Vector3 newScale = size;
614 newScale.X = PhysicsScene.Params.avatarCapsuleRadius; 623 // newScale.X = PhysicsScene.Params.avatarCapsuleWidth;
615 newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; 624 // newScale.Y = PhysicsScene.Params.avatarCapsuleDepth;
616 625
617 // From the total height, remove the capsule half spheres that are at each end 626 // From the total height, remove the capsule half spheres that are at each end
618 newScale.Z = size.Z- (newScale.X + newScale.Y); 627 // The 1.15f came from ODE. Not sure what this factors in.
619 Scale = newScale; 628 // newScale.Z = (size.Z * 1.15f) - (newScale.X + newScale.Y);
629
630 // The total scale height is the central cylindar plus the caps on the two ends.
631 newScale.Z = size.Z + (Math.Min(size.X, size.Y) * 2f);
632
633 // Convert diameters to radii and height to half height -- the way Bullet expects it.
634 Scale = newScale / 2f;
620 } 635 }
621 636
622 // set _avatarVolume and _mass based on capsule size, _density and Scale 637 // set _avatarVolume and _mass based on capsule size, _density and Scale
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
index dbc9039..74eb9ab 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs
@@ -80,10 +80,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
80 private Quaternion m_referenceFrame = Quaternion.Identity; 80 private Quaternion m_referenceFrame = Quaternion.Identity;
81 81
82 // Linear properties 82 // Linear properties
83 private BSVMotor m_linearMotor = new BSVMotor("LinearMotor");
83 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time 84 private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
84 private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center 85 private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center
85 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL 86 private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
86 private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body
87 private Vector3 m_linearFrictionTimescale = Vector3.Zero; 87 private Vector3 m_linearFrictionTimescale = Vector3.Zero;
88 private float m_linearMotorDecayTimescale = 0; 88 private float m_linearMotorDecayTimescale = 0;
89 private float m_linearMotorTimescale = 0; 89 private float m_linearMotorTimescale = 0;
@@ -93,6 +93,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
93 // private Vector3 m_linearMotorOffset = Vector3.Zero; 93 // private Vector3 m_linearMotorOffset = Vector3.Zero;
94 94
95 //Angular properties 95 //Angular properties
96 private BSVMotor m_angularMotor = new BSVMotor("AngularMotor");
96 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor 97 private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor
97 // private int m_angularMotorApply = 0; // application frame counter 98 // private int m_angularMotorApply = 0; // application frame counter
98 private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity 99 private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity
@@ -124,6 +125,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
124 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity. 125 // Therefore only m_VehicleBuoyancy=1 (0g) will use the script-requested .Z velocity.
125 126
126 //Attractor properties 127 //Attractor properties
128 private BSVMotor m_verticalAttractionMotor = new BSVMotor("VerticalAttraction");
127 private float m_verticalAttractionEfficiency = 1.0f; // damped 129 private float m_verticalAttractionEfficiency = 1.0f; // damped
128 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. 130 private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor.
129 131
@@ -152,10 +154,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
152 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); 154 m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
153 break; 155 break;
154 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: 156 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
155 m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f); 157 m_angularMotorDecayTimescale = Math.Max(0.01f, Math.Min(pValue,120));
158 m_angularMotor.TargetValueDecayTimeScale = m_angularMotorDecayTimescale;
156 break; 159 break;
157 case Vehicle.ANGULAR_MOTOR_TIMESCALE: 160 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
158 m_angularMotorTimescale = Math.Max(pValue, 0.01f); 161 m_angularMotorTimescale = Math.Max(pValue, 0.01f);
162 m_angularMotor.TimeScale = m_angularMotorTimescale;
159 break; 163 break;
160 case Vehicle.BANKING_EFFICIENCY: 164 case Vehicle.BANKING_EFFICIENCY:
161 m_bankingEfficiency = Math.Max(-1f, Math.Min(pValue, 1f)); 165 m_bankingEfficiency = Math.Max(-1f, Math.Min(pValue, 1f));
@@ -185,33 +189,40 @@ namespace OpenSim.Region.Physics.BulletSPlugin
185 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); 189 m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
186 break; 190 break;
187 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: 191 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
188 m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f); 192 m_linearMotorDecayTimescale = Math.Max(0.01f, Math.Min(pValue,120));
193 m_linearMotor.TargetValueDecayTimeScale = m_linearMotorDecayTimescale;
189 break; 194 break;
190 case Vehicle.LINEAR_MOTOR_TIMESCALE: 195 case Vehicle.LINEAR_MOTOR_TIMESCALE:
191 m_linearMotorTimescale = Math.Max(pValue, 0.01f); 196 m_linearMotorTimescale = Math.Max(pValue, 0.01f);
197 m_linearMotor.TimeScale = m_linearMotorTimescale;
192 break; 198 break;
193 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: 199 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
194 m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f)); 200 m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f));
201 m_verticalAttractionMotor.Efficiency = m_verticalAttractionEfficiency;
195 break; 202 break;
196 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: 203 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
197 m_verticalAttractionTimescale = Math.Max(pValue, 0.01f); 204 m_verticalAttractionTimescale = Math.Max(pValue, 0.01f);
205 m_verticalAttractionMotor.TimeScale = m_verticalAttractionTimescale;
198 break; 206 break;
199 207
200 // These are vector properties but the engine lets you use a single float value to 208 // These are vector properties but the engine lets you use a single float value to
201 // set all of the components to the same value 209 // set all of the components to the same value
202 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 210 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
203 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); 211 m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
212 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
204 break; 213 break;
205 case Vehicle.ANGULAR_MOTOR_DIRECTION: 214 case Vehicle.ANGULAR_MOTOR_DIRECTION:
206 m_angularMotorDirection = new Vector3(pValue, pValue, pValue); 215 m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
207 // m_angularMotorApply = 100; 216 m_angularMotor.SetTarget(m_angularMotorDirection);
208 break; 217 break;
209 case Vehicle.LINEAR_FRICTION_TIMESCALE: 218 case Vehicle.LINEAR_FRICTION_TIMESCALE:
210 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); 219 m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
220 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
211 break; 221 break;
212 case Vehicle.LINEAR_MOTOR_DIRECTION: 222 case Vehicle.LINEAR_MOTOR_DIRECTION:
213 m_linearMotorDirection = new Vector3(pValue, pValue, pValue); 223 m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
214 m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); 224 m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
225 m_linearMotor.SetTarget(m_linearMotorDirection);
215 break; 226 break;
216 case Vehicle.LINEAR_MOTOR_OFFSET: 227 case Vehicle.LINEAR_MOTOR_OFFSET:
217 m_linearMotorOffset = new Vector3(pValue, pValue, pValue); 228 m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
@@ -227,6 +238,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
227 { 238 {
228 case Vehicle.ANGULAR_FRICTION_TIMESCALE: 239 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
229 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 240 m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
241 m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
230 break; 242 break;
231 case Vehicle.ANGULAR_MOTOR_DIRECTION: 243 case Vehicle.ANGULAR_MOTOR_DIRECTION:
232 // Limit requested angular speed to 2 rps= 4 pi rads/sec 244 // Limit requested angular speed to 2 rps= 4 pi rads/sec
@@ -234,14 +246,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
234 pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f)); 246 pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f));
235 pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f)); 247 pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f));
236 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); 248 m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
237 // m_angularMotorApply = 100; 249 m_angularMotor.SetTarget(m_angularMotorDirection);
238 break; 250 break;
239 case Vehicle.LINEAR_FRICTION_TIMESCALE: 251 case Vehicle.LINEAR_FRICTION_TIMESCALE:
240 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); 252 m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
253 m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
241 break; 254 break;
242 case Vehicle.LINEAR_MOTOR_DIRECTION: 255 case Vehicle.LINEAR_MOTOR_DIRECTION:
243 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); 256 m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
244 m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); 257 m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
258 m_linearMotor.SetTarget(m_linearMotorDirection);
245 break; 259 break;
246 case Vehicle.LINEAR_MOTOR_OFFSET: 260 case Vehicle.LINEAR_MOTOR_OFFSET:
247 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); 261 m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
@@ -303,7 +317,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
303 m_VhoverEfficiency = 0; 317 m_VhoverEfficiency = 0;
304 m_VhoverTimescale = 0; 318 m_VhoverTimescale = 0;
305 m_VehicleBuoyancy = 0; 319 m_VehicleBuoyancy = 0;
306 320
307 m_linearDeflectionEfficiency = 1; 321 m_linearDeflectionEfficiency = 1;
308 m_linearDeflectionTimescale = 1; 322 m_linearDeflectionTimescale = 1;
309 323
@@ -319,6 +333,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
319 333
320 m_referenceFrame = Quaternion.Identity; 334 m_referenceFrame = Quaternion.Identity;
321 m_flags = (VehicleFlag)0; 335 m_flags = (VehicleFlag)0;
336
322 break; 337 break;
323 338
324 case Vehicle.TYPE_SLED: 339 case Vehicle.TYPE_SLED:
@@ -351,10 +366,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
351 m_bankingMix = 1; 366 m_bankingMix = 1;
352 367
353 m_referenceFrame = Quaternion.Identity; 368 m_referenceFrame = Quaternion.Identity;
354 m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); 369 m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY
355 m_flags &= 370 | VehicleFlag.HOVER_TERRAIN_ONLY
356 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | 371 | VehicleFlag.HOVER_GLOBAL_HEIGHT
357 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); 372 | VehicleFlag.HOVER_UP_ONLY);
373 m_flags |= (VehicleFlag.NO_DEFLECTION_UP
374 | VehicleFlag.LIMIT_ROLL_ONLY
375 | VehicleFlag.LIMIT_MOTOR_UP);
358 break; 376 break;
359 case Vehicle.TYPE_CAR: 377 case Vehicle.TYPE_CAR:
360 m_linearMotorDirection = Vector3.Zero; 378 m_linearMotorDirection = Vector3.Zero;
@@ -510,6 +528,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin
510 | VehicleFlag.HOVER_GLOBAL_HEIGHT); 528 | VehicleFlag.HOVER_GLOBAL_HEIGHT);
511 break; 529 break;
512 } 530 }
531
532 // Update any physical parameters based on this type.
533 Refresh();
534
535 m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale,
536 m_linearMotorDecayTimescale, m_linearFrictionTimescale,
537 1f);
538 m_linearMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
539
540 m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale,
541 m_angularMotorDecayTimescale, m_angularFrictionTimescale,
542 1f);
543 m_angularMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
544
545 m_verticalAttractionMotor = new BSVMotor("VerticalAttraction", m_verticalAttractionTimescale,
546 BSMotor.Infinite, BSMotor.InfiniteVector,
547 m_verticalAttractionEfficiency);
548 // Z goes away and we keep X and Y
549 m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
550 m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
551
552 // m_bankingMotor = new BSVMotor("BankingMotor", ...);
513 } 553 }
514 554
515 // Some of the properties of this prim may have changed. 555 // Some of the properties of this prim may have changed.
@@ -518,13 +558,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin
518 { 558 {
519 if (IsActive) 559 if (IsActive)
520 { 560 {
521 // Friction effects are handled by this vehicle code 561 m_vehicleMass = Prim.Linkset.LinksetMass;
522 BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f);
523 BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f);
524
525 // BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, 0.8f);
526 562
527 VDetailLog("{0},BSDynamics.Refresh,zeroingFriction and adding damping", Prim.LocalID); 563 // Friction effects are handled by this vehicle code
564 float friction = 0f;
565 BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, friction);
566
567 // Moderate angular movement introduced by Bullet.
568 // TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
569 // Maybe compute linear and angular factor and damping from params.
570 float angularDamping = PhysicsScene.Params.vehicleAngularDamping;
571 BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping);
572
573 // DEBUG DEBUG DEBUG: use uniform inertia to smooth movement added by Bullet
574 // Vector3 localInertia = new Vector3(1f, 1f, 1f);
575 Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass);
576 BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
577
578 VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}",
579 Prim.LocalID, friction, localInertia, angularDamping);
528 } 580 }
529 } 581 }
530 582
@@ -551,111 +603,109 @@ namespace OpenSim.Region.Physics.BulletSPlugin
551 { 603 {
552 if (!IsActive) return; 604 if (!IsActive) return;
553 605
554 // DEBUG
555 // Because Bullet does apply forces to the vehicle, our last computed
556 // linear and angular velocities are not what is happening now.
557 // Vector3 externalAngularVelocity = Prim.ForceRotationalVelocity - m_lastAngularVelocity;
558 // m_lastAngularVelocity += (externalAngularVelocity * 0.5f) * pTimestep;
559 // m_lastAngularVelocity = Prim.ForceRotationalVelocity; // DEBUG: account for what Bullet did last time
560 // m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG:
561 // END DEBUG
562
563 m_vehicleMass = Prim.Linkset.LinksetMass;
564
565 MoveLinear(pTimestep); 606 MoveLinear(pTimestep);
566 // Commented out for debug
567 MoveAngular(pTimestep); 607 MoveAngular(pTimestep);
568 // Prim.ApplyTorqueImpulse(-Prim.RotationalVelocity * m_vehicleMass, false); // DEBUG DEBUG
569 // Prim.ForceRotationalVelocity = -Prim.RotationalVelocity; // DEBUG DEBUG
570 608
571 LimitRotation(pTimestep); 609 LimitRotation(pTimestep);
572 610
573 // remember the position so next step we can limit absolute movement effects 611 // remember the position so next step we can limit absolute movement effects
574 m_lastPositionVector = Prim.ForcePosition; 612 m_lastPositionVector = Prim.ForcePosition;
575 613
576 VDetailLog("{0},BSDynamics.Step,frict={1},grav={2},inertia={3},mass={4}", // DEBUG DEBUG
577 Prim.LocalID,
578 BulletSimAPI.GetFriction2(Prim.PhysBody.ptr),
579 BulletSimAPI.GetGravity2(Prim.PhysBody.ptr),
580 Prim.Inertia,
581 m_vehicleMass
582 );
583 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", 614 VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
584 Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); 615 Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity);
585 }// end Step 616 }
586 617
587 // Apply the effect of the linear motor. 618 // Apply the effect of the linear motor.
588 // Also does hover and float. 619 // Also does hover and float.
589 private void MoveLinear(float pTimestep) 620 private void MoveLinear(float pTimestep)
590 { 621 {
591 // m_linearMotorDirection is the target direction we are moving relative to the vehicle coordinates 622 Vector3 linearMotorContribution = m_linearMotor.Step(pTimestep);
592 // m_lastLinearVelocityVector is the current speed we are moving in that direction
593 if (m_linearMotorDirection.LengthSquared() > 0.001f)
594 {
595 Vector3 origDir = m_linearMotorDirection; // DEBUG
596 Vector3 origVel = m_lastLinearVelocityVector; // DEBUG
597 // DEBUG: the vehicle velocity rotated to be relative to vehicle coordinates for comparison
598 Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG
599 623
600 // Add (desiredVelocity - lastAppliedVelocity) / howLongItShouldTakeToComplete 624 // Rotate new object velocity from vehicle relative to world coordinates
601 Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep; 625 linearMotorContribution *= Prim.ForceOrientation;
602 m_lastLinearVelocityVector += addAmount;
603 626
604 float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep; 627 // ==================================================================
605 m_linearMotorDirection *= (1f - decayFactor); 628 // Gravity and Buoyancy
629 // There is some gravity, make a gravity force vector that is applied after object velocity.
630 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g;
631 Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy);
606 632
607 // Rotate new object velocity from vehicle relative to world coordinates 633 Vector3 pos = Prim.ForcePosition;
608 m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; 634 float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
609 635
610 // Apply friction for next time 636 Vector3 terrainHeightContribution = ComputeLinearTerrainHeightCorrection(pTimestep, ref pos, terrainHeight);
611 Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep;
612 m_lastLinearVelocityVector *= (Vector3.One - frictionFactor);
613 637
614 VDetailLog("{0},MoveLinear,nonZero,origlmDir={1},origlvVel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lvVec={8},newVel={9}", 638 Vector3 hoverContribution = ComputeLinearHover(pTimestep, ref pos, terrainHeight);
615 Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor, 639
616 m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity); 640 ComputeLinearBlockingEndPoint(pTimestep, ref pos);
617 } 641
618 else 642 Vector3 limitMotorUpContribution = ComputeLinearMotorUp(pTimestep, pos, terrainHeight);
619 { 643
620 // if what remains of direction is very small, zero it. 644 // ==================================================================
621 m_linearMotorDirection = Vector3.Zero; 645 Vector3 newVelocity = linearMotorContribution
622 m_lastLinearVelocityVector = Vector3.Zero; 646 + terrainHeightContribution
623 m_newVelocity = Vector3.Zero; 647 + hoverContribution
648 + limitMotorUpContribution;
649
650 // If not changing some axis, reduce out velocity
651 if ((m_flags & (VehicleFlag.NO_X)) != 0)
652 newVelocity.X = 0;
653 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
654 newVelocity.Y = 0;
655 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
656 newVelocity.Z = 0;
624 657
625 VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); 658 // ==================================================================
659 // Clamp REALLY high or low velocities
660 float newVelocityLengthSq = newVelocity.LengthSquared();
661 if (newVelocityLengthSq > 1e6f)
662 {
663 newVelocity /= newVelocity.Length();
664 newVelocity *= 1000f;
626 } 665 }
666 else if (newVelocityLengthSq < 1e-6f)
667 newVelocity = Vector3.Zero;
627 668
628 // m_newVelocity is velocity computed from linear motor in world coordinates 669 // ==================================================================
670 // Stuff new linear velocity into the vehicle
671 Prim.ForceVelocity = newVelocity;
672 // Prim.ApplyForceImpulse((m_newVelocity - Prim.Velocity) * m_vehicleMass, false); // DEBUG DEBUG
629 673
630 // Gravity and Buoyancy 674 // Other linear forces are applied as forces.
631 // There is some gravity, make a gravity force vector that is applied after object velocity. 675 Vector3 totalDownForce = grav * m_vehicleMass;
632 // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; 676 if (totalDownForce != Vector3.Zero)
633 Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); 677 {
678 Prim.AddForce(totalDownForce, false);
679 }
634 680
635 /* 681 VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},primVel={4},totalDown={5}",
636 * RA: Not sure why one would do this unless we are hoping external forces are doing gravity, ... 682 Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector,
637 // Preserve the current Z velocity 683 newVelocity, Prim.Velocity, totalDownForce);
638 Vector3 vel_now = m_prim.Velocity;
639 m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity
640 */
641 684
642 Vector3 pos = Prim.ForcePosition; 685 } // end MoveLinear()
643// 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);
644 686
687 public Vector3 ComputeLinearTerrainHeightCorrection(float pTimestep, ref Vector3 pos, float terrainHeight)
688 {
689 Vector3 ret = Vector3.Zero;
645 // If below the terrain, move us above the ground a little. 690 // If below the terrain, move us above the ground a little.
646 float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos);
647 // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. 691 // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset.
648 // TODO: Add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. 692 // TODO: Add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass.
649 // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation; 693 // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation;
650 // if (rotatedSize.Z < terrainHeight) 694 // if (rotatedSize.Z < terrainHeight)
651 if (pos.Z < terrainHeight) 695 if (pos.Z < terrainHeight)
652 { 696 {
697 // TODO: correct position by applying force rather than forcing position.
653 pos.Z = terrainHeight + 2; 698 pos.Z = terrainHeight + 2;
654 Prim.ForcePosition = pos; 699 Prim.ForcePosition = pos;
655 VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos); 700 VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos);
656 } 701 }
702 return ret;
703 }
704
705 public Vector3 ComputeLinearHover(float pTimestep, ref Vector3 pos, float terrainHeight)
706 {
707 Vector3 ret = Vector3.Zero;
657 708
658 // Check if hovering
659 // m_VhoverEfficiency: 0=bouncy, 1=totally damped 709 // m_VhoverEfficiency: 0=bouncy, 1=totally damped
660 // m_VhoverTimescale: time to achieve height 710 // m_VhoverTimescale: time to achieve height
661 if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) 711 if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
@@ -694,28 +744,31 @@ namespace OpenSim.Region.Physics.BulletSPlugin
694 // RA: where does the 50 come from? 744 // RA: where does the 50 come from?
695 float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale); 745 float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale);
696 // Replace Vertical speed with correction figure if significant 746 // Replace Vertical speed with correction figure if significant
697 if (Math.Abs(verticalError) > 0.01f) 747 if (verticalError > 0.01f)
698 { 748 {
699 m_newVelocity.Z += verticalCorrectionVelocity; 749 ret = new Vector3(0f, 0f, verticalCorrectionVelocity);
700 //KF: m_VhoverEfficiency is not yet implemented 750 //KF: m_VhoverEfficiency is not yet implemented
701 } 751 }
702 else if (verticalError < -0.01) 752 else if (verticalError < -0.01)
703 { 753 {
704 m_newVelocity.Z -= verticalCorrectionVelocity; 754 ret = new Vector3(0f, 0f, -verticalCorrectionVelocity);
705 }
706 else
707 {
708 m_newVelocity.Z = 0f;
709 } 755 }
710 } 756 }
711 757
712 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", Prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight); 758 VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}",
759 Prim.LocalID, pos, ret, m_VhoverHeight, m_VhoverTargetHeight);
713 } 760 }
714 761
762 return ret;
763 }
764
765 public bool ComputeLinearBlockingEndPoint(float pTimestep, ref Vector3 pos)
766 {
767 bool changed = false;
768
715 Vector3 posChange = pos - m_lastPositionVector; 769 Vector3 posChange = pos - m_lastPositionVector;
716 if (m_BlockingEndPoint != Vector3.Zero) 770 if (m_BlockingEndPoint != Vector3.Zero)
717 { 771 {
718 bool changed = false;
719 if (pos.X >= (m_BlockingEndPoint.X - (float)1)) 772 if (pos.X >= (m_BlockingEndPoint.X - (float)1))
720 { 773 {
721 pos.X -= posChange.X + 1; 774 pos.X -= posChange.X + 1;
@@ -748,75 +801,45 @@ namespace OpenSim.Region.Physics.BulletSPlugin
748 Prim.LocalID, m_BlockingEndPoint, posChange, pos); 801 Prim.LocalID, m_BlockingEndPoint, posChange, pos);
749 } 802 }
750 } 803 }
804 return changed;
805 }
751 806
752 #region downForce 807 public Vector3 ComputeLinearMotorUp(float pTimestep, Vector3 pos, float terrainHeight)
753 Vector3 downForce = Vector3.Zero; 808 {
754 809 Vector3 ret = Vector3.Zero;
755 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) 810 if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0)
756 { 811 {
757 // If the vehicle is motoring into the sky, get it going back down. 812 // If the vehicle is motoring into the sky, get it going back down.
758 // Is this an angular force or both linear and angular??
759 float distanceAboveGround = pos.Z - terrainHeight; 813 float distanceAboveGround = pos.Z - terrainHeight;
760 if (distanceAboveGround > 2f) 814 if (distanceAboveGround > 1f)
761 { 815 {
762 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep); 816 // downForce = new Vector3(0, 0, (-distanceAboveGround / m_bankingTimescale) * pTimestep);
763 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale); 817 // downForce = new Vector3(0, 0, -distanceAboveGround / m_bankingTimescale);
764 downForce = new Vector3(0, 0, -distanceAboveGround); 818 ret = new Vector3(0, 0, -distanceAboveGround);
765 } 819 }
766 // TODO: this calculation is all wrong. From the description at 820 // TODO: this calculation is all wrong. From the description at
767 // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce 821 // (http://wiki.secondlife.com/wiki/Category:LSL_Vehicle), the downForce
768 // has a decay factor. This says this force should 822 // has a decay factor. This says this force should
769 // be computed with a motor. 823 // be computed with a motor.
770 VDetailLog("{0},MoveLinear,limitMotorUp,distAbove={1},downForce={2}", 824 VDetailLog("{0},MoveLinear,limitMotorUp,distAbove={1},downForce={2}",
771 Prim.LocalID, distanceAboveGround, downForce); 825 Prim.LocalID, distanceAboveGround, ret);
772 } 826 }
773 #endregion // downForce 827 return ret;
774 828 }
775 // If not changing some axis, reduce out velocity
776 if ((m_flags & (VehicleFlag.NO_X)) != 0)
777 m_newVelocity.X = 0;
778 if ((m_flags & (VehicleFlag.NO_Y)) != 0)
779 m_newVelocity.Y = 0;
780 if ((m_flags & (VehicleFlag.NO_Z)) != 0)
781 m_newVelocity.Z = 0;
782
783 // Clamp REALLY high or low velocities
784 if (m_newVelocity.LengthSquared() > 1e6f)
785 {
786 m_newVelocity /= m_newVelocity.Length();
787 m_newVelocity *= 1000f;
788 }
789 else if (m_newVelocity.LengthSquared() < 1e-6f)
790 m_newVelocity = Vector3.Zero;
791
792 // Stuff new linear velocity into the vehicle
793 Prim.ForceVelocity = m_newVelocity;
794 // Prim.ApplyForceImpulse((m_newVelocity - Prim.Velocity) * m_vehicleMass, false); // DEBUG DEBUG
795
796 Vector3 totalDownForce = downForce + grav;
797 if (totalDownForce != Vector3.Zero)
798 {
799 Prim.AddForce(totalDownForce * m_vehicleMass, false);
800 // Prim.ApplyForceImpulse(totalDownForce * m_vehicleMass, false);
801 }
802
803 VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},primVel={4},totalDown={5}",
804 Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, Prim.Velocity, totalDownForce);
805
806 } // end MoveLinear()
807 829
808 // ======================================================================= 830 // =======================================================================
831 // =======================================================================
809 // Apply the effect of the angular motor. 832 // Apply the effect of the angular motor.
810 private void MoveAngular(float pTimestep) 833 private void MoveAngular(float pTimestep)
811 { 834 {
812 // m_angularMotorDirection // angular velocity requested by LSL motor 835 // m_angularMotorDirection // angular velocity requested by LSL motor
813 // m_angularMotorApply // application frame counter
814 // m_angularMotorVelocity // current angular motor velocity (ramps up and down) 836 // m_angularMotorVelocity // current angular motor velocity (ramps up and down)
815 // m_angularMotorTimescale // motor angular velocity ramp up rate 837 // m_angularMotorTimescale // motor angular velocity ramp up time
816 // m_angularMotorDecayTimescale // motor angular velocity decay rate 838 // m_angularMotorDecayTimescale // motor angular velocity decay rate
817 // m_angularFrictionTimescale // body angular velocity decay rate 839 // m_angularFrictionTimescale // body angular velocity decay rate
818 // m_lastAngularVelocity // what was last applied to body 840 // m_lastAngularVelocity // what was last applied to body
819 841
842 /*
820 if (m_angularMotorDirection.LengthSquared() > 0.0001) 843 if (m_angularMotorDirection.LengthSquared() > 0.0001)
821 { 844 {
822 Vector3 origVel = m_angularMotorVelocity; 845 Vector3 origVel = m_angularMotorVelocity;
@@ -835,59 +858,152 @@ namespace OpenSim.Region.Physics.BulletSPlugin
835 { 858 {
836 m_angularMotorVelocity = Vector3.Zero; 859 m_angularMotorVelocity = Vector3.Zero;
837 } 860 }
861 */
862
863 Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep);
838 864
839 #region Vertical attactor 865 // ==================================================================
866 // NO_DEFLECTION_UP says angular motion should not add any pitch or roll movement
867 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
868 {
869 angularMotorContribution.X = 0f;
870 angularMotorContribution.Y = 0f;
871 VDetailLog("{0},MoveAngular,noDeflectionUp,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution);
872 }
840 873
841 Vector3 vertattr = Vector3.Zero; 874 Vector3 verticalAttractionContribution = ComputeAngularVerticalAttraction(pTimestep);
842 Vector3 deflection = Vector3.Zero;
843 Vector3 banking = Vector3.Zero;
844 875
845 // If vertical attaction timescale is reasonable and we applied an angular force last time... 876 Vector3 deflectionContribution = ComputeAngularDeflection(pTimestep);
846 if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) 877
878 Vector3 bankingContribution = ComputeAngularBanking(pTimestep);
879
880 // ==================================================================
881 m_lastVertAttractor = verticalAttractionContribution;
882
883 // Sum velocities
884 m_lastAngularVelocity = angularMotorContribution
885 + verticalAttractionContribution
886 + bankingContribution
887 + deflectionContribution;
888
889 // ==================================================================
890 //Offset section
891 if (m_linearMotorOffset != Vector3.Zero)
892 {
893 //Offset of linear velocity doesn't change the linear velocity,
894 // but causes a torque to be applied, for example...
895 //
896 // IIIII >>> IIIII
897 // IIIII >>> IIIII
898 // IIIII >>> IIIII
899 // ^
900 // | Applying a force at the arrow will cause the object to move forward, but also rotate
901 //
902 //
903 // The torque created is the linear velocity crossed with the offset
904
905 // TODO: this computation should be in the linear section
906 // because that is where we know the impulse being applied.
907 Vector3 torqueFromOffset = Vector3.Zero;
908 // torqueFromOffset = Vector3.Cross(m_linearMotorOffset, appliedImpulse);
909 if (float.IsNaN(torqueFromOffset.X))
910 torqueFromOffset.X = 0;
911 if (float.IsNaN(torqueFromOffset.Y))
912 torqueFromOffset.Y = 0;
913 if (float.IsNaN(torqueFromOffset.Z))
914 torqueFromOffset.Z = 0;
915 torqueFromOffset *= m_vehicleMass;
916 Prim.ApplyTorqueImpulse(torqueFromOffset, true);
917 VDetailLog("{0},BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
918 }
919
920 // ==================================================================
921 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
922 {
923 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
924 Prim.ZeroAngularMotion(true);
925 VDetailLog("{0},MoveAngular,zeroAngularMotion,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
926 }
927 else
847 { 928 {
848 float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale; 929 // Apply to the body.
849 if (Prim.IsColliding) 930 // The above calculates the absolute angular velocity needed. Angular velocity is massless.
850 VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale); 931 // Since we are stuffing the angular velocity directly into the object, the computed
932 // velocity needs to be scaled by the timestep.
933 // Also remove any motion that is on the object so added motion is only from vehicle.
934 Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep)
935 - Prim.ForceRotationalVelocity);
936 // Unscale the force by the angular factor so it overwhelmes the Bullet additions.
937 Prim.ForceRotationalVelocity = applyAngularForce;
938
939 VDetailLog("{0},MoveAngular,done,angMotor={1},vertAttr={2},bank={3},deflect={4},newAngForce={5},lastAngular={6}",
940 Prim.LocalID,
941 angularMotorContribution, verticalAttractionContribution,
942 bankingContribution, deflectionContribution,
943 applyAngularForce, m_lastAngularVelocity
944 );
945 }
946 }
851 947
852 VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); 948 public Vector3 ComputeAngularVerticalAttraction(float pTimestep)
949 {
950 Vector3 ret = Vector3.Zero;
853 951
854 // Create a vector of the vehicle "up" in world coordinates 952 // If vertical attaction timescale is reasonable and we applied an angular force last time...
953 if (m_verticalAttractionTimescale < 500)
954 {
955 Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation;
956 verticalError.Normalize();
957 m_verticalAttractionMotor.SetCurrent(verticalError);
958 m_verticalAttractionMotor.SetTarget(Vector3.UnitZ);
959 ret = m_verticalAttractionMotor.Step(pTimestep);
960 /*
961 // Take a vector pointing up and convert it from world to vehicle relative coords.
855 Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; 962 Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation;
856 // verticalError.X and .Y are the World error amounts. They are 0 when there is no 963 verticalError.Normalize();
857 // error (Vehicle Body is 'vertical'), and .Z will be 1. As the body leans to its 964
858 // side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall 965 // If vertical attraction correction is needed, the vector that was pointing up (UnitZ)
859 // and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be 966 // is now leaning to one side (rotated around the X axis) and the Y value will
860 // modulated to prevent a stable inverted body. 967 // go from zero (nearly straight up) to one (completely to the side) or leaning
861 968 // front-to-back (rotated around the Y axis) and the value of X will be between
862 // Error is 0 (no error) to +/- 2 (max error) 969 // zero and one.
863 if (verticalError.Z < 0.0f) 970 // The value of Z is how far the rotation is off with 1 meaning none and 0 being 90 degrees.
971
972 // If verticalError.Z is negative, the vehicle is upside down. Add additional push.
973 if (verticalError.Z < 0f)
864 { 974 {
865 verticalError.X = 2.0f - verticalError.X; 975 verticalError.X = 2f - verticalError.X;
866 verticalError.Y = 2.0f - verticalError.Y; 976 verticalError.Y = 2f - verticalError.Y;
867 } 977 }
868 // scale it by VAservo (timestep and timescale)
869 verticalError = verticalError * VAservo;
870 978
871 // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y 979 // Y error means needed rotation around X axis and visa versa.
872 // then .X increases, so change Body angular velocity X based on Y, and Y based on X. 980 verticalAttractionContribution.X = verticalError.Y;
873 // Z is not changed. 981 verticalAttractionContribution.Y = - verticalError.X;
874 vertattr.X = verticalError.Y; 982 verticalAttractionContribution.Z = 0f;
875 vertattr.Y = - verticalError.X; 983
876 vertattr.Z = 0f; 984 // scale by the time scale and timestep
985 Vector3 unscaledContrib = verticalAttractionContribution;
986 verticalAttractionContribution /= m_verticalAttractionTimescale;
987 verticalAttractionContribution *= pTimestep;
877 988
878 // scaling appears better usingsquare-law 989 // apply efficiency
879 Vector3 angularVelocity = Prim.ForceRotationalVelocity; 990 Vector3 preEfficiencyContrib = verticalAttractionContribution;
880 float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); 991 float efficencySquared = m_verticalAttractionEfficiency * m_verticalAttractionEfficiency;
881 vertattr.X += bounce * angularVelocity.X; 992 verticalAttractionContribution *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency);
882 vertattr.Y += bounce * angularVelocity.Y;
883 993
884 VDetailLog("{0},MoveAngular,verticalAttraction,VAservo={1},effic={2},verticalError={3},bounce={4},vertattr={5}", 994 VDetailLog("{0},MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},preEff={3},eff={4},effSq={5},vertAttr={6}",
885 Prim.LocalID, VAservo, m_verticalAttractionEfficiency, verticalError, bounce, vertattr); 995 Prim.LocalID, verticalError, unscaledContrib, preEfficiencyContrib,
996 m_verticalAttractionEfficiency, efficencySquared,
997 verticalAttractionContribution);
998 */
886 999
887 } 1000 }
888 #endregion // Vertical attactor 1001 return ret;
1002 }
889 1003
890 #region Deflection 1004 public Vector3 ComputeAngularDeflection(float pTimestep)
1005 {
1006 Vector3 ret = Vector3.Zero;
891 1007
892 if (m_angularDeflectionEfficiency != 0) 1008 if (m_angularDeflectionEfficiency != 0)
893 { 1009 {
@@ -899,32 +1015,35 @@ namespace OpenSim.Region.Physics.BulletSPlugin
899 Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); 1015 Vector3 preferredAxisOfMotion = scaledDefaultDirection * Quaternion.Add(Prim.ForceOrientation, m_referenceFrame);
900 1016
901 // Scale by efficiency and timescale 1017 // Scale by efficiency and timescale
902 deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; 1018 ret = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep;
1019
1020 VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", Prim.LocalID, preferredAxisOfMotion, ret);
903 1021
904 VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}",
905 Prim.LocalID, preferredAxisOfMotion, deflection);
906 // This deflection computation is not correct. 1022 // This deflection computation is not correct.
907 deflection = Vector3.Zero; 1023 ret = Vector3.Zero;
908 } 1024 }
1025 return ret;
1026 }
909 1027
910 #endregion 1028 public Vector3 ComputeAngularBanking(float pTimestep)
911 1029 {
912 #region Banking 1030 Vector3 ret = Vector3.Zero;
913 1031
914 if (m_bankingEfficiency != 0) 1032 if (m_bankingEfficiency != 0)
915 { 1033 {
916 Vector3 dir = Vector3.One * Prim.ForceOrientation; 1034 Vector3 dir = Vector3.One * Prim.ForceOrientation;
917 float mult = (m_bankingMix*m_bankingMix)*-1*(m_bankingMix < 0 ? -1 : 1); 1035 float mult = (m_bankingMix * m_bankingMix) * -1 * (m_bankingMix < 0 ? -1 : 1);
918 //Changes which way it banks in and out of turns 1036 //Changes which way it banks in and out of turns
919 1037
920 //Use the square of the efficiency, as it looks much more how SL banking works 1038 //Use the square of the efficiency, as it looks much more how SL banking works
921 float effSquared = (m_bankingEfficiency*m_bankingEfficiency); 1039 float effSquared = (m_bankingEfficiency * m_bankingEfficiency);
922 if (m_bankingEfficiency < 0) 1040 if (m_bankingEfficiency < 0)
923 effSquared *= -1; //Keep the negative! 1041 effSquared *= -1; //Keep the negative!
924 1042
925 float mix = Math.Abs(m_bankingMix); 1043 float mix = Math.Abs(m_bankingMix);
926 if (m_angularMotorVelocity.X == 0) 1044 if (m_angularMotorVelocity.X == 0)
927 { 1045 {
1046 // The vehicle is stopped
928 /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f)) 1047 /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f))
929 { 1048 {
930 Vector3 axisAngle; 1049 Vector3 axisAngle;
@@ -938,101 +1057,39 @@ namespace OpenSim.Region.Physics.BulletSPlugin
938 }*/ 1057 }*/
939 } 1058 }
940 else 1059 else
941 banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4; 1060 {
1061 ret.Z += (effSquared * (mult * mix)) * (m_angularMotorVelocity.X) * 4;
1062 }
1063
1064 //If they are colliding, we probably shouldn't shove the prim around... probably
942 if (!Prim.IsColliding && Math.Abs(m_angularMotorVelocity.X) > mix) 1065 if (!Prim.IsColliding && Math.Abs(m_angularMotorVelocity.X) > mix)
943 //If they are colliding, we probably shouldn't shove the prim around... probably
944 { 1066 {
945 float angVelZ = m_angularMotorVelocity.X*-1; 1067 float angVelZ = m_angularMotorVelocity.X * -1;
946 /*if(angVelZ > mix) 1068 /*if(angVelZ > mix)
947 angVelZ = mix; 1069 angVelZ = mix;
948 else if(angVelZ < -mix) 1070 else if(angVelZ < -mix)
949 angVelZ = -mix;*/ 1071 angVelZ = -mix;*/
950 //This controls how fast and how far the banking occurs 1072 //This controls how fast and how far the banking occurs
951 Vector3 bankingRot = new Vector3(angVelZ*(effSquared*mult), 0, 0); 1073 Vector3 bankingRot = new Vector3(angVelZ * (effSquared * mult), 0, 0);
952 if (bankingRot.X > 3) 1074 if (bankingRot.X > 3)
953 bankingRot.X = 3; 1075 bankingRot.X = 3;
954 else if (bankingRot.X < -3) 1076 else if (bankingRot.X < -3)
955 bankingRot.X = -3; 1077 bankingRot.X = -3;
956 bankingRot *= Prim.ForceOrientation; 1078 bankingRot *= Prim.ForceOrientation;
957 banking += bankingRot; 1079 ret += bankingRot;
958 } 1080 }
959 m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; 1081 m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency;
960 VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},banking={3}", 1082 VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},effSq={3},mult={4},mix={5},banking={6}",
961 Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, banking); 1083 Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, effSquared, mult, mix, ret);
962 } 1084 }
1085 return ret;
1086 }
963 1087
964 #endregion
965
966 m_lastVertAttractor = vertattr;
967
968 // Sum velocities
969 m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection;
970
971 #region Linear Motor Offset
972
973 //Offset section
974 if (m_linearMotorOffset != Vector3.Zero)
975 {
976 //Offset of linear velocity doesn't change the linear velocity,
977 // but causes a torque to be applied, for example...
978 //
979 // IIIII >>> IIIII
980 // IIIII >>> IIIII
981 // IIIII >>> IIIII
982 // ^
983 // | Applying a force at the arrow will cause the object to move forward, but also rotate
984 //
985 //
986 // The torque created is the linear velocity crossed with the offset
987
988 // NOTE: this computation does should be in the linear section
989 // because there we know the impulse being applied.
990 Vector3 torqueFromOffset = Vector3.Zero;
991 // torqueFromOffset = Vector3.Cross(m_linearMotorOffset, appliedImpulse);
992 if (float.IsNaN(torqueFromOffset.X))
993 torqueFromOffset.X = 0;
994 if (float.IsNaN(torqueFromOffset.Y))
995 torqueFromOffset.Y = 0;
996 if (float.IsNaN(torqueFromOffset.Z))
997 torqueFromOffset.Z = 0;
998 torqueFromOffset *= m_vehicleMass;
999 Prim.ApplyTorqueImpulse(torqueFromOffset, true);
1000 VDetailLog("{0},BSDynamic.MoveAngular,motorOffset,applyTorqueImpulse={1}", Prim.LocalID, torqueFromOffset);
1001 }
1002
1003 #endregion
1004
1005 if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0)
1006 {
1007 m_lastAngularVelocity.X = 0;
1008 m_lastAngularVelocity.Y = 0;
1009 VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
1010 }
1011
1012 if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
1013 {
1014 m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
1015 Prim.ZeroAngularMotion(true);
1016 VDetailLog("{0},MoveAngular,zeroAngularMotion,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity);
1017 }
1018 else
1019 {
1020 // Apply to the body.
1021 // The above calculates the absolute angular velocity needed. Angular velocity is massless.
1022 // Since we are stuffing the angular velocity directly into the object, the computed
1023 // velocity needs to be scaled by the timestep.
1024 Vector3 applyAngularForce = ((m_lastAngularVelocity * pTimestep) - Prim.ForceRotationalVelocity);
1025 Prim.ForceRotationalVelocity = applyAngularForce;
1026
1027 // Decay the angular movement for next time
1028 Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep;
1029 m_lastAngularVelocity *= Vector3.One - decayamount;
1030
1031 VDetailLog("{0},MoveAngular,done,newRotVel={1},decay={2},lastAngular={3}",
1032 Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity);
1033 }
1034 } //end MoveAngular
1035 1088
1089 // This is from previous instantiations of XXXDynamics.cs.
1090 // Applies roll reference frame.
1091 // TODO: is this the right way to separate the code to do this operation?
1092 // Should this be in MoveAngular()?
1036 internal void LimitRotation(float timestep) 1093 internal void LimitRotation(float timestep)
1037 { 1094 {
1038 Quaternion rotq = Prim.ForceOrientation; 1095 Quaternion rotq = Prim.ForceOrientation;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index 436e043..0df4310 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -82,9 +82,9 @@ public abstract class BSLinkset
82 82
83 // Some linksets have a preferred physical shape. 83 // Some linksets have a preferred physical shape.
84 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. 84 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
85 public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) 85 public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
86 { 86 {
87 return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; 87 return BSPhysicsShapeType.SHAPE_UNKNOWN;
88 } 88 }
89 89
90 // Linksets move around the children so the linkset might need to compute the child position 90 // Linksets move around the children so the linkset might need to compute the child position
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index 3238c85..b9c2cf9 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -42,12 +42,12 @@ public sealed class BSLinksetCompound : BSLinkset
42 } 42 }
43 43
44 // For compound implimented linksets, if there are children, use compound shape for the root. 44 // For compound implimented linksets, if there are children, use compound shape for the root.
45 public override ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) 45 public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
46 { 46 {
47 ShapeData.PhysicsShapeType ret = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; 47 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
48 if (IsRoot(requestor) && HasAnyChildren) 48 if (IsRoot(requestor) && HasAnyChildren)
49 { 49 {
50 ret = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; 50 ret = BSPhysicsShapeType.SHAPE_COMPOUND;
51 } 51 }
52 // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); 52 // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
53 return ret; 53 return ret;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
new file mode 100755
index 0000000..663b6f4
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMaterials.cs
@@ -0,0 +1,191 @@
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 System.Reflection;
31using Nini.Config;
32
33namespace OpenSim.Region.Physics.BulletSPlugin
34{
35
36public struct MaterialAttributes
37{
38 // Material type values that correspond with definitions for LSL
39 public enum Material : int
40 {
41 Stone = 0,
42 Metal,
43 Glass,
44 Wood,
45 Flesh,
46 Plastic,
47 Rubber,
48 Light,
49 // Hereafter are BulletSim additions
50 Avatar,
51 NumberOfTypes // the count of types in the enum.
52 }
53 // Names must be in the order of the above enum.
54 public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
55 "Flesh", "Plastic", "Rubber", "Light", "Avatar" };
56 public static string[] MaterialAttribs = { "Density", "Friction", "Restitution",
57 "ccdMotionThreshold", "ccdSweptSphereRadius" };
58
59 public MaterialAttributes(string t, float d, float f, float r, float ccdM, float ccdS)
60 {
61 type = t;
62 density = d;
63 friction = f;
64 restitution = r;
65 ccdMotionThreshold = ccdM;
66 ccdSweptSphereRadius = ccdS;
67 }
68 public string type;
69 public float density;
70 public float friction;
71 public float restitution;
72 public float ccdMotionThreshold;
73 public float ccdSweptSphereRadius;
74}
75
76public static class BSMaterials
77{
78 public static MaterialAttributes[] Attributes;
79
80 static BSMaterials()
81 {
82 // Attribute sets for both the non-physical and physical instances of materials.
83 Attributes = new MaterialAttributes[(int)MaterialAttributes.Material.NumberOfTypes * 2];
84 }
85
86 // This is where all the default material attributes are defined.
87 public static void InitializeFromDefaults(ConfigurationParameters parms)
88 {
89 // public static string[] MaterialNames = { "Stone", "Metal", "Glass", "Wood",
90 // "Flesh", "Plastic", "Rubber", "Light", "Avatar" };
91 float dFriction = parms.defaultFriction;
92 float dRestitution = parms.defaultRestitution;
93 float dDensity = parms.defaultDensity;
94 float dCcdM = parms.ccdMotionThreshold;
95 float dCcdS = parms.ccdSweptSphereRadius;
96 Attributes[(int)MaterialAttributes.Material.Stone] =
97 new MaterialAttributes("stone",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
98 Attributes[(int)MaterialAttributes.Material.Metal] =
99 new MaterialAttributes("metal",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
100 Attributes[(int)MaterialAttributes.Material.Glass] =
101 new MaterialAttributes("glass",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
102 Attributes[(int)MaterialAttributes.Material.Wood] =
103 new MaterialAttributes("wood",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
104 Attributes[(int)MaterialAttributes.Material.Flesh] =
105 new MaterialAttributes("flesh",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
106 Attributes[(int)MaterialAttributes.Material.Plastic] =
107 new MaterialAttributes("plastic",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
108 Attributes[(int)MaterialAttributes.Material.Rubber] =
109 new MaterialAttributes("rubber",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
110 Attributes[(int)MaterialAttributes.Material.Light] =
111 new MaterialAttributes("light",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
112 Attributes[(int)MaterialAttributes.Material.Avatar] =
113 new MaterialAttributes("avatar",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
114
115 Attributes[(int)MaterialAttributes.Material.Stone + (int)MaterialAttributes.Material.NumberOfTypes] =
116 new MaterialAttributes("stonePhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
117 Attributes[(int)MaterialAttributes.Material.Metal + (int)MaterialAttributes.Material.NumberOfTypes] =
118 new MaterialAttributes("metalPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
119 Attributes[(int)MaterialAttributes.Material.Glass + (int)MaterialAttributes.Material.NumberOfTypes] =
120 new MaterialAttributes("glassPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
121 Attributes[(int)MaterialAttributes.Material.Wood + (int)MaterialAttributes.Material.NumberOfTypes] =
122 new MaterialAttributes("woodPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
123 Attributes[(int)MaterialAttributes.Material.Flesh + (int)MaterialAttributes.Material.NumberOfTypes] =
124 new MaterialAttributes("fleshPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
125 Attributes[(int)MaterialAttributes.Material.Plastic + (int)MaterialAttributes.Material.NumberOfTypes] =
126 new MaterialAttributes("plasticPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
127 Attributes[(int)MaterialAttributes.Material.Rubber + (int)MaterialAttributes.Material.NumberOfTypes] =
128 new MaterialAttributes("rubberPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
129 Attributes[(int)MaterialAttributes.Material.Light + (int)MaterialAttributes.Material.NumberOfTypes] =
130 new MaterialAttributes("lightPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
131 Attributes[(int)MaterialAttributes.Material.Avatar + (int)MaterialAttributes.Material.NumberOfTypes] =
132 new MaterialAttributes("avatarPhysical",dDensity,dFriction,dRestitution, dCcdM, dCcdS);
133 }
134
135 // Under the [BulletSim] section, one can change the individual material
136 // attribute values. The format of the configuration parameter is:
137 // <materialName><Attribute>["Physical"] = floatValue
138 // For instance:
139 // [BulletSim]
140 // StoneFriction = 0.2
141 // FleshRestitutionPhysical = 0.8
142 // Materials can have different parameters for their static and
143 // physical instantiations. When setting the non-physical value,
144 // both values are changed. Setting the physical value only changes
145 // the physical value.
146 public static void InitializefromParameters(IConfig pConfig)
147 {
148 int matType = 0;
149 foreach (string matName in MaterialAttributes.MaterialNames)
150 {
151 foreach (string attribName in MaterialAttributes.MaterialAttribs)
152 {
153 string paramName = matName + attribName;
154 if (pConfig.Contains(paramName))
155 {
156 float paramValue = pConfig.GetFloat(paramName);
157 SetAttributeValue(matType, attribName, paramValue);
158 // set the physical value also
159 SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
160 }
161 paramName += "Physical";
162 if (pConfig.Contains(paramName))
163 {
164 float paramValue = pConfig.GetFloat(paramName);
165 SetAttributeValue(matType + (int)MaterialAttributes.Material.NumberOfTypes, attribName, paramValue);
166 }
167 }
168 matType++;
169 }
170 }
171
172 private static void SetAttributeValue(int matType, string attribName, float val)
173 {
174 MaterialAttributes thisAttrib = Attributes[matType];
175 FieldInfo fieldInfo = thisAttrib.GetType().GetField(attribName);
176 if (fieldInfo != null)
177 {
178 fieldInfo.SetValue(thisAttrib, val);
179 Attributes[matType] = thisAttrib;
180 }
181 }
182
183 public static MaterialAttributes GetAttributes(MaterialAttributes.Material type, bool isPhysical)
184 {
185 int ind = (int)type;
186 if (isPhysical) ind += (int)MaterialAttributes.Material.NumberOfTypes;
187 return Attributes[ind];
188 }
189
190}
191}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
index bc6e4c4..e91bfa8 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSMotors.cs
@@ -1,104 +1,169 @@
1using System; 1using System;
2using System.Collections.Generic; 2using System.Collections.Generic;
3using System.Text; 3using System.Text;
4using OpenMetaverse; 4using OpenMetaverse;
5 5
6namespace OpenSim.Region.Physics.BulletSPlugin 6namespace OpenSim.Region.Physics.BulletSPlugin
7{ 7{
8public abstract class BSMotor 8public abstract class BSMotor
9{ 9{
10 public virtual void Reset() { } 10 // Timescales and other things can be turned off by setting them to 'infinite'.
11 public virtual void Zero() { } 11 public const float Infinite = 10000f;
12} 12 public readonly static Vector3 InfiniteVector = new Vector3(BSMotor.Infinite, BSMotor.Infinite, BSMotor.Infinite);
13// Can all the incremental stepping be replaced with motor classes? 13
14public class BSVMotor : BSMotor 14 public BSMotor(string useName)
15{ 15 {
16 public Vector3 FrameOfReference { get; set; } 16 UseName = useName;
17 public Vector3 Offset { get; set; } 17 PhysicsScene = null;
18 18 }
19 public float TimeScale { get; set; } 19 public virtual void Reset() { }
20 public float TargetValueDecayTimeScale { get; set; } 20 public virtual void Zero() { }
21 public Vector3 CurrentValueReductionTimescale { get; set; } 21
22 public float Efficiency { get; set; } 22 public string UseName { get; private set; }
23 23 // Used only for outputting debug information. Might not be set so check for null.
24 public Vector3 TargetValue { get; private set; } 24 public BSScene PhysicsScene { get; set; }
25 public Vector3 CurrentValue { get; private set; } 25 protected void MDetailLog(string msg, params Object[] parms)
26 26 {
27 27 if (PhysicsScene != null)
28 28 {
29 BSVMotor(float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency) 29 if (PhysicsScene.VehicleLoggingEnabled)
30 { 30 {
31 TimeScale = timeScale; 31 PhysicsScene.DetailLog(msg, parms);
32 TargetValueDecayTimeScale = decayTimeScale; 32 }
33 CurrentValueReductionTimescale = frictionTimeScale; 33 }
34 Efficiency = efficiency; 34 }
35 } 35}
36 public void SetCurrent(Vector3 current) 36// Can all the incremental stepping be replaced with motor classes?
37 { 37public class BSVMotor : BSMotor
38 CurrentValue = current; 38{
39 } 39 public Vector3 FrameOfReference { get; set; }
40 public void SetTarget(Vector3 target) 40 public Vector3 Offset { get; set; }
41 { 41
42 TargetValue = target; 42 public float TimeScale { get; set; }
43 } 43 public float TargetValueDecayTimeScale { get; set; }
44 public Vector3 Step(float timeStep) 44 public Vector3 FrictionTimescale { get; set; }
45 { 45 public float Efficiency { get; set; }
46 if (CurrentValue.LengthSquared() > 0.001f) 46
47 { 47 public Vector3 TargetValue { get; private set; }
48 // Vector3 origDir = Target; // DEBUG 48 public Vector3 CurrentValue { get; private set; }
49 // Vector3 origVel = CurrentValue; // DEBUG 49
50 50 public BSVMotor(string useName)
51 // Add (desiredVelocity - currentAppliedVelocity) / howLongItShouldTakeToComplete 51 : base(useName)
52 Vector3 addAmount = (TargetValue - CurrentValue)/(TargetValue) * timeStep; 52 {
53 CurrentValue += addAmount; 53 TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite;
54 54 Efficiency = 1f;
55 float decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep; 55 FrictionTimescale = BSMotor.InfiniteVector;
56 TargetValue *= (1f - decayFactor); 56 CurrentValue = TargetValue = Vector3.Zero;
57 57 }
58 Vector3 frictionFactor = (Vector3.One / CurrentValueReductionTimescale) * timeStep; 58 public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency)
59 CurrentValue *= (Vector3.One - frictionFactor); 59 : this(useName)
60 } 60 {
61 else 61 TimeScale = timeScale;
62 { 62 TargetValueDecayTimeScale = decayTimeScale;
63 // if what remains of direction is very small, zero it. 63 FrictionTimescale = frictionTimeScale;
64 TargetValue = Vector3.Zero; 64 Efficiency = efficiency;
65 CurrentValue = Vector3.Zero; 65 CurrentValue = TargetValue = Vector3.Zero;
66 66 }
67 // VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); 67 public void SetCurrent(Vector3 current)
68 } 68 {
69 return CurrentValue; 69 CurrentValue = current;
70 } 70 }
71} 71 public void SetTarget(Vector3 target)
72 72 {
73public class BSFMotor : BSMotor 73 TargetValue = target;
74{ 74 }
75 public float TimeScale { get; set; } 75 public Vector3 Step(float timeStep)
76 public float DecayTimeScale { get; set; } 76 {
77 public float Friction { get; set; } 77 Vector3 returnCurrent = Vector3.Zero;
78 public float Efficiency { get; set; } 78 if (!CurrentValue.ApproxEquals(TargetValue, 0.01f))
79 79 {
80 public float Target { get; private set; } 80 Vector3 origTarget = TargetValue; // DEBUG
81 public float CurrentValue { get; private set; } 81 Vector3 origCurrVal = CurrentValue; // DEBUG
82 82
83 BSFMotor(float timeScale, float decayTimescale, float friction, float efficiency) 83 // Addition = (desiredVector - currentAppliedVector) / secondsItShouldTakeToComplete
84 { 84 Vector3 addAmount = (TargetValue - CurrentValue)/TimeScale * timeStep;
85 } 85 CurrentValue += addAmount;
86 public void SetCurrent(float target) 86
87 { 87 returnCurrent = CurrentValue;
88 } 88
89 public void SetTarget(float target) 89 // The desired value reduces to zero which also reduces the difference with current.
90 { 90 // If the decay time is infinite, don't decay at all.
91 } 91 float decayFactor = 0f;
92 public float Step(float timeStep) 92 if (TargetValueDecayTimeScale != BSMotor.Infinite)
93 { 93 {
94 return 0f; 94 decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep;
95 } 95 TargetValue *= (1f - decayFactor);
96} 96 }
97public class BSPIDMotor : BSMotor 97
98{ 98 Vector3 frictionFactor = Vector3.Zero;
99 // TODO: write and use this one 99 if (FrictionTimescale != BSMotor.InfiniteVector)
100 BSPIDMotor() 100 {
101 { 101 // frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
102 } 102 frictionFactor.X = FrictionTimescale.X == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.X) * timeStep;
103} 103 frictionFactor.Y = FrictionTimescale.Y == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Y) * timeStep;
104} 104 frictionFactor.Z = FrictionTimescale.Z == BSMotor.Infinite ? 0f : (1f / FrictionTimescale.Z) * timeStep;
105 CurrentValue *= (Vector3.One - frictionFactor);
106 }
107
108 MDetailLog("{0},BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},timeScale={5},addAmnt={6},targetDecay={7},decayFact={8},fricTS={9},frictFact={10}",
109 BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
110 timeStep, TimeScale, addAmount,
111 TargetValueDecayTimeScale, decayFactor,
112 FrictionTimescale, frictionFactor);
113 MDetailLog("{0},BSVMotor.Step,nonZero,{1},curr={2},target={3},add={4},decay={5},frict={6},ret={7}",
114 BSScene.DetailLogZero, UseName, CurrentValue, TargetValue,
115 addAmount, decayFactor, frictionFactor, returnCurrent);
116 }
117 else
118 {
119 // Difference between what we have and target is small. Motor is done.
120 CurrentValue = Vector3.Zero;
121 TargetValue = Vector3.Zero;
122
123 MDetailLog("{0},BSVMotor.Step,zero,{1},curr={2},target={3},ret={4}",
124 BSScene.DetailLogZero, UseName, TargetValue, CurrentValue, returnCurrent);
125
126 }
127 return returnCurrent;
128 }
129 public override string ToString()
130 {
131 return String.Format("<{0},curr={1},targ={2},decayTS={3},frictTS={4}>",
132 UseName, CurrentValue, TargetValue, TargetValueDecayTimeScale, FrictionTimescale);
133 }
134}
135
136public class BSFMotor : BSMotor
137{
138 public float TimeScale { get; set; }
139 public float DecayTimeScale { get; set; }
140 public float Friction { get; set; }
141 public float Efficiency { get; set; }
142
143 public float Target { get; private set; }
144 public float CurrentValue { get; private set; }
145
146 public BSFMotor(string useName, float timeScale, float decayTimescale, float friction, float efficiency)
147 : base(useName)
148 {
149 }
150 public void SetCurrent(float target)
151 {
152 }
153 public void SetTarget(float target)
154 {
155 }
156 public float Step(float timeStep)
157 {
158 return 0f;
159 }
160}
161public class BSPIDMotor : BSMotor
162{
163 // TODO: write and use this one
164 public BSPIDMotor(string useName)
165 : base(useName)
166 {
167 }
168}
169}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index e803072..f6a890e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -47,7 +47,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
47 */ 47 */
48public abstract class BSPhysObject : PhysicsActor 48public abstract class BSPhysObject : PhysicsActor
49{ 49{
50 protected void BaseInitialize(BSScene parentScene, uint localID, string name, string typeName) 50 protected BSPhysObject()
51 {
52 }
53 protected BSPhysObject(BSScene parentScene, uint localID, string name, string typeName)
51 { 54 {
52 PhysicsScene = parentScene; 55 PhysicsScene = parentScene;
53 LocalID = localID; 56 LocalID = localID;
@@ -91,9 +94,9 @@ public abstract class BSPhysObject : PhysicsActor
91 public PrimitiveBaseShape BaseShape { get; protected set; } 94 public PrimitiveBaseShape BaseShape { get; protected set; }
92 // Some types of objects have preferred physical representations. 95 // Some types of objects have preferred physical representations.
93 // Returns SHAPE_UNKNOWN if there is no preference. 96 // Returns SHAPE_UNKNOWN if there is no preference.
94 public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape 97 public virtual BSPhysicsShapeType PreferredPhysicalShape
95 { 98 {
96 get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } 99 get { return BSPhysicsShapeType.SHAPE_UNKNOWN; }
97 } 100 }
98 101
99 // When the physical properties are updated, an EntityProperty holds the update values. 102 // When the physical properties are updated, an EntityProperty holds the update values.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 14eb505..c62c79a 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -47,7 +47,6 @@ public sealed class BSPrim : BSPhysObject
47 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. 47 // _size is what the user passed. Scale is what we pass to the physics engine with the mesh.
48 // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. 48 // Often Scale is unity because the meshmerizer will apply _size when creating the mesh.
49 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user 49 private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user
50 // private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer
51 50
52 private bool _grabbed; 51 private bool _grabbed;
53 private bool _isSelected; 52 private bool _isSelected;
@@ -88,13 +87,13 @@ public sealed class BSPrim : BSPhysObject
88 87
89 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, 88 public BSPrim(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
90 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) 89 OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
90 : base(parent_scene, localID, primName, "BSPrim")
91 { 91 {
92 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); 92 // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID);
93 base.BaseInitialize(parent_scene, localID, primName, "BSPrim");
94 _physicsActorType = (int)ActorTypes.Prim; 93 _physicsActorType = (int)ActorTypes.Prim;
95 _position = pos; 94 _position = pos;
96 _size = size; 95 _size = size;
97 Scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type 96 Scale = size; // the scale will be set by CreateGeom depending on object type
98 _orientation = rotation; 97 _orientation = rotation;
99 _buoyancy = 1f; 98 _buoyancy = 1f;
100 _velocity = OMV.Vector3.Zero; 99 _velocity = OMV.Vector3.Zero;
@@ -155,6 +154,8 @@ public sealed class BSPrim : BSPhysObject
155 public override OMV.Vector3 Size { 154 public override OMV.Vector3 Size {
156 get { return _size; } 155 get { return _size; }
157 set { 156 set {
157 // We presume the scale and size are the same. If scale must be changed for
158 // the physical shape, that is done when the geometry is built.
158 _size = value; 159 _size = value;
159 ForceBodyShapeRebuild(false); 160 ForceBodyShapeRebuild(false);
160 } 161 }
@@ -170,7 +171,7 @@ public sealed class BSPrim : BSPhysObject
170 } 171 }
171 } 172 }
172 // Whatever the linkset wants is what I want. 173 // Whatever the linkset wants is what I want.
173 public override ShapeData.PhysicsShapeType PreferredPhysicalShape 174 public override BSPhysicsShapeType PreferredPhysicalShape
174 { get { return Linkset.PreferredPhysicalShape(this); } } 175 { get { return Linkset.PreferredPhysicalShape(this); } }
175 176
176 public override bool ForceBodyShapeRebuild(bool inTaintTime) 177 public override bool ForceBodyShapeRebuild(bool inTaintTime)
@@ -274,19 +275,19 @@ public sealed class BSPrim : BSPhysObject
274 if (!Linkset.IsRoot(this)) 275 if (!Linkset.IsRoot(this))
275 _position = Linkset.Position(this); 276 _position = Linkset.Position(this);
276 277
277 // don't do the GetObjectPosition for root elements because this function is called a zillion times 278 // don't do the GetObjectPosition for root elements because this function is called a zillion times.
278 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); 279 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
279 return _position; 280 return _position;
280 } 281 }
281 set { 282 set {
282 // If you must push the position into the physics engine, use ForcePosition. 283 // If the position must be forced into the physics engine, use ForcePosition.
283 if (_position == value) 284 if (_position == value)
284 { 285 {
285 return; 286 return;
286 } 287 }
287 _position = value; 288 _position = value;
288 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? 289 // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
289 PositionSanityCheck(); 290 PositionSanityCheck(false);
290 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() 291 PhysicsScene.TaintedObject("BSPrim.setPosition", delegate()
291 { 292 {
292 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); 293 // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
@@ -302,7 +303,7 @@ public sealed class BSPrim : BSPhysObject
302 } 303 }
303 set { 304 set {
304 _position = value; 305 _position = value;
305 PositionSanityCheck(); 306 // PositionSanityCheck(); // Don't do this! Causes a loop and caller should know better.
306 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); 307 BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation);
307 ActivateIfPhysical(false); 308 ActivateIfPhysical(false);
308 } 309 }
@@ -311,52 +312,42 @@ public sealed class BSPrim : BSPhysObject
311 // Check that the current position is sane and, if not, modify the position to make it so. 312 // Check that the current position is sane and, if not, modify the position to make it so.
312 // Check for being below terrain and being out of bounds. 313 // Check for being below terrain and being out of bounds.
313 // Returns 'true' of the position was made sane by some action. 314 // Returns 'true' of the position was made sane by some action.
314 private bool PositionSanityCheck() 315 private bool PositionSanityCheck(bool inTaintTime)
315 { 316 {
316 bool ret = false; 317 bool ret = false;
317 318
318 // If totally below the ground, move the prim up
319 // TODO: figure out the right solution for this... only for dynamic objects?
320 /*
321 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); 319 float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position);
320 OMV.Vector3 upForce = OMV.Vector3.Zero;
322 if (Position.Z < terrainHeight) 321 if (Position.Z < terrainHeight)
323 { 322 {
324 DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); 323 DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
325 _position.Z = terrainHeight + 2.0f; 324 float targetHeight = terrainHeight + (Size.Z / 2f);
325 // Upforce proportional to the distance away from the terrain. Correct the error in 1 sec.
326 upForce.Z = (terrainHeight - Position.Z) * 1f;
326 ret = true; 327 ret = true;
327 } 328 }
328 */ 329
329 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) 330 if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0)
330 { 331 {
331 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); 332 float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position);
332 // TODO: a floating motor so object will bob in the water 333 // TODO: a floating motor so object will bob in the water
333 if (Position.Z < waterHeight) 334 if (Math.Abs(Position.Z - waterHeight) > 0.1f)
334 { 335 {
335 _position.Z = waterHeight; 336 // Upforce proportional to the distance away from the water. Correct the error in 1 sec.
337 upForce.Z = (waterHeight - Position.Z) * 1f;
336 ret = true; 338 ret = true;
337 } 339 }
338 } 340 }
339 341
340 // TODO: check for out of bounds 342 // TODO: check for out of bounds
341 return ret;
342 }
343 343
344 // A version of the sanity check that also makes sure a new position value is 344 // The above code computes a force to apply to correct any out-of-bounds problems. Apply same.
345 // pushed to the physics engine. This routine would be used by anyone 345 // TODO: This should be intergrated with a geneal physics action mechanism.
346 // who is not already pushing the value. 346 // TODO: This should be moderated with PID'ness.
347 private bool PositionSanityCheck(bool inTaintTime) 347 if (ret)
348 {
349 bool ret = false;
350 if (PositionSanityCheck())
351 { 348 {
352 // The new position value must be pushed into the physics engine but we can't 349 // Apply upforce and overcome gravity.
353 // just assign to "Position" because of potential call loops. 350 AddForce(upForce - PhysicsScene.DefaultGravity, false, inTaintTime);
354 PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate()
355 {
356 DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
357 ForcePosition = _position;
358 });
359 ret = true;
360 } 351 }
361 return ret; 352 return ret;
362 } 353 }
@@ -940,6 +931,7 @@ public sealed class BSPrim : BSPhysObject
940 public override void AddForce(OMV.Vector3 force, bool pushforce) { 931 public override void AddForce(OMV.Vector3 force, bool pushforce) {
941 AddForce(force, pushforce, false); 932 AddForce(force, pushforce, false);
942 } 933 }
934 // Applying a force just adds this to the total force on the object.
943 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { 935 public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) {
944 // for an object, doesn't matter if force is a pushforce or not 936 // for an object, doesn't matter if force is a pushforce or not
945 if (force.IsFinite()) 937 if (force.IsFinite())
@@ -971,6 +963,7 @@ public sealed class BSPrim : BSPhysObject
971 }); 963 });
972 } 964 }
973 965
966 // An impulse force is scaled by the mass of the object.
974 public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime) 967 public void ApplyForceImpulse(OMV.Vector3 impulse, bool inTaintTime)
975 { 968 {
976 OMV.Vector3 applyImpulse = impulse; 969 OMV.Vector3 applyImpulse = impulse;
@@ -1387,67 +1380,34 @@ public sealed class BSPrim : BSPhysObject
1387 1380
1388 public override void UpdateProperties(EntityProperties entprop) 1381 public override void UpdateProperties(EntityProperties entprop)
1389 { 1382 {
1390 /* 1383 // Updates only for individual prims and for the root object of a linkset.
1391 UpdatedProperties changed = 0; 1384 if (Linkset.IsRoot(this))
1392 // assign to the local variables so the normal set action does not happen
1393 // if (_position != entprop.Position)
1394 if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE))
1395 {
1396 _position = entprop.Position;
1397 changed |= UpdatedProperties.Position;
1398 }
1399 // if (_orientation != entprop.Rotation)
1400 if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE))
1401 {
1402 _orientation = entprop.Rotation;
1403 changed |= UpdatedProperties.Rotation;
1404 }
1405 // if (_velocity != entprop.Velocity)
1406 if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE))
1407 {
1408 _velocity = entprop.Velocity;
1409 changed |= UpdatedProperties.Velocity;
1410 }
1411 // if (_acceleration != entprop.Acceleration)
1412 if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE))
1413 {
1414 _acceleration = entprop.Acceleration;
1415 changed |= UpdatedProperties.Acceleration;
1416 }
1417 // if (_rotationalVelocity != entprop.RotationalVelocity)
1418 if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE))
1419 {
1420 _rotationalVelocity = entprop.RotationalVelocity;
1421 changed |= UpdatedProperties.RotationalVel;
1422 }
1423 if (changed != 0)
1424 { 1385 {
1425 // Only update the position of single objects and linkset roots 1386 // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
1426 if (this._parentPrim == null) 1387 // TODO: handle physics introduced by Bullet with computed vehicle physics.
1388 if (_vehicle.IsActive)
1427 { 1389 {
1428 base.RequestPhysicsterseUpdate(); 1390 entprop.RotationalVelocity = OMV.Vector3.Zero;
1429 } 1391 }
1430 }
1431 */
1432
1433 // Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
1434 1392
1435 // Updates only for individual prims and for the root object of a linkset. 1393 // Assign directly to the local variables so the normal set action does not happen
1436 if (Linkset.IsRoot(this))
1437 {
1438 // Assign to the local variables so the normal set action does not happen
1439 _position = entprop.Position; 1394 _position = entprop.Position;
1440 _orientation = entprop.Rotation; 1395 _orientation = entprop.Rotation;
1441 _velocity = entprop.Velocity; 1396 _velocity = entprop.Velocity;
1442 _acceleration = entprop.Acceleration; 1397 _acceleration = entprop.Acceleration;
1443 _rotationalVelocity = entprop.RotationalVelocity; 1398 _rotationalVelocity = entprop.RotationalVelocity;
1444 1399
1400 // The sanity check can change the velocity and/or position.
1401 if (PositionSanityCheck(true))
1402 {
1403 entprop.Position = _position;
1404 entprop.Velocity = _velocity;
1405 }
1406
1445 // remember the current and last set values 1407 // remember the current and last set values
1446 LastEntityProperties = CurrentEntityProperties; 1408 LastEntityProperties = CurrentEntityProperties;
1447 CurrentEntityProperties = entprop; 1409 CurrentEntityProperties = entprop;
1448 1410
1449 PositionSanityCheck(true);
1450
1451 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; 1411 OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation;
1452 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", 1412 DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}",
1453 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); 1413 LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 1cc607a..09b1423 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -39,23 +39,10 @@ using log4net;
39using OpenMetaverse; 39using OpenMetaverse;
40 40
41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) 41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
42// Test sculpties (verified that they don't work)
43// Compute physics FPS reasonably
44// Based on material, set density and friction 42// Based on material, set density and friction
45// Don't use constraints in linksets of non-physical objects. Means having to move children manually.
46// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly?
47// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground)
48// At the moment, physical and phantom causes object to drop through the terrain
49// Physical phantom objects and related typing (collision options )
50// Check out llVolumeDetect. Must do something for that.
51// Use collision masks for collision with terrain and phantom objects
52// More efficient memory usage when passing hull information from BSPrim to BulletSim 43// More efficient memory usage when passing hull information from BSPrim to BulletSim
53// Should prim.link() and prim.delink() membership checking happen at taint time?
54// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once.
55// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 44// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
56// Implement LockAngularMotion 45// Implement LockAngularMotion
57// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
58// Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet.
59// Add PID movement operations. What does ScenePresence.MoveToTarget do? 46// Add PID movement operations. What does ScenePresence.MoveToTarget do?
60// Check terrain size. 128 or 127? 47// Check terrain size. 128 or 127?
61// Raycast 48// Raycast
@@ -234,6 +221,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
234 if (m_physicsLoggingEnabled) 221 if (m_physicsLoggingEnabled)
235 { 222 {
236 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); 223 PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes);
224 PhysicsLogging.ErrorLogger = m_log; // for DEBUG. Let's the logger output error messages.
237 } 225 }
238 else 226 else
239 { 227 {
@@ -308,6 +296,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
308 // Do any replacements in the parameters 296 // Do any replacements in the parameters
309 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); 297 m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
310 } 298 }
299
300 // The material characteristics.
301 BSMaterials.InitializeFromDefaults(Params);
302 if (pConfig != null)
303 {
304 BSMaterials.InitializefromParameters(pConfig);
305 }
311 } 306 }
312 } 307 }
313 308
@@ -520,9 +515,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
520 collidersCount = 0; 515 collidersCount = 0;
521 } 516 }
522 517
523 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in 518 // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in.
524 519
525 // Get a value for 'now' so all the collision and update routines don't have to get their own 520 // Get a value for 'now' so all the collision and update routines don't have to get their own.
526 SimulationNowTime = Util.EnvironmentTickCount(); 521 SimulationNowTime = Util.EnvironmentTickCount();
527 522
528 // If there were collisions, process them by sending the event to the prim. 523 // If there were collisions, process them by sending the event to the prim.
@@ -568,6 +563,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
568 ObjectsWithCollisions.Remove(po); 563 ObjectsWithCollisions.Remove(po);
569 ObjectsWithNoMoreCollisions.Clear(); 564 ObjectsWithNoMoreCollisions.Clear();
570 } 565 }
566 // Done with collisions.
571 567
572 // If any of the objects had updated properties, tell the object it has been changed by the physics engine 568 // If any of the objects had updated properties, tell the object it has been changed by the physics engine
573 if (updatedEntityCount > 0) 569 if (updatedEntityCount > 0)
@@ -591,9 +587,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
591 587
592 // The physics engine returns the number of milliseconds it simulated this call. 588 // The physics engine returns the number of milliseconds it simulated this call.
593 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. 589 // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS.
594 // We multiply by 55 to give a recognizable running rate (55 or less). 590 // Multiply by 55 to give a nominal frame rate of 55.
595 return numSubSteps * m_fixedTimeStep * 1000 * 55; 591 return (float)numSubSteps * m_fixedTimeStep * 1000f * 55f;
596 // return timeStep * 1000 * 55;
597 } 592 }
598 593
599 // Something has collided 594 // Something has collided
@@ -683,7 +678,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
683 #region Taints 678 #region Taints
684 679
685 // Calls to the PhysicsActors can't directly call into the physics engine 680 // Calls to the PhysicsActors can't directly call into the physics engine
686 // because it might be busy. We delay changes to a known time. 681 // because it might be busy. We delay changes to a known time.
687 // We rely on C#'s closure to save and restore the context for the delegate. 682 // We rely on C#'s closure to save and restore the context for the delegate.
688 public void TaintedObject(String ident, TaintCallback callback) 683 public void TaintedObject(String ident, TaintCallback callback)
689 { 684 {
@@ -712,7 +707,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
712 // here just before the physics engine is called to step the simulation. 707 // here just before the physics engine is called to step the simulation.
713 public void ProcessTaints() 708 public void ProcessTaints()
714 { 709 {
715 InTaintTime = true; 710 InTaintTime = true; // Only used for debugging so locking is not necessary.
716 ProcessRegularTaints(); 711 ProcessRegularTaints();
717 ProcessPostTaintTaints(); 712 ProcessPostTaintTaints();
718 InTaintTime = false; 713 InTaintTime = false;
@@ -758,6 +753,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
758 DetailLog("{0},BSScene.ProcessTaints,leftTaintsOnList,numNotProcessed={1}", DetailLogZero, _taintOperations.Count); 753 DetailLog("{0},BSScene.ProcessTaints,leftTaintsOnList,numNotProcessed={1}", DetailLogZero, _taintOperations.Count);
759 } 754 }
760 */ 755 */
756
761 // swizzle a new list into the list location so we can process what's there 757 // swizzle a new list into the list location so we can process what's there
762 List<TaintCallbackEntry> oldList; 758 List<TaintCallbackEntry> oldList;
763 lock (_taintLock) 759 lock (_taintLock)
@@ -787,8 +783,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
787 // will replace any previous operation by the same object. 783 // will replace any previous operation by the same object.
788 public void PostTaintObject(String ident, uint ID, TaintCallback callback) 784 public void PostTaintObject(String ident, uint ID, TaintCallback callback)
789 { 785 {
790 if (!m_initialized) return;
791
792 string uniqueIdent = ident + "-" + ID.ToString(); 786 string uniqueIdent = ident + "-" + ID.ToString();
793 lock (_taintLock) 787 lock (_taintLock)
794 { 788 {
@@ -864,13 +858,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
864 } 858 }
865 } 859 }
866 860
861 // Only used for debugging. Does not change state of anything so locking is not necessary.
867 public bool AssertInTaintTime(string whereFrom) 862 public bool AssertInTaintTime(string whereFrom)
868 { 863 {
869 if (!InTaintTime) 864 if (!InTaintTime)
870 { 865 {
871 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); 866 DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
872 m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); 867 m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
873 Util.PrintCallStack(); 868 Util.PrintCallStack(); // Prints the stack into the DEBUG log file.
874 } 869 }
875 return InTaintTime; 870 return InTaintTime;
876 } 871 }
@@ -1069,7 +1064,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1069 (s,p,l,v) => { s.PID_P = v; } ), 1064 (s,p,l,v) => { s.PID_P = v; } ),
1070 1065
1071 new ParameterDefn("DefaultFriction", "Friction factor used on new objects", 1066 new ParameterDefn("DefaultFriction", "Friction factor used on new objects",
1072 0.5f, 1067 0.2f,
1073 (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); }, 1068 (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); },
1074 (s) => { return s.m_params[0].defaultFriction; }, 1069 (s) => { return s.m_params[0].defaultFriction; },
1075 (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ), 1070 (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ),
@@ -1084,7 +1079,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1084 (s) => { return s.m_params[0].defaultRestitution; }, 1079 (s) => { return s.m_params[0].defaultRestitution; },
1085 (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ), 1080 (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ),
1086 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)", 1081 new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)",
1087 0f, 1082 0.04f,
1088 (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); }, 1083 (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); },
1089 (s) => { return s.m_params[0].collisionMargin; }, 1084 (s) => { return s.m_params[0].collisionMargin; },
1090 (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ), 1085 (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ),
@@ -1145,8 +1140,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1145 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, 1140 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); },
1146 (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ), 1141 (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ),
1147 1142
1143 new ParameterDefn("TerrainImplementation", "Type of shape to use for terrain (0=heightmap, 1=mesh)",
1144 (float)BSTerrainPhys.TerrainImplementation.Mesh,
1145 (s,cf,p,v) => { s.m_params[0].terrainImplementation = cf.GetFloat(p,v); },
1146 (s) => { return s.m_params[0].terrainImplementation; },
1147 (s,p,l,v) => { s.m_params[0].terrainImplementation = v; } ),
1148 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 1148 new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
1149 0.5f, 1149 0.3f,
1150 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, 1150 (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); },
1151 (s) => { return s.m_params[0].terrainFriction; }, 1151 (s) => { return s.m_params[0].terrainFriction; },
1152 (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ), 1152 (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ),
@@ -1160,13 +1160,19 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1160 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, 1160 (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); },
1161 (s) => { return s.m_params[0].terrainRestitution; }, 1161 (s) => { return s.m_params[0].terrainRestitution; },
1162 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ), 1162 (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ),
1163 new ParameterDefn("TerrainCollisionMargin", "Margin where collision checking starts" ,
1164 0.04f,
1165 (s,cf,p,v) => { s.m_params[0].terrainCollisionMargin = cf.GetFloat(p, v); },
1166 (s) => { return s.m_params[0].terrainCollisionMargin; },
1167 (s,p,l,v) => { s.m_params[0].terrainCollisionMargin = v; /* TODO: set on real terrain */ } ),
1168
1163 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", 1169 new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
1164 0.2f, 1170 0.2f,
1165 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, 1171 (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
1166 (s) => { return s.m_params[0].avatarFriction; }, 1172 (s) => { return s.m_params[0].avatarFriction; },
1167 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ), 1173 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
1168 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", 1174 new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
1169 10f, 1175 10.0f,
1170 (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); }, 1176 (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); },
1171 (s) => { return s.m_params[0].avatarStandingFriction; }, 1177 (s) => { return s.m_params[0].avatarStandingFriction; },
1172 (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ), 1178 (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ),
@@ -1180,11 +1186,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1180 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, 1186 (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
1181 (s) => { return s.m_params[0].avatarRestitution; }, 1187 (s) => { return s.m_params[0].avatarRestitution; },
1182 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ), 1188 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ),
1183 new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", 1189 new ParameterDefn("AvatarCapsuleWidth", "The distance between the sides of the avatar capsule",
1184 0.37f, 1190 0.6f,
1185 (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, 1191 (s,cf,p,v) => { s.m_params[0].avatarCapsuleWidth = cf.GetFloat(p, v); },
1186 (s) => { return s.m_params[0].avatarCapsuleRadius; }, 1192 (s) => { return s.m_params[0].avatarCapsuleWidth; },
1187 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), 1193 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleWidth, p, l, v); } ),
1194 new ParameterDefn("AvatarCapsuleDepth", "The distance between the front and back of the avatar capsule",
1195 0.45f,
1196 (s,cf,p,v) => { s.m_params[0].avatarCapsuleDepth = cf.GetFloat(p, v); },
1197 (s) => { return s.m_params[0].avatarCapsuleDepth; },
1198 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleDepth, p, l, v); } ),
1188 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", 1199 new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
1189 1.5f, 1200 1.5f,
1190 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, 1201 (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
@@ -1196,6 +1207,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
1196 (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, 1207 (s) => { return s.m_params[0].avatarContactProcessingThreshold; },
1197 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), 1208 (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
1198 1209
1210 new ParameterDefn("VehicleAngularDamping", "Factor to damp vehicle angular movement per second (0.0 - 1.0)",
1211 0.95f,
1212 (s,cf,p,v) => { s.m_params[0].vehicleAngularDamping = cf.GetFloat(p, v); },
1213 (s) => { return s.m_params[0].vehicleAngularDamping; },
1214 (s,p,l,v) => { s.m_params[0].vehicleAngularDamping = v; } ),
1199 1215
1200 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", 1216 new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
1201 0f, 1217 0f,
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 29a23c0..892c34b 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -178,7 +178,7 @@ public sealed class BSShapeCollection : IDisposable
178 bool ret = false; 178 bool ret = false;
179 switch (shape.type) 179 switch (shape.type)
180 { 180 {
181 case ShapeData.PhysicsShapeType.SHAPE_MESH: 181 case BSPhysicsShapeType.SHAPE_MESH:
182 MeshDesc meshDesc; 182 MeshDesc meshDesc;
183 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) 183 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
184 { 184 {
@@ -201,7 +201,7 @@ public sealed class BSShapeCollection : IDisposable
201 meshDesc.lastReferenced = System.DateTime.Now; 201 meshDesc.lastReferenced = System.DateTime.Now;
202 Meshes[shape.shapeKey] = meshDesc; 202 Meshes[shape.shapeKey] = meshDesc;
203 break; 203 break;
204 case ShapeData.PhysicsShapeType.SHAPE_HULL: 204 case BSPhysicsShapeType.SHAPE_HULL:
205 HullDesc hullDesc; 205 HullDesc hullDesc;
206 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) 206 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
207 { 207 {
@@ -224,7 +224,7 @@ public sealed class BSShapeCollection : IDisposable
224 hullDesc.lastReferenced = System.DateTime.Now; 224 hullDesc.lastReferenced = System.DateTime.Now;
225 Hulls[shape.shapeKey] = hullDesc; 225 Hulls[shape.shapeKey] = hullDesc;
226 break; 226 break;
227 case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: 227 case BSPhysicsShapeType.SHAPE_UNKNOWN:
228 break; 228 break;
229 default: 229 default:
230 // Native shapes are not tracked and they don't go into any list 230 // Native shapes are not tracked and they don't go into any list
@@ -255,16 +255,16 @@ public sealed class BSShapeCollection : IDisposable
255 { 255 {
256 switch (shape.type) 256 switch (shape.type)
257 { 257 {
258 case ShapeData.PhysicsShapeType.SHAPE_HULL: 258 case BSPhysicsShapeType.SHAPE_HULL:
259 DereferenceHull(shape, shapeCallback); 259 DereferenceHull(shape, shapeCallback);
260 break; 260 break;
261 case ShapeData.PhysicsShapeType.SHAPE_MESH: 261 case BSPhysicsShapeType.SHAPE_MESH:
262 DereferenceMesh(shape, shapeCallback); 262 DereferenceMesh(shape, shapeCallback);
263 break; 263 break;
264 case ShapeData.PhysicsShapeType.SHAPE_COMPOUND: 264 case BSPhysicsShapeType.SHAPE_COMPOUND:
265 DereferenceCompound(shape, shapeCallback); 265 DereferenceCompound(shape, shapeCallback);
266 break; 266 break;
267 case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: 267 case BSPhysicsShapeType.SHAPE_UNKNOWN:
268 break; 268 break;
269 default: 269 default:
270 break; 270 break;
@@ -352,28 +352,28 @@ public sealed class BSShapeCollection : IDisposable
352 BulletShape shapeInfo = new BulletShape(cShape); 352 BulletShape shapeInfo = new BulletShape(cShape);
353 if (TryGetMeshByPtr(cShape, out meshDesc)) 353 if (TryGetMeshByPtr(cShape, out meshDesc))
354 { 354 {
355 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_MESH; 355 shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH;
356 shapeInfo.shapeKey = meshDesc.shapeKey; 356 shapeInfo.shapeKey = meshDesc.shapeKey;
357 } 357 }
358 else 358 else
359 { 359 {
360 if (TryGetHullByPtr(cShape, out hullDesc)) 360 if (TryGetHullByPtr(cShape, out hullDesc))
361 { 361 {
362 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_HULL; 362 shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL;
363 shapeInfo.shapeKey = hullDesc.shapeKey; 363 shapeInfo.shapeKey = hullDesc.shapeKey;
364 } 364 }
365 else 365 else
366 { 366 {
367 if (BulletSimAPI.IsCompound2(cShape)) 367 if (BulletSimAPI.IsCompound2(cShape))
368 { 368 {
369 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; 369 shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND;
370 } 370 }
371 else 371 else
372 { 372 {
373 if (BulletSimAPI.IsNativeShape2(cShape)) 373 if (BulletSimAPI.IsNativeShape2(cShape))
374 { 374 {
375 shapeInfo.isNativeShape = true; 375 shapeInfo.isNativeShape = true;
376 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) 376 shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter)
377 } 377 }
378 } 378 }
379 } 379 }
@@ -381,7 +381,7 @@ public sealed class BSShapeCollection : IDisposable
381 381
382 DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); 382 DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
383 383
384 if (shapeInfo.type != ShapeData.PhysicsShapeType.SHAPE_UNKNOWN) 384 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
385 { 385 {
386 DereferenceShape(shapeInfo, true, null); 386 DereferenceShape(shapeInfo, true, null);
387 } 387 }
@@ -405,11 +405,11 @@ public sealed class BSShapeCollection : IDisposable
405 bool ret = false; 405 bool ret = false;
406 bool haveShape = false; 406 bool haveShape = false;
407 407
408 if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) 408 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
409 { 409 {
410 // an avatar capsule is close to a native shape (it is not shared) 410 // an avatar capsule is close to a native shape (it is not shared)
411 ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, 411 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE,
412 ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); 412 FixedShapeKey.KEY_CAPSULE, shapeCallback);
413 DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); 413 DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
414 ret = true; 414 ret = true;
415 haveShape = true; 415 haveShape = true;
@@ -417,7 +417,7 @@ public sealed class BSShapeCollection : IDisposable
417 417
418 // Compound shapes are handled special as they are rebuilt from scratch. 418 // Compound shapes are handled special as they are rebuilt from scratch.
419 // This isn't too great a hardship since most of the child shapes will already been created. 419 // This isn't too great a hardship since most of the child shapes will already been created.
420 if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) 420 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
421 { 421 {
422 ret = GetReferenceToCompoundShape(prim, shapeCallback); 422 ret = GetReferenceToCompoundShape(prim, shapeCallback);
423 DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); 423 DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
@@ -460,11 +460,11 @@ public sealed class BSShapeCollection : IDisposable
460 haveShape = true; 460 haveShape = true;
461 if (forceRebuild 461 if (forceRebuild
462 || prim.Scale != prim.Size 462 || prim.Scale != prim.Size
463 || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE 463 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE
464 ) 464 )
465 { 465 {
466 ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_SPHERE, 466 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE,
467 ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); 467 FixedShapeKey.KEY_SPHERE, shapeCallback);
468 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", 468 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
469 prim.LocalID, forceRebuild, prim.PhysShape); 469 prim.LocalID, forceRebuild, prim.PhysShape);
470 } 470 }
@@ -474,11 +474,11 @@ public sealed class BSShapeCollection : IDisposable
474 haveShape = true; 474 haveShape = true;
475 if (forceRebuild 475 if (forceRebuild
476 || prim.Scale != prim.Size 476 || prim.Scale != prim.Size
477 || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX 477 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX
478 ) 478 )
479 { 479 {
480 ret = GetReferenceToNativeShape( prim, ShapeData.PhysicsShapeType.SHAPE_BOX, 480 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX,
481 ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); 481 FixedShapeKey.KEY_BOX, shapeCallback);
482 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", 482 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
483 prim.LocalID, forceRebuild, prim.PhysShape); 483 prim.LocalID, forceRebuild, prim.PhysShape);
484 } 484 }
@@ -519,15 +519,12 @@ public sealed class BSShapeCollection : IDisposable
519 // Creates a native shape and assignes it to prim.BSShape. 519 // Creates a native shape and assignes it to prim.BSShape.
520 // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). 520 // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape().
521 private bool GetReferenceToNativeShape(BSPhysObject prim, 521 private bool GetReferenceToNativeShape(BSPhysObject prim,
522 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, 522 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey,
523 ShapeDestructionCallback shapeCallback) 523 ShapeDestructionCallback shapeCallback)
524 { 524 {
525 // release any previous shape 525 // release any previous shape
526 DereferenceShape(prim.PhysShape, true, shapeCallback); 526 DereferenceShape(prim.PhysShape, true, shapeCallback);
527 527
528 // Bullet native objects are scaled by the Bullet engine so pass the size in
529 prim.Scale = prim.Size;
530
531 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); 528 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
532 529
533 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. 530 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
@@ -538,8 +535,8 @@ public sealed class BSShapeCollection : IDisposable
538 return true; 535 return true;
539 } 536 }
540 537
541 private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, ShapeData.PhysicsShapeType shapeType, 538 private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, BSPhysicsShapeType shapeType,
542 ShapeData.FixedShapeKey shapeKey) 539 FixedShapeKey shapeKey)
543 { 540 {
544 BulletShape newShape; 541 BulletShape newShape;
545 // Need to make sure the passed shape information is for the native type. 542 // Need to make sure the passed shape information is for the native type.
@@ -547,12 +544,13 @@ public sealed class BSShapeCollection : IDisposable
547 nativeShapeData.Type = shapeType; 544 nativeShapeData.Type = shapeType;
548 nativeShapeData.ID = prim.LocalID; 545 nativeShapeData.ID = prim.LocalID;
549 nativeShapeData.Scale = prim.Scale; 546 nativeShapeData.Scale = prim.Scale;
550 nativeShapeData.Size = prim.Scale; 547 nativeShapeData.Size = prim.Scale; // unneeded, I think.
551 nativeShapeData.MeshKey = (ulong)shapeKey; 548 nativeShapeData.MeshKey = (ulong)shapeKey;
552 nativeShapeData.HullKey = (ulong)shapeKey; 549 nativeShapeData.HullKey = (ulong)shapeKey;
553 550
554 if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) 551 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
555 { 552 {
553 // The proper scale has been calculated in the prim.
556 newShape = new BulletShape( 554 newShape = new BulletShape(
557 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) 555 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale)
558 , shapeType); 556 , shapeType);
@@ -560,6 +558,9 @@ public sealed class BSShapeCollection : IDisposable
560 } 558 }
561 else 559 else
562 { 560 {
561 // Native shapes are scaled in Bullet so set the scaling to the size
562 prim.Scale = prim.Size;
563 nativeShapeData.Scale = prim.Scale;
563 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); 564 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType);
564 } 565 }
565 if (newShape.ptr == IntPtr.Zero) 566 if (newShape.ptr == IntPtr.Zero)
@@ -585,7 +586,7 @@ public sealed class BSShapeCollection : IDisposable
585 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); 586 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
586 587
587 // if this new shape is the same as last time, don't recreate the mesh 588 // if this new shape is the same as last time, don't recreate the mesh
588 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) 589 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
589 return false; 590 return false;
590 591
591 DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", 592 DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}",
@@ -643,7 +644,7 @@ public sealed class BSShapeCollection : IDisposable
643 indices.GetLength(0), indices, vertices.Count, verticesAsFloats); 644 indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
644 } 645 }
645 } 646 }
646 BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); 647 BulletShape newShape = new BulletShape(meshPtr, BSPhysicsShapeType.SHAPE_MESH);
647 newShape.shapeKey = newMeshKey; 648 newShape.shapeKey = newMeshKey;
648 649
649 return newShape; 650 return newShape;
@@ -659,7 +660,7 @@ public sealed class BSShapeCollection : IDisposable
659 System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); 660 System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
660 661
661 // if the hull hasn't changed, don't rebuild it 662 // if the hull hasn't changed, don't rebuild it
662 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) 663 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
663 return false; 664 return false;
664 665
665 DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", 666 DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
@@ -780,7 +781,7 @@ public sealed class BSShapeCollection : IDisposable
780 } 781 }
781 } 782 }
782 783
783 BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); 784 BulletShape newShape = new BulletShape(hullPtr, BSPhysicsShapeType.SHAPE_HULL);
784 newShape.shapeKey = newHullKey; 785 newShape.shapeKey = newHullKey;
785 786
786 return newShape; // 'true' means a new shape has been added to this prim 787 return newShape; // 'true' means a new shape has been added to this prim
@@ -803,7 +804,7 @@ public sealed class BSShapeCollection : IDisposable
803 // DereferenceShape(prim.PhysShape, true, shapeCallback); 804 // DereferenceShape(prim.PhysShape, true, shapeCallback);
804 805
805 BulletShape cShape = new BulletShape( 806 BulletShape cShape = new BulletShape(
806 BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); 807 BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), BSPhysicsShapeType.SHAPE_COMPOUND);
807 808
808 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. 809 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
809 CreateGeomMeshOrHull(prim, shapeCallback); 810 CreateGeomMeshOrHull(prim, shapeCallback);
@@ -894,7 +895,7 @@ public sealed class BSShapeCollection : IDisposable
894 895
895 // While we figure out the real problem, stick a simple native shape on the object. 896 // While we figure out the real problem, stick a simple native shape on the object.
896 BulletShape fillinShape = 897 BulletShape fillinShape =
897 BuildPhysicalNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); 898 BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
898 899
899 return fillinShape; 900 return fillinShape;
900 } 901 }
@@ -940,7 +941,7 @@ public sealed class BSShapeCollection : IDisposable
940 else 941 else
941 { 942 {
942 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, 943 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
943 prim.LocalID, prim.ForcePosition, prim.ForceOrientation); 944 prim.LocalID, prim.RawPosition, prim.RawOrientation);
944 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); 945 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
945 } 946 }
946 aBody = new BulletBody(prim.LocalID, bodyPtr); 947 aBody = new BulletBody(prim.LocalID, bodyPtr);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
index 5e2c4a8..96cd55e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
@@ -1,213 +1,208 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD 9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 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 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 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq; 30using System.Linq;
31using System.Text; 31using System.Text;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35public abstract class BSShape 35public abstract class BSShape
36{ 36{
37 public IntPtr ptr { get; set; } 37 public IntPtr ptr { get; set; }
38 public ShapeData.PhysicsShapeType type { get; set; } 38 public BSPhysicsShapeType type { get; set; }
39 public System.UInt64 key { get; set; } 39 public System.UInt64 key { get; set; }
40 public int referenceCount { get; set; } 40 public int referenceCount { get; set; }
41 public DateTime lastReferenced { get; set; } 41 public DateTime lastReferenced { get; set; }
42 42
43 protected void Initialize() 43 public BSShape()
44 { 44 {
45 ptr = IntPtr.Zero; 45 ptr = IntPtr.Zero;
46 type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; 46 type = BSPhysicsShapeType.SHAPE_UNKNOWN;
47 key = 0; 47 key = 0;
48 referenceCount = 0; 48 referenceCount = 0;
49 lastReferenced = DateTime.Now; 49 lastReferenced = DateTime.Now;
50 } 50 }
51 51
52 // Get a reference to a physical shape. Create if it doesn't exist 52 // Get a reference to a physical shape. Create if it doesn't exist
53 public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 53 public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
54 { 54 {
55 BSShape ret = null; 55 BSShape ret = null;
56 56
57 if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) 57 if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
58 { 58 {
59 // an avatar capsule is close to a native shape (it is not shared) 59 // an avatar capsule is close to a native shape (it is not shared)
60 ret = BSShapeNative.GetReference(physicsScene, prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, 60 ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE,
61 ShapeData.FixedShapeKey.KEY_CAPSULE); 61 FixedShapeKey.KEY_CAPSULE);
62 physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); 62 physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret);
63 } 63 }
64 64
65 // Compound shapes are handled special as they are rebuilt from scratch. 65 // Compound shapes are handled special as they are rebuilt from scratch.
66 // This isn't too great a hardship since most of the child shapes will already been created. 66 // This isn't too great a hardship since most of the child shapes will already been created.
67 if (ret == null && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) 67 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
68 { 68 {
69 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added 69 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
70 ret = BSShapeCompound.GetReference(prim); 70 ret = BSShapeCompound.GetReference(prim);
71 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret); 71 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
72 } 72 }
73 73
74 if (ret == null) 74 if (ret == null)
75 ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim); 75 ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim);
76 76
77 return ret; 77 return ret;
78 } 78 }
79 public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 79 public static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
80 { 80 {
81 return null; 81 return null;
82 } 82 }
83 public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 83 public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
84 { 84 {
85 return null; 85 return null;
86 } 86 }
87 87
88 // Release the use of a physical shape. 88 // Release the use of a physical shape.
89 public abstract void Dereference(BSScene physicsScene); 89 public abstract void Dereference(BSScene physicsScene);
90 90
91 // All shapes have a static call to get a reference to the physical shape 91 // All shapes have a static call to get a reference to the physical shape
92 // protected abstract static BSShape GetReference(); 92 // protected abstract static BSShape GetReference();
93 93
94 public override string ToString() 94 public override string ToString()
95 { 95 {
96 StringBuilder buff = new StringBuilder(); 96 StringBuilder buff = new StringBuilder();
97 buff.Append("<p="); 97 buff.Append("<p=");
98 buff.Append(ptr.ToString("X")); 98 buff.Append(ptr.ToString("X"));
99 buff.Append(",s="); 99 buff.Append(",s=");
100 buff.Append(type.ToString()); 100 buff.Append(type.ToString());
101 buff.Append(",k="); 101 buff.Append(",k=");
102 buff.Append(key.ToString("X")); 102 buff.Append(key.ToString("X"));
103 buff.Append(",c="); 103 buff.Append(",c=");
104 buff.Append(referenceCount.ToString()); 104 buff.Append(referenceCount.ToString());
105 buff.Append(">"); 105 buff.Append(">");
106 return buff.ToString(); 106 return buff.ToString();
107 } 107 }
108} 108}
109 109
110public class BSShapeNull : BSShape 110public class BSShapeNull : BSShape
111{ 111{
112 public BSShapeNull() 112 public BSShapeNull() : base()
113 { 113 {
114 base.Initialize(); 114 }
115 } 115 public static BSShape GetReference() { return new BSShapeNull(); }
116 public static BSShape GetReference() { return new BSShapeNull(); } 116 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ }
117 public override void Dereference(BSScene physicsScene) { /* The magic of garbage collection will make this go away */ } 117}
118} 118
119 119public class BSShapeNative : BSShape
120public class BSShapeNative : BSShape 120{
121{ 121 private static string LogHeader = "[BULLETSIM SHAPE NATIVE]";
122 private static string LogHeader = "[BULLETSIM SHAPE NATIVE]"; 122 public BSShapeNative() : base()
123 public BSShapeNative() 123 {
124 { 124 }
125 base.Initialize(); 125 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim,
126 } 126 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
127 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, 127 {
128 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) 128 // Native shapes are not shared and are always built anew.
129 { 129 return new BSShapeNative(physicsScene, prim, shapeType, shapeKey);
130 // Native shapes are not shared and are always built anew. 130 }
131 return new BSShapeNative(physicsScene, prim, shapeType, shapeKey); 131
132 } 132 private BSShapeNative(BSScene physicsScene, BSPhysObject prim,
133 133 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
134 private BSShapeNative(BSScene physicsScene, BSPhysObject prim, 134 {
135 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey) 135 ShapeData nativeShapeData = new ShapeData();
136 { 136 nativeShapeData.Type = shapeType;
137 ShapeData nativeShapeData = new ShapeData(); 137 nativeShapeData.ID = prim.LocalID;
138 nativeShapeData.Type = shapeType; 138 nativeShapeData.Scale = prim.Scale;
139 nativeShapeData.ID = prim.LocalID; 139 nativeShapeData.Size = prim.Scale;
140 nativeShapeData.Scale = prim.Scale; 140 nativeShapeData.MeshKey = (ulong)shapeKey;
141 nativeShapeData.Size = prim.Scale; 141 nativeShapeData.HullKey = (ulong)shapeKey;
142 nativeShapeData.MeshKey = (ulong)shapeKey; 142
143 nativeShapeData.HullKey = (ulong)shapeKey; 143
144 144 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
145 145 {
146 if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) 146 ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale);
147 { 147 physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
148 ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale); 148 }
149 physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); 149 else
150 } 150 {
151 else 151 ptr = BulletSimAPI.BuildNativeShape2(physicsScene.World.ptr, nativeShapeData);
152 { 152 }
153 ptr = BulletSimAPI.BuildNativeShape2(physicsScene.World.ptr, nativeShapeData); 153 if (ptr == IntPtr.Zero)
154 } 154 {
155 if (ptr == IntPtr.Zero) 155 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
156 { 156 LogHeader, prim.LocalID, shapeType);
157 physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", 157 }
158 LogHeader, prim.LocalID, shapeType); 158 type = shapeType;
159 } 159 key = (UInt64)shapeKey;
160 type = shapeType; 160 }
161 key = (UInt64)shapeKey; 161 // Make this reference to the physical shape go away since native shapes are not shared.
162 } 162 public override void Dereference(BSScene physicsScene)
163 // Make this reference to the physical shape go away since native shapes are not shared. 163 {
164 public override void Dereference(BSScene physicsScene) 164 // Native shapes are not tracked and are released immediately
165 { 165 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this);
166 // Native shapes are not tracked and are released immediately 166 BulletSimAPI.DeleteCollisionShape2(physicsScene.World.ptr, ptr);
167 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,shape={1}", BSScene.DetailLogZero, this); 167 ptr = IntPtr.Zero;
168 BulletSimAPI.DeleteCollisionShape2(physicsScene.World.ptr, ptr); 168 // Garbage collection will free up this instance.
169 ptr = IntPtr.Zero; 169 }
170 // Garbage collection will free up this instance. 170}
171 } 171
172} 172public class BSShapeMesh : BSShape
173 173{
174public class BSShapeMesh : BSShape 174 private static string LogHeader = "[BULLETSIM SHAPE MESH]";
175{ 175 private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>();
176 private static string LogHeader = "[BULLETSIM SHAPE MESH]"; 176
177 private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>(); 177 public BSShapeMesh() : base()
178 178 {
179 public BSShapeMesh() 179 }
180 { 180 public static BSShape GetReference() { return new BSShapeNull(); }
181 base.Initialize(); 181 public override void Dereference(BSScene physicsScene) { }
182 } 182}
183 public static BSShape GetReference() { return new BSShapeNull(); } 183
184 public override void Dereference(BSScene physicsScene) { } 184public class BSShapeHull : BSShape
185} 185{
186 186 private static string LogHeader = "[BULLETSIM SHAPE HULL]";
187public class BSShapeHull : BSShape 187 private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>();
188{ 188
189 private static string LogHeader = "[BULLETSIM SHAPE HULL]"; 189 public BSShapeHull() : base()
190 private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>(); 190 {
191 191 }
192 public BSShapeHull() 192 public static BSShape GetReference() { return new BSShapeNull(); }
193 { 193 public override void Dereference(BSScene physicsScene) { }
194 base.Initialize(); 194}
195 } 195
196 public static BSShape GetReference() { return new BSShapeNull(); } 196public class BSShapeCompound : BSShape
197 public override void Dereference(BSScene physicsScene) { } 197{
198} 198 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
199 199 public BSShapeCompound() : base()
200public class BSShapeCompound : BSShape 200 {
201{ 201 }
202 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]"; 202 public static BSShape GetReference(BSPhysObject prim)
203 public BSShapeCompound() 203 {
204 { 204 return new BSShapeNull();
205 base.Initialize(); 205 }
206 } 206 public override void Dereference(BSScene physicsScene) { }
207 public static BSShape GetReference(BSPhysObject prim) 207}
208 { 208}
209 return new BSShapeNull();
210 }
211 public override void Dereference(BSScene physicsScene) { }
212}
213}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
new file mode 100755
index 0000000..1450f66
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainHeightmap.cs
@@ -0,0 +1,170 @@
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 OpenSim.Framework;
32using OpenSim.Region.Framework;
33using OpenSim.Region.CoreModules;
34using OpenSim.Region.Physics.Manager;
35
36using Nini.Config;
37using log4net;
38
39using OpenMetaverse;
40
41namespace OpenSim.Region.Physics.BulletSPlugin
42{
43public sealed class BSTerrainHeightmap : BSTerrainPhys
44{
45 static string LogHeader = "[BULLETSIM TERRAIN HEIGHTMAP]";
46
47 BulletHeightMapInfo m_mapInfo = null;
48
49 // Constructor to build a default, flat heightmap terrain.
50 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
51 : base(physicsScene, regionBase, id)
52 {
53 Vector3 minTerrainCoords = new Vector3(0f, 0f, BSTerrainManager.HEIGHT_INITIALIZATION - BSTerrainManager.HEIGHT_EQUAL_FUDGE);
54 Vector3 maxTerrainCoords = new Vector3(regionSize.X, regionSize.Y, BSTerrainManager.HEIGHT_INITIALIZATION);
55 int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y;
56 float[] initialMap = new float[totalHeights];
57 for (int ii = 0; ii < totalHeights; ii++)
58 {
59 initialMap[ii] = BSTerrainManager.HEIGHT_INITIALIZATION;
60 }
61 m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero);
62 m_mapInfo.minCoords = minTerrainCoords;
63 m_mapInfo.maxCoords = maxTerrainCoords;
64 m_mapInfo.terrainRegionBase = TerrainBase;
65 // Don't have to free any previous since we just got here.
66 BuildHeightmapTerrain();
67 }
68
69 // This minCoords and maxCoords passed in give the size of the terrain (min and max Z
70 // are the high and low points of the heightmap).
71 public BSTerrainHeightmap(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
72 Vector3 minCoords, Vector3 maxCoords)
73 : base(physicsScene, regionBase, id)
74 {
75 m_mapInfo = new BulletHeightMapInfo(id, initialMap, IntPtr.Zero);
76 m_mapInfo.minCoords = minCoords;
77 m_mapInfo.maxCoords = maxCoords;
78 m_mapInfo.minZ = minCoords.Z;
79 m_mapInfo.maxZ = maxCoords.Z;
80 m_mapInfo.terrainRegionBase = TerrainBase;
81
82 // Don't have to free any previous since we just got here.
83 BuildHeightmapTerrain();
84 }
85
86 public override void Dispose()
87 {
88 ReleaseHeightMapTerrain();
89 }
90
91 // Using the information in m_mapInfo, create the physical representation of the heightmap.
92 private void BuildHeightmapTerrain()
93 {
94 m_mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, m_mapInfo.ID,
95 m_mapInfo.minCoords, m_mapInfo.maxCoords,
96 m_mapInfo.heightMap, PhysicsScene.Params.terrainCollisionMargin);
97
98 // Create the terrain shape from the mapInfo
99 m_mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(m_mapInfo.Ptr),
100 BSPhysicsShapeType.SHAPE_TERRAIN);
101
102 // The terrain object initial position is at the center of the object
103 Vector3 centerPos;
104 centerPos.X = m_mapInfo.minCoords.X + (m_mapInfo.sizeX / 2f);
105 centerPos.Y = m_mapInfo.minCoords.Y + (m_mapInfo.sizeY / 2f);
106 centerPos.Z = m_mapInfo.minZ + ((m_mapInfo.maxZ - m_mapInfo.minZ) / 2f);
107
108 m_mapInfo.terrainBody = new BulletBody(m_mapInfo.ID,
109 BulletSimAPI.CreateBodyWithDefaultMotionState2(m_mapInfo.terrainShape.ptr,
110 m_mapInfo.ID, centerPos, Quaternion.Identity));
111
112 // Set current terrain attributes
113 BulletSimAPI.SetFriction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction);
114 BulletSimAPI.SetHitFraction2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction);
115 BulletSimAPI.SetRestitution2(m_mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution);
116 BulletSimAPI.SetCollisionFlags2(m_mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
117
118 // Return the new terrain to the world of physical objects
119 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
120
121 // redo its bounding box now that it is in the world
122 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
123
124 BulletSimAPI.SetCollisionFilterMask2(m_mapInfo.terrainBody.ptr,
125 (uint)CollisionFilterGroups.TerrainFilter,
126 (uint)CollisionFilterGroups.TerrainMask);
127
128 // Make it so the terrain will not move or be considered for movement.
129 BulletSimAPI.ForceActivationState2(m_mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
130
131 return;
132 }
133
134 // If there is information in m_mapInfo pointing to physical structures, release same.
135 private void ReleaseHeightMapTerrain()
136 {
137 if (m_mapInfo != null)
138 {
139 if (m_mapInfo.terrainBody.ptr != IntPtr.Zero)
140 {
141 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
142 // Frees both the body and the shape.
143 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_mapInfo.terrainBody.ptr);
144 BulletSimAPI.ReleaseHeightMapInfo2(m_mapInfo.Ptr);
145 }
146 }
147 m_mapInfo = null;
148 }
149
150 // The passed position is relative to the base of the region.
151 public override float GetHeightAtXYZ(Vector3 pos)
152 {
153 float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
154
155 int mapIndex = (int)pos.Y * (int)m_mapInfo.sizeY + (int)pos.X;
156 try
157 {
158 ret = m_mapInfo.heightMap[mapIndex];
159 }
160 catch
161 {
162 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
163 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
164 LogHeader, m_mapInfo.terrainRegionBase, pos);
165 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
166 }
167 return ret;
168 }
169}
170}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 7c34af2..cd623f1 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -40,6 +40,32 @@ using OpenMetaverse;
40 40
41namespace OpenSim.Region.Physics.BulletSPlugin 41namespace OpenSim.Region.Physics.BulletSPlugin
42{ 42{
43
44// The physical implementation of the terrain is wrapped in this class.
45public abstract class BSTerrainPhys : IDisposable
46{
47 public enum TerrainImplementation
48 {
49 Heightmap = 0,
50 Mesh = 1
51 }
52
53 public BSScene PhysicsScene { get; private set; }
54 // Base of the region in world coordinates. Coordinates inside the region are relative to this.
55 public Vector3 TerrainBase { get; private set; }
56 public uint ID { get; private set; }
57
58 public BSTerrainPhys(BSScene physicsScene, Vector3 regionBase, uint id)
59 {
60 PhysicsScene = physicsScene;
61 TerrainBase = regionBase;
62 ID = id;
63 }
64 public abstract void Dispose();
65 public abstract float GetHeightAtXYZ(Vector3 pos);
66}
67
68// ==========================================================================================
43public sealed class BSTerrainManager 69public sealed class BSTerrainManager
44{ 70{
45 static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; 71 static string LogHeader = "[BULLETSIM TERRAIN MANAGER]";
@@ -54,8 +80,6 @@ public sealed class BSTerrainManager
54 // amount to make sure that a bounding box is built for the terrain. 80 // amount to make sure that a bounding box is built for the terrain.
55 public const float HEIGHT_EQUAL_FUDGE = 0.2f; 81 public const float HEIGHT_EQUAL_FUDGE = 0.2f;
56 82
57 public const float TERRAIN_COLLISION_MARGIN = 0.0f;
58
59 // Until the whole simulator is changed to pass us the region size, we rely on constants. 83 // Until the whole simulator is changed to pass us the region size, we rely on constants.
60 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); 84 public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
61 85
@@ -67,11 +91,10 @@ public sealed class BSTerrainManager
67 91
68 // If doing mega-regions, if we're region zero we will be managing multiple 92 // If doing mega-regions, if we're region zero we will be managing multiple
69 // region terrains since region zero does the physics for the whole mega-region. 93 // region terrains since region zero does the physics for the whole mega-region.
70 private Dictionary<Vector2, BulletHeightMapInfo> m_heightMaps; 94 private Dictionary<Vector3, BSTerrainPhys> m_terrains;
71 95
72 // True of the terrain has been modified. 96 // Flags used to know when to recalculate the height.
73 // Used to force recalculation of terrain height after terrain has been modified 97 private bool m_terrainModified = false;
74 private bool m_terrainModified;
75 98
76 // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount. 99 // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount.
77 // This is incremented before assigning to new region so it is the last ID allocated. 100 // This is incremented before assigning to new region so it is the last ID allocated.
@@ -89,8 +112,7 @@ public sealed class BSTerrainManager
89 public BSTerrainManager(BSScene physicsScene) 112 public BSTerrainManager(BSScene physicsScene)
90 { 113 {
91 PhysicsScene = physicsScene; 114 PhysicsScene = physicsScene;
92 m_heightMaps = new Dictionary<Vector2,BulletHeightMapInfo>(); 115 m_terrains = new Dictionary<Vector3,BSTerrainPhys>();
93 m_terrainModified = false;
94 116
95 // Assume one region of default size 117 // Assume one region of default size
96 m_worldOffset = Vector3.Zero; 118 m_worldOffset = Vector3.Zero;
@@ -99,17 +121,15 @@ public sealed class BSTerrainManager
99 } 121 }
100 122
101 // Create the initial instance of terrain and the underlying ground plane. 123 // Create the initial instance of terrain and the underlying ground plane.
102 // The objects are allocated in the unmanaged space and the pointers are tracked
103 // by the managed code.
104 // The terrains and the groundPlane are not added to the list of PhysObjects.
105 // This is called from the initialization routine so we presume it is 124 // This is called from the initialization routine so we presume it is
106 // safe to call Bullet in real time. We hope no one is moving prims around yet. 125 // safe to call Bullet in real time. We hope no one is moving prims around yet.
107 public void CreateInitialGroundPlaneAndTerrain() 126 public void CreateInitialGroundPlaneAndTerrain()
108 { 127 {
109 // The ground plane is here to catch things that are trying to drop to negative infinity 128 // The ground plane is here to catch things that are trying to drop to negative infinity
110 BulletShape groundPlaneShape = new BulletShape( 129 BulletShape groundPlaneShape = new BulletShape(
111 BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), 130 BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f,
112 ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE); 131 PhysicsScene.Params.terrainCollisionMargin),
132 BSPhysicsShapeType.SHAPE_GROUNDPLANE);
113 m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, 133 m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
114 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, 134 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID,
115 Vector3.Zero, Quaternion.Identity)); 135 Vector3.Zero, Quaternion.Identity));
@@ -121,15 +141,9 @@ public sealed class BSTerrainManager
121 BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, 141 BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr,
122 (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); 142 (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask);
123 143
124 Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE); 144 // Build an initial terrain and put it in the world. This quickly gets replaced by the real region terrain.
125 Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION); 145 BSTerrainPhys initialTerrain = new BSTerrainHeightmap(PhysicsScene, Vector3.Zero, BSScene.TERRAIN_ID, DefaultRegionSize);
126 int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; 146 m_terrains.Add(Vector3.Zero, initialTerrain);
127 float[] initialMap = new float[totalHeights];
128 for (int ii = 0; ii < totalHeights; ii++)
129 {
130 initialMap[ii] = HEIGHT_INITIALIZATION;
131 }
132 UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true);
133 } 147 }
134 148
135 // Release all the terrain structures we might have allocated 149 // Release all the terrain structures we might have allocated
@@ -150,21 +164,22 @@ public sealed class BSTerrainManager
150 // Release all the terrain we have allocated 164 // Release all the terrain we have allocated
151 public void ReleaseTerrain() 165 public void ReleaseTerrain()
152 { 166 {
153 foreach (KeyValuePair<Vector2, BulletHeightMapInfo> kvp in m_heightMaps) 167 lock (m_terrains)
154 { 168 {
155 if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr)) 169 foreach (KeyValuePair<Vector3, BSTerrainPhys> kvp in m_terrains)
156 { 170 {
157 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr); 171 kvp.Value.Dispose();
158 BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr);
159 } 172 }
173 m_terrains.Clear();
160 } 174 }
161 m_heightMaps.Clear();
162 } 175 }
163 176
164 // The simulator wants to set a new heightmap for the terrain. 177 // The simulator wants to set a new heightmap for the terrain.
165 public void SetTerrain(float[] heightMap) { 178 public void SetTerrain(float[] heightMap) {
166 float[] localHeightMap = heightMap; 179 float[] localHeightMap = heightMap;
167 PhysicsScene.TaintedObject("TerrainManager.SetTerrain", delegate() 180 // If there are multiple requests for changes to the same terrain between ticks,
181 // only do that last one.
182 PhysicsScene.PostTaintObject("TerrainManager.SetTerrain-"+ m_worldOffset.ToString(), 0, delegate()
168 { 183 {
169 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) 184 if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null)
170 { 185 {
@@ -176,8 +191,9 @@ public sealed class BSTerrainManager
176 { 191 {
177 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", 192 DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
178 BSScene.DetailLogZero, m_worldOffset, m_worldMax); 193 BSScene.DetailLogZero, m_worldOffset, m_worldMax);
179 ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, 194 ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateTerrain(
180 localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); 195 BSScene.CHILDTERRAIN_ID, localHeightMap,
196 m_worldOffset, m_worldOffset + DefaultRegionSize, true);
181 } 197 }
182 } 198 }
183 else 199 else
@@ -185,7 +201,7 @@ public sealed class BSTerrainManager
185 // If not doing the mega-prim thing, just change the terrain 201 // If not doing the mega-prim thing, just change the terrain
186 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); 202 DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
187 203
188 UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, 204 UpdateTerrain(BSScene.TERRAIN_ID, localHeightMap,
189 m_worldOffset, m_worldOffset + DefaultRegionSize, true); 205 m_worldOffset, m_worldOffset + DefaultRegionSize, true);
190 } 206 }
191 }); 207 });
@@ -195,56 +211,64 @@ public sealed class BSTerrainManager
195 // based on the passed information. The 'id' should be either the terrain id or 211 // based on the passed information. The 'id' should be either the terrain id or
196 // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used. 212 // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
197 // The latter feature is for creating child terrains for mega-regions. 213 // The latter feature is for creating child terrains for mega-regions.
198 // If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0)
199 // then a new body and shape is created and the mapInfo is filled.
200 // This call is used for doing the initial terrain creation.
201 // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new 214 // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new
202 // terrain shape is created and added to the body. 215 // terrain shape is created and added to the body.
203 // This call is most often used to update the heightMap and parameters of the terrain. 216 // This call is most often used to update the heightMap and parameters of the terrain.
204 // (The above does suggest that some simplification/refactoring is in order.) 217 // (The above does suggest that some simplification/refactoring is in order.)
205 private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) 218 // Called during taint-time.
219 private void UpdateTerrain(uint id, float[] heightMap,
220 Vector3 minCoords, Vector3 maxCoords, bool inTaintTime)
206 { 221 {
207 DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}", 222 DetailLog("{0},BSTerrainManager.UpdateTerrain,call,minC={1},maxC={2},inTaintTime={3}",
208 BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); 223 BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime);
209 224
225 // Find high and low points of passed heightmap.
226 // The min and max passed in is usually the area objects can be in (maximum
227 // object height, for instance). The terrain wants the bounding box for the
228 // terrain so replace passed min and max Z with the actual terrain min/max Z.
210 float minZ = float.MaxValue; 229 float minZ = float.MaxValue;
211 float maxZ = float.MinValue; 230 float maxZ = float.MinValue;
212 Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y); 231 foreach (float height in heightMap)
213
214 int heightMapSize = heightMap.Length;
215 for (int ii = 0; ii < heightMapSize; ii++)
216 { 232 {
217 float height = heightMap[ii];
218 if (height < minZ) minZ = height; 233 if (height < minZ) minZ = height;
219 if (height > maxZ) maxZ = height; 234 if (height > maxZ) maxZ = height;
220 } 235 }
221 236 if (minZ == maxZ)
222 // The shape of the terrain is from its base to its extents. 237 {
238 // If min and max are the same, reduce min a little bit so a good bounding box is created.
239 minZ -= BSTerrainManager.HEIGHT_EQUAL_FUDGE;
240 }
223 minCoords.Z = minZ; 241 minCoords.Z = minZ;
224 maxCoords.Z = maxZ; 242 maxCoords.Z = maxZ;
225 243
226 BulletHeightMapInfo mapInfo; 244 Vector3 terrainRegionBase = new Vector3(minCoords.X, minCoords.Y, 0f);
227 if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo)) 245
246 lock (m_terrains)
228 { 247 {
229 // If this is terrain we know about, it's easy to update 248 BSTerrainPhys terrainPhys;
230 249 if (m_terrains.TryGetValue(terrainRegionBase, out terrainPhys))
231 mapInfo.heightMap = heightMap;
232 mapInfo.minCoords = minCoords;
233 mapInfo.maxCoords = maxCoords;
234 mapInfo.minZ = minZ;
235 mapInfo.maxZ = maxZ;
236 mapInfo.sizeX = maxCoords.X - minCoords.X;
237 mapInfo.sizeY = maxCoords.Y - minCoords.Y;
238 DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
239 BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
240
241 PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:UpdateExisting", delegate()
242 { 250 {
243 if (MegaRegionParentPhysicsScene != null) 251 // There is already a terrain in this spot. Free the old and build the new.
252 DetailLog("{0},UpdateTerrain:UpdateExisting,call,id={1},base={2},minC={3},maxC={4}",
253 BSScene.DetailLogZero, id, terrainRegionBase, minCoords, minCoords);
254
255 // Remove old terrain from the collection
256 m_terrains.Remove(terrainRegionBase);
257 // Release any physical memory it may be using.
258 terrainPhys.Dispose();
259
260 if (MegaRegionParentPhysicsScene == null)
261 {
262 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
263 m_terrains.Add(terrainRegionBase, newTerrainPhys);
264
265 m_terrainModified = true;
266 }
267 else
244 { 268 {
245 // It's possible that Combine() was called after this code was queued. 269 // It's possible that Combine() was called after this code was queued.
246 // If we are a child of combined regions, we don't create any terrain for us. 270 // If we are a child of combined regions, we don't create any terrain for us.
247 DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero); 271 DetailLog("{0},BSTerrainManager.UpdateTerrain:AmACombineChild,taint", BSScene.DetailLogZero);
248 272
249 // Get rid of any terrain that may have been allocated for us. 273 // Get rid of any terrain that may have been allocated for us.
250 ReleaseGroundPlaneAndTerrain(); 274 ReleaseGroundPlaneAndTerrain();
@@ -252,135 +276,56 @@ public sealed class BSTerrainManager
252 // I hate doing this, but just bail 276 // I hate doing this, but just bail
253 return; 277 return;
254 } 278 }
279 }
280 else
281 {
282 // We don't know about this terrain so either we are creating a new terrain or
283 // our mega-prim child is giving us a new terrain to add to the phys world
255 284
256 if (mapInfo.terrainBody.ptr != IntPtr.Zero) 285 // if this is a child terrain, calculate a unique terrain id
257 { 286 uint newTerrainID = id;
258 // Updating an existing terrain. 287 if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
259 DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", 288 newTerrainID = ++m_terrainCount;
260 BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
261
262 // Remove from the dynamics world because we're going to mangle this object
263 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
264
265 // Get rid of the old terrain
266 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
267 BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr);
268 mapInfo.Ptr = IntPtr.Zero;
269
270 /*
271 // NOTE: This routine is half here because I can't get the terrain shape replacement
272 // to work. In the short term, the above three lines completely delete the old
273 // terrain and the code below recreates one from scratch.
274 // Hopefully the Bullet community will help me out on this one.
275
276 // First, release the old collision shape (there is only one terrain)
277 BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr);
278
279 // Fill the existing height map info with the new location and size information
280 BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID,
281 mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
282
283 // Create a terrain shape based on the new info
284 mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
285
286 // Stuff the shape into the existing terrain body
287 BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr);
288 */
289 }
290 // else
291 {
292 // Creating a new terrain.
293 DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}",
294 BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ);
295
296 mapInfo.ID = id;
297 mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID,
298 mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
299
300 // Create the terrain shape from the mapInfo
301 mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr),
302 ShapeData.PhysicsShapeType.SHAPE_TERRAIN);
303
304 // The terrain object initial position is at the center of the object
305 Vector3 centerPos;
306 centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
307 centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
308 centerPos.Z = minZ + ((maxZ - minZ) / 2f);
309
310 mapInfo.terrainBody = new BulletBody(mapInfo.ID,
311 BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr,
312 id, centerPos, Quaternion.Identity));
313 }
314
315 // Make sure the entry is in the heightmap table
316 m_heightMaps[terrainRegionBase] = mapInfo;
317
318 // Set current terrain attributes
319 BulletSimAPI.SetFriction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction);
320 BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction);
321 BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution);
322 BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
323
324 // Return the new terrain to the world of physical objects
325 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
326
327 // redo its bounding box now that it is in the world
328 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr);
329
330 BulletSimAPI.SetCollisionFilterMask2(mapInfo.terrainBody.ptr,
331 (uint)CollisionFilterGroups.TerrainFilter,
332 (uint)CollisionFilterGroups.TerrainMask);
333
334 // Make sure the new shape is processed.
335 // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true);
336 // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING);
337 BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
338
339 m_terrainModified = true;
340 });
341 }
342 else
343 {
344 // We don't know about this terrain so either we are creating a new terrain or
345 // our mega-prim child is giving us a new terrain to add to the phys world
346
347 // if this is a child terrain, calculate a unique terrain id
348 uint newTerrainID = id;
349 if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
350 newTerrainID = ++m_terrainCount;
351
352 float[] heightMapX = heightMap;
353 Vector3 minCoordsX = minCoords;
354 Vector3 maxCoordsX = maxCoords;
355
356 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}",
357 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
358 289
359 // Code that must happen at taint-time 290 DetailLog("{0},UpdateTerrain:NewTerrain,taint,newID={1},minCoord={2},maxCoord={3}",
360 PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:NewTerrain", delegate() 291 BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
361 { 292 BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
362 DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); 293 m_terrains.Add(terrainRegionBase, newTerrainPhys);
363 // Create a new mapInfo that will be filled with the new info
364 mapInfo = new BulletHeightMapInfo(id, heightMapX,
365 BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, newTerrainID,
366 minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN));
367 // Put the unfilled heightmap info into the collection of same
368 m_heightMaps.Add(terrainRegionBase, mapInfo);
369 // Build the terrain
370 UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true);
371 294
372 m_terrainModified = true; 295 m_terrainModified = true;
373 }); 296 }
374 } 297 }
375 } 298 }
376 299
377 // Someday we will have complex terrain with caves and tunnels 300 // TODO: redo terrain implementation selection to allow other base types than heightMap.
378 public float GetTerrainHeightAtXYZ(Vector3 loc) 301 private BSTerrainPhys BuildPhysicalTerrain(Vector3 terrainRegionBase, uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords)
379 { 302 {
380 // For the moment, it's flat and convex 303 PhysicsScene.Logger.DebugFormat("{0} Terrain for {1}/{2} created with {3}",
381 return GetTerrainHeightAtXY(loc.X, loc.Y); 304 LogHeader, PhysicsScene.RegionName, terrainRegionBase,
305 (BSTerrainPhys.TerrainImplementation)PhysicsScene.Params.terrainImplementation);
306 BSTerrainPhys newTerrainPhys = null;
307 switch ((int)PhysicsScene.Params.terrainImplementation)
308 {
309 case (int)BSTerrainPhys.TerrainImplementation.Heightmap:
310 newTerrainPhys = new BSTerrainHeightmap(PhysicsScene, terrainRegionBase, id,
311 heightMap, minCoords, maxCoords);
312 break;
313 case (int)BSTerrainPhys.TerrainImplementation.Mesh:
314 newTerrainPhys = new BSTerrainMesh(PhysicsScene, terrainRegionBase, id,
315 heightMap, minCoords, maxCoords);
316 break;
317 default:
318 PhysicsScene.Logger.ErrorFormat("{0} Bad terrain implementation specified. Type={1}/{2},Region={3}/{4}",
319 LogHeader,
320 (int)PhysicsScene.Params.terrainImplementation,
321 PhysicsScene.Params.terrainImplementation,
322 PhysicsScene.RegionName, terrainRegionBase);
323 break;
324 }
325 return newTerrainPhys;
382 } 326 }
383 327
328
384 // Given an X and Y, find the height of the terrain. 329 // Given an X and Y, find the height of the terrain.
385 // Since we could be handling multiple terrains for a mega-region, 330 // Since we could be handling multiple terrains for a mega-region,
386 // the base of the region is calcuated assuming all regions are 331 // the base of the region is calcuated assuming all regions are
@@ -390,12 +335,15 @@ public sealed class BSTerrainManager
390 private float lastHeightTX = 999999f; 335 private float lastHeightTX = 999999f;
391 private float lastHeightTY = 999999f; 336 private float lastHeightTY = 999999f;
392 private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; 337 private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
393 private float GetTerrainHeightAtXY(float tX, float tY) 338 public float GetTerrainHeightAtXYZ(Vector3 loc)
394 { 339 {
340 float tX = loc.X;
341 float tY = loc.Y;
395 // You'd be surprized at the number of times this routine is called 342 // You'd be surprized at the number of times this routine is called
396 // with the same parameters as last time. 343 // with the same parameters as last time.
397 if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY) 344 if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY)
398 return lastHeight; 345 return lastHeight;
346 m_terrainModified = false;
399 347
400 lastHeightTX = tX; 348 lastHeightTX = tX;
401 lastHeightTY = tY; 349 lastHeightTY = tY;
@@ -403,34 +351,21 @@ public sealed class BSTerrainManager
403 351
404 int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; 352 int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
405 int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; 353 int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
406 Vector2 terrainBaseXY = new Vector2(offsetX, offsetY); 354 Vector3 terrainBaseXYZ = new Vector3(offsetX, offsetY, 0f);
407 355
408 BulletHeightMapInfo mapInfo; 356 lock (m_terrains)
409 if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo))
410 { 357 {
411 float regionX = tX - offsetX; 358 BSTerrainPhys physTerrain;
412 float regionY = tY - offsetY; 359 if (m_terrains.TryGetValue(terrainBaseXYZ, out physTerrain))
413 int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX;
414 try
415 { 360 {
416 ret = mapInfo.heightMap[mapIndex]; 361 ret = physTerrain.GetHeightAtXYZ(loc - terrainBaseXYZ);
417 } 362 }
418 catch 363 else
419 { 364 {
420 // Sometimes they give us wonky values of X and Y. Give a warning and return something. 365 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
421 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}", 366 LogHeader, PhysicsScene.RegionName, tX, tY);
422 LogHeader, terrainBaseXY, regionX, regionY);
423 ret = HEIGHT_GETHEIGHT_RET;
424 } 367 }
425 // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}",
426 // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret);
427 }
428 else
429 {
430 PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
431 LogHeader, PhysicsScene.RegionName, tX, tY);
432 } 368 }
433 m_terrainModified = false;
434 lastHeight = ret; 369 lastHeight = ret;
435 return ret; 370 return ret;
436 } 371 }
@@ -466,7 +401,7 @@ public sealed class BSTerrainManager
466 // Unhook all the combining that I know about. 401 // Unhook all the combining that I know about.
467 public void UnCombine(PhysicsScene pScene) 402 public void UnCombine(PhysicsScene pScene)
468 { 403 {
469 // Just like ODE, for the moment a NOP 404 // Just like ODE, we don't do anything yet.
470 DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero); 405 DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero);
471 } 406 }
472 407
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
new file mode 100755
index 0000000..5f6675d
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainMesh.cs
@@ -0,0 +1,262 @@
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 OpenSim.Framework;
32using OpenSim.Region.Framework;
33using OpenSim.Region.CoreModules;
34using OpenSim.Region.Physics.Manager;
35
36using Nini.Config;
37using log4net;
38
39using OpenMetaverse;
40
41namespace OpenSim.Region.Physics.BulletSPlugin
42{
43public sealed class BSTerrainMesh : BSTerrainPhys
44{
45 static string LogHeader = "[BULLETSIM TERRAIN MESH]";
46
47 private float[] m_savedHeightMap;
48 int m_sizeX;
49 int m_sizeY;
50
51 BulletShape m_terrainShape;
52 BulletBody m_terrainBody;
53
54 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, Vector3 regionSize)
55 : base(physicsScene, regionBase, id)
56 {
57 }
58
59 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id /* parameters for making mesh */)
60 : base(physicsScene, regionBase, id)
61 {
62 }
63
64 // Create terrain mesh from a heightmap.
65 public BSTerrainMesh(BSScene physicsScene, Vector3 regionBase, uint id, float[] initialMap,
66 Vector3 minCoords, Vector3 maxCoords)
67 : base(physicsScene, regionBase, id)
68 {
69 int indicesCount;
70 int[] indices;
71 int verticesCount;
72 float[] vertices;
73
74 m_savedHeightMap = initialMap;
75
76 m_sizeX = (int)(maxCoords.X - minCoords.X);
77 m_sizeY = (int)(maxCoords.Y - minCoords.Y);
78
79 if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap,
80 m_sizeX, m_sizeY,
81 (float)m_sizeX, (float)m_sizeY,
82 Vector3.Zero, 1.0f,
83 out indicesCount, out indices, out verticesCount, out vertices))
84 {
85 // DISASTER!!
86 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID);
87 PhysicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh! base={1}", LogHeader, TerrainBase);
88 // Something is very messed up and a crash is in our future.
89 return;
90 }
91 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,indices={1},indSz={2},vertices={3},vertSz={4}",
92 ID, indicesCount, indices.Length, verticesCount, vertices.Length);
93
94 m_terrainShape = new BulletShape(BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
95 indicesCount, indices, verticesCount, vertices),
96 BSPhysicsShapeType.SHAPE_MESH);
97 if (m_terrainShape.ptr == IntPtr.Zero)
98 {
99 // DISASTER!!
100 PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedCreationOfShape", ID);
101 physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain mesh! base={1}", LogHeader, TerrainBase);
102 // Something is very messed up and a crash is in our future.
103 return;
104 }
105
106 Vector3 pos = regionBase;
107 Quaternion rot = Quaternion.Identity;
108
109 m_terrainBody = new BulletBody(id, BulletSimAPI.CreateBodyWithDefaultMotionState2( m_terrainShape.ptr, ID, pos, rot));
110 if (m_terrainBody.ptr == IntPtr.Zero)
111 {
112 // DISASTER!!
113 physicsScene.Logger.ErrorFormat("{0} Failed creation of terrain body! base={1}", LogHeader, TerrainBase);
114 // Something is very messed up and a crash is in our future.
115 return;
116 }
117
118 // Set current terrain attributes
119 BulletSimAPI.SetFriction2(m_terrainBody.ptr, PhysicsScene.Params.terrainFriction);
120 BulletSimAPI.SetHitFraction2(m_terrainBody.ptr, PhysicsScene.Params.terrainHitFraction);
121 BulletSimAPI.SetRestitution2(m_terrainBody.ptr, PhysicsScene.Params.terrainRestitution);
122 BulletSimAPI.SetCollisionFlags2(m_terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT);
123
124 // Static objects are not very massive.
125 BulletSimAPI.SetMassProps2(m_terrainBody.ptr, 0f, Vector3.Zero);
126
127 // Put the new terrain to the world of physical objects
128 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr);
129
130 // Redo its bounding box now that it is in the world
131 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_terrainBody.ptr);
132
133 BulletSimAPI.SetCollisionFilterMask2(m_terrainBody.ptr,
134 (uint)CollisionFilterGroups.TerrainFilter,
135 (uint)CollisionFilterGroups.TerrainMask);
136
137 // Make it so the terrain will not move or be considered for movement.
138 BulletSimAPI.ForceActivationState2(m_terrainBody.ptr, ActivationState.DISABLE_SIMULATION);
139 }
140
141 public override void Dispose()
142 {
143 if (m_terrainBody.ptr != IntPtr.Zero)
144 {
145 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_terrainBody.ptr);
146 // Frees both the body and the shape.
147 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_terrainBody.ptr);
148 }
149 }
150
151 public override float GetHeightAtXYZ(Vector3 pos)
152 {
153 // For the moment use the saved heightmap to get the terrain height.
154 // TODO: raycast downward to find the true terrain below the position.
155 float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
156
157 int mapIndex = (int)pos.Y * m_sizeY + (int)pos.X;
158 try
159 {
160 ret = m_savedHeightMap[mapIndex];
161 }
162 catch
163 {
164 // Sometimes they give us wonky values of X and Y. Give a warning and return something.
165 PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, pos={2}",
166 LogHeader, TerrainBase, pos);
167 ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET;
168 }
169 return ret;
170 }
171
172 // Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
173 // Return 'true' if successfully created.
174 public static bool ConvertHeightmapToMesh(
175 BSScene physicsScene,
176 float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap
177 float extentX, float extentY, // zero based range for output vertices
178 Vector3 extentBase, // base to be added to all vertices
179 float magnification, // number of vertices to create between heightMap coords
180 out int indicesCountO, out int[] indicesO,
181 out int verticesCountO, out float[] verticesO)
182 {
183 bool ret = false;
184
185 int indicesCount = 0;
186 int verticesCount = 0;
187 int[] indices = new int[0];
188 float[] vertices = new float[0];
189
190 // Simple mesh creation which assumes magnification == 1.
191 // TODO: do a more general solution that scales, adds new vertices and smoothes the result.
192
193 // Create an array of vertices that is sizeX+1 by sizeY+1 (note the loop
194 // from zero to <= sizeX). The triangle indices are then generated as two triangles
195 // per heightmap point. There are sizeX by sizeY of these squares. The extra row and
196 // column of vertices are used to complete the triangles of the last row and column
197 // of the heightmap.
198 try
199 {
200 // One vertice per heightmap value plus the vertices off the top and bottom edge.
201 int totalVertices = (sizeX + 1) * (sizeY + 1);
202 vertices = new float[totalVertices * 3];
203 int totalIndices = sizeX * sizeY * 6;
204 indices = new int[totalIndices];
205
206 float magX = (float)sizeX / extentX;
207 float magY = (float)sizeY / extentY;
208 physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}",
209 BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY);
210 float minHeight = float.MaxValue;
211 // Note that sizeX+1 vertices are created since there is land between this and the next region.
212 for (int yy = 0; yy <= sizeY; yy++)
213 {
214 for (int xx = 0; xx <= sizeX; xx++) // Hint: the "<=" means we go around sizeX + 1 times
215 {
216 int offset = yy * sizeX + xx;
217 // Extend the height with the height from the last row or column
218 if (yy == sizeY) offset -= sizeX;
219 if (xx == sizeX) offset -= 1;
220 float height = heightMap[offset];
221 minHeight = Math.Min(minHeight, height);
222 vertices[verticesCount + 0] = (float)xx * magX + extentBase.X;
223 vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y;
224 vertices[verticesCount + 2] = height + extentBase.Z;
225 verticesCount += 3;
226 }
227 }
228 verticesCount = verticesCount / 3;
229
230 for (int yy = 0; yy < sizeY; yy++)
231 {
232 for (int xx = 0; xx < sizeX; xx++)
233 {
234 int offset = yy * (sizeX + 1) + xx;
235 // Each vertices is presumed to be the upper left corner of a box of two triangles
236 indices[indicesCount + 0] = offset;
237 indices[indicesCount + 1] = offset + 1;
238 indices[indicesCount + 2] = offset + sizeX + 1; // accounting for the extra column
239 indices[indicesCount + 3] = offset + 1;
240 indices[indicesCount + 4] = offset + sizeX + 2;
241 indices[indicesCount + 5] = offset + sizeX + 1;
242 indicesCount += 6;
243 }
244 }
245
246 ret = true;
247 }
248 catch (Exception e)
249 {
250 physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}",
251 LogHeader, physicsScene.RegionName, extentBase, e);
252 }
253
254 indicesCountO = indicesCount;
255 indicesO = indices;
256 verticesCountO = verticesCount;
257 verticesO = vertices;
258
259 return ret;
260 }
261}
262}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 07149d8..1e003e6 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -88,11 +88,11 @@ public struct BulletShape
88 public BulletShape(IntPtr xx) 88 public BulletShape(IntPtr xx)
89 { 89 {
90 ptr = xx; 90 ptr = xx;
91 type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; 91 type=BSPhysicsShapeType.SHAPE_UNKNOWN;
92 shapeKey = 0; 92 shapeKey = (System.UInt64)FixedShapeKey.KEY_NONE;
93 isNativeShape = false; 93 isNativeShape = false;
94 } 94 }
95 public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) 95 public BulletShape(IntPtr xx, BSPhysicsShapeType typ)
96 { 96 {
97 ptr = xx; 97 ptr = xx;
98 type = typ; 98 type = typ;
@@ -100,7 +100,7 @@ public struct BulletShape
100 isNativeShape = false; 100 isNativeShape = false;
101 } 101 }
102 public IntPtr ptr; 102 public IntPtr ptr;
103 public ShapeData.PhysicsShapeType type; 103 public BSPhysicsShapeType type;
104 public System.UInt64 shapeKey; 104 public System.UInt64 shapeKey;
105 public bool isNativeShape; 105 public bool isNativeShape;
106 public override string ToString() 106 public override string ToString()
@@ -152,7 +152,7 @@ public class BulletHeightMapInfo
152 ID = id; 152 ID = id;
153 Ptr = xx; 153 Ptr = xx;
154 heightMap = hm; 154 heightMap = hm;
155 terrainRegionBase = new Vector2(0f, 0f); 155 terrainRegionBase = Vector3.Zero;
156 minCoords = new Vector3(100f, 100f, 25f); 156 minCoords = new Vector3(100f, 100f, 25f);
157 maxCoords = new Vector3(101f, 101f, 26f); 157 maxCoords = new Vector3(101f, 101f, 26f);
158 minZ = maxZ = 0f; 158 minZ = maxZ = 0f;
@@ -161,7 +161,7 @@ public class BulletHeightMapInfo
161 public uint ID; 161 public uint ID;
162 public IntPtr Ptr; 162 public IntPtr Ptr;
163 public float[] heightMap; 163 public float[] heightMap;
164 public Vector2 terrainRegionBase; 164 public Vector3 terrainRegionBase;
165 public Vector3 minCoords; 165 public Vector3 minCoords;
166 public Vector3 maxCoords; 166 public Vector3 maxCoords;
167 public float sizeX, sizeY; 167 public float sizeX, sizeY;
@@ -178,26 +178,39 @@ public struct ConvexHull
178 int VertexCount; 178 int VertexCount;
179 Vector3[] Vertices; 179 Vector3[] Vertices;
180} 180}
181public enum BSPhysicsShapeType
182{
183 SHAPE_UNKNOWN = 0,
184 SHAPE_CAPSULE = 1,
185 SHAPE_BOX = 2,
186 SHAPE_CONE = 3,
187 SHAPE_CYLINDER = 4,
188 SHAPE_SPHERE = 5,
189 SHAPE_MESH = 6,
190 SHAPE_HULL = 7,
191 // following defined by BulletSim
192 SHAPE_GROUNDPLANE = 20,
193 SHAPE_TERRAIN = 21,
194 SHAPE_COMPOUND = 22,
195 SHAPE_HEIGHTMAP = 23,
196};
197
198// The native shapes have predefined shape hash keys
199public enum FixedShapeKey : ulong
200{
201 KEY_NONE = 0,
202 KEY_BOX = 1,
203 KEY_SPHERE = 2,
204 KEY_CONE = 3,
205 KEY_CYLINDER = 4,
206 KEY_CAPSULE = 5,
207}
208
181[StructLayout(LayoutKind.Sequential)] 209[StructLayout(LayoutKind.Sequential)]
182public struct ShapeData 210public struct ShapeData
183{ 211{
184 public enum PhysicsShapeType
185 {
186 SHAPE_UNKNOWN = 0,
187 SHAPE_AVATAR = 1,
188 SHAPE_BOX = 2,
189 SHAPE_CONE = 3,
190 SHAPE_CYLINDER = 4,
191 SHAPE_SPHERE = 5,
192 SHAPE_MESH = 6,
193 SHAPE_HULL = 7,
194 // following defined by BulletSim
195 SHAPE_GROUNDPLANE = 20,
196 SHAPE_TERRAIN = 21,
197 SHAPE_COMPOUND = 22,
198 };
199 public uint ID; 212 public uint ID;
200 public PhysicsShapeType Type; 213 public BSPhysicsShapeType Type;
201 public Vector3 Position; 214 public Vector3 Position;
202 public Quaternion Rotation; 215 public Quaternion Rotation;
203 public Vector3 Velocity; 216 public Vector3 Velocity;
@@ -216,16 +229,6 @@ public struct ShapeData
216 // note that bools are passed as floats since bool size changes by language and architecture 229 // note that bools are passed as floats since bool size changes by language and architecture
217 public const float numericTrue = 1f; 230 public const float numericTrue = 1f;
218 public const float numericFalse = 0f; 231 public const float numericFalse = 0f;
219
220 // The native shapes have predefined shape hash keys
221 public enum FixedShapeKey : ulong
222 {
223 KEY_BOX = 1,
224 KEY_SPHERE = 2,
225 KEY_CONE = 3,
226 KEY_CYLINDER = 4,
227 KEY_CAPSULE = 5,
228 }
229} 232}
230[StructLayout(LayoutKind.Sequential)] 233[StructLayout(LayoutKind.Sequential)]
231public struct SweepHit 234public struct SweepHit
@@ -280,17 +283,23 @@ public struct ConfigurationParameters
280 public float ccdSweptSphereRadius; 283 public float ccdSweptSphereRadius;
281 public float contactProcessingThreshold; 284 public float contactProcessingThreshold;
282 285
286 public float terrainImplementation;
283 public float terrainFriction; 287 public float terrainFriction;
284 public float terrainHitFraction; 288 public float terrainHitFraction;
285 public float terrainRestitution; 289 public float terrainRestitution;
290 public float terrainCollisionMargin;
291
286 public float avatarFriction; 292 public float avatarFriction;
287 public float avatarStandingFriction; 293 public float avatarStandingFriction;
288 public float avatarDensity; 294 public float avatarDensity;
289 public float avatarRestitution; 295 public float avatarRestitution;
290 public float avatarCapsuleRadius; 296 public float avatarCapsuleWidth;
297 public float avatarCapsuleDepth;
291 public float avatarCapsuleHeight; 298 public float avatarCapsuleHeight;
292 public float avatarContactProcessingThreshold; 299 public float avatarContactProcessingThreshold;
293 300
301 public float vehicleAngularDamping;
302
294 public float maxPersistantManifoldPoolSize; 303 public float maxPersistantManifoldPoolSize;
295 public float maxCollisionAlgorithmPoolSize; 304 public float maxCollisionAlgorithmPoolSize;
296 public float shouldDisableContactPoolDynamicAllocation; 305 public float shouldDisableContactPoolDynamicAllocation;
@@ -348,7 +357,7 @@ public enum CollisionFlags : uint
348 CF_CHARACTER_OBJECT = 1 << 4, 357 CF_CHARACTER_OBJECT = 1 << 4,
349 CF_DISABLE_VISUALIZE_OBJECT = 1 << 5, 358 CF_DISABLE_VISUALIZE_OBJECT = 1 << 5,
350 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, 359 CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
351 // Following used by BulletSim to control collisions 360 // Following used by BulletSim to control collisions and updates
352 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, 361 BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
353 BS_FLOATS_ON_WATER = 1 << 11, 362 BS_FLOATS_ON_WATER = 1 << 11,
354 BS_NONE = 0, 363 BS_NONE = 0,
@@ -388,13 +397,13 @@ public enum CollisionFilterGroups : uint
388 ObjectFilter = BSolidFilter, 397 ObjectFilter = BSolidFilter,
389 ObjectMask = BAllFilter, 398 ObjectMask = BAllFilter,
390 StaticObjectFilter = BStaticFilter, 399 StaticObjectFilter = BStaticFilter,
391 StaticObjectMask = BAllFilter, 400 StaticObjectMask = BAllFilter & ~BStaticFilter, // static objects don't collide with each other
392 LinksetFilter = BLinksetFilter, 401 LinksetFilter = BLinksetFilter,
393 LinksetMask = BAllFilter & ~BLinksetFilter, 402 LinksetMask = BAllFilter & ~BLinksetFilter, // linkset objects don't collide with each other
394 VolumeDetectFilter = BSensorTrigger, 403 VolumeDetectFilter = BSensorTrigger,
395 VolumeDetectMask = ~BSensorTrigger, 404 VolumeDetectMask = ~BSensorTrigger,
396 TerrainFilter = BTerrainFilter, 405 TerrainFilter = BTerrainFilter,
397 TerrainMask = BAllFilter & ~BStaticFilter, 406 TerrainMask = BAllFilter & ~BStaticFilter, // static objects on the ground don't collide
398 GroundPlaneFilter = BGroundPlaneFilter, 407 GroundPlaneFilter = BGroundPlaneFilter,
399 GroundPlaneMask = BAllFilter 408 GroundPlaneMask = BAllFilter
400 409
@@ -429,140 +438,6 @@ static class BulletSimAPI {
429[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 438[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
430public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); 439public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
431 440
432[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
433[return: MarshalAs(UnmanagedType.LPStr)]
434public static extern string GetVersion();
435
436/* Remove the linkage to the old api methods
437[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
438public static extern uint Initialize(Vector3 maxPosition, IntPtr parms,
439 int maxCollisions, IntPtr collisionArray,
440 int maxUpdates, IntPtr updateArray,
441 DebugLogCallback logRoutine);
442
443[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
444public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID);
445
446[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
447public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
448
449[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
450public static extern void Shutdown(uint worldID);
451
452[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
453public static extern bool UpdateParameter(uint worldID, uint localID,
454 [MarshalAs(UnmanagedType.LPStr)]string paramCode, float value);
455
456// ===============================================================================
457[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
458public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep,
459 out int updatedEntityCount,
460 out IntPtr updatedEntitiesPtr,
461 out int collidersCount,
462 out IntPtr collidersPtr);
463
464[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
465public static extern bool CreateHull(uint worldID, System.UInt64 meshKey,
466 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls
467 );
468
469[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
470public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey,
471 int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
472 int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices
473 );
474
475[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
476public static extern bool DestroyHull(uint worldID, System.UInt64 meshKey);
477
478[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
479public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey);
480
481[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
482public static extern bool CreateObject(uint worldID, ShapeData shapeData);
483
484[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
485public static extern Vector3 GetObjectPosition(uint WorldID, uint id);
486
487[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
488public static extern Quaternion GetObjectOrientation(uint WorldID, uint id);
489
490[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
491public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation);
492
493[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
494public static extern bool SetObjectVelocity(uint worldID, uint id, Vector3 velocity);
495
496[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
497public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity);
498
499// Set the current force acting on the object
500[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
501public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force);
502
503[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
504public static extern bool SetObjectScaleMass(uint worldID, uint id, Vector3 scale, float mass, bool isDynamic);
505
506[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
507public static extern bool SetObjectCollidable(uint worldID, uint id, bool phantom);
508
509[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
510public static extern bool SetObjectDynamic(uint worldID, uint id, bool isDynamic, float mass);
511
512[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
513public static extern bool SetObjectGhost(uint worldID, uint id, bool ghostly);
514
515[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
516public static extern bool SetObjectProperties(uint worldID, uint id, bool isStatic, bool isSolid, bool genCollisions, float mass);
517
518[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
519public static extern bool SetObjectBuoyancy(uint worldID, uint id, float buoyancy);
520
521[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
522public static extern bool HasObject(uint worldID, uint id);
523
524[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
525public static extern bool DestroyObject(uint worldID, uint id);
526
527// ===============================================================================
528[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
529public static extern SweepHit ConvexSweepTest(uint worldID, uint id, Vector3 to, float extraMargin);
530
531[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
532public static extern RaycastHit RayTest(uint worldID, uint id, Vector3 from, Vector3 to);
533
534[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
535public static extern Vector3 RecoverFromPenetration(uint worldID, uint id);
536
537// ===============================================================================
538[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
539public static extern void DumpBulletStatistics();
540*/
541// Log a debug message
542[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
543public static extern void SetDebugLogCallback(DebugLogCallback callback);
544
545// ===============================================================================
546// ===============================================================================
547// ===============================================================================
548// A new version of the API that enables moving all the logic out of the C++ code and into
549// the C# code. This will make modifications easier for the next person.
550// This interface passes the actual pointers to the objects in the unmanaged
551// address space. All the management (calls for creation/destruction/lookup)
552// is done in the C# code.
553// The names have a "2" tacked on. This will be removed as the C# code gets rebuilt
554// and the old code is removed.
555
556// Functions use while converting from API1 to API2. Can be removed when totally converted.
557[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
558public static extern IntPtr GetSimHandle2(uint worldID);
559
560[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
561public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
562
563[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
564public static extern IntPtr GetBodyHandle2(IntPtr world, uint id);
565
566// =============================================================================== 441// ===============================================================================
567// Initialization and simulation 442// Initialization and simulation
568[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 443[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@@ -611,6 +486,9 @@ public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData)
611public static extern bool IsNativeShape2(IntPtr shape); 486public static extern bool IsNativeShape2(IntPtr shape);
612 487
613[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 488[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
489public static extern void SetShapeCollisionMargin(IntPtr shape, float margin);
490
491[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
614public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale); 492public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale);
615 493
616[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 494[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
diff --git a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs
index cbc6b95..16404c6 100644
--- a/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs
+++ b/OpenSim/Region/Physics/OdePlugin/Tests/ODETestClass.cs
@@ -32,13 +32,14 @@ using OpenMetaverse;
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager; 33using OpenSim.Region.Physics.Manager;
34using OpenSim.Region.Physics.OdePlugin; 34using OpenSim.Region.Physics.OdePlugin;
35using OpenSim.Tests.Common;
35using log4net; 36using log4net;
36using System.Reflection; 37using System.Reflection;
37 38
38namespace OpenSim.Region.Physics.OdePlugin.Tests 39namespace OpenSim.Region.Physics.OdePlugin.Tests
39{ 40{
40 [TestFixture] 41 [TestFixture]
41 public class ODETestClass 42 public class ODETestClass : OpenSimTestCase
42 { 43 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 44 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44 45
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
index 7763619..77e087c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
@@ -39,7 +39,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools.Tests
39 /// The generated C# code is compared against the expected C# code. 39 /// The generated C# code is compared against the expected C# code.
40 /// </summary> 40 /// </summary>
41 [TestFixture] 41 [TestFixture]
42 public class CSCodeGeneratorTest 42 public class CSCodeGeneratorTest : OpenSimTestCase
43 { 43 {
44 [Test] 44 [Test]
45 public void TestDefaultState() 45 public void TestDefaultState()
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
index 1fa6954..05a8756 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools.Tests
41 /// the LSL source. 41 /// the LSL source.
42 /// </summary> 42 /// </summary>
43 [TestFixture] 43 [TestFixture]
44 public class CompilerTest 44 public class CompilerTest : OpenSimTestCase
45 { 45 {
46 private string m_testDir; 46 private string m_testDir;
47 private CSharpCodeProvider m_CSCodeProvider; 47 private CSharpCodeProvider m_CSCodeProvider;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
index c73e22f..2c9d9e8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
51 /// Tests for inventory functions in LSL 51 /// Tests for inventory functions in LSL
52 /// </summary> 52 /// </summary>
53 [TestFixture] 53 [TestFixture]
54 public class LSL_ApiInventoryTests 54 public class LSL_ApiInventoryTests : OpenSimTestCase
55 { 55 {
56 protected Scene m_scene; 56 protected Scene m_scene;
57 protected XEngine.XEngine m_engine; 57 protected XEngine.XEngine m_engine;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
index 2565ae7..57f19b9 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
@@ -56,7 +56,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
56 /// OpenSim.Region.Framework.Scenes.Tests.SceneObjectLinkingTests. 56 /// OpenSim.Region.Framework.Scenes.Tests.SceneObjectLinkingTests.
57 /// </remarks> 57 /// </remarks>
58 [TestFixture] 58 [TestFixture]
59 public class LSL_ApiLinkingTests 59 public class LSL_ApiLinkingTests : OpenSimTestCase
60 { 60 {
61 protected Scene m_scene; 61 protected Scene m_scene;
62 protected XEngine.XEngine m_engine; 62 protected XEngine.XEngine m_engine;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
index dd23be8..182b07b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
@@ -46,7 +46,7 @@ using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
46namespace OpenSim.Region.ScriptEngine.Shared.Tests 46namespace OpenSim.Region.ScriptEngine.Shared.Tests
47{ 47{
48 [TestFixture] 48 [TestFixture]
49 public class LSL_ApiListTests 49 public class LSL_ApiListTests : OpenSimTestCase
50 { 50 {
51 private LSL_Api m_lslApi; 51 private LSL_Api m_lslApi;
52 52
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
index 3ed2562..c8c7f82 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLFloat 36 public class LSL_TypesTestLSLFloat : OpenSimTestCase
37 { 37 {
38 // Used for testing equality of two floats. 38 // Used for testing equality of two floats.
39 private double _lowPrecisionTolerance = 0.000001; 39 private double _lowPrecisionTolerance = 0.000001;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
index 8d1169a..c664108 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLInteger 36 public class LSL_TypesTestLSLInteger : OpenSimTestCase
37 { 37 {
38 private Dictionary<double, int> m_doubleIntSet; 38 private Dictionary<double, int> m_doubleIntSet;
39 private Dictionary<string, int> m_stringIntSet; 39 private Dictionary<string, int> m_stringIntSet;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
index c4ca1a8..8550f2d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLString 36 public class LSL_TypesTestLSLString : OpenSimTestCase
37 { 37 {
38 private Dictionary<double, string> m_doubleStringSet; 38 private Dictionary<double, string> m_doubleStringSet;
39 39
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
index b81225f..71b88bc 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
36 /// Tests the LSL_Types.list class. 36 /// Tests the LSL_Types.list class.
37 /// </summary> 37 /// </summary>
38 [TestFixture] 38 [TestFixture]
39 public class LSL_TypesTestList 39 public class LSL_TypesTestList : OpenSimTestCase
40 { 40 {
41 /// <summary> 41 /// <summary>
42 /// Tests concatenating a string to a list. 42 /// Tests concatenating a string to a list.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
index ebf8001..0c838af 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
36 /// Tests for Vector3 36 /// Tests for Vector3
37 /// </summary> 37 /// </summary>
38 [TestFixture] 38 [TestFixture]
39 public class LSL_TypesTestVector3 39 public class LSL_TypesTestVector3 : OpenSimTestCase
40 { 40 {
41 [Test] 41 [Test]
42 public void TestDotProduct() 42 public void TestDotProduct()
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
index c401794..213f33f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
51 /// Tests for OSSL_Api 51 /// Tests for OSSL_Api
52 /// </summary> 52 /// </summary>
53 [TestFixture] 53 [TestFixture]
54 public class OSSL_ApiAppearanceTest 54 public class OSSL_ApiAppearanceTest : OpenSimTestCase
55 { 55 {
56 protected Scene m_scene; 56 protected Scene m_scene;
57 protected XEngine.XEngine m_engine; 57 protected XEngine.XEngine m_engine;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
index f331658..5abfe9a 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
44 /// XEngine tests. 44 /// XEngine tests.
45 /// </summary> 45 /// </summary>
46 [TestFixture] 46 [TestFixture]
47 public class XEngineTest 47 public class XEngineTest : OpenSimTestCase
48 { 48 {
49 private TestScene m_scene; 49 private TestScene m_scene;
50 private XEngine m_xEngine; 50 private XEngine m_xEngine;