diff options
Diffstat (limited to 'OpenSim')
86 files changed, 3110 insertions, 1220 deletions
diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs index a9432c2..87ec99e 100644 --- a/OpenSim/Framework/IScene.cs +++ b/OpenSim/Framework/IScene.cs | |||
@@ -66,6 +66,19 @@ namespace OpenSim.Framework | |||
66 | 66 | ||
67 | IConfigSource Config { get; } | 67 | IConfigSource Config { get; } |
68 | 68 | ||
69 | /// <summary> | ||
70 | /// Are logins enabled on this simulator? | ||
71 | /// </summary> | ||
72 | bool LoginsEnabled { get; set; } | ||
73 | |||
74 | /// <summary> | ||
75 | /// Is this region ready for use? | ||
76 | /// </summary> | ||
77 | /// <remarks> | ||
78 | /// This does not mean that logins are enabled, merely that they can be. | ||
79 | /// </remarks> | ||
80 | bool Ready { get; set; } | ||
81 | |||
69 | float TimeDilation { get; } | 82 | float TimeDilation { get; } |
70 | 83 | ||
71 | bool AllowScriptCrossings { get; } | 84 | bool AllowScriptCrossings { get; } |
diff --git a/OpenSim/Framework/Statistics/AssetStatsCollector.cs b/OpenSim/Framework/Monitoring/AssetStatsCollector.cs index 7082ef3..2a4d45b 100644 --- a/OpenSim/Framework/Statistics/AssetStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/AssetStatsCollector.cs | |||
@@ -28,7 +28,7 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Timers; | 29 | using System.Timers; |
30 | 30 | ||
31 | namespace OpenSim.Framework.Statistics | 31 | namespace OpenSim.Framework.Monitoring |
32 | { | 32 | { |
33 | /// <summary> | 33 | /// <summary> |
34 | /// Asset service statistics collection | 34 | /// Asset service statistics collection |
diff --git a/OpenSim/Framework/Statistics/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs index 3f918f3..9ee0876 100644 --- a/OpenSim/Framework/Statistics/BaseStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs | |||
@@ -31,8 +31,7 @@ using System.Text; | |||
31 | using OpenMetaverse; | 31 | using OpenMetaverse; |
32 | using OpenMetaverse.StructuredData; | 32 | using OpenMetaverse.StructuredData; |
33 | 33 | ||
34 | 34 | namespace OpenSim.Framework.Monitoring | |
35 | namespace OpenSim.Framework.Statistics | ||
36 | { | 35 | { |
37 | /// <summary> | 36 | /// <summary> |
38 | /// Statistics which all collectors are interested in reporting | 37 | /// Statistics which all collectors are interested in reporting |
diff --git a/OpenSim/Framework/Statistics/Interfaces/IPullStatsProvider.cs b/OpenSim/Framework/Monitoring/Interfaces/IPullStatsProvider.cs index 430e580..86a6620 100644 --- a/OpenSim/Framework/Statistics/Interfaces/IPullStatsProvider.cs +++ b/OpenSim/Framework/Monitoring/Interfaces/IPullStatsProvider.cs | |||
@@ -25,7 +25,7 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | namespace OpenSim.Framework.Statistics.Interfaces | 28 | namespace OpenSim.Framework.Monitoring.Interfaces |
29 | { | 29 | { |
30 | /// <summary> | 30 | /// <summary> |
31 | /// Implemented by objects which allow statistical information to be pulled from them. | 31 | /// Implemented by objects which allow statistical information to be pulled from them. |
diff --git a/OpenSim/Framework/Statistics/Interfaces/IStatsCollector.cs b/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs index 477bbb3..99f75e3 100644 --- a/OpenSim/Framework/Statistics/Interfaces/IStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/Interfaces/IStatsCollector.cs | |||
@@ -25,7 +25,7 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | namespace OpenSim.Framework.Statistics | 28 | namespace OpenSim.Framework.Monitoring |
29 | { | 29 | { |
30 | /// <summary> | 30 | /// <summary> |
31 | /// Implemented by classes which collect up non-viewer statistical information | 31 | /// Implemented by classes which collect up non-viewer statistical information |
diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs new file mode 100644 index 0000000..a23cf1f --- /dev/null +++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs | |||
@@ -0,0 +1,129 @@ | |||
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using System.Linq; | ||
31 | using System.Reflection; | ||
32 | using System.Threading; | ||
33 | using log4net; | ||
34 | |||
35 | namespace OpenSim.Framework.Monitoring | ||
36 | { | ||
37 | /// <summary> | ||
38 | /// Experimental watchdog for memory usage. | ||
39 | /// </summary> | ||
40 | public static class MemoryWatchdog | ||
41 | { | ||
42 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
43 | |||
44 | /// <summary> | ||
45 | /// Is this watchdog active? | ||
46 | /// </summary> | ||
47 | public static bool Enabled | ||
48 | { | ||
49 | get { return m_enabled; } | ||
50 | set | ||
51 | { | ||
52 | // m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value); | ||
53 | |||
54 | if (value && !m_enabled) | ||
55 | UpdateLastRecord(GC.GetTotalMemory(false), Util.EnvironmentTickCount()); | ||
56 | |||
57 | m_enabled = value; | ||
58 | } | ||
59 | } | ||
60 | private static bool m_enabled; | ||
61 | |||
62 | /// <summary> | ||
63 | /// Average memory churn in bytes per millisecond. | ||
64 | /// </summary> | ||
65 | public static double AverageMemoryChurn | ||
66 | { | ||
67 | get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } | ||
68 | } | ||
69 | |||
70 | /// <summary> | ||
71 | /// Maximum number of statistical samples. | ||
72 | /// </summary> | ||
73 | /// <remarks> | ||
74 | /// At the moment this corresponds to 1 minute since the sampling rate is every 2.5 seconds as triggered from | ||
75 | /// the main Watchdog. | ||
76 | /// </remarks> | ||
77 | private static int m_maxSamples = 24; | ||
78 | |||
79 | /// <summary> | ||
80 | /// Time when the watchdog was last updated. | ||
81 | /// </summary> | ||
82 | private static int m_lastUpdateTick; | ||
83 | |||
84 | /// <summary> | ||
85 | /// Memory used at time of last watchdog update. | ||
86 | /// </summary> | ||
87 | private static long m_lastUpdateMemory; | ||
88 | |||
89 | /// <summary> | ||
90 | /// Memory churn rate per millisecond. | ||
91 | /// </summary> | ||
92 | // private static double m_churnRatePerMillisecond; | ||
93 | |||
94 | /// <summary> | ||
95 | /// Historical samples for calculating moving average. | ||
96 | /// </summary> | ||
97 | private static Queue<double> m_samples = new Queue<double>(m_maxSamples); | ||
98 | |||
99 | public static void Update() | ||
100 | { | ||
101 | int now = Util.EnvironmentTickCount(); | ||
102 | long memoryNow = GC.GetTotalMemory(false); | ||
103 | long memoryDiff = memoryNow - m_lastUpdateMemory; | ||
104 | |||
105 | if (memoryDiff >= 0) | ||
106 | { | ||
107 | if (m_samples.Count >= m_maxSamples) | ||
108 | m_samples.Dequeue(); | ||
109 | |||
110 | double elapsed = Util.EnvironmentTickCountSubtract(now, m_lastUpdateTick); | ||
111 | |||
112 | // This should never happen since it's not useful for updates to occur with no time elapsed, but | ||
113 | // protect ourselves from a divide-by-zero just in case. | ||
114 | if (elapsed == 0) | ||
115 | return; | ||
116 | |||
117 | m_samples.Enqueue(memoryDiff / (double)elapsed); | ||
118 | } | ||
119 | |||
120 | UpdateLastRecord(memoryNow, now); | ||
121 | } | ||
122 | |||
123 | private static void UpdateLastRecord(long memoryNow, int timeNow) | ||
124 | { | ||
125 | m_lastUpdateMemory = memoryNow; | ||
126 | m_lastUpdateTick = timeNow; | ||
127 | } | ||
128 | } | ||
129 | } \ No newline at end of file | ||
diff --git a/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs index a506e3b..cdd7cc7 100644 --- a/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs | |||
@@ -28,12 +28,11 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Text; | 30 | using System.Text; |
31 | |||
32 | using OpenMetaverse; | 31 | using OpenMetaverse; |
33 | using OpenSim.Framework.Statistics.Interfaces; | ||
34 | using OpenMetaverse.StructuredData; | 32 | using OpenMetaverse.StructuredData; |
33 | using OpenSim.Framework.Monitoring.Interfaces; | ||
35 | 34 | ||
36 | namespace OpenSim.Framework.Statistics | 35 | namespace OpenSim.Framework.Monitoring |
37 | { | 36 | { |
38 | /// <summary> | 37 | /// <summary> |
39 | /// Collects sim statistics which aren't already being collected for the linden viewer's statistics pane | 38 | /// Collects sim statistics which aren't already being collected for the linden viewer's statistics pane |
diff --git a/OpenSim/Framework/Statistics/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs index 436ce2f..d78fa6a 100644 --- a/OpenSim/Framework/Statistics/StatsManager.cs +++ b/OpenSim/Framework/Monitoring/StatsManager.cs | |||
@@ -25,7 +25,7 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | namespace OpenSim.Framework.Statistics | 28 | namespace OpenSim.Framework.Monitoring |
29 | { | 29 | { |
30 | /// <summary> | 30 | /// <summary> |
31 | /// Singleton used to provide access to statistics reporters | 31 | /// Singleton used to provide access to statistics reporters |
diff --git a/OpenSim/Framework/Statistics/UserStatsCollector.cs b/OpenSim/Framework/Monitoring/UserStatsCollector.cs index fd2a9bf..e89c8e6 100644 --- a/OpenSim/Framework/Statistics/UserStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/UserStatsCollector.cs | |||
@@ -27,7 +27,7 @@ | |||
27 | 27 | ||
28 | using System.Timers; | 28 | using System.Timers; |
29 | 29 | ||
30 | namespace OpenSim.Framework.Statistics | 30 | namespace OpenSim.Framework.Monitoring |
31 | { | 31 | { |
32 | /// <summary> | 32 | /// <summary> |
33 | /// Collects user service statistics | 33 | /// Collects user service statistics |
diff --git a/OpenSim/Framework/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs index 449d014..e4db964 100644 --- a/OpenSim/Framework/Watchdog.cs +++ b/OpenSim/Framework/Monitoring/Watchdog.cs | |||
@@ -31,7 +31,7 @@ using System.Linq; | |||
31 | using System.Threading; | 31 | using System.Threading; |
32 | using log4net; | 32 | using log4net; |
33 | 33 | ||
34 | namespace OpenSim.Framework | 34 | namespace OpenSim.Framework.Monitoring |
35 | { | 35 | { |
36 | /// <summary> | 36 | /// <summary> |
37 | /// Manages launching threads and keeping watch over them for timeouts | 37 | /// Manages launching threads and keeping watch over them for timeouts |
@@ -325,6 +325,9 @@ namespace OpenSim.Framework | |||
325 | callback(callbackInfo); | 325 | callback(callbackInfo); |
326 | } | 326 | } |
327 | 327 | ||
328 | if (MemoryWatchdog.Enabled) | ||
329 | MemoryWatchdog.Update(); | ||
330 | |||
328 | m_watchdogTimer.Start(); | 331 | m_watchdogTimer.Start(); |
329 | } | 332 | } |
330 | } | 333 | } |
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index 1b2f681..4bde7be 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs | |||
@@ -482,9 +482,16 @@ namespace OpenSim.Framework | |||
482 | MainConsole.Instance.Output("=====================================\n"); | 482 | MainConsole.Instance.Output("=====================================\n"); |
483 | 483 | ||
484 | if (name == String.Empty) | 484 | if (name == String.Empty) |
485 | name = MainConsole.Instance.CmdPrompt("New region name", name); | 485 | { |
486 | if (name == String.Empty) | 486 | while (name.Trim() == string.Empty) |
487 | throw new Exception("Cannot interactively create region with no name"); | 487 | { |
488 | name = MainConsole.Instance.CmdPrompt("New region name", name); | ||
489 | if (name.Trim() == string.Empty) | ||
490 | { | ||
491 | MainConsole.Instance.Output("Cannot interactively create region with no name"); | ||
492 | } | ||
493 | } | ||
494 | } | ||
488 | 495 | ||
489 | source.AddConfig(name); | 496 | source.AddConfig(name); |
490 | 497 | ||
@@ -515,15 +522,20 @@ namespace OpenSim.Framework | |||
515 | // | 522 | // |
516 | allKeys.Remove("RegionUUID"); | 523 | allKeys.Remove("RegionUUID"); |
517 | string regionUUID = config.GetString("RegionUUID", string.Empty); | 524 | string regionUUID = config.GetString("RegionUUID", string.Empty); |
518 | if (regionUUID == String.Empty) | 525 | if (!UUID.TryParse(regionUUID.Trim(), out RegionID)) |
519 | { | 526 | { |
520 | UUID newID = UUID.Random(); | 527 | UUID newID = UUID.Random(); |
521 | 528 | while (RegionID == UUID.Zero) | |
522 | regionUUID = MainConsole.Instance.CmdPrompt("RegionUUID", newID.ToString()); | 529 | { |
530 | regionUUID = MainConsole.Instance.CmdPrompt("RegionUUID", newID.ToString()); | ||
531 | if (!UUID.TryParse(regionUUID.Trim(), out RegionID)) | ||
532 | { | ||
533 | MainConsole.Instance.Output("RegionUUID must be a valid UUID"); | ||
534 | } | ||
535 | } | ||
523 | config.Set("RegionUUID", regionUUID); | 536 | config.Set("RegionUUID", regionUUID); |
524 | } | 537 | } |
525 | 538 | ||
526 | RegionID = new UUID(regionUUID); | ||
527 | originRegionID = RegionID; // What IS this?! (Needed for RegionCombinerModule?) | 539 | originRegionID = RegionID; // What IS this?! (Needed for RegionCombinerModule?) |
528 | 540 | ||
529 | // Location | 541 | // Location |
diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 9a2cd0e..cf19002 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs | |||
@@ -40,9 +40,9 @@ using log4net.Core; | |||
40 | using log4net.Repository; | 40 | using log4net.Repository; |
41 | using OpenSim.Framework; | 41 | using OpenSim.Framework; |
42 | using OpenSim.Framework.Console; | 42 | using OpenSim.Framework.Console; |
43 | using OpenSim.Framework.Monitoring; | ||
43 | using OpenSim.Framework.Servers; | 44 | using OpenSim.Framework.Servers; |
44 | using OpenSim.Framework.Servers.HttpServer; | 45 | using OpenSim.Framework.Servers.HttpServer; |
45 | using OpenSim.Framework.Statistics; | ||
46 | using Timer=System.Timers.Timer; | 46 | using Timer=System.Timers.Timer; |
47 | 47 | ||
48 | using OpenMetaverse; | 48 | using OpenMetaverse; |
diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 24f986a..e45cb89 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs | |||
@@ -45,6 +45,7 @@ using OpenMetaverse.StructuredData; | |||
45 | using CoolHTTPListener = HttpServer.HttpListener; | 45 | using CoolHTTPListener = HttpServer.HttpListener; |
46 | using HttpListener=System.Net.HttpListener; | 46 | using HttpListener=System.Net.HttpListener; |
47 | using LogPrio=HttpServer.LogPrio; | 47 | using LogPrio=HttpServer.LogPrio; |
48 | using OpenSim.Framework.Monitoring; | ||
48 | 49 | ||
49 | namespace OpenSim.Framework.Servers.HttpServer | 50 | namespace OpenSim.Framework.Servers.HttpServer |
50 | { | 51 | { |
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs index a3bd330..a385110 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs | |||
@@ -32,6 +32,7 @@ using System.Reflection; | |||
32 | using log4net; | 32 | using log4net; |
33 | using HttpServer; | 33 | using HttpServer; |
34 | using OpenSim.Framework; | 34 | using OpenSim.Framework; |
35 | using OpenSim.Framework.Monitoring; | ||
35 | 36 | ||
36 | 37 | ||
37 | /* | 38 | /* |
diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs index 1e3fbf0..1c529b6 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs | |||
@@ -36,6 +36,7 @@ using HttpServer; | |||
36 | using OpenMetaverse; | 36 | using OpenMetaverse; |
37 | using System.Reflection; | 37 | using System.Reflection; |
38 | using log4net; | 38 | using log4net; |
39 | using OpenSim.Framework.Monitoring; | ||
39 | 40 | ||
40 | namespace OpenSim.Framework.Servers.HttpServer | 41 | namespace OpenSim.Framework.Servers.HttpServer |
41 | { | 42 | { |
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index e6b57c2..ba8aa9f 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs | |||
@@ -40,7 +40,7 @@ using OpenMetaverse; | |||
40 | using OpenSim.Framework; | 40 | using OpenSim.Framework; |
41 | using OpenSim.Framework.Console; | 41 | using OpenSim.Framework.Console; |
42 | using OpenSim.Framework.Servers; | 42 | using OpenSim.Framework.Servers; |
43 | using OpenSim.Framework.Statistics; | 43 | using OpenSim.Framework.Monitoring; |
44 | using OpenSim.Region.Framework.Interfaces; | 44 | using OpenSim.Region.Framework.Interfaces; |
45 | using OpenSim.Region.Framework.Scenes; | 45 | using OpenSim.Region.Framework.Scenes; |
46 | 46 | ||
@@ -200,9 +200,9 @@ namespace OpenSim | |||
200 | PrintFileToConsole("startuplogo.txt"); | 200 | PrintFileToConsole("startuplogo.txt"); |
201 | 201 | ||
202 | // For now, start at the 'root' level by default | 202 | // For now, start at the 'root' level by default |
203 | if (m_sceneManager.Scenes.Count == 1) // If there is only one region, select it | 203 | if (SceneManager.Scenes.Count == 1) // If there is only one region, select it |
204 | ChangeSelectedRegion("region", | 204 | ChangeSelectedRegion("region", |
205 | new string[] {"change", "region", m_sceneManager.Scenes[0].RegionInfo.RegionName}); | 205 | new string[] {"change", "region", SceneManager.Scenes[0].RegionInfo.RegionName}); |
206 | else | 206 | else |
207 | ChangeSelectedRegion("region", new string[] {"change", "region", "root"}); | 207 | ChangeSelectedRegion("region", new string[] {"change", "region", "root"}); |
208 | 208 | ||
@@ -461,7 +461,7 @@ namespace OpenSim | |||
461 | if (cmdparams.Length > 4) | 461 | if (cmdparams.Length > 4) |
462 | alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); | 462 | alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); |
463 | 463 | ||
464 | IList agents = m_sceneManager.GetCurrentSceneAvatars(); | 464 | IList agents = SceneManager.GetCurrentSceneAvatars(); |
465 | 465 | ||
466 | foreach (ScenePresence presence in agents) | 466 | foreach (ScenePresence presence in agents) |
467 | { | 467 | { |
@@ -542,7 +542,7 @@ namespace OpenSim | |||
542 | private void HandleForceUpdate(string module, string[] args) | 542 | private void HandleForceUpdate(string module, string[] args) |
543 | { | 543 | { |
544 | MainConsole.Instance.Output("Updating all clients"); | 544 | MainConsole.Instance.Output("Updating all clients"); |
545 | m_sceneManager.ForceCurrentSceneClientUpdate(); | 545 | SceneManager.ForceCurrentSceneClientUpdate(); |
546 | } | 546 | } |
547 | 547 | ||
548 | /// <summary> | 548 | /// <summary> |
@@ -554,7 +554,7 @@ namespace OpenSim | |||
554 | { | 554 | { |
555 | if (args.Length == 6) | 555 | if (args.Length == 6) |
556 | { | 556 | { |
557 | m_sceneManager.HandleEditCommandOnCurrentScene(args); | 557 | SceneManager.HandleEditCommandOnCurrentScene(args); |
558 | } | 558 | } |
559 | else | 559 | else |
560 | { | 560 | { |
@@ -765,7 +765,7 @@ namespace OpenSim | |||
765 | case "load": | 765 | case "load": |
766 | if (cmdparams.Length > 1) | 766 | if (cmdparams.Length > 1) |
767 | { | 767 | { |
768 | foreach (Scene s in new ArrayList(m_sceneManager.Scenes)) | 768 | foreach (Scene s in new ArrayList(SceneManager.Scenes)) |
769 | { | 769 | { |
770 | MainConsole.Instance.Output(String.Format("Loading module: {0}", cmdparams[1])); | 770 | MainConsole.Instance.Output(String.Format("Loading module: {0}", cmdparams[1])); |
771 | m_moduleLoader.LoadRegionModules(cmdparams[1], s); | 771 | m_moduleLoader.LoadRegionModules(cmdparams[1], s); |
@@ -803,14 +803,14 @@ namespace OpenSim | |||
803 | 803 | ||
804 | case "backup": | 804 | case "backup": |
805 | MainConsole.Instance.Output("Triggering save of pending object updates to persistent store"); | 805 | MainConsole.Instance.Output("Triggering save of pending object updates to persistent store"); |
806 | m_sceneManager.BackupCurrentScene(); | 806 | SceneManager.BackupCurrentScene(); |
807 | break; | 807 | break; |
808 | 808 | ||
809 | case "remove-region": | 809 | case "remove-region": |
810 | string regRemoveName = CombineParams(cmdparams, 0); | 810 | string regRemoveName = CombineParams(cmdparams, 0); |
811 | 811 | ||
812 | Scene removeScene; | 812 | Scene removeScene; |
813 | if (m_sceneManager.TryGetScene(regRemoveName, out removeScene)) | 813 | if (SceneManager.TryGetScene(regRemoveName, out removeScene)) |
814 | RemoveRegion(removeScene, false); | 814 | RemoveRegion(removeScene, false); |
815 | else | 815 | else |
816 | MainConsole.Instance.Output("No region with that name"); | 816 | MainConsole.Instance.Output("No region with that name"); |
@@ -820,14 +820,14 @@ namespace OpenSim | |||
820 | string regDeleteName = CombineParams(cmdparams, 0); | 820 | string regDeleteName = CombineParams(cmdparams, 0); |
821 | 821 | ||
822 | Scene killScene; | 822 | Scene killScene; |
823 | if (m_sceneManager.TryGetScene(regDeleteName, out killScene)) | 823 | if (SceneManager.TryGetScene(regDeleteName, out killScene)) |
824 | RemoveRegion(killScene, true); | 824 | RemoveRegion(killScene, true); |
825 | else | 825 | else |
826 | MainConsole.Instance.Output("no region with that name"); | 826 | MainConsole.Instance.Output("no region with that name"); |
827 | break; | 827 | break; |
828 | 828 | ||
829 | case "restart": | 829 | case "restart": |
830 | m_sceneManager.RestartCurrentScene(); | 830 | SceneManager.RestartCurrentScene(); |
831 | break; | 831 | break; |
832 | } | 832 | } |
833 | } | 833 | } |
@@ -842,7 +842,7 @@ namespace OpenSim | |||
842 | { | 842 | { |
843 | string newRegionName = CombineParams(cmdparams, 2); | 843 | string newRegionName = CombineParams(cmdparams, 2); |
844 | 844 | ||
845 | if (!m_sceneManager.TrySetCurrentScene(newRegionName)) | 845 | if (!SceneManager.TrySetCurrentScene(newRegionName)) |
846 | MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName)); | 846 | MainConsole.Instance.Output(String.Format("Couldn't select region {0}", newRegionName)); |
847 | } | 847 | } |
848 | else | 848 | else |
@@ -850,7 +850,7 @@ namespace OpenSim | |||
850 | MainConsole.Instance.Output("Usage: change region <region name>"); | 850 | MainConsole.Instance.Output("Usage: change region <region name>"); |
851 | } | 851 | } |
852 | 852 | ||
853 | string regionName = (m_sceneManager.CurrentScene == null ? "root" : m_sceneManager.CurrentScene.RegionInfo.RegionName); | 853 | string regionName = (SceneManager.CurrentScene == null ? "root" : SceneManager.CurrentScene.RegionInfo.RegionName); |
854 | MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName)); | 854 | MainConsole.Instance.Output(String.Format("Currently selected region is {0}", regionName)); |
855 | 855 | ||
856 | // m_log.DebugFormat("Original prompt is {0}", m_consolePrompt); | 856 | // m_log.DebugFormat("Original prompt is {0}", m_consolePrompt); |
@@ -868,7 +868,7 @@ namespace OpenSim | |||
868 | }); | 868 | }); |
869 | 869 | ||
870 | m_console.DefaultPrompt = prompt; | 870 | m_console.DefaultPrompt = prompt; |
871 | m_console.ConsoleScene = m_sceneManager.CurrentScene; | 871 | m_console.ConsoleScene = SceneManager.CurrentScene; |
872 | } | 872 | } |
873 | 873 | ||
874 | /// <summary> | 874 | /// <summary> |
@@ -892,7 +892,7 @@ namespace OpenSim | |||
892 | int newDebug; | 892 | int newDebug; |
893 | if (int.TryParse(args[2], out newDebug)) | 893 | if (int.TryParse(args[2], out newDebug)) |
894 | { | 894 | { |
895 | m_sceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name); | 895 | SceneManager.SetDebugPacketLevelOnCurrentScene(newDebug, name); |
896 | // We provide user information elsewhere if any clients had their debug level set. | 896 | // We provide user information elsewhere if any clients had their debug level set. |
897 | // MainConsole.Instance.OutputFormat("Debug packet level set to {0}", newDebug); | 897 | // MainConsole.Instance.OutputFormat("Debug packet level set to {0}", newDebug); |
898 | } | 898 | } |
@@ -907,7 +907,7 @@ namespace OpenSim | |||
907 | case "scene": | 907 | case "scene": |
908 | if (args.Length == 4) | 908 | if (args.Length == 4) |
909 | { | 909 | { |
910 | if (m_sceneManager.CurrentScene == null) | 910 | if (SceneManager.CurrentScene == null) |
911 | { | 911 | { |
912 | MainConsole.Instance.Output("Please use 'change region <regioname>' first"); | 912 | MainConsole.Instance.Output("Please use 'change region <regioname>' first"); |
913 | } | 913 | } |
@@ -915,7 +915,7 @@ namespace OpenSim | |||
915 | { | 915 | { |
916 | string key = args[2]; | 916 | string key = args[2]; |
917 | string value = args[3]; | 917 | string value = args[3]; |
918 | m_sceneManager.CurrentScene.SetSceneCoreDebug( | 918 | SceneManager.CurrentScene.SetSceneCoreDebug( |
919 | new Dictionary<string, string>() { { key, value } }); | 919 | new Dictionary<string, string>() { { key, value } }); |
920 | 920 | ||
921 | MainConsole.Instance.OutputFormat("Set debug scene {0} = {1}", key, value); | 921 | MainConsole.Instance.OutputFormat("Set debug scene {0} = {1}", key, value); |
@@ -954,10 +954,10 @@ namespace OpenSim | |||
954 | IList agents; | 954 | IList agents; |
955 | if (showParams.Length > 1 && showParams[1] == "full") | 955 | if (showParams.Length > 1 && showParams[1] == "full") |
956 | { | 956 | { |
957 | agents = m_sceneManager.GetCurrentScenePresences(); | 957 | agents = SceneManager.GetCurrentScenePresences(); |
958 | } else | 958 | } else |
959 | { | 959 | { |
960 | agents = m_sceneManager.GetCurrentSceneAvatars(); | 960 | agents = SceneManager.GetCurrentSceneAvatars(); |
961 | } | 961 | } |
962 | 962 | ||
963 | MainConsole.Instance.Output(String.Format("\nAgents connected: {0}\n", agents.Count)); | 963 | MainConsole.Instance.Output(String.Format("\nAgents connected: {0}\n", agents.Count)); |
@@ -1037,7 +1037,7 @@ namespace OpenSim | |||
1037 | MainConsole.Instance.Output("Shared Module: " + module.Name); | 1037 | MainConsole.Instance.Output("Shared Module: " + module.Name); |
1038 | } | 1038 | } |
1039 | 1039 | ||
1040 | m_sceneManager.ForEachScene( | 1040 | SceneManager.ForEachScene( |
1041 | delegate(Scene scene) { | 1041 | delegate(Scene scene) { |
1042 | m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:"); | 1042 | m_log.Error("The currently loaded modules in " + scene.RegionInfo.RegionName + " are:"); |
1043 | foreach (IRegionModule module in scene.Modules.Values) | 1043 | foreach (IRegionModule module in scene.Modules.Values) |
@@ -1050,7 +1050,7 @@ namespace OpenSim | |||
1050 | } | 1050 | } |
1051 | ); | 1051 | ); |
1052 | 1052 | ||
1053 | m_sceneManager.ForEachScene( | 1053 | SceneManager.ForEachScene( |
1054 | delegate(Scene scene) { | 1054 | delegate(Scene scene) { |
1055 | MainConsole.Instance.Output("Loaded new region modules in" + scene.RegionInfo.RegionName + " are:"); | 1055 | MainConsole.Instance.Output("Loaded new region modules in" + scene.RegionInfo.RegionName + " are:"); |
1056 | foreach (IRegionModuleBase module in scene.RegionModules.Values) | 1056 | foreach (IRegionModuleBase module in scene.RegionModules.Values) |
@@ -1066,7 +1066,7 @@ namespace OpenSim | |||
1066 | break; | 1066 | break; |
1067 | 1067 | ||
1068 | case "regions": | 1068 | case "regions": |
1069 | m_sceneManager.ForEachScene( | 1069 | SceneManager.ForEachScene( |
1070 | delegate(Scene scene) | 1070 | delegate(Scene scene) |
1071 | { | 1071 | { |
1072 | MainConsole.Instance.Output(String.Format( | 1072 | MainConsole.Instance.Output(String.Format( |
@@ -1080,7 +1080,7 @@ namespace OpenSim | |||
1080 | break; | 1080 | break; |
1081 | 1081 | ||
1082 | case "ratings": | 1082 | case "ratings": |
1083 | m_sceneManager.ForEachScene( | 1083 | SceneManager.ForEachScene( |
1084 | delegate(Scene scene) | 1084 | delegate(Scene scene) |
1085 | { | 1085 | { |
1086 | string rating = ""; | 1086 | string rating = ""; |
@@ -1115,7 +1115,7 @@ namespace OpenSim | |||
1115 | cdt.AddColumn("IP", 16); | 1115 | cdt.AddColumn("IP", 16); |
1116 | cdt.AddColumn("Viewer Name", 24); | 1116 | cdt.AddColumn("Viewer Name", 24); |
1117 | 1117 | ||
1118 | m_sceneManager.ForEachScene( | 1118 | SceneManager.ForEachScene( |
1119 | s => | 1119 | s => |
1120 | { | 1120 | { |
1121 | foreach (AgentCircuitData aCircuit in s.AuthenticateHandler.GetAgentCircuits().Values) | 1121 | foreach (AgentCircuitData aCircuit in s.AuthenticateHandler.GetAgentCircuits().Values) |
@@ -1140,13 +1140,13 @@ namespace OpenSim | |||
1140 | cdt.AddColumn("Endpoint", 23); | 1140 | cdt.AddColumn("Endpoint", 23); |
1141 | cdt.AddColumn("Active?", 7); | 1141 | cdt.AddColumn("Active?", 7); |
1142 | 1142 | ||
1143 | m_sceneManager.ForEachScene( | 1143 | SceneManager.ForEachScene( |
1144 | s => s.ForEachClient( | 1144 | s => s.ForEachClient( |
1145 | c => cdt.AddRow( | 1145 | c => cdt.AddRow( |
1146 | s.Name, | 1146 | s.Name, |
1147 | c.Name, | 1147 | c.Name, |
1148 | c.RemoteEndPoint.ToString(), | ||
1149 | c.CircuitCode.ToString(), | 1148 | c.CircuitCode.ToString(), |
1149 | c.RemoteEndPoint.ToString(), | ||
1150 | c.IsActive.ToString()))); | 1150 | c.IsActive.ToString()))); |
1151 | 1151 | ||
1152 | MainConsole.Instance.Output(cdt.ToString()); | 1152 | MainConsole.Instance.Output(cdt.ToString()); |
@@ -1161,11 +1161,11 @@ namespace OpenSim | |||
1161 | { | 1161 | { |
1162 | if (cmdparams.Length > 5) | 1162 | if (cmdparams.Length > 5) |
1163 | { | 1163 | { |
1164 | m_sceneManager.SaveNamedPrimsToXml2(cmdparams[3], cmdparams[4]); | 1164 | SceneManager.SaveNamedPrimsToXml2(cmdparams[3], cmdparams[4]); |
1165 | } | 1165 | } |
1166 | else | 1166 | else |
1167 | { | 1167 | { |
1168 | m_sceneManager.SaveNamedPrimsToXml2("Primitive", DEFAULT_PRIM_BACKUP_FILENAME); | 1168 | SceneManager.SaveNamedPrimsToXml2("Primitive", DEFAULT_PRIM_BACKUP_FILENAME); |
1169 | } | 1169 | } |
1170 | } | 1170 | } |
1171 | 1171 | ||
@@ -1180,11 +1180,11 @@ namespace OpenSim | |||
1180 | 1180 | ||
1181 | if (cmdparams.Length > 0) | 1181 | if (cmdparams.Length > 0) |
1182 | { | 1182 | { |
1183 | m_sceneManager.SaveCurrentSceneToXml(cmdparams[2]); | 1183 | SceneManager.SaveCurrentSceneToXml(cmdparams[2]); |
1184 | } | 1184 | } |
1185 | else | 1185 | else |
1186 | { | 1186 | { |
1187 | m_sceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME); | 1187 | SceneManager.SaveCurrentSceneToXml(DEFAULT_PRIM_BACKUP_FILENAME); |
1188 | } | 1188 | } |
1189 | } | 1189 | } |
1190 | 1190 | ||
@@ -1221,13 +1221,13 @@ namespace OpenSim | |||
1221 | MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z)); | 1221 | MainConsole.Instance.Output(String.Format("loadOffsets <X,Y,Z> = <{0},{1},{2}>",loadOffset.X,loadOffset.Y,loadOffset.Z)); |
1222 | } | 1222 | } |
1223 | } | 1223 | } |
1224 | m_sceneManager.LoadCurrentSceneFromXml(cmdparams[0], generateNewIDS, loadOffset); | 1224 | SceneManager.LoadCurrentSceneFromXml(cmdparams[2], generateNewIDS, loadOffset); |
1225 | } | 1225 | } |
1226 | else | 1226 | else |
1227 | { | 1227 | { |
1228 | try | 1228 | try |
1229 | { | 1229 | { |
1230 | m_sceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset); | 1230 | SceneManager.LoadCurrentSceneFromXml(DEFAULT_PRIM_BACKUP_FILENAME, false, loadOffset); |
1231 | } | 1231 | } |
1232 | catch (FileNotFoundException) | 1232 | catch (FileNotFoundException) |
1233 | { | 1233 | { |
@@ -1244,11 +1244,11 @@ namespace OpenSim | |||
1244 | { | 1244 | { |
1245 | if (cmdparams.Length > 2) | 1245 | if (cmdparams.Length > 2) |
1246 | { | 1246 | { |
1247 | m_sceneManager.SaveCurrentSceneToXml2(cmdparams[2]); | 1247 | SceneManager.SaveCurrentSceneToXml2(cmdparams[2]); |
1248 | } | 1248 | } |
1249 | else | 1249 | else |
1250 | { | 1250 | { |
1251 | m_sceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME); | 1251 | SceneManager.SaveCurrentSceneToXml2(DEFAULT_PRIM_BACKUP_FILENAME); |
1252 | } | 1252 | } |
1253 | } | 1253 | } |
1254 | 1254 | ||
@@ -1263,7 +1263,7 @@ namespace OpenSim | |||
1263 | { | 1263 | { |
1264 | try | 1264 | try |
1265 | { | 1265 | { |
1266 | m_sceneManager.LoadCurrentSceneFromXml2(cmdparams[2]); | 1266 | SceneManager.LoadCurrentSceneFromXml2(cmdparams[2]); |
1267 | } | 1267 | } |
1268 | catch (FileNotFoundException) | 1268 | catch (FileNotFoundException) |
1269 | { | 1269 | { |
@@ -1274,7 +1274,7 @@ namespace OpenSim | |||
1274 | { | 1274 | { |
1275 | try | 1275 | try |
1276 | { | 1276 | { |
1277 | m_sceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME); | 1277 | SceneManager.LoadCurrentSceneFromXml2(DEFAULT_PRIM_BACKUP_FILENAME); |
1278 | } | 1278 | } |
1279 | catch (FileNotFoundException) | 1279 | catch (FileNotFoundException) |
1280 | { | 1280 | { |
@@ -1291,7 +1291,7 @@ namespace OpenSim | |||
1291 | { | 1291 | { |
1292 | try | 1292 | try |
1293 | { | 1293 | { |
1294 | m_sceneManager.LoadArchiveToCurrentScene(cmdparams); | 1294 | SceneManager.LoadArchiveToCurrentScene(cmdparams); |
1295 | } | 1295 | } |
1296 | catch (Exception e) | 1296 | catch (Exception e) |
1297 | { | 1297 | { |
@@ -1305,7 +1305,7 @@ namespace OpenSim | |||
1305 | /// <param name="cmdparams"></param> | 1305 | /// <param name="cmdparams"></param> |
1306 | protected void SaveOar(string module, string[] cmdparams) | 1306 | protected void SaveOar(string module, string[] cmdparams) |
1307 | { | 1307 | { |
1308 | m_sceneManager.SaveCurrentSceneToArchive(cmdparams); | 1308 | SceneManager.SaveCurrentSceneToArchive(cmdparams); |
1309 | } | 1309 | } |
1310 | 1310 | ||
1311 | private static string CombineParams(string[] commandParams, int pos) | 1311 | private static string CombineParams(string[] commandParams, int pos) |
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 76ac246..f378153 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs | |||
@@ -40,7 +40,7 @@ using OpenSim.Framework.Communications; | |||
40 | using OpenSim.Framework.Console; | 40 | using OpenSim.Framework.Console; |
41 | using OpenSim.Framework.Servers; | 41 | using OpenSim.Framework.Servers; |
42 | using OpenSim.Framework.Servers.HttpServer; | 42 | using OpenSim.Framework.Servers.HttpServer; |
43 | using OpenSim.Framework.Statistics; | 43 | using OpenSim.Framework.Monitoring; |
44 | using OpenSim.Region.ClientStack; | 44 | using OpenSim.Region.ClientStack; |
45 | using OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts; | 45 | using OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts; |
46 | using OpenSim.Region.Framework; | 46 | using OpenSim.Region.Framework; |
@@ -300,7 +300,7 @@ namespace OpenSim | |||
300 | 300 | ||
301 | private void HandleCommanderCommand(string module, string[] cmd) | 301 | private void HandleCommanderCommand(string module, string[] cmd) |
302 | { | 302 | { |
303 | m_sceneManager.SendCommandToPluginModules(cmd); | 303 | SceneManager.SendCommandToPluginModules(cmd); |
304 | } | 304 | } |
305 | 305 | ||
306 | private void HandleCommanderHelp(string module, string[] cmd) | 306 | private void HandleCommanderHelp(string module, string[] cmd) |
@@ -318,7 +318,10 @@ namespace OpenSim | |||
318 | // Called from base.StartUp() | 318 | // Called from base.StartUp() |
319 | 319 | ||
320 | m_httpServerPort = m_networkServersInfo.HttpListenerPort; | 320 | m_httpServerPort = m_networkServersInfo.HttpListenerPort; |
321 | m_sceneManager.OnRestartSim += handleRestartRegion; | 321 | SceneManager.OnRestartSim += handleRestartRegion; |
322 | |||
323 | // Only start the memory watchdog once all regions are ready | ||
324 | SceneManager.OnRegionsReadyStatusChange += sm => MemoryWatchdog.Enabled = sm.AllRegionsReady; | ||
322 | } | 325 | } |
323 | 326 | ||
324 | /// <summary> | 327 | /// <summary> |
@@ -480,7 +483,7 @@ namespace OpenSim | |||
480 | scene.SnmpService.BootInfo("ScriptEngine started", scene); | 483 | scene.SnmpService.BootInfo("ScriptEngine started", scene); |
481 | } | 484 | } |
482 | 485 | ||
483 | m_sceneManager.Add(scene); | 486 | SceneManager.Add(scene); |
484 | 487 | ||
485 | if (m_autoCreateClientStack) | 488 | if (m_autoCreateClientStack) |
486 | { | 489 | { |
@@ -510,7 +513,6 @@ namespace OpenSim | |||
510 | } | 513 | } |
511 | 514 | ||
512 | scene.Start(); | 515 | scene.Start(); |
513 | |||
514 | scene.StartScripts(); | 516 | scene.StartScripts(); |
515 | 517 | ||
516 | return clientServer; | 518 | return clientServer; |
@@ -644,14 +646,14 @@ namespace OpenSim | |||
644 | { | 646 | { |
645 | // only need to check this if we are not at the | 647 | // only need to check this if we are not at the |
646 | // root level | 648 | // root level |
647 | if ((m_sceneManager.CurrentScene != null) && | 649 | if ((SceneManager.CurrentScene != null) && |
648 | (m_sceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID)) | 650 | (SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID)) |
649 | { | 651 | { |
650 | m_sceneManager.TrySetCurrentScene(".."); | 652 | SceneManager.TrySetCurrentScene(".."); |
651 | } | 653 | } |
652 | 654 | ||
653 | scene.DeleteAllSceneObjects(); | 655 | scene.DeleteAllSceneObjects(); |
654 | m_sceneManager.CloseScene(scene); | 656 | SceneManager.CloseScene(scene); |
655 | ShutdownClientServer(scene.RegionInfo); | 657 | ShutdownClientServer(scene.RegionInfo); |
656 | 658 | ||
657 | if (!cleanup) | 659 | if (!cleanup) |
@@ -693,7 +695,7 @@ namespace OpenSim | |||
693 | public void RemoveRegion(string name, bool cleanUp) | 695 | public void RemoveRegion(string name, bool cleanUp) |
694 | { | 696 | { |
695 | Scene target; | 697 | Scene target; |
696 | if (m_sceneManager.TryGetScene(name, out target)) | 698 | if (SceneManager.TryGetScene(name, out target)) |
697 | RemoveRegion(target, cleanUp); | 699 | RemoveRegion(target, cleanUp); |
698 | } | 700 | } |
699 | 701 | ||
@@ -706,13 +708,13 @@ namespace OpenSim | |||
706 | { | 708 | { |
707 | // only need to check this if we are not at the | 709 | // only need to check this if we are not at the |
708 | // root level | 710 | // root level |
709 | if ((m_sceneManager.CurrentScene != null) && | 711 | if ((SceneManager.CurrentScene != null) && |
710 | (m_sceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID)) | 712 | (SceneManager.CurrentScene.RegionInfo.RegionID == scene.RegionInfo.RegionID)) |
711 | { | 713 | { |
712 | m_sceneManager.TrySetCurrentScene(".."); | 714 | SceneManager.TrySetCurrentScene(".."); |
713 | } | 715 | } |
714 | 716 | ||
715 | m_sceneManager.CloseScene(scene); | 717 | SceneManager.CloseScene(scene); |
716 | ShutdownClientServer(scene.RegionInfo); | 718 | ShutdownClientServer(scene.RegionInfo); |
717 | } | 719 | } |
718 | 720 | ||
@@ -724,7 +726,7 @@ namespace OpenSim | |||
724 | public void CloseRegion(string name) | 726 | public void CloseRegion(string name) |
725 | { | 727 | { |
726 | Scene target; | 728 | Scene target; |
727 | if (m_sceneManager.TryGetScene(name, out target)) | 729 | if (SceneManager.TryGetScene(name, out target)) |
728 | CloseRegion(target); | 730 | CloseRegion(target); |
729 | } | 731 | } |
730 | 732 | ||
@@ -980,7 +982,7 @@ namespace OpenSim | |||
980 | 982 | ||
981 | try | 983 | try |
982 | { | 984 | { |
983 | m_sceneManager.Close(); | 985 | SceneManager.Close(); |
984 | } | 986 | } |
985 | catch (Exception e) | 987 | catch (Exception e) |
986 | { | 988 | { |
@@ -1005,7 +1007,7 @@ namespace OpenSim | |||
1005 | /// <param name="usernum">The first out parameter describing the number of all the avatars in the Region server</param> | 1007 | /// <param name="usernum">The first out parameter describing the number of all the avatars in the Region server</param> |
1006 | public void GetAvatarNumber(out int usernum) | 1008 | public void GetAvatarNumber(out int usernum) |
1007 | { | 1009 | { |
1008 | usernum = m_sceneManager.GetCurrentSceneAvatars().Count; | 1010 | usernum = SceneManager.GetCurrentSceneAvatars().Count; |
1009 | } | 1011 | } |
1010 | 1012 | ||
1011 | /// <summary> | 1013 | /// <summary> |
@@ -1014,7 +1016,7 @@ namespace OpenSim | |||
1014 | /// <param name="regionnum">The first out parameter describing the number of regions</param> | 1016 | /// <param name="regionnum">The first out parameter describing the number of regions</param> |
1015 | public void GetRegionNumber(out int regionnum) | 1017 | public void GetRegionNumber(out int regionnum) |
1016 | { | 1018 | { |
1017 | regionnum = m_sceneManager.Scenes.Count; | 1019 | regionnum = SceneManager.Scenes.Count; |
1018 | } | 1020 | } |
1019 | 1021 | ||
1020 | /// <summary> | 1022 | /// <summary> |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index ad9074c..f7bb817 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |||
@@ -41,7 +41,7 @@ using OpenMetaverse.Messages.Linden; | |||
41 | using OpenMetaverse.StructuredData; | 41 | using OpenMetaverse.StructuredData; |
42 | using OpenSim.Framework; | 42 | using OpenSim.Framework; |
43 | using OpenSim.Framework.Client; | 43 | using OpenSim.Framework.Client; |
44 | using OpenSim.Framework.Statistics; | 44 | using OpenSim.Framework.Monitoring; |
45 | using OpenSim.Region.Framework.Interfaces; | 45 | using OpenSim.Region.Framework.Interfaces; |
46 | using OpenSim.Region.Framework.Scenes; | 46 | using OpenSim.Region.Framework.Scenes; |
47 | using OpenSim.Services.Interfaces; | 47 | using OpenSim.Services.Interfaces; |
@@ -355,8 +355,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
355 | private int m_animationSequenceNumber = 1; | 355 | private int m_animationSequenceNumber = 1; |
356 | private bool m_SendLogoutPacketWhenClosing = true; | 356 | private bool m_SendLogoutPacketWhenClosing = true; |
357 | private AgentUpdateArgs lastarg; | 357 | private AgentUpdateArgs lastarg; |
358 | private bool m_IsActive = true; | ||
359 | private bool m_IsLoggingOut = false; | ||
360 | 358 | ||
361 | protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); | 359 | protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); |
362 | protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers | 360 | protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers |
@@ -428,16 +426,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
428 | public uint CircuitCode { get { return m_circuitCode; } } | 426 | public uint CircuitCode { get { return m_circuitCode; } } |
429 | public int MoneyBalance { get { return m_moneyBalance; } } | 427 | public int MoneyBalance { get { return m_moneyBalance; } } |
430 | public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } } | 428 | public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } } |
431 | public bool IsActive | 429 | |
432 | { | 430 | /// <summary> |
433 | get { return m_IsActive; } | 431 | /// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to |
434 | set { m_IsActive = value; } | 432 | /// prevent race conditions by different threads calling Close(). |
435 | } | 433 | /// </summary> |
436 | public bool IsLoggingOut | 434 | public bool IsActive { get; set; } |
437 | { | 435 | |
438 | get { return m_IsLoggingOut; } | 436 | /// <summary> |
439 | set { m_IsLoggingOut = value; } | 437 | /// Used to synchronise threads when client is being closed. |
440 | } | 438 | /// </summary> |
439 | public Object CloseSyncLock { get; private set; } | ||
440 | |||
441 | public bool IsLoggingOut { get; set; } | ||
441 | 442 | ||
442 | public bool DisableFacelights | 443 | public bool DisableFacelights |
443 | { | 444 | { |
@@ -462,6 +463,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
462 | { | 463 | { |
463 | // DebugPacketLevel = 1; | 464 | // DebugPacketLevel = 1; |
464 | 465 | ||
466 | CloseSyncLock = new Object(); | ||
467 | |||
465 | RegisterInterface<IClientIM>(this); | 468 | RegisterInterface<IClientIM>(this); |
466 | RegisterInterface<IClientInventory>(this); | 469 | RegisterInterface<IClientInventory>(this); |
467 | RegisterInterface<IClientChat>(this); | 470 | RegisterInterface<IClientChat>(this); |
@@ -494,13 +497,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
494 | m_prioritizer = new Prioritizer(m_scene); | 497 | m_prioritizer = new Prioritizer(m_scene); |
495 | 498 | ||
496 | RegisterLocalPacketHandlers(); | 499 | RegisterLocalPacketHandlers(); |
500 | |||
501 | IsActive = true; | ||
497 | } | 502 | } |
498 | 503 | ||
499 | #region Client Methods | 504 | #region Client Methods |
500 | 505 | ||
501 | 506 | ||
502 | /// <summary> | 507 | /// <summary> |
503 | /// Shut down the client view | 508 | /// Close down the client view |
504 | /// </summary> | 509 | /// </summary> |
505 | public void Close() | 510 | public void Close() |
506 | { | 511 | { |
@@ -513,7 +518,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
513 | public void Close(bool sendStop) | 518 | public void Close(bool sendStop) |
514 | { | 519 | { |
515 | IsActive = false; | 520 | IsActive = false; |
521 | // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. | ||
522 | // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. | ||
523 | lock (CloseSyncLock) | ||
524 | { | ||
525 | if (!IsActive) | ||
526 | return; | ||
527 | |||
528 | IsActive = false; | ||
529 | CloseWithoutChecks(sendStop); | ||
530 | } | ||
531 | } | ||
516 | 532 | ||
533 | /// <summary> | ||
534 | /// Closes down the client view without first checking whether it is active. | ||
535 | /// </summary> | ||
536 | /// <remarks> | ||
537 | /// This exists because LLUDPServer has to set IsActive = false in earlier synchronous code before calling | ||
538 | /// CloseWithoutIsActiveCheck asynchronously. | ||
539 | /// | ||
540 | /// Callers must lock ClosingSyncLock before calling. | ||
541 | /// </remarks> | ||
542 | public void CloseWithoutChecks(bool sendStop) | ||
543 | { | ||
517 | m_log.DebugFormat( | 544 | m_log.DebugFormat( |
518 | "[CLIENT]: Close has been called for {0} attached to scene {1}", | 545 | "[CLIENT]: Close has been called for {0} attached to scene {1}", |
519 | Name, m_scene.RegionInfo.RegionName); | 546 | Name, m_scene.RegionInfo.RegionName); |
@@ -3634,7 +3661,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3634 | 3661 | ||
3635 | public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) | 3662 | public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) |
3636 | { | 3663 | { |
3637 | if (!IsActive) return; // We don't need to update inactive clients. | 3664 | // We don't need to update inactive clients. |
3665 | if (!IsActive) | ||
3666 | return; | ||
3638 | 3667 | ||
3639 | CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); | 3668 | CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); |
3640 | loc.Header.Reliable = false; | 3669 | loc.Header.Reliable = false; |
@@ -5267,7 +5296,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5267 | AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); | 5296 | AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); |
5268 | AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate); | 5297 | AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate); |
5269 | AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply); | 5298 | AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply); |
5270 | AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage, false); | 5299 | AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage); |
5271 | AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship); | 5300 | AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship); |
5272 | AddLocalPacketHandler(PacketType.DeclineFriendship, HandlerDeclineFriendship); | 5301 | AddLocalPacketHandler(PacketType.DeclineFriendship, HandlerDeclineFriendship); |
5273 | AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFriendship); | 5302 | AddLocalPacketHandler(PacketType.TerminateFriendship, HandlerTerminateFriendship); |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs index ae72175..c472176 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs | |||
@@ -279,7 +279,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
279 | public string GetStats() | 279 | public string GetStats() |
280 | { | 280 | { |
281 | return string.Format( | 281 | return string.Format( |
282 | "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}", | 282 | "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7} {12,7}", |
283 | Util.EnvironmentTickCountSubtract(TickLastPacketReceived), | ||
283 | PacketsReceived, | 284 | PacketsReceived, |
284 | PacketsSent, | 285 | PacketsSent, |
285 | PacketsResent, | 286 | PacketsResent, |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index f5f9c02..7042c9a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -37,7 +37,7 @@ using log4net; | |||
37 | using Nini.Config; | 37 | using Nini.Config; |
38 | using OpenMetaverse.Packets; | 38 | using OpenMetaverse.Packets; |
39 | using OpenSim.Framework; | 39 | using OpenSim.Framework; |
40 | using OpenSim.Framework.Statistics; | 40 | using OpenSim.Framework.Monitoring; |
41 | using OpenSim.Region.Framework.Scenes; | 41 | using OpenSim.Region.Framework.Scenes; |
42 | using OpenMetaverse; | 42 | using OpenMetaverse; |
43 | 43 | ||
@@ -1181,22 +1181,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1181 | /// regular client pings. | 1181 | /// regular client pings. |
1182 | /// </remarks> | 1182 | /// </remarks> |
1183 | /// <param name='client'></param> | 1183 | /// <param name='client'></param> |
1184 | private void DeactivateClientDueToTimeout(IClientAPI client) | 1184 | private void DeactivateClientDueToTimeout(LLClientView client) |
1185 | { | 1185 | { |
1186 | // We must set IsActive synchronously so that we can stop the packet loop reinvoking this method, even | 1186 | lock (client.CloseSyncLock) |
1187 | // though it's set later on by LLClientView.Close() | 1187 | { |
1188 | client.IsActive = false; | 1188 | m_log.WarnFormat( |
1189 | 1189 | "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}", | |
1190 | m_log.WarnFormat( | 1190 | client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName); |
1191 | "[LLUDPSERVER]: Ack timeout, disconnecting {0} agent for {1} in {2}", | 1191 | |
1192 | client.SceneAgent.IsChildAgent ? "child" : "root", client.Name, m_scene.RegionInfo.RegionName); | 1192 | StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); |
1193 | 1193 | ||
1194 | StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); | 1194 | if (!client.SceneAgent.IsChildAgent) |
1195 | 1195 | client.Kick("Simulator logged you out due to connection timeout"); | |
1196 | if (!client.SceneAgent.IsChildAgent) | 1196 | |
1197 | client.Kick("Simulator logged you out due to connection timeout"); | 1197 | client.CloseWithoutChecks(true); |
1198 | 1198 | } | |
1199 | Util.FireAndForget(o => client.Close()); | ||
1200 | } | 1199 | } |
1201 | 1200 | ||
1202 | private void IncomingPacketHandler() | 1201 | private void IncomingPacketHandler() |
diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs index c4324e8..4672f8a 100644 --- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs +++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs | |||
@@ -53,9 +53,8 @@ namespace OpenSim.Region.ClientStack | |||
53 | protected ISimulationDataService m_simulationDataService; | 53 | protected ISimulationDataService m_simulationDataService; |
54 | protected IEstateDataService m_estateDataService; | 54 | protected IEstateDataService m_estateDataService; |
55 | protected ClientStackManager m_clientStackManager; | 55 | protected ClientStackManager m_clientStackManager; |
56 | protected SceneManager m_sceneManager = new SceneManager(); | ||
57 | 56 | ||
58 | public SceneManager SceneManager { get { return m_sceneManager; } } | 57 | public SceneManager SceneManager { get; protected set; } |
59 | public NetworkServersInfo NetServersInfo { get { return m_networkServersInfo; } } | 58 | public NetworkServersInfo NetServersInfo { get { return m_networkServersInfo; } } |
60 | public ISimulationDataService SimulationDataService { get { return m_simulationDataService; } } | 59 | public ISimulationDataService SimulationDataService { get { return m_simulationDataService; } } |
61 | public IEstateDataService EstateDataService { get { return m_estateDataService; } } | 60 | public IEstateDataService EstateDataService { get { return m_estateDataService; } } |
@@ -77,6 +76,7 @@ namespace OpenSim.Region.ClientStack | |||
77 | 76 | ||
78 | protected override void StartupSpecific() | 77 | protected override void StartupSpecific() |
79 | { | 78 | { |
79 | SceneManager = new SceneManager(); | ||
80 | m_clientStackManager = CreateClientStackManager(); | 80 | m_clientStackManager = CreateClientStackManager(); |
81 | 81 | ||
82 | Initialize(); | 82 | Initialize(); |
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 31e8a2e..b588704 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -626,10 +626,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
626 | 626 | ||
627 | m_scene.InventoryService.UpdateItem(item); | 627 | m_scene.InventoryService.UpdateItem(item); |
628 | 628 | ||
629 | // this gets called when the agent logs off! | 629 | // If the name of the object has been changed whilst attached then we want to update the inventory |
630 | // item in the viewer. | ||
630 | if (sp.ControllingClient != null) | 631 | if (sp.ControllingClient != null) |
631 | sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0); | 632 | sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0); |
632 | } | 633 | } |
634 | |||
633 | grp.HasGroupChanged = false; // Prevent it being saved over and over | 635 | grp.HasGroupChanged = false; // Prevent it being saved over and over |
634 | } | 636 | } |
635 | // else | 637 | // else |
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index cd1e1c1..273e290 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs | |||
@@ -47,6 +47,7 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; | |||
47 | using OpenSim.Region.CoreModules.World.Serialiser; | 47 | using OpenSim.Region.CoreModules.World.Serialiser; |
48 | using OpenSim.Region.Framework.Scenes; | 48 | using OpenSim.Region.Framework.Scenes; |
49 | using OpenSim.Region.Framework.Interfaces; | 49 | using OpenSim.Region.Framework.Interfaces; |
50 | using OpenSim.Region.ScriptEngine.Interfaces; | ||
50 | using OpenSim.Region.ScriptEngine.XEngine; | 51 | using OpenSim.Region.ScriptEngine.XEngine; |
51 | using OpenSim.Services.Interfaces; | 52 | using OpenSim.Services.Interfaces; |
52 | using OpenSim.Tests.Common; | 53 | using OpenSim.Tests.Common; |
@@ -289,21 +290,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
289 | { | 290 | { |
290 | TestHelpers.InMethod(); | 291 | TestHelpers.InMethod(); |
291 | 292 | ||
292 | Scene scene = CreateTestScene(); | 293 | Scene scene = CreateScriptingEnabledTestScene(); |
293 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); | 294 | UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); |
294 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1.PrincipalID); | 295 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); |
295 | 296 | ||
296 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); | 297 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); |
297 | TaskInventoryHelpers.AddScript(scene, so.RootPart); | 298 | TaskInventoryItem scriptItem |
299 | = TaskInventoryHelpers.AddScript( | ||
300 | scene, | ||
301 | so.RootPart, | ||
302 | "scriptItem", | ||
303 | "default { attach(key id) { if (id != NULL_KEY) { llSay(0, \"Hello World\"); } } }"); | ||
304 | |||
298 | InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); | 305 | InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); |
299 | 306 | ||
307 | // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running. | ||
308 | // In the future, we need to be able to do this programatically more predicably. | ||
309 | scene.EventManager.OnChatFromWorld += OnChatFromWorld; | ||
310 | |||
300 | scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); | 311 | scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); |
301 | 312 | ||
313 | m_chatEvent.WaitOne(60000); | ||
314 | |||
302 | // TODO: Need to have a test that checks the script is actually started but this involves a lot more | 315 | // TODO: Need to have a test that checks the script is actually started but this involves a lot more |
303 | // plumbing of the script engine and either pausing for events or more infrastructure to turn off various | 316 | // plumbing of the script engine and either pausing for events or more infrastructure to turn off various |
304 | // script engine delays/asychronicity that isn't helpful in an automated regression testing context. | 317 | // script engine delays/asychronicity that isn't helpful in an automated regression testing context. |
305 | SceneObjectGroup attSo = scene.GetSceneObjectGroup(so.Name); | 318 | SceneObjectGroup attSo = scene.GetSceneObjectGroup(so.Name); |
306 | Assert.That(attSo.ContainsScripts(), Is.True); | 319 | Assert.That(attSo.ContainsScripts(), Is.True); |
320 | |||
321 | TaskInventoryItem reRezzedScriptItem = attSo.RootPart.Inventory.GetInventoryItem(scriptItem.Name); | ||
322 | IScriptModule xengine = scene.RequestModuleInterface<IScriptModule>(); | ||
323 | Assert.That(xengine.GetScriptState(reRezzedScriptItem.ItemID), Is.True); | ||
307 | } | 324 | } |
308 | 325 | ||
309 | [Test] | 326 | [Test] |
@@ -379,29 +396,49 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
379 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); | 396 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); |
380 | 397 | ||
381 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); | 398 | SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, sp.UUID, "att-name", 0x10); |
382 | TaskInventoryHelpers.AddScript(scene, so.RootPart); | 399 | TaskInventoryItem scriptTaskItem |
400 | = TaskInventoryHelpers.AddScript( | ||
401 | scene, | ||
402 | so.RootPart, | ||
403 | "scriptItem", | ||
404 | "default { attach(key id) { if (id != NULL_KEY) { llSay(0, \"Hello World\"); } } }"); | ||
405 | |||
383 | InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); | 406 | InventoryItemBase userItem = UserInventoryHelpers.AddInventoryItem(scene, so, 0x100, 0x1000); |
384 | 407 | ||
385 | // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running. | 408 | // FIXME: Right now, we have to do a tricksy chat listen to make sure we know when the script is running. |
386 | // In the future, we need to be able to do this programatically more predicably. | 409 | // In the future, we need to be able to do this programatically more predicably. |
387 | scene.EventManager.OnChatFromWorld += OnChatFromWorld; | 410 | scene.EventManager.OnChatFromWorld += OnChatFromWorld; |
388 | 411 | ||
389 | SceneObjectGroup soRezzed | 412 | SceneObjectGroup rezzedSo |
390 | = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest); | 413 | = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest)); |
391 | 414 | ||
392 | // Wait for chat to signal rezzed script has been started. | 415 | // Wait for chat to signal rezzed script has been started. |
393 | m_chatEvent.WaitOne(60000); | 416 | m_chatEvent.WaitOne(60000); |
394 | 417 | ||
395 | scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, soRezzed); | 418 | scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, rezzedSo); |
396 | 419 | ||
397 | InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem); | 420 | InventoryItemBase userItemUpdated = scene.InventoryService.GetItem(userItem); |
398 | AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString()); | 421 | AssetBase asset = scene.AssetService.Get(userItemUpdated.AssetID.ToString()); |
399 | 422 | ||
423 | // TODO: It would probably be better here to check script state via the saving and retrieval of state | ||
424 | // information at a higher level, rather than having to inspect the serialization. | ||
400 | XmlDocument soXml = new XmlDocument(); | 425 | XmlDocument soXml = new XmlDocument(); |
401 | soXml.LoadXml(Encoding.UTF8.GetString(asset.Data)); | 426 | soXml.LoadXml(Encoding.UTF8.GetString(asset.Data)); |
402 | 427 | ||
403 | XmlNodeList scriptStateNodes = soXml.GetElementsByTagName("ScriptState"); | 428 | XmlNodeList scriptStateNodes = soXml.GetElementsByTagName("ScriptState"); |
404 | Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); | 429 | Assert.That(scriptStateNodes.Count, Is.EqualTo(1)); |
430 | |||
431 | // Re-rez the attachment to check script running state | ||
432 | SceneObjectGroup reRezzedSo = (SceneObjectGroup)(scene.AttachmentsModule.RezSingleAttachmentFromInventory(sp, userItem.ID, (uint)AttachmentPoint.Chest)); | ||
433 | |||
434 | // Wait for chat to signal rezzed script has been started. | ||
435 | m_chatEvent.WaitOne(60000); | ||
436 | |||
437 | TaskInventoryItem reRezzedScriptItem = reRezzedSo.RootPart.Inventory.GetInventoryItem(scriptTaskItem.Name); | ||
438 | IScriptModule xengine = scene.RequestModuleInterface<IScriptModule>(); | ||
439 | Assert.That(xengine.GetScriptState(reRezzedScriptItem.ItemID), Is.True); | ||
440 | |||
441 | // Console.WriteLine(soXml.OuterXml); | ||
405 | } | 442 | } |
406 | 443 | ||
407 | /// <summary> | 444 | /// <summary> |
diff --git a/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs index 4bcd2ac..764adf9 100644 --- a/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Commands/UserCommandsModule.cs | |||
@@ -37,7 +37,7 @@ using Nini.Config; | |||
37 | using OpenMetaverse; | 37 | using OpenMetaverse; |
38 | using OpenSim.Framework; | 38 | using OpenSim.Framework; |
39 | using OpenSim.Framework.Console; | 39 | using OpenSim.Framework.Console; |
40 | using OpenSim.Framework.Statistics; | 40 | using OpenSim.Framework.Monitoring; |
41 | using OpenSim.Region.Framework.Interfaces; | 41 | using OpenSim.Region.Framework.Interfaces; |
42 | using OpenSim.Region.Framework.Scenes; | 42 | using OpenSim.Region.Framework.Scenes; |
43 | 43 | ||
diff --git a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs index 31363e5..b258e13 100644 --- a/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Groups/GroupsModule.cs | |||
@@ -96,7 +96,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups | |||
96 | 96 | ||
97 | scene.EventManager.OnNewClient += OnNewClient; | 97 | scene.EventManager.OnNewClient += OnNewClient; |
98 | scene.EventManager.OnClientClosed += OnClientClosed; | 98 | scene.EventManager.OnClientClosed += OnClientClosed; |
99 | scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; | 99 | // scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; |
100 | } | 100 | } |
101 | 101 | ||
102 | public void PostInitialise() | 102 | public void PostInitialise() |
@@ -133,7 +133,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups | |||
133 | private void OnNewClient(IClientAPI client) | 133 | private void OnNewClient(IClientAPI client) |
134 | { | 134 | { |
135 | // Subscribe to instant messages | 135 | // Subscribe to instant messages |
136 | client.OnInstantMessage += OnInstantMessage; | 136 | // client.OnInstantMessage += OnInstantMessage; |
137 | client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; | 137 | client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; |
138 | client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; | 138 | client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; |
139 | lock (m_ClientMap) | 139 | lock (m_ClientMap) |
@@ -171,15 +171,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Groups | |||
171 | ActiveGroupTitle); | 171 | ActiveGroupTitle); |
172 | } | 172 | } |
173 | 173 | ||
174 | private void OnInstantMessage(IClientAPI client, GridInstantMessage im) | 174 | // private void OnInstantMessage(IClientAPI client, GridInstantMessage im) |
175 | { | 175 | // { |
176 | } | 176 | // } |
177 | 177 | ||
178 | private void OnGridInstantMessage(GridInstantMessage msg) | 178 | // private void OnGridInstantMessage(GridInstantMessage msg) |
179 | { | 179 | // { |
180 | // Trigger the above event handler | 180 | // // Trigger the above event handler |
181 | OnInstantMessage(null, msg); | 181 | // OnInstantMessage(null, msg); |
182 | } | 182 | // } |
183 | 183 | ||
184 | private void HandleUUIDGroupNameRequest(UUID id,IClientAPI remote_client) | 184 | private void HandleUUIDGroupNameRequest(UUID id,IClientAPI remote_client) |
185 | { | 185 | { |
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index 6064ddc..1406aae 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs | |||
@@ -141,13 +141,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage | |||
141 | foreach (Scene scene in m_Scenes) | 141 | foreach (Scene scene in m_Scenes) |
142 | { | 142 | { |
143 | // m_log.DebugFormat( | 143 | // m_log.DebugFormat( |
144 | // "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", | 144 | // "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", |
145 | // toAgentID.ToString(), scene.RegionInfo.RegionName); | 145 | // toAgentID.ToString(), scene.RegionInfo.RegionName); |
146 | |||
146 | ScenePresence sp = scene.GetScenePresence(toAgentID); | 147 | ScenePresence sp = scene.GetScenePresence(toAgentID); |
147 | if (sp != null && !sp.IsChildAgent) | 148 | if (sp != null && !sp.IsChildAgent) |
148 | { | 149 | { |
149 | // Local message | 150 | // Local message |
150 | // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); | 151 | m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", sp.Name, toAgentID); |
152 | |||
151 | sp.ControllingClient.SendInstantMessage(im); | 153 | sp.ControllingClient.SendInstantMessage(im); |
152 | 154 | ||
153 | // Message sent | 155 | // Message sent |
@@ -159,13 +161,15 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage | |||
159 | // try child avatar second | 161 | // try child avatar second |
160 | foreach (Scene scene in m_Scenes) | 162 | foreach (Scene scene in m_Scenes) |
161 | { | 163 | { |
162 | // m_log.DebugFormat( | 164 | m_log.DebugFormat( |
163 | // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); | 165 | "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); |
166 | |||
164 | ScenePresence sp = scene.GetScenePresence(toAgentID); | 167 | ScenePresence sp = scene.GetScenePresence(toAgentID); |
165 | if (sp != null) | 168 | if (sp != null) |
166 | { | 169 | { |
167 | // Local message | 170 | // Local message |
168 | // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); | 171 | m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", sp.Name, toAgentID); |
172 | |||
169 | sp.ControllingClient.SendInstantMessage(im); | 173 | sp.ControllingClient.SendInstantMessage(im); |
170 | 174 | ||
171 | // Message sent | 175 | // Message sent |
@@ -174,10 +178,9 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage | |||
174 | } | 178 | } |
175 | } | 179 | } |
176 | 180 | ||
177 | // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); | 181 | m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); |
178 | SendGridInstantMessageViaXMLRPC(im, result); | ||
179 | 182 | ||
180 | return; | 183 | SendGridInstantMessageViaXMLRPC(im, result); |
181 | } | 184 | } |
182 | 185 | ||
183 | private void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result) | 186 | private void HandleUndeliveredMessage(GridInstantMessage im, MessageResultNotification result) |
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index 80554fb..81de29c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs | |||
@@ -313,8 +313,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer | |||
313 | m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); | 313 | m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); |
314 | } | 314 | } |
315 | } | 315 | } |
316 | else if (im.dialog == (byte) InstantMessageDialog.InventoryDeclined || | 316 | else if ( |
317 | im.dialog == (byte) InstantMessageDialog.TaskInventoryDeclined) | 317 | im.dialog == (byte)InstantMessageDialog.InventoryDeclined |
318 | || im.dialog == (byte)InstantMessageDialog.TaskInventoryDeclined) | ||
318 | { | 319 | { |
319 | // Here, the recipient is local and we can assume that the | 320 | // Here, the recipient is local and we can assume that the |
320 | // inventory is loaded. Courtesy of the above bulk update, | 321 | // inventory is loaded. Courtesy of the above bulk update, |
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index d30c2e2..9a56f42 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs | |||
@@ -204,8 +204,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
204 | 204 | ||
205 | AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); | 205 | AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); |
206 | m_Scene.AssetService.Store(asset); | 206 | m_Scene.AssetService.Store(asset); |
207 | 207 | m_Scene.CreateNewInventoryItem( | |
208 | m_Scene.CreateNewInventoryItem(remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, asset.Name, 0, callbackID, asset, invType, nextOwnerMask, creationDate); | 208 | remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, |
209 | name, description, 0, callbackID, asset, invType, nextOwnerMask, creationDate); | ||
209 | } | 210 | } |
210 | else | 211 | else |
211 | { | 212 | { |
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs index a75ff62..fb74cc6 100644 --- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs | |||
@@ -39,7 +39,7 @@ using OpenSim.Region.Framework; | |||
39 | using OpenSim.Region.Framework.Interfaces; | 39 | using OpenSim.Region.Framework.Interfaces; |
40 | using OpenSim.Region.Framework.Scenes; | 40 | using OpenSim.Region.Framework.Scenes; |
41 | 41 | ||
42 | namespace OpenSim.Region.CoreModules.Avatar.Attachments | 42 | namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging |
43 | { | 43 | { |
44 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BinaryLoggingModule")] | 44 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "BinaryLoggingModule")] |
45 | public class BinaryLoggingModule : INonSharedRegionModule | 45 | public class BinaryLoggingModule : INonSharedRegionModule |
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs new file mode 100755 index 0000000..65e4c90 --- /dev/null +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs | |||
@@ -0,0 +1,161 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSimulator Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.IO; | ||
30 | using System.Text; | ||
31 | using log4net; | ||
32 | |||
33 | namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | ||
34 | { | ||
35 | /// <summary> | ||
36 | /// Class for writing a high performance, high volume log file. | ||
37 | /// Sometimes, to debug, one has a high volume logging to do and the regular | ||
38 | /// log file output is not appropriate. | ||
39 | /// Create a new instance with the parameters needed and | ||
40 | /// call Write() to output a line. Call Close() when finished. | ||
41 | /// If created with no parameters, it will not log anything. | ||
42 | /// </summary> | ||
43 | public class LogWriter : IDisposable | ||
44 | { | ||
45 | public bool Enabled { get; private set; } | ||
46 | |||
47 | private string m_logDirectory = "."; | ||
48 | private int m_logMaxFileTimeMin = 5; // 5 minutes | ||
49 | public String LogFileHeader { get; set; } | ||
50 | |||
51 | private StreamWriter m_logFile = null; | ||
52 | private TimeSpan m_logFileLife; | ||
53 | private DateTime m_logFileEndTime; | ||
54 | private Object m_logFileWriteLock = new Object(); | ||
55 | |||
56 | // set externally when debugging. If let 'null', this does not write any error messages. | ||
57 | public ILog ErrorLogger = null; | ||
58 | private string LogHeader = "[LOG WRITER]"; | ||
59 | |||
60 | /// <summary> | ||
61 | /// Create a log writer that will not write anything. Good for when not enabled | ||
62 | /// but the write statements are still in the code. | ||
63 | /// </summary> | ||
64 | public LogWriter() | ||
65 | { | ||
66 | Enabled = false; | ||
67 | m_logFile = null; | ||
68 | } | ||
69 | |||
70 | /// <summary> | ||
71 | /// Create a log writer instance. | ||
72 | /// </summary> | ||
73 | /// <param name="dir">The directory to create the log file in. May be 'null' for default.</param> | ||
74 | /// <param name="headr">The characters that begin the log file name. May be 'null' for default.</param> | ||
75 | /// <param name="maxFileTime">Maximum age of a log file in minutes. If zero, will set default.</param> | ||
76 | public LogWriter(string dir, string headr, int maxFileTime) | ||
77 | { | ||
78 | m_logDirectory = dir == null ? "." : dir; | ||
79 | |||
80 | LogFileHeader = headr == null ? "log-" : headr; | ||
81 | |||
82 | m_logMaxFileTimeMin = maxFileTime; | ||
83 | if (m_logMaxFileTimeMin < 1) | ||
84 | m_logMaxFileTimeMin = 5; | ||
85 | |||
86 | m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); | ||
87 | m_logFileEndTime = DateTime.Now + m_logFileLife; | ||
88 | |||
89 | Enabled = true; | ||
90 | } | ||
91 | |||
92 | public void Dispose() | ||
93 | { | ||
94 | this.Close(); | ||
95 | } | ||
96 | |||
97 | public void Close() | ||
98 | { | ||
99 | Enabled = false; | ||
100 | if (m_logFile != null) | ||
101 | { | ||
102 | m_logFile.Close(); | ||
103 | m_logFile.Dispose(); | ||
104 | m_logFile = null; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | public void Write(string line, params object[] args) | ||
109 | { | ||
110 | if (!Enabled) return; | ||
111 | Write(String.Format(line, args)); | ||
112 | } | ||
113 | |||
114 | public void Write(string line) | ||
115 | { | ||
116 | if (!Enabled) return; | ||
117 | try | ||
118 | { | ||
119 | lock (m_logFileWriteLock) | ||
120 | { | ||
121 | DateTime now = DateTime.Now; | ||
122 | if (m_logFile == null || now > m_logFileEndTime) | ||
123 | { | ||
124 | if (m_logFile != null) | ||
125 | { | ||
126 | m_logFile.Close(); | ||
127 | m_logFile.Dispose(); | ||
128 | m_logFile = null; | ||
129 | } | ||
130 | |||
131 | // First log file or time has expired, start writing to a new log file | ||
132 | m_logFileEndTime = now + m_logFileLife; | ||
133 | string path = (m_logDirectory.Length > 0 ? m_logDirectory | ||
134 | + System.IO.Path.DirectorySeparatorChar.ToString() : "") | ||
135 | + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); | ||
136 | m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); | ||
137 | } | ||
138 | if (m_logFile != null) | ||
139 | { | ||
140 | StringBuilder buff = new StringBuilder(line.Length + 25); | ||
141 | buff.Append(now.ToString("yyyyMMddHHmmssfff")); | ||
142 | // buff.Append(now.ToString("yyyyMMddHHmmss")); | ||
143 | buff.Append(","); | ||
144 | buff.Append(line); | ||
145 | buff.Append("\r\n"); | ||
146 | m_logFile.Write(buff.ToString()); | ||
147 | } | ||
148 | } | ||
149 | } | ||
150 | catch (Exception e) | ||
151 | { | ||
152 | if (ErrorLogger != null) | ||
153 | { | ||
154 | ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); | ||
155 | } | ||
156 | Enabled = false; | ||
157 | } | ||
158 | return; | ||
159 | } | ||
160 | } | ||
161 | } \ No newline at end of file | ||
diff --git a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs index a6e2548..4a76b00 100644 --- a/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs +++ b/OpenSim/Region/CoreModules/InterGrid/OpenGridProtocolModule.cs | |||
@@ -40,6 +40,7 @@ using OpenMetaverse; | |||
40 | using OpenMetaverse.StructuredData; | 40 | using OpenMetaverse.StructuredData; |
41 | using OpenSim.Framework; | 41 | using OpenSim.Framework; |
42 | using OpenSim.Framework.Capabilities; | 42 | using OpenSim.Framework.Capabilities; |
43 | using OpenSim.Framework.Monitoring; | ||
43 | using OpenSim.Framework.Servers; | 44 | using OpenSim.Framework.Servers; |
44 | using OpenSim.Region.Framework.Interfaces; | 45 | using OpenSim.Region.Framework.Interfaces; |
45 | using OpenSim.Region.Framework.Scenes; | 46 | using OpenSim.Region.Framework.Scenes; |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs index 990dffb..11e0150 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs | |||
@@ -31,7 +31,7 @@ using System.Collections.Generic; | |||
31 | using System.Reflection; | 31 | using System.Reflection; |
32 | using Nini.Config; | 32 | using Nini.Config; |
33 | using OpenSim.Framework; | 33 | using OpenSim.Framework; |
34 | using OpenSim.Framework.Statistics; | 34 | using OpenSim.Framework.Monitoring; |
35 | using OpenSim.Services.Connectors; | 35 | using OpenSim.Services.Connectors; |
36 | using OpenSim.Region.Framework.Interfaces; | 36 | using OpenSim.Region.Framework.Interfaces; |
37 | using OpenSim.Region.Framework.Scenes; | 37 | using OpenSim.Region.Framework.Scenes; |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs index 6cd077a..e4c6c1a 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs | |||
@@ -134,11 +134,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage | |||
134 | ///<summary> | 134 | ///<summary> |
135 | /// | 135 | /// |
136 | ///</summary> | 136 | ///</summary> |
137 | |||
138 | |||
139 | ///<summary> | ||
140 | /// | ||
141 | ///</summary> | ||
142 | public void AddRegion(Scene scene) | 137 | public void AddRegion(Scene scene) |
143 | { | 138 | { |
144 | if (! m_enabled) | 139 | if (! m_enabled) |
@@ -149,10 +144,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage | |||
149 | lock (m_scenes) | 144 | lock (m_scenes) |
150 | m_scenes[scene.RegionInfo.RegionID] = scene; | 145 | m_scenes[scene.RegionInfo.RegionID] = scene; |
151 | 146 | ||
152 | scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; | 147 | scene.EventManager.OnRegionReadyStatusChange += s => { if (s.Ready) UploadMapTile(s); }; |
153 | } | 148 | } |
154 | 149 | ||
155 | |||
156 | ///<summary> | 150 | ///<summary> |
157 | /// | 151 | /// |
158 | ///</summary> | 152 | ///</summary> |
@@ -166,21 +160,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage | |||
166 | } | 160 | } |
167 | 161 | ||
168 | #endregion ISharedRegionModule | 162 | #endregion ISharedRegionModule |
169 | 163 | ||
170 | void OnLoginsEnabled(string regionName) | ||
171 | { | ||
172 | Scene scene = null; | ||
173 | foreach (Scene s in m_scenes.Values) | ||
174 | if (s.RegionInfo.RegionName == regionName) | ||
175 | { | ||
176 | scene = s; | ||
177 | break; | ||
178 | } | ||
179 | if (scene != null) | ||
180 | UploadMapTile(scene); | ||
181 | } | ||
182 | |||
183 | |||
184 | ///<summary> | 164 | ///<summary> |
185 | /// | 165 | /// |
186 | ///</summary> | 166 | ///</summary> |
diff --git a/OpenSim/Region/CoreModules/World/Access/AccessModule.cs b/OpenSim/Region/CoreModules/World/Access/AccessModule.cs index 553a32d..e7b1454 100644 --- a/OpenSim/Region/CoreModules/World/Access/AccessModule.cs +++ b/OpenSim/Region/CoreModules/World/Access/AccessModule.cs | |||
@@ -129,18 +129,18 @@ namespace OpenSim.Region.CoreModules.World | |||
129 | switch (cmd[1]) | 129 | switch (cmd[1]) |
130 | { | 130 | { |
131 | case "enable": | 131 | case "enable": |
132 | scene.LoginsDisabled = false; | 132 | scene.LoginsEnabled = true; |
133 | MainConsole.Instance.Output(String.Format("Logins are enabled for region {0}", scene.RegionInfo.RegionName)); | 133 | MainConsole.Instance.Output(String.Format("Logins are enabled for region {0}", scene.RegionInfo.RegionName)); |
134 | break; | 134 | break; |
135 | case "disable": | 135 | case "disable": |
136 | scene.LoginsDisabled = true; | 136 | scene.LoginsEnabled = false; |
137 | MainConsole.Instance.Output(String.Format("Logins are disabled for region {0}", scene.RegionInfo.RegionName)); | 137 | MainConsole.Instance.Output(String.Format("Logins are disabled for region {0}", scene.RegionInfo.RegionName)); |
138 | break; | 138 | break; |
139 | case "status": | 139 | case "status": |
140 | if (scene.LoginsDisabled) | 140 | if (scene.LoginsEnabled) |
141 | MainConsole.Instance.Output(String.Format("Login in {0} are disabled", scene.RegionInfo.RegionName)); | ||
142 | else | ||
143 | MainConsole.Instance.Output(String.Format("Login in {0} are enabled", scene.RegionInfo.RegionName)); | 141 | MainConsole.Instance.Output(String.Format("Login in {0} are enabled", scene.RegionInfo.RegionName)); |
142 | else | ||
143 | MainConsole.Instance.Output(String.Format("Login in {0} are disabled", scene.RegionInfo.RegionName)); | ||
144 | break; | 144 | break; |
145 | default: | 145 | default: |
146 | MainConsole.Instance.Output("Syntax: login enable|disable|status"); | 146 | MainConsole.Instance.Output("Syntax: login enable|disable|status"); |
diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index e5cd3e2..09f6758 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs | |||
@@ -37,7 +37,7 @@ using Nini.Config; | |||
37 | using OpenMetaverse; | 37 | using OpenMetaverse; |
38 | using OpenSim.Framework; | 38 | using OpenSim.Framework; |
39 | using OpenSim.Framework.Console; | 39 | using OpenSim.Framework.Console; |
40 | using OpenSim.Framework.Statistics; | 40 | using OpenSim.Framework.Monitoring; |
41 | using OpenSim.Region.Framework.Interfaces; | 41 | using OpenSim.Region.Framework.Interfaces; |
42 | using OpenSim.Region.Framework.Scenes; | 42 | using OpenSim.Region.Framework.Scenes; |
43 | 43 | ||
diff --git a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs index 2838e0c..7d35473 100644 --- a/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Region/RegionCommandsModule.cs | |||
@@ -37,7 +37,7 @@ using Nini.Config; | |||
37 | using OpenMetaverse; | 37 | using OpenMetaverse; |
38 | using OpenSim.Framework; | 38 | using OpenSim.Framework; |
39 | using OpenSim.Framework.Console; | 39 | using OpenSim.Framework.Console; |
40 | using OpenSim.Framework.Statistics; | 40 | using OpenSim.Framework.Monitoring; |
41 | using OpenSim.Region.Framework.Interfaces; | 41 | using OpenSim.Region.Framework.Interfaces; |
42 | using OpenSim.Region.Framework.Scenes; | 42 | using OpenSim.Region.Framework.Scenes; |
43 | 43 | ||
diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 309856f..26b406e 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs | |||
@@ -42,6 +42,7 @@ using OpenMetaverse.Imaging; | |||
42 | using OpenMetaverse.StructuredData; | 42 | using OpenMetaverse.StructuredData; |
43 | using OpenSim.Framework; | 43 | using OpenSim.Framework; |
44 | using OpenSim.Framework.Capabilities; | 44 | using OpenSim.Framework.Capabilities; |
45 | using OpenSim.Framework.Monitoring; | ||
45 | using OpenSim.Framework.Servers; | 46 | using OpenSim.Framework.Servers; |
46 | using OpenSim.Framework.Servers.HttpServer; | 47 | using OpenSim.Framework.Servers.HttpServer; |
47 | using OpenSim.Region.Framework.Interfaces; | 48 | using OpenSim.Region.Framework.Interfaces; |
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs index aa4a757..136ca92 100644 --- a/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs | |||
@@ -25,14 +25,23 @@ | |||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | |||
29 | using System; | 28 | using System; |
29 | using OpenSim.Framework; | ||
30 | 30 | ||
31 | namespace OpenSim.Region.Framework.Interfaces | 31 | namespace OpenSim.Region.Framework.Interfaces |
32 | { | 32 | { |
33 | public interface IRegionReadyModule | 33 | public interface IRegionReadyModule |
34 | { | 34 | { |
35 | void OarLoadingAlert(string msg); | 35 | void OarLoadingAlert(string msg); |
36 | |||
37 | /// <summary> | ||
38 | /// Trigger region ready status manually. | ||
39 | /// </summary> | ||
40 | /// <remarks> | ||
41 | /// This should be called by the scene if the IRegionReadyModule has set Scene.LoginLock == true | ||
42 | /// </remarks> | ||
43 | /// <param name='scene'></param> | ||
44 | void TriggerRegionReady(IScene scene); | ||
36 | } | 45 | } |
37 | } | 46 | } |
38 | 47 | ||
diff --git a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs index 3f68ee0..0fe681f 100644 --- a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs +++ b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs | |||
@@ -40,8 +40,6 @@ namespace OpenSim.Region.Framework.Interfaces | |||
40 | /// </remarks> | 40 | /// </remarks> |
41 | public interface IScenePresence : ISceneAgent | 41 | public interface IScenePresence : ISceneAgent |
42 | { | 42 | { |
43 | PresenceType PresenceType { get; } | ||
44 | |||
45 | /// <summary> | 43 | /// <summary> |
46 | /// Copy of the script states while the agent is in transit. This state may | 44 | /// Copy of the script states while the agent is in transit. This state may |
47 | /// need to be placed back in case of transfer fail. | 45 | /// need to be placed back in case of transfer fail. |
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 9ddac19..50a176b 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs | |||
@@ -551,11 +551,5 @@ namespace OpenSim.Region.Framework.Scenes.Animation | |||
551 | 551 | ||
552 | SendAnimPack(animIDs, sequenceNums, objectIDs); | 552 | SendAnimPack(animIDs, sequenceNums, objectIDs); |
553 | } | 553 | } |
554 | |||
555 | public void Close() | ||
556 | { | ||
557 | m_animations = null; | ||
558 | m_scenePresence = null; | ||
559 | } | ||
560 | } | 554 | } |
561 | } | 555 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index d783e57..7cb3811 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs | |||
@@ -500,15 +500,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
500 | public delegate void RegionHeartbeatEnd(Scene scene); | 500 | public delegate void RegionHeartbeatEnd(Scene scene); |
501 | public event RegionHeartbeatEnd OnRegionHeartbeatEnd; | 501 | public event RegionHeartbeatEnd OnRegionHeartbeatEnd; |
502 | 502 | ||
503 | public delegate void LoginsEnabled(string regionName); | 503 | /// <summary> |
504 | /// Fired when logins to a region are enabled or disabled. | ||
505 | /// </summary> | ||
506 | /// <remarks> | ||
507 | /// | ||
508 | /// </remarks> | ||
509 | /// Fired | ||
510 | public event RegionLoginsStatusChange OnRegionLoginsStatusChange; | ||
511 | public delegate void RegionLoginsStatusChange(IScene scene); | ||
504 | 512 | ||
505 | /// <summary> | 513 | /// <summary> |
506 | /// This should only fire in all circumstances if the RegionReady module is active. | 514 | /// Fired when a region is considered ready for use. |
507 | /// </summary> | 515 | /// </summary> |
508 | /// <remarks> | 516 | /// <remarks> |
509 | /// TODO: Fire this even when the RegionReady module is not active. | 517 | /// A region is considered ready when startup operations such as loading of scripts already on the region |
518 | /// have been completed. | ||
510 | /// </remarks> | 519 | /// </remarks> |
511 | public event LoginsEnabled OnLoginsEnabled; | 520 | public event Action<IScene> OnRegionReadyStatusChange; |
512 | 521 | ||
513 | public delegate void PrimsLoaded(Scene s); | 522 | public delegate void PrimsLoaded(Scene s); |
514 | public event PrimsLoaded OnPrimsLoaded; | 523 | public event PrimsLoaded OnPrimsLoaded; |
@@ -2502,21 +2511,42 @@ namespace OpenSim.Region.Framework.Scenes | |||
2502 | } | 2511 | } |
2503 | } | 2512 | } |
2504 | 2513 | ||
2505 | public void TriggerLoginsEnabled (string regionName) | 2514 | public void TriggerRegionLoginsStatusChange(IScene scene) |
2506 | { | 2515 | { |
2507 | LoginsEnabled handler = OnLoginsEnabled; | 2516 | RegionLoginsStatusChange handler = OnRegionLoginsStatusChange; |
2508 | 2517 | ||
2509 | if ( handler != null) | 2518 | if (handler != null) |
2510 | { | 2519 | { |
2511 | foreach (LoginsEnabled d in handler.GetInvocationList()) | 2520 | foreach (RegionLoginsStatusChange d in handler.GetInvocationList()) |
2512 | { | 2521 | { |
2513 | try | 2522 | try |
2514 | { | 2523 | { |
2515 | d(regionName); | 2524 | d(scene); |
2525 | } | ||
2526 | catch (Exception e) | ||
2527 | { | ||
2528 | m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionLoginsStatusChange failed - continuing {0} - {1}", | ||
2529 | e.Message, e.StackTrace); | ||
2530 | } | ||
2531 | } | ||
2532 | } | ||
2533 | } | ||
2534 | |||
2535 | public void TriggerRegionReadyStatusChange(IScene scene) | ||
2536 | { | ||
2537 | Action<IScene> handler = OnRegionReadyStatusChange; | ||
2538 | |||
2539 | if (handler != null) | ||
2540 | { | ||
2541 | foreach (Action<IScene> d in handler.GetInvocationList()) | ||
2542 | { | ||
2543 | try | ||
2544 | { | ||
2545 | d(scene); | ||
2516 | } | 2546 | } |
2517 | catch (Exception e) | 2547 | catch (Exception e) |
2518 | { | 2548 | { |
2519 | m_log.ErrorFormat("[EVENT MANAGER]: Delegate for LoginsEnabled failed - continuing {0} - {1}", | 2549 | m_log.ErrorFormat("[EVENT MANAGER]: Delegate for OnRegionReadyStatusChange failed - continuing {0} - {1}", |
2520 | e.Message, e.StackTrace); | 2550 | e.Message, e.StackTrace); |
2521 | } | 2551 | } |
2522 | } | 2552 | } |
diff --git a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs index 1365831..c11174d 100644 --- a/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs +++ b/OpenSim/Region/Framework/Scenes/RegionStatsHandler.cs | |||
@@ -39,7 +39,7 @@ using OpenSim.Framework.Communications; | |||
39 | using OpenSim.Framework.Console; | 39 | using OpenSim.Framework.Console; |
40 | using OpenSim.Framework.Servers; | 40 | using OpenSim.Framework.Servers; |
41 | using OpenSim.Framework.Servers.HttpServer; | 41 | using OpenSim.Framework.Servers.HttpServer; |
42 | using OpenSim.Framework.Statistics; | 42 | using OpenSim.Framework.Monitoring; |
43 | using OpenSim.Region.Framework; | 43 | using OpenSim.Region.Framework; |
44 | using OpenSim.Region.Framework.Interfaces; | 44 | using OpenSim.Region.Framework.Interfaces; |
45 | using OpenSim.Region.Framework.Scenes; | 45 | using OpenSim.Region.Framework.Scenes; |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 98b8fcc..672d95a 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs | |||
@@ -811,16 +811,20 @@ namespace OpenSim.Region.Framework.Scenes | |||
811 | && oldAgentID == LibraryService.LibraryRootFolder.Owner)) | 811 | && oldAgentID == LibraryService.LibraryRootFolder.Owner)) |
812 | { | 812 | { |
813 | CreateNewInventoryItem( | 813 | CreateNewInventoryItem( |
814 | remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Flags, callbackID, asset, (sbyte)item.InvType, | 814 | remoteClient, item.CreatorId, item.CreatorData, newFolderID, |
815 | item.BasePermissions, item.CurrentPermissions, item.EveryOnePermissions, item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch()); | 815 | newName, item.Description, item.Flags, callbackID, asset, (sbyte)item.InvType, |
816 | item.BasePermissions, item.CurrentPermissions, item.EveryOnePermissions, | ||
817 | item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch()); | ||
816 | } | 818 | } |
817 | else | 819 | else |
818 | { | 820 | { |
819 | // If item is transfer or permissions are off or calling agent is allowed to copy item owner's inventory item. | 821 | // If item is transfer or permissions are off or calling agent is allowed to copy item owner's inventory item. |
820 | if (((item.CurrentPermissions & (uint)PermissionMask.Transfer) != 0) && (m_permissions.BypassPermissions() || m_permissions.CanCopyUserInventory(remoteClient.AgentId, oldItemID))) | 822 | if (((item.CurrentPermissions & (uint)PermissionMask.Transfer) != 0) |
823 | && (m_permissions.BypassPermissions() | ||
824 | || m_permissions.CanCopyUserInventory(remoteClient.AgentId, oldItemID))) | ||
821 | { | 825 | { |
822 | CreateNewInventoryItem( | 826 | CreateNewInventoryItem( |
823 | remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Flags, callbackID, | 827 | remoteClient, item.CreatorId, item.CreatorData, newFolderID, newName, item.Description, item.Flags, callbackID, |
824 | asset, (sbyte) item.InvType, | 828 | asset, (sbyte) item.InvType, |
825 | item.NextPermissions, item.NextPermissions, item.EveryOnePermissions & item.NextPermissions, | 829 | item.NextPermissions, item.NextPermissions, item.EveryOnePermissions & item.NextPermissions, |
826 | item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch()); | 830 | item.NextPermissions, item.GroupPermissions, Util.UnixTimeSinceEpoch()); |
@@ -885,32 +889,50 @@ namespace OpenSim.Region.Framework.Scenes | |||
885 | /// <summary> | 889 | /// <summary> |
886 | /// Create a new inventory item. | 890 | /// Create a new inventory item. |
887 | /// </summary> | 891 | /// </summary> |
888 | /// <param name="remoteClient"></param> | 892 | /// <param name="remoteClient">Client creating this inventory item.</param> |
889 | /// <param name="folderID"></param> | 893 | /// <param name="creatorID"></param> |
890 | /// <param name="callbackID"></param> | 894 | /// <param name="creatorData"></param> |
891 | /// <param name="asset"></param> | 895 | /// <param name="folderID">UUID of folder in which this item should be placed.</param> |
892 | /// <param name="invType"></param> | 896 | /// <param name="name">Item name.</para> |
893 | /// <param name="nextOwnerMask"></param> | 897 | /// <param name="description">Item description.</param> |
894 | public void CreateNewInventoryItem(IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, | 898 | /// <param name="flags">Item flags</param> |
895 | AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate) | 899 | /// <param name="callbackID">Generated by the client.</para> |
900 | /// <param name="asset">Asset to which this item refers.</param> | ||
901 | /// <param name="invType">Type of inventory item.</param> | ||
902 | /// <param name="nextOwnerMask">Next owner pemrissions mask.</param> | ||
903 | /// <param name="creationDate">Unix timestamp at which this item was created.</param> | ||
904 | public void CreateNewInventoryItem( | ||
905 | IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, | ||
906 | string name, string description, uint flags, uint callbackID, | ||
907 | AssetBase asset, sbyte invType, uint nextOwnerMask, int creationDate) | ||
896 | { | 908 | { |
897 | CreateNewInventoryItem( | 909 | CreateNewInventoryItem( |
898 | remoteClient, creatorID, creatorData, folderID, name, flags, callbackID, asset, invType, | 910 | remoteClient, creatorID, creatorData, folderID, name, description, flags, callbackID, asset, invType, |
899 | (uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate); | 911 | (uint)PermissionMask.All, (uint)PermissionMask.All, 0, nextOwnerMask, 0, creationDate); |
900 | } | 912 | } |
901 | 913 | ||
902 | /// <summary> | 914 | /// <summary> |
903 | /// Create a new Inventory Item | 915 | /// Create a new Inventory Item |
904 | /// </summary> | 916 | /// </summary> |
905 | /// <param name="remoteClient"></param> | 917 | /// <param name="remoteClient">Client creating this inventory item.</param> |
906 | /// <param name="folderID"></param> | 918 | /// <param name="creatorID"></param> |
907 | /// <param name="callbackID"></param> | 919 | /// <param name="creatorData"></param> |
908 | /// <param name="asset"></param> | 920 | /// <param name="folderID">UUID of folder in which this item should be placed.</param> |
909 | /// <param name="invType"></param> | 921 | /// <param name="name">Item name.</para> |
910 | /// <param name="nextOwnerMask"></param> | 922 | /// <param name="description">Item description.</param> |
911 | /// <param name="creationDate"></param> | 923 | /// <param name="flags">Item flags</param> |
924 | /// <param name="callbackID">Generated by the client.</para> | ||
925 | /// <param name="asset">Asset to which this item refers.</param> | ||
926 | /// <param name="invType">Type of inventory item.</param> | ||
927 | /// <param name="baseMask">Base permissions mask.</param> | ||
928 | /// <param name="currentMask">Current permissions mask.</param> | ||
929 | /// <param name="everyoneMask">Everyone permissions mask.</param> | ||
930 | /// <param name="nextOwnerMask">Next owner pemrissions mask.</param> | ||
931 | /// <param name="groupMask">Group permissions mask.</param> | ||
932 | /// <param name="creationDate">Unix timestamp at which this item was created.</param> | ||
912 | private void CreateNewInventoryItem( | 933 | private void CreateNewInventoryItem( |
913 | IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, string name, uint flags, uint callbackID, AssetBase asset, sbyte invType, | 934 | IClientAPI remoteClient, string creatorID, string creatorData, UUID folderID, |
935 | string name, string description, uint flags, uint callbackID, AssetBase asset, sbyte invType, | ||
914 | uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate) | 936 | uint baseMask, uint currentMask, uint everyoneMask, uint nextOwnerMask, uint groupMask, int creationDate) |
915 | { | 937 | { |
916 | InventoryItemBase item = new InventoryItemBase(); | 938 | InventoryItemBase item = new InventoryItemBase(); |
@@ -919,8 +941,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
919 | item.CreatorData = creatorData; | 941 | item.CreatorData = creatorData; |
920 | item.ID = UUID.Random(); | 942 | item.ID = UUID.Random(); |
921 | item.AssetID = asset.FullID; | 943 | item.AssetID = asset.FullID; |
922 | item.Description = asset.Description; | ||
923 | item.Name = name; | 944 | item.Name = name; |
945 | item.Description = description; | ||
924 | item.Flags = flags; | 946 | item.Flags = flags; |
925 | item.AssetType = asset.Type; | 947 | item.AssetType = asset.Type; |
926 | item.InvType = invType; | 948 | item.InvType = invType; |
@@ -1002,7 +1024,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1002 | asset.Description = description; | 1024 | asset.Description = description; |
1003 | 1025 | ||
1004 | CreateNewInventoryItem( | 1026 | CreateNewInventoryItem( |
1005 | remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, name, 0, callbackID, asset, invType, | 1027 | remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, |
1028 | name, description, 0, callbackID, asset, invType, | ||
1006 | (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All, | 1029 | (uint)PermissionMask.All, (uint)PermissionMask.All, (uint)PermissionMask.All, |
1007 | (uint)PermissionMask.All, (uint)PermissionMask.All, Util.UnixTimeSinceEpoch()); | 1030 | (uint)PermissionMask.All, (uint)PermissionMask.All, Util.UnixTimeSinceEpoch()); |
1008 | } | 1031 | } |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index ad9e91d..f7d74db 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -40,6 +40,7 @@ using OpenMetaverse; | |||
40 | using OpenMetaverse.Packets; | 40 | using OpenMetaverse.Packets; |
41 | using OpenMetaverse.Imaging; | 41 | using OpenMetaverse.Imaging; |
42 | using OpenSim.Framework; | 42 | using OpenSim.Framework; |
43 | using OpenSim.Framework.Monitoring; | ||
43 | using OpenSim.Services.Interfaces; | 44 | using OpenSim.Services.Interfaces; |
44 | using OpenSim.Framework.Communications; | 45 | using OpenSim.Framework.Communications; |
45 | using OpenSim.Framework.Console; | 46 | using OpenSim.Framework.Console; |
@@ -129,9 +130,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
129 | public bool m_strictAccessControl = true; | 130 | public bool m_strictAccessControl = true; |
130 | public bool m_seeIntoBannedRegion = false; | 131 | public bool m_seeIntoBannedRegion = false; |
131 | public int MaxUndoCount = 5; | 132 | public int MaxUndoCount = 5; |
133 | |||
132 | // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; | 134 | // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; |
133 | public bool LoginLock = false; | 135 | public bool LoginLock = false; |
134 | public bool LoginsDisabled = true; | 136 | |
135 | public bool StartDisabled = false; | 137 | public bool StartDisabled = false; |
136 | public bool LoadingPrims; | 138 | public bool LoadingPrims; |
137 | public IXfer XferManager; | 139 | public IXfer XferManager; |
@@ -727,6 +729,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
727 | { | 729 | { |
728 | IConfig startupConfig = m_config.Configs["Startup"]; | 730 | IConfig startupConfig = m_config.Configs["Startup"]; |
729 | 731 | ||
732 | StartDisabled = startupConfig.GetBoolean("StartDisabled", false); | ||
733 | |||
730 | m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); | 734 | m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); |
731 | m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup); | 735 | m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup); |
732 | if (!m_useBackup) | 736 | if (!m_useBackup) |
@@ -1229,15 +1233,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
1229 | avatar.ControllingClient.SendShutdownConnectionNotice(); | 1233 | avatar.ControllingClient.SendShutdownConnectionNotice(); |
1230 | }); | 1234 | }); |
1231 | 1235 | ||
1236 | // Stop updating the scene objects and agents. | ||
1237 | m_shuttingDown = true; | ||
1238 | |||
1232 | // Wait here, or the kick messages won't actually get to the agents before the scene terminates. | 1239 | // Wait here, or the kick messages won't actually get to the agents before the scene terminates. |
1240 | // We also need to wait to avoid a race condition with the scene update loop which might not yet | ||
1241 | // have checked ShuttingDown. | ||
1233 | Thread.Sleep(500); | 1242 | Thread.Sleep(500); |
1234 | 1243 | ||
1235 | // Stop all client threads. | 1244 | // Stop all client threads. |
1236 | ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); | 1245 | ForEachScenePresence(delegate(ScenePresence avatar) { avatar.ControllingClient.Close(); }); |
1237 | 1246 | ||
1238 | // Stop updating the scene objects and agents. | ||
1239 | m_shuttingDown = true; | ||
1240 | |||
1241 | m_log.Debug("[SCENE]: Persisting changed objects"); | 1247 | m_log.Debug("[SCENE]: Persisting changed objects"); |
1242 | EventManager.TriggerSceneShuttingDown(this); | 1248 | EventManager.TriggerSceneShuttingDown(this); |
1243 | 1249 | ||
@@ -1252,6 +1258,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
1252 | 1258 | ||
1253 | m_sceneGraph.Close(); | 1259 | m_sceneGraph.Close(); |
1254 | 1260 | ||
1261 | if (PhysicsScene != null) | ||
1262 | { | ||
1263 | PhysicsScene phys = PhysicsScene; | ||
1264 | // remove the physics engine from both Scene and SceneGraph | ||
1265 | PhysicsScene = null; | ||
1266 | phys.Dispose(); | ||
1267 | phys = null; | ||
1268 | } | ||
1269 | |||
1255 | if (!GridService.DeregisterRegion(RegionInfo.RegionID)) | 1270 | if (!GridService.DeregisterRegion(RegionInfo.RegionID)) |
1256 | m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); | 1271 | m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); |
1257 | 1272 | ||
@@ -1530,7 +1545,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1530 | // landMS = Util.EnvironmentTickCountSubtract(ldMS); | 1545 | // landMS = Util.EnvironmentTickCountSubtract(ldMS); |
1531 | //} | 1546 | //} |
1532 | 1547 | ||
1533 | if (LoginsDisabled && Frame == 20) | 1548 | if (!LoginsEnabled && Frame == 20) |
1534 | { | 1549 | { |
1535 | // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock); | 1550 | // m_log.DebugFormat("{0} {1} {2}", LoginsDisabled, m_sceneGraph.GetActiveScriptsCount(), LoginLock); |
1536 | 1551 | ||
@@ -1538,31 +1553,34 @@ namespace OpenSim.Region.Framework.Scenes | |||
1538 | // this is a rare case where we know we have just went through a long cycle of heap | 1553 | // this is a rare case where we know we have just went through a long cycle of heap |
1539 | // allocations, and there is no more work to be done until someone logs in | 1554 | // allocations, and there is no more work to be done until someone logs in |
1540 | GC.Collect(); | 1555 | GC.Collect(); |
1541 | 1556 | ||
1542 | IConfig startupConfig = m_config.Configs["Startup"]; | 1557 | if (!LoginLock) |
1543 | if (startupConfig == null || !startupConfig.GetBoolean("StartDisabled", false)) | ||
1544 | { | 1558 | { |
1545 | // This handles a case of a region having no scripts for the RegionReady module | 1559 | if (!StartDisabled) |
1546 | if (m_sceneGraph.GetActiveScriptsCount() == 0) | ||
1547 | { | ||
1548 | // need to be able to tell these have changed in RegionReady | ||
1549 | LoginLock = false; | ||
1550 | EventManager.TriggerLoginsEnabled(RegionInfo.RegionName); | ||
1551 | } | ||
1552 | |||
1553 | // For RegionReady lockouts | ||
1554 | if (!LoginLock) | ||
1555 | { | 1560 | { |
1556 | m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); | 1561 | m_log.InfoFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); |
1557 | LoginsDisabled = false; | 1562 | LoginsEnabled = true; |
1558 | } | 1563 | } |
1559 | 1564 | ||
1560 | m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface<INeighbourService>(), RegionInfo); | 1565 | m_sceneGridService.InformNeighborsThatRegionisUp( |
1566 | RequestModuleInterface<INeighbourService>(), RegionInfo); | ||
1567 | |||
1568 | // Region ready should always be set | ||
1569 | Ready = true; | ||
1561 | } | 1570 | } |
1562 | else | 1571 | else |
1563 | { | 1572 | { |
1564 | StartDisabled = true; | 1573 | // This handles a case of a region having no scripts for the RegionReady module |
1565 | LoginsDisabled = true; | 1574 | if (m_sceneGraph.GetActiveScriptsCount() == 0) |
1575 | { | ||
1576 | // In this case, we leave it to the IRegionReadyModule to enable logins | ||
1577 | |||
1578 | // LoginLock can currently only be set by a region module implementation. | ||
1579 | // If somehow this hasn't been done then the quickest way to bugfix is to see the | ||
1580 | // NullReferenceException | ||
1581 | IRegionReadyModule rrm = RequestModuleInterface<IRegionReadyModule>(); | ||
1582 | rrm.TriggerRegionReady(this); | ||
1583 | } | ||
1566 | } | 1584 | } |
1567 | } | 1585 | } |
1568 | } | 1586 | } |
@@ -3477,25 +3495,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
3477 | if (AgentTransactionsModule != null) | 3495 | if (AgentTransactionsModule != null) |
3478 | AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); | 3496 | AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); |
3479 | 3497 | ||
3480 | avatar.Close(); | ||
3481 | |||
3482 | m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); | 3498 | m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); |
3483 | m_log.Debug("[Scene] The avatar has left the building"); | 3499 | m_log.Debug("[Scene] The avatar has left the building"); |
3484 | } | 3500 | } |
3485 | catch (Exception e) | 3501 | catch (Exception e) |
3486 | { | 3502 | { |
3487 | m_log.Error( | 3503 | m_log.Error( |
3488 | string.Format("[SCENE]: Exception removing {0} from {1}, ", avatar.Name, RegionInfo.RegionName), e); | 3504 | string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); |
3489 | } | 3505 | } |
3490 | finally | 3506 | finally |
3491 | { | 3507 | { |
3492 | // Always clean these structures up so that any failure above doesn't cause them to remain in the | 3508 | try |
3493 | // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering | 3509 | { |
3494 | // the same cleanup exception continually. | 3510 | // Always clean these structures up so that any failure above doesn't cause them to remain in the |
3495 | // TODO: This should probably extend to the whole method, but we don't want to also catch the NRE | 3511 | // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering |
3496 | // since this would hide the underlying failure and other associated problems. | 3512 | // the same cleanup exception continually. |
3497 | m_sceneGraph.RemoveScenePresence(agentID); | 3513 | m_sceneGraph.RemoveScenePresence(agentID); |
3498 | m_clientManager.Remove(agentID); | 3514 | m_clientManager.Remove(agentID); |
3515 | |||
3516 | avatar.Close(); | ||
3517 | } | ||
3518 | catch (Exception e) | ||
3519 | { | ||
3520 | m_log.Error( | ||
3521 | string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); | ||
3522 | } | ||
3499 | } | 3523 | } |
3500 | 3524 | ||
3501 | //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); | 3525 | //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); |
@@ -3609,7 +3633,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3609 | agent.startpos | 3633 | agent.startpos |
3610 | ); | 3634 | ); |
3611 | 3635 | ||
3612 | if (LoginsDisabled) | 3636 | if (!LoginsEnabled) |
3613 | { | 3637 | { |
3614 | reason = "Logins Disabled"; | 3638 | reason = "Logins Disabled"; |
3615 | return false; | 3639 | return false; |
@@ -3666,8 +3690,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3666 | // We have a zombie from a crashed session. | 3690 | // We have a zombie from a crashed session. |
3667 | // Or the same user is trying to be root twice here, won't work. | 3691 | // Or the same user is trying to be root twice here, won't work. |
3668 | // Kill it. | 3692 | // Kill it. |
3669 | m_log.DebugFormat( | 3693 | m_log.WarnFormat( |
3670 | "[SCENE]: Zombie scene presence detected for {0} {1} in {2}", | 3694 | "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", |
3671 | sp.Name, sp.UUID, RegionInfo.RegionName); | 3695 | sp.Name, sp.UUID, RegionInfo.RegionName); |
3672 | 3696 | ||
3673 | sp.ControllingClient.Close(); | 3697 | sp.ControllingClient.Close(); |
@@ -4658,6 +4682,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
4658 | } | 4682 | } |
4659 | 4683 | ||
4660 | /// <summary> | 4684 | /// <summary> |
4685 | /// Gets all the scene presences in this scene. | ||
4686 | /// </summary> | ||
4687 | /// <remarks> | ||
4688 | /// This method will return both root and child scene presences. | ||
4689 | /// | ||
4690 | /// Consider using ForEachScenePresence() or ForEachRootScenePresence() if possible since these will not | ||
4691 | /// involving creating a new List object. | ||
4692 | /// </remarks> | ||
4693 | /// <returns> | ||
4694 | /// A list of the scene presences. Adding or removing from the list will not affect the presences in the scene. | ||
4695 | /// </returns> | ||
4696 | public List<ScenePresence> GetScenePresences() | ||
4697 | { | ||
4698 | return new List<ScenePresence>(m_sceneGraph.GetScenePresences()); | ||
4699 | } | ||
4700 | |||
4701 | /// <summary> | ||
4661 | /// Performs action on all avatars in the scene (root scene presences) | 4702 | /// Performs action on all avatars in the scene (root scene presences) |
4662 | /// Avatars may be an NPC or a 'real' client. | 4703 | /// Avatars may be an NPC or a 'real' client. |
4663 | /// </summary> | 4704 | /// </summary> |
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index 8db4397..7c8bd88 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs | |||
@@ -106,6 +106,42 @@ namespace OpenSim.Region.Framework.Scenes | |||
106 | 106 | ||
107 | protected readonly ClientManager m_clientManager = new ClientManager(); | 107 | protected readonly ClientManager m_clientManager = new ClientManager(); |
108 | 108 | ||
109 | public bool LoginsEnabled | ||
110 | { | ||
111 | get | ||
112 | { | ||
113 | return m_loginsEnabled; | ||
114 | } | ||
115 | |||
116 | set | ||
117 | { | ||
118 | if (m_loginsEnabled != value) | ||
119 | { | ||
120 | m_loginsEnabled = value; | ||
121 | EventManager.TriggerRegionLoginsStatusChange(this); | ||
122 | } | ||
123 | } | ||
124 | } | ||
125 | private bool m_loginsEnabled; | ||
126 | |||
127 | public bool Ready | ||
128 | { | ||
129 | get | ||
130 | { | ||
131 | return m_ready; | ||
132 | } | ||
133 | |||
134 | set | ||
135 | { | ||
136 | if (m_ready != value) | ||
137 | { | ||
138 | m_ready = value; | ||
139 | EventManager.TriggerRegionReadyStatusChange(this); | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | private bool m_ready; | ||
144 | |||
109 | public float TimeDilation | 145 | public float TimeDilation |
110 | { | 146 | { |
111 | get { return 1.0f; } | 147 | get { return 1.0f; } |
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index c3d66eb..e0260e2 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs | |||
@@ -848,7 +848,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
848 | /// pass a delegate to ForEachScenePresence. | 848 | /// pass a delegate to ForEachScenePresence. |
849 | /// </summary> | 849 | /// </summary> |
850 | /// <returns></returns> | 850 | /// <returns></returns> |
851 | private List<ScenePresence> GetScenePresences() | 851 | protected internal List<ScenePresence> GetScenePresences() |
852 | { | 852 | { |
853 | return m_scenePresenceArray; | 853 | return m_scenePresenceArray; |
854 | } | 854 | } |
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs index e3fed49..f1b09ca 100644 --- a/OpenSim/Region/Framework/Scenes/SceneManager.cs +++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs | |||
@@ -47,6 +47,48 @@ namespace OpenSim.Region.Framework.Scenes | |||
47 | 47 | ||
48 | public event RestartSim OnRestartSim; | 48 | public event RestartSim OnRestartSim; |
49 | 49 | ||
50 | /// <summary> | ||
51 | /// Fired when either all regions are ready for use or at least one region has become unready for use where | ||
52 | /// previously all regions were ready. | ||
53 | /// </summary> | ||
54 | public event Action<SceneManager> OnRegionsReadyStatusChange; | ||
55 | |||
56 | /// <summary> | ||
57 | /// Are all regions ready for use? | ||
58 | /// </summary> | ||
59 | public bool AllRegionsReady | ||
60 | { | ||
61 | get | ||
62 | { | ||
63 | return m_allRegionsReady; | ||
64 | } | ||
65 | |||
66 | private set | ||
67 | { | ||
68 | if (m_allRegionsReady != value) | ||
69 | { | ||
70 | m_allRegionsReady = value; | ||
71 | Action<SceneManager> handler = OnRegionsReadyStatusChange; | ||
72 | if (handler != null) | ||
73 | { | ||
74 | foreach (Action<SceneManager> d in handler.GetInvocationList()) | ||
75 | { | ||
76 | try | ||
77 | { | ||
78 | d(this); | ||
79 | } | ||
80 | catch (Exception e) | ||
81 | { | ||
82 | m_log.ErrorFormat("[SCENE MANAGER]: Delegate for OnRegionsReadyStatusChange failed - continuing {0} - {1}", | ||
83 | e.Message, e.StackTrace); | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | private bool m_allRegionsReady; | ||
91 | |||
50 | private static SceneManager m_instance = null; | 92 | private static SceneManager m_instance = null; |
51 | public static SceneManager Instance | 93 | public static SceneManager Instance |
52 | { | 94 | { |
@@ -128,9 +170,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
128 | 170 | ||
129 | public void Add(Scene scene) | 171 | public void Add(Scene scene) |
130 | { | 172 | { |
131 | scene.OnRestart += HandleRestart; | 173 | lock (m_localScenes) |
174 | m_localScenes.Add(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, scene); | ||
132 | 175 | ||
133 | m_localScenes.Add(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, scene); | 176 | scene.OnRestart += HandleRestart; |
177 | scene.EventManager.OnRegionReadyStatusChange += HandleRegionReadyStatusChange; | ||
134 | } | 178 | } |
135 | 179 | ||
136 | public void HandleRestart(RegionInfo rdata) | 180 | public void HandleRestart(RegionInfo rdata) |
@@ -138,12 +182,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
138 | m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main"); | 182 | m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main"); |
139 | int RegionSceneElement = -1; | 183 | int RegionSceneElement = -1; |
140 | 184 | ||
141 | m_localScenes.Remove(rdata.RegionID); | 185 | lock (m_localScenes) |
186 | m_localScenes.Remove(rdata.RegionID); | ||
142 | 187 | ||
143 | // Send signal to main that we're restarting this sim. | 188 | // Send signal to main that we're restarting this sim. |
144 | OnRestartSim(rdata); | 189 | OnRestartSim(rdata); |
145 | } | 190 | } |
146 | 191 | ||
192 | private void HandleRegionReadyStatusChange(IScene scene) | ||
193 | { | ||
194 | lock (m_localScenes) | ||
195 | AllRegionsReady = m_localScenes.FindAll(s => !s.Ready).Count == 0; | ||
196 | } | ||
197 | |||
147 | public void SendSimOnlineNotification(ulong regionHandle) | 198 | public void SendSimOnlineNotification(ulong regionHandle) |
148 | { | 199 | { |
149 | RegionInfo Result = null; | 200 | RegionInfo Result = null; |
@@ -483,7 +534,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
483 | 534 | ||
484 | public void CloseScene(Scene scene) | 535 | public void CloseScene(Scene scene) |
485 | { | 536 | { |
486 | m_localScenes.Remove(scene.RegionInfo.RegionID); | 537 | lock (m_localScenes) |
538 | m_localScenes.Remove(scene.RegionInfo.RegionID); | ||
487 | 539 | ||
488 | scene.Close(); | 540 | scene.Close(); |
489 | } | 541 | } |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 6ab0027..08c7a58 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -1991,7 +1991,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1991 | try | 1991 | try |
1992 | { | 1992 | { |
1993 | if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart | 1993 | if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart |
1994 | m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things | 1994 | !m_scene.LoginsEnabled || // We're starting up or doing maintenance, don't mess with things |
1995 | m_scene.LoadingPrims) // Land may not be valid yet | 1995 | m_scene.LoadingPrims) // Land may not be valid yet |
1996 | 1996 | ||
1997 | { | 1997 | { |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 89df0ce..628fd20 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -110,15 +110,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
110 | 110 | ||
111 | public UUID currentParcelUUID = UUID.Zero; | 111 | public UUID currentParcelUUID = UUID.Zero; |
112 | 112 | ||
113 | protected ScenePresenceAnimator m_animator; | ||
114 | /// <value> | 113 | /// <value> |
115 | /// The animator for this avatar | 114 | /// The animator for this avatar |
116 | /// </value> | 115 | /// </value> |
117 | public ScenePresenceAnimator Animator | 116 | public ScenePresenceAnimator Animator { get; private set; } |
118 | { | ||
119 | get { return m_animator; } | ||
120 | private set { m_animator = value; } | ||
121 | } | ||
122 | 117 | ||
123 | /// <summary> | 118 | /// <summary> |
124 | /// Attachments recorded on this avatar. | 119 | /// Attachments recorded on this avatar. |
@@ -2761,8 +2756,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2761 | //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); | 2756 | //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); |
2762 | 2757 | ||
2763 | avatar.ControllingClient.SendAvatarDataImmediate(this); | 2758 | avatar.ControllingClient.SendAvatarDataImmediate(this); |
2764 | if (Animator != null) | 2759 | Animator.SendAnimPackToClient(avatar.ControllingClient); |
2765 | Animator.SendAnimPackToClient(avatar.ControllingClient); | ||
2766 | } | 2760 | } |
2767 | 2761 | ||
2768 | /// <summary> | 2762 | /// <summary> |
@@ -3438,6 +3432,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
3438 | if (IsChildAgent) | 3432 | if (IsChildAgent) |
3439 | return; | 3433 | return; |
3440 | 3434 | ||
3435 | //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) | ||
3436 | // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents( | ||
3437 | // as of this comment the interval is set in AddToPhysicalScene | ||
3438 | |||
3439 | // if (m_updateCount > 0) | ||
3440 | // { | ||
3441 | Animator.UpdateMovementAnimations(); | ||
3442 | // m_updateCount--; | ||
3443 | // } | ||
3444 | |||
3441 | CollisionEventUpdate collisionData = (CollisionEventUpdate)e; | 3445 | CollisionEventUpdate collisionData = (CollisionEventUpdate)e; |
3442 | Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; | 3446 | Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; |
3443 | 3447 | ||
@@ -3451,7 +3455,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3451 | // m_lastColCount = coldata.Count; | 3455 | // m_lastColCount = coldata.Count; |
3452 | // } | 3456 | // } |
3453 | 3457 | ||
3454 | if (coldata.Count != 0 && Animator != null) | 3458 | if (coldata.Count != 0) |
3455 | { | 3459 | { |
3456 | switch (Animator.CurrentMovementAnimation) | 3460 | switch (Animator.CurrentMovementAnimation) |
3457 | { | 3461 | { |
@@ -3563,7 +3567,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3563 | ControllingClient.SendHealth(Health); | 3567 | ControllingClient.SendHealth(Health); |
3564 | } | 3568 | } |
3565 | 3569 | ||
3566 | public void Close() | 3570 | protected internal void Close() |
3567 | { | 3571 | { |
3568 | // Clear known regions | 3572 | // Clear known regions |
3569 | KnownRegions = new Dictionary<ulong, string>(); | 3573 | KnownRegions = new Dictionary<ulong, string>(); |
@@ -3579,9 +3583,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3579 | // m_reprioritizationTimer.Dispose(); | 3583 | // m_reprioritizationTimer.Dispose(); |
3580 | 3584 | ||
3581 | RemoveFromPhysicalScene(); | 3585 | RemoveFromPhysicalScene(); |
3582 | if(Animator != null) | ||
3583 | Animator.Close(); | ||
3584 | Animator = null; | ||
3585 | } | 3586 | } |
3586 | 3587 | ||
3587 | public void AddAttachment(SceneObjectGroup gobj) | 3588 | public void AddAttachment(SceneObjectGroup gobj) |
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index d6ff5a2..20919a1 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs | |||
@@ -30,7 +30,7 @@ using System.Collections.Generic; | |||
30 | using System.Timers; | 30 | using System.Timers; |
31 | using OpenMetaverse.Packets; | 31 | using OpenMetaverse.Packets; |
32 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
33 | using OpenSim.Framework.Statistics; | 33 | using OpenSim.Framework.Monitoring; |
34 | using OpenSim.Region.Framework.Interfaces; | 34 | using OpenSim.Region.Framework.Interfaces; |
35 | 35 | ||
36 | namespace OpenSim.Region.Framework.Scenes | 36 | namespace OpenSim.Region.Framework.Scenes |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index 02c45ef..5758869 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs | |||
@@ -53,62 +53,94 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
53 | /// Scene presence tests | 53 | /// Scene presence tests |
54 | /// </summary> | 54 | /// </summary> |
55 | [TestFixture] | 55 | [TestFixture] |
56 | public class ScenePresenceAgentTests | 56 | public class ScenePresenceAgentTests : OpenSimTestCase |
57 | { | 57 | { |
58 | public Scene scene, scene2, scene3; | 58 | // public Scene scene, scene2, scene3; |
59 | public UUID agent1, agent2, agent3; | 59 | // public UUID agent1, agent2, agent3; |
60 | public static Random random; | 60 | // public static Random random; |
61 | public ulong region1,region2,region3; | 61 | // public ulong region1, region2, region3; |
62 | public AgentCircuitData acd1; | 62 | // public AgentCircuitData acd1; |
63 | public SceneObjectGroup sog1, sog2, sog3; | 63 | // public TestClient testclient; |
64 | public TestClient testclient; | 64 | |
65 | 65 | // [TestFixtureSetUp] | |
66 | [TestFixtureSetUp] | 66 | // public void Init() |
67 | public void Init() | 67 | // { |
68 | //// TestHelpers.InMethod(); | ||
69 | //// | ||
70 | //// SceneHelpers sh = new SceneHelpers(); | ||
71 | //// | ||
72 | //// scene = sh.SetupScene("Neighbour x", UUID.Random(), 1000, 1000); | ||
73 | //// scene2 = sh.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000); | ||
74 | //// scene3 = sh.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000); | ||
75 | //// | ||
76 | //// ISharedRegionModule interregionComms = new LocalSimulationConnectorModule(); | ||
77 | //// interregionComms.Initialise(new IniConfigSource()); | ||
78 | //// interregionComms.PostInitialise(); | ||
79 | //// SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), interregionComms); | ||
80 | //// SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), interregionComms); | ||
81 | //// SceneHelpers.SetupSceneModules(scene3, new IniConfigSource(), interregionComms); | ||
82 | // | ||
83 | //// agent1 = UUID.Random(); | ||
84 | //// agent2 = UUID.Random(); | ||
85 | //// agent3 = UUID.Random(); | ||
86 | // | ||
87 | //// region1 = scene.RegionInfo.RegionHandle; | ||
88 | //// region2 = scene2.RegionInfo.RegionHandle; | ||
89 | //// region3 = scene3.RegionInfo.RegionHandle; | ||
90 | // } | ||
91 | |||
92 | [Test] | ||
93 | public void TestCreateRootScenePresence() | ||
68 | { | 94 | { |
69 | TestHelpers.InMethod(); | 95 | TestHelpers.InMethod(); |
96 | // TestHelpers.EnableLogging(); | ||
97 | |||
98 | UUID spUuid = TestHelpers.ParseTail(0x1); | ||
70 | 99 | ||
71 | SceneHelpers sh = new SceneHelpers(); | 100 | TestScene scene = new SceneHelpers().SetupScene(); |
72 | 101 | SceneHelpers.AddScenePresence(scene, spUuid); | |
73 | scene = sh.SetupScene("Neighbour x", UUID.Random(), 1000, 1000); | 102 | |
74 | scene2 = sh.SetupScene("Neighbour x+1", UUID.Random(), 1001, 1000); | 103 | Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null); |
75 | scene3 = sh.SetupScene("Neighbour x-1", UUID.Random(), 999, 1000); | 104 | Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); |
76 | 105 | ||
77 | ISharedRegionModule interregionComms = new LocalSimulationConnectorModule(); | 106 | ScenePresence sp = scene.GetScenePresence(spUuid); |
78 | interregionComms.Initialise(new IniConfigSource()); | 107 | Assert.That(sp, Is.Not.Null); |
79 | interregionComms.PostInitialise(); | 108 | Assert.That(sp.IsChildAgent, Is.False); |
80 | SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), interregionComms); | 109 | Assert.That(sp.UUID, Is.EqualTo(spUuid)); |
81 | SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), interregionComms); | 110 | |
82 | SceneHelpers.SetupSceneModules(scene3, new IniConfigSource(), interregionComms); | 111 | Assert.That(scene.GetScenePresences().Count, Is.EqualTo(1)); |
83 | |||
84 | agent1 = UUID.Random(); | ||
85 | agent2 = UUID.Random(); | ||
86 | agent3 = UUID.Random(); | ||
87 | random = new Random(); | ||
88 | sog1 = SceneHelpers.CreateSceneObject(1, agent1); | ||
89 | scene.AddSceneObject(sog1); | ||
90 | sog2 = SceneHelpers.CreateSceneObject(1, agent1); | ||
91 | scene.AddSceneObject(sog2); | ||
92 | sog3 = SceneHelpers.CreateSceneObject(1, agent1); | ||
93 | scene.AddSceneObject(sog3); | ||
94 | |||
95 | region1 = scene.RegionInfo.RegionHandle; | ||
96 | region2 = scene2.RegionInfo.RegionHandle; | ||
97 | region3 = scene3.RegionInfo.RegionHandle; | ||
98 | } | 112 | } |
99 | 113 | ||
100 | [Test] | 114 | [Test] |
101 | public void TestCloseAgent() | 115 | public void TestCreateDuplicateRootScenePresence() |
102 | { | 116 | { |
103 | TestHelpers.InMethod(); | 117 | TestHelpers.InMethod(); |
104 | // TestHelpers.EnableLogging(); | 118 | // TestHelpers.EnableLogging(); |
105 | 119 | ||
120 | UUID spUuid = TestHelpers.ParseTail(0x1); | ||
121 | |||
106 | TestScene scene = new SceneHelpers().SetupScene(); | 122 | TestScene scene = new SceneHelpers().SetupScene(); |
107 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); | 123 | SceneHelpers.AddScenePresence(scene, spUuid); |
124 | SceneHelpers.AddScenePresence(scene, spUuid); | ||
108 | 125 | ||
109 | Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Not.Null); | 126 | Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(spUuid), Is.Not.Null); |
110 | Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); | 127 | Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); |
111 | 128 | ||
129 | ScenePresence sp = scene.GetScenePresence(spUuid); | ||
130 | Assert.That(sp, Is.Not.Null); | ||
131 | Assert.That(sp.IsChildAgent, Is.False); | ||
132 | Assert.That(sp.UUID, Is.EqualTo(spUuid)); | ||
133 | } | ||
134 | |||
135 | [Test] | ||
136 | public void TestCloseAgent() | ||
137 | { | ||
138 | TestHelpers.InMethod(); | ||
139 | // TestHelpers.EnableLogging(); | ||
140 | |||
141 | TestScene scene = new SceneHelpers().SetupScene(); | ||
142 | ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); | ||
143 | |||
112 | scene.IncomingCloseAgent(sp.UUID); | 144 | scene.IncomingCloseAgent(sp.UUID); |
113 | 145 | ||
114 | Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); | 146 | Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); |
@@ -266,99 +298,99 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
266 | // but things are synchronous among them. So there should be | 298 | // but things are synchronous among them. So there should be |
267 | // 3 threads in here. | 299 | // 3 threads in here. |
268 | //[Test] | 300 | //[Test] |
269 | public void T021_TestCrossToNewRegion() | 301 | // public void T021_TestCrossToNewRegion() |
270 | { | 302 | // { |
271 | TestHelpers.InMethod(); | 303 | // TestHelpers.InMethod(); |
272 | 304 | // | |
273 | scene.RegisterRegionWithGrid(); | 305 | // scene.RegisterRegionWithGrid(); |
274 | scene2.RegisterRegionWithGrid(); | 306 | // scene2.RegisterRegionWithGrid(); |
275 | 307 | // | |
276 | // Adding child agent to region 1001 | 308 | // // Adding child agent to region 1001 |
277 | string reason; | 309 | // string reason; |
278 | scene2.NewUserConnection(acd1,0, out reason); | 310 | // scene2.NewUserConnection(acd1,0, out reason); |
279 | scene2.AddNewClient(testclient, PresenceType.User); | 311 | // scene2.AddNewClient(testclient, PresenceType.User); |
280 | 312 | // | |
281 | ScenePresence presence = scene.GetScenePresence(agent1); | 313 | // ScenePresence presence = scene.GetScenePresence(agent1); |
282 | presence.MakeRootAgent(new Vector3(0,unchecked(Constants.RegionSize-1),0), true); | 314 | // presence.MakeRootAgent(new Vector3(0,unchecked(Constants.RegionSize-1),0), true); |
283 | 315 | // | |
284 | ScenePresence presence2 = scene2.GetScenePresence(agent1); | 316 | // ScenePresence presence2 = scene2.GetScenePresence(agent1); |
285 | 317 | // | |
286 | // Adding neighbour region caps info to presence2 | 318 | // // Adding neighbour region caps info to presence2 |
287 | 319 | // | |
288 | string cap = presence.ControllingClient.RequestClientInfo().CapsPath; | 320 | // string cap = presence.ControllingClient.RequestClientInfo().CapsPath; |
289 | presence2.AddNeighbourRegion(region1, cap); | 321 | // presence2.AddNeighbourRegion(region1, cap); |
290 | 322 | // | |
291 | Assert.That(presence.IsChildAgent, Is.False, "Did not start root in origin region."); | 323 | // Assert.That(presence.IsChildAgent, Is.False, "Did not start root in origin region."); |
292 | Assert.That(presence2.IsChildAgent, Is.True, "Is not a child on destination region."); | 324 | // Assert.That(presence2.IsChildAgent, Is.True, "Is not a child on destination region."); |
293 | 325 | // | |
294 | // Cross to x+1 | 326 | // // Cross to x+1 |
295 | presence.AbsolutePosition = new Vector3(Constants.RegionSize+1,3,100); | 327 | // presence.AbsolutePosition = new Vector3(Constants.RegionSize+1,3,100); |
296 | presence.Update(); | 328 | // presence.Update(); |
297 | 329 | // | |
298 | EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing"); | 330 | // EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing"); |
299 | 331 | // | |
300 | // Mimicking communication between client and server, by waiting OK from client | 332 | // // Mimicking communication between client and server, by waiting OK from client |
301 | // sent by TestClient.CrossRegion call. Originally, this is network comm. | 333 | // // sent by TestClient.CrossRegion call. Originally, this is network comm. |
302 | if (!wh.WaitOne(5000,false)) | 334 | // if (!wh.WaitOne(5000,false)) |
303 | { | 335 | // { |
304 | presence.Update(); | 336 | // presence.Update(); |
305 | if (!wh.WaitOne(8000,false)) | 337 | // if (!wh.WaitOne(8000,false)) |
306 | throw new ArgumentException("1 - Timeout waiting for signal/variable."); | 338 | // throw new ArgumentException("1 - Timeout waiting for signal/variable."); |
307 | } | 339 | // } |
308 | 340 | // | |
309 | // This is a TestClient specific method that fires OnCompleteMovementToRegion event, which | 341 | // // This is a TestClient specific method that fires OnCompleteMovementToRegion event, which |
310 | // would normally be fired after receiving the reply packet from comm. done on the last line. | 342 | // // would normally be fired after receiving the reply packet from comm. done on the last line. |
311 | testclient.CompleteMovement(); | 343 | // testclient.CompleteMovement(); |
312 | 344 | // | |
313 | // Crossings are asynchronous | 345 | // // Crossings are asynchronous |
314 | int timer = 10; | 346 | // int timer = 10; |
315 | 347 | // | |
316 | // Make sure cross hasn't already finished | 348 | // // Make sure cross hasn't already finished |
317 | if (!presence.IsInTransit && !presence.IsChildAgent) | 349 | // if (!presence.IsInTransit && !presence.IsChildAgent) |
318 | { | 350 | // { |
319 | // If not and not in transit yet, give it some more time | 351 | // // If not and not in transit yet, give it some more time |
320 | Thread.Sleep(5000); | 352 | // Thread.Sleep(5000); |
321 | } | 353 | // } |
322 | 354 | // | |
323 | // Enough time, should at least be in transit by now. | 355 | // // Enough time, should at least be in transit by now. |
324 | while (presence.IsInTransit && timer > 0) | 356 | // while (presence.IsInTransit && timer > 0) |
325 | { | 357 | // { |
326 | Thread.Sleep(1000); | 358 | // Thread.Sleep(1000); |
327 | timer-=1; | 359 | // timer-=1; |
328 | } | 360 | // } |
329 | 361 | // | |
330 | Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 2->1."); | 362 | // Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 2->1."); |
331 | Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected."); | 363 | // Assert.That(presence.IsChildAgent, Is.True, "Did not complete region cross as expected."); |
332 | Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent."); | 364 | // Assert.That(presence2.IsChildAgent, Is.False, "Did not receive root status after receiving agent."); |
333 | 365 | // | |
334 | // Cross Back | 366 | // // Cross Back |
335 | presence2.AbsolutePosition = new Vector3(-10, 3, 100); | 367 | // presence2.AbsolutePosition = new Vector3(-10, 3, 100); |
336 | presence2.Update(); | 368 | // presence2.Update(); |
337 | 369 | // | |
338 | if (!wh.WaitOne(5000,false)) | 370 | // if (!wh.WaitOne(5000,false)) |
339 | { | 371 | // { |
340 | presence2.Update(); | 372 | // presence2.Update(); |
341 | if (!wh.WaitOne(8000,false)) | 373 | // if (!wh.WaitOne(8000,false)) |
342 | throw new ArgumentException("2 - Timeout waiting for signal/variable."); | 374 | // throw new ArgumentException("2 - Timeout waiting for signal/variable."); |
343 | } | 375 | // } |
344 | testclient.CompleteMovement(); | 376 | // testclient.CompleteMovement(); |
345 | 377 | // | |
346 | if (!presence2.IsInTransit && !presence2.IsChildAgent) | 378 | // if (!presence2.IsInTransit && !presence2.IsChildAgent) |
347 | { | 379 | // { |
348 | // If not and not in transit yet, give it some more time | 380 | // // If not and not in transit yet, give it some more time |
349 | Thread.Sleep(5000); | 381 | // Thread.Sleep(5000); |
350 | } | 382 | // } |
351 | 383 | // | |
352 | // Enough time, should at least be in transit by now. | 384 | // // Enough time, should at least be in transit by now. |
353 | while (presence2.IsInTransit && timer > 0) | 385 | // while (presence2.IsInTransit && timer > 0) |
354 | { | 386 | // { |
355 | Thread.Sleep(1000); | 387 | // Thread.Sleep(1000); |
356 | timer-=1; | 388 | // timer-=1; |
357 | } | 389 | // } |
358 | 390 | // | |
359 | Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 1->2."); | 391 | // Assert.That(timer,Is.GreaterThan(0),"Timed out waiting to cross 1->2."); |
360 | Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected."); | 392 | // Assert.That(presence2.IsChildAgent, Is.True, "Did not return from region as expected."); |
361 | Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again."); | 393 | // Assert.That(presence.IsChildAgent, Is.False, "Presence was not made root in old region again."); |
362 | } | 394 | // } |
363 | } | 395 | } |
364 | } \ No newline at end of file | 396 | } \ No newline at end of file |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs index a407f01..37b5184 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs | |||
@@ -301,7 +301,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests | |||
301 | sp.AbsolutePosition = preTeleportPosition; | 301 | sp.AbsolutePosition = preTeleportPosition; |
302 | 302 | ||
303 | // Make sceneB refuse CreateAgent | 303 | // Make sceneB refuse CreateAgent |
304 | sceneB.LoginsDisabled = true; | 304 | sceneB.LoginsEnabled = false; |
305 | 305 | ||
306 | sceneA.RequestTeleportLocation( | 306 | sceneA.RequestTeleportLocation( |
307 | sp.ControllingClient, | 307 | sp.ControllingClient, |
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 86f33eb..3b83e58 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs | |||
@@ -38,6 +38,7 @@ using OpenMetaverse; | |||
38 | using OpenMetaverse.Packets; | 38 | using OpenMetaverse.Packets; |
39 | using OpenSim.Framework; | 39 | using OpenSim.Framework; |
40 | using OpenSim.Framework.Client; | 40 | using OpenSim.Framework.Client; |
41 | using OpenSim.Framework.Monitoring; | ||
41 | using OpenSim.Region.Framework.Scenes; | 42 | using OpenSim.Region.Framework.Scenes; |
42 | 43 | ||
43 | namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | 44 | namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server |
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs index a7c5020..9d27386 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCServer.cs | |||
@@ -34,6 +34,7 @@ using System.Text; | |||
34 | using System.Threading; | 34 | using System.Threading; |
35 | using log4net; | 35 | using log4net; |
36 | using OpenSim.Framework; | 36 | using OpenSim.Framework; |
37 | using OpenSim.Framework.Monitoring; | ||
37 | using OpenSim.Region.Framework.Scenes; | 38 | using OpenSim.Region.Framework.Scenes; |
38 | 39 | ||
39 | namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server | 40 | namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server |
diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs index a7ebecc..5fe5948 100644 --- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs | |||
@@ -35,7 +35,7 @@ using Nini.Config; | |||
35 | using OpenMetaverse; | 35 | using OpenMetaverse; |
36 | using OpenSim.Framework; | 36 | using OpenSim.Framework; |
37 | using OpenSim.Framework.Console; | 37 | using OpenSim.Framework.Console; |
38 | using OpenSim.Framework.Statistics; | 38 | using OpenSim.Framework.Monitoring; |
39 | using OpenSim.Region.ClientStack.LindenUDP; | 39 | using OpenSim.Region.ClientStack.LindenUDP; |
40 | using OpenSim.Region.Framework.Interfaces; | 40 | using OpenSim.Region.Framework.Interfaces; |
41 | using OpenSim.Region.Framework.Scenes; | 41 | using OpenSim.Region.Framework.Scenes; |
@@ -82,18 +82,6 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
82 | m_scenes[scene.RegionInfo.RegionID] = scene; | 82 | m_scenes[scene.RegionInfo.RegionID] = scene; |
83 | 83 | ||
84 | scene.AddCommand( | 84 | scene.AddCommand( |
85 | "Comms", this, "image queues clear", | ||
86 | "image queues clear <first-name> <last-name>", | ||
87 | "Clear the image queues (textures downloaded via UDP) for a particular client.", | ||
88 | (mod, cmd) => MainConsole.Instance.Output(HandleImageQueuesClear(cmd))); | ||
89 | |||
90 | scene.AddCommand( | ||
91 | "Comms", this, "image queues show", | ||
92 | "image queues show <first-name> <last-name>", | ||
93 | "Show the image queues (textures downloaded via UDP) for a particular client.", | ||
94 | (mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd))); | ||
95 | |||
96 | scene.AddCommand( | ||
97 | "Comms", this, "show pqueues", | 85 | "Comms", this, "show pqueues", |
98 | "show pqueues [full]", | 86 | "show pqueues [full]", |
99 | "Show priority queue data for each client", | 87 | "Show priority queue data for each client", |
@@ -105,8 +93,15 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
105 | "Comms", this, "show queues", | 93 | "Comms", this, "show queues", |
106 | "show queues [full]", | 94 | "show queues [full]", |
107 | "Show queue data for each client", | 95 | "Show queue data for each client", |
108 | "Without the 'full' option, only root agents are shown." | 96 | "Without the 'full' option, only root agents are shown.\n" |
109 | + " With the 'full' option child agents are also shown.", | 97 | + "With the 'full' option child agents are also shown.\n\n" |
98 | + "Type - Rt is a root (avatar) client whilst cd is a child (neighbour interacting) client.\n" | ||
99 | + "Since Last In - Time in milliseconds since last packet received.\n" | ||
100 | + "Pkts In - Number of packets processed from the client.\n" | ||
101 | + "Pkts Out - Number of packets sent to the client.\n" | ||
102 | + "Pkts Resent - Number of packets resent to the client.\n" | ||
103 | + "Bytes Unacked - Number of bytes transferred to the client that are awaiting acknowledgement.\n" | ||
104 | + "Q Pkts * - Number of packets of various types (land, wind, etc.) to be sent to the client that are waiting for available bandwidth.\n", | ||
110 | (mod, cmd) => MainConsole.Instance.Output(GetQueuesReport(cmd))); | 105 | (mod, cmd) => MainConsole.Instance.Output(GetQueuesReport(cmd))); |
111 | 106 | ||
112 | scene.AddCommand( | 107 | scene.AddCommand( |
@@ -114,6 +109,12 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
114 | "show image queues <first-name> <last-name>", | 109 | "show image queues <first-name> <last-name>", |
115 | "Show the image queues (textures downloaded via UDP) for a particular client.", | 110 | "Show the image queues (textures downloaded via UDP) for a particular client.", |
116 | (mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd))); | 111 | (mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd))); |
112 | |||
113 | scene.AddCommand( | ||
114 | "Comms", this, "clear image queues", | ||
115 | "clear image queues <first-name> <last-name>", | ||
116 | "Clear the image queues (textures downloaded via UDP) for a particular client.", | ||
117 | (mod, cmd) => MainConsole.Instance.Output(HandleImageQueuesClear(cmd))); | ||
117 | 118 | ||
118 | scene.AddCommand( | 119 | scene.AddCommand( |
119 | "Comms", this, "show throttles", | 120 | "Comms", this, "show throttles", |
@@ -373,17 +374,22 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
373 | int maxNameLength = 18; | 374 | int maxNameLength = 18; |
374 | int maxRegionNameLength = 14; | 375 | int maxRegionNameLength = 14; |
375 | int maxTypeLength = 4; | 376 | int maxTypeLength = 4; |
376 | int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding; | 377 | |
378 | int totalInfoFieldsLength | ||
379 | = maxNameLength + columnPadding | ||
380 | + maxRegionNameLength + columnPadding | ||
381 | + maxTypeLength + columnPadding; | ||
377 | 382 | ||
378 | report.Append(GetColumnEntry("User", maxNameLength, columnPadding)); | 383 | report.Append(GetColumnEntry("User", maxNameLength, columnPadding)); |
379 | report.Append(GetColumnEntry("Region", maxRegionNameLength, columnPadding)); | 384 | report.Append(GetColumnEntry("Region", maxRegionNameLength, columnPadding)); |
380 | report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding)); | 385 | report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding)); |
381 | 386 | ||
382 | report.AppendFormat( | 387 | report.AppendFormat( |
383 | "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}\n", | 388 | "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n", |
389 | "Since", | ||
390 | "Pkts", | ||
384 | "Pkts", | 391 | "Pkts", |
385 | "Pkts", | 392 | "Pkts", |
386 | "Pkts", | ||
387 | "Bytes", | 393 | "Bytes", |
388 | "Q Pkts", | 394 | "Q Pkts", |
389 | "Q Pkts", | 395 | "Q Pkts", |
@@ -396,7 +402,8 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
396 | 402 | ||
397 | report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", ""); | 403 | report.AppendFormat("{0,-" + totalInfoFieldsLength + "}", ""); |
398 | report.AppendFormat( | 404 | report.AppendFormat( |
399 | "{0,7} {1,7} {2,7} {3,9} {4,7} {5,7} {6,7} {7,7} {8,7} {9,8} {10,7} {11,7}\n", | 405 | "{0,7} {1,7} {2,7} {3,7} {4,9} {5,7} {6,7} {7,7} {8,7} {9,7} {10,8} {11,7} {12,7}\n", |
406 | "Last In", | ||
400 | "In", | 407 | "In", |
401 | "Out", | 408 | "Out", |
402 | "Resent", | 409 | "Resent", |
@@ -417,22 +424,22 @@ namespace OpenSim.Region.CoreModules.UDP.Linden | |||
417 | scene.ForEachClient( | 424 | scene.ForEachClient( |
418 | delegate(IClientAPI client) | 425 | delegate(IClientAPI client) |
419 | { | 426 | { |
420 | if (client is IStatsCollector) | 427 | bool isChild = client.SceneAgent.IsChildAgent; |
421 | { | 428 | if (isChild && !showChildren) |
422 | bool isChild = client.SceneAgent.IsChildAgent; | 429 | return; |
423 | if (isChild && !showChildren) | 430 | |
424 | return; | 431 | string name = client.Name; |
425 | 432 | if (pname != "" && name != pname) | |
426 | string name = client.Name; | 433 | return; |
427 | if (pname != "" && name != pname) | ||
428 | return; | ||
429 | 434 | ||
430 | string regionName = scene.RegionInfo.RegionName; | 435 | string regionName = scene.RegionInfo.RegionName; |
431 | 436 | ||
432 | report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); | 437 | report.Append(GetColumnEntry(name, maxNameLength, columnPadding)); |
433 | report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding)); | 438 | report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding)); |
434 | report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding)); | 439 | report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding)); |
435 | 440 | ||
441 | if (client is IStatsCollector) | ||
442 | { | ||
436 | IStatsCollector stats = (IStatsCollector)client; | 443 | IStatsCollector stats = (IStatsCollector)client; |
437 | 444 | ||
438 | report.AppendLine(stats.Report()); | 445 | report.AppendLine(stats.Report()); |
diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs index 6bb6729..d718a2f 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs | |||
@@ -36,7 +36,7 @@ using Nini.Config; | |||
36 | using OpenMetaverse; | 36 | using OpenMetaverse; |
37 | using OpenSim.Framework; | 37 | using OpenSim.Framework; |
38 | using OpenSim.Framework.Console; | 38 | using OpenSim.Framework.Console; |
39 | using OpenSim.Framework.Statistics; | 39 | using OpenSim.Framework.Monitoring; |
40 | using OpenSim.Region.ClientStack.LindenUDP; | 40 | using OpenSim.Region.ClientStack.LindenUDP; |
41 | using OpenSim.Region.Framework.Interfaces; | 41 | using OpenSim.Region.Framework.Interfaces; |
42 | using OpenSim.Region.Framework.Scenes; | 42 | using OpenSim.Region.Framework.Scenes; |
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs index 1b9e3ac..d68aabc 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs | |||
@@ -36,7 +36,7 @@ using Nini.Config; | |||
36 | using OpenMetaverse; | 36 | using OpenMetaverse; |
37 | using OpenSim.Framework; | 37 | using OpenSim.Framework; |
38 | using OpenSim.Framework.Console; | 38 | using OpenSim.Framework.Console; |
39 | using OpenSim.Framework.Statistics; | 39 | using OpenSim.Framework.Monitoring; |
40 | using OpenSim.Region.ClientStack.LindenUDP; | 40 | using OpenSim.Region.ClientStack.LindenUDP; |
41 | using OpenSim.Region.Framework.Interfaces; | 41 | using OpenSim.Region.Framework.Interfaces; |
42 | using OpenSim.Region.Framework.Scenes; | 42 | using OpenSim.Region.Framework.Scenes; |
diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs index cd401a6..ca956fb 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs | |||
@@ -37,6 +37,7 @@ using OpenMetaverse; | |||
37 | using log4net; | 37 | using log4net; |
38 | using Nini.Config; | 38 | using Nini.Config; |
39 | using OpenSim.Framework; | 39 | using OpenSim.Framework; |
40 | using OpenSim.Framework.Monitoring; | ||
40 | using OpenSim.Region.Framework.Interfaces; | 41 | using OpenSim.Region.Framework.Interfaces; |
41 | using OpenSim.Region.Framework.Scenes; | 42 | using OpenSim.Region.Framework.Scenes; |
42 | 43 | ||
diff --git a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs index 2602050..4e84364 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs | |||
@@ -37,7 +37,7 @@ using Nini.Config; | |||
37 | using OpenMetaverse; | 37 | using OpenMetaverse; |
38 | using OpenSim.Framework; | 38 | using OpenSim.Framework; |
39 | using OpenSim.Framework.Console; | 39 | using OpenSim.Framework.Console; |
40 | using OpenSim.Framework.Statistics; | 40 | using OpenSim.Framework.Monitoring; |
41 | using OpenSim.Region.ClientStack.LindenUDP; | 41 | using OpenSim.Region.ClientStack.LindenUDP; |
42 | using OpenSim.Region.CoreModules.Avatar.Friends; | 42 | using OpenSim.Region.CoreModules.Avatar.Friends; |
43 | using OpenSim.Region.Framework.Interfaces; | 43 | using OpenSim.Region.Framework.Interfaces; |
diff --git a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs index e452124..40f7fbc 100755 --- a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs +++ b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs | |||
@@ -47,7 +47,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters | |||
47 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PhysicsParameters")] | 47 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "PhysicsParameters")] |
48 | public class PhysicsParameters : ISharedRegionModule | 48 | public class PhysicsParameters : ISharedRegionModule |
49 | { | 49 | { |
50 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 50 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
51 | // private static string LogHeader = "[PHYSICS PARAMETERS]"; | 51 | // private static string LogHeader = "[PHYSICS PARAMETERS]"; |
52 | 52 | ||
53 | private List<Scene> m_scenes = new List<Scene>(); | 53 | private List<Scene> m_scenes = new List<Scene>(); |
diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index 600cafb..fff3a32 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs | |||
@@ -31,16 +31,14 @@ using System.Reflection; | |||
31 | using System.Net; | 31 | using System.Net; |
32 | using System.IO; | 32 | using System.IO; |
33 | using System.Text; | 33 | using System.Text; |
34 | |||
35 | using log4net; | 34 | using log4net; |
36 | using Nini.Config; | 35 | using Nini.Config; |
37 | using OpenMetaverse; | 36 | using OpenMetaverse; |
38 | using OpenMetaverse.StructuredData; | 37 | using OpenMetaverse.StructuredData; |
39 | using OpenSim.Services.Interfaces; | ||
40 | |||
41 | using OpenSim.Framework; | 38 | using OpenSim.Framework; |
42 | using OpenSim.Region.Framework.Interfaces; | 39 | using OpenSim.Region.Framework.Interfaces; |
43 | using OpenSim.Region.Framework.Scenes; | 40 | using OpenSim.Region.Framework.Scenes; |
41 | using OpenSim.Services.Interfaces; | ||
44 | 42 | ||
45 | namespace OpenSim.Region.OptionalModules.Scripting.RegionReady | 43 | namespace OpenSim.Region.OptionalModules.Scripting.RegionReady |
46 | { | 44 | { |
@@ -50,16 +48,15 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady | |||
50 | LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 48 | LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
51 | 49 | ||
52 | private IConfig m_config = null; | 50 | private IConfig m_config = null; |
53 | private bool m_ScriptRez; | ||
54 | private bool m_firstEmptyCompileQueue; | 51 | private bool m_firstEmptyCompileQueue; |
55 | private bool m_oarFileLoading; | 52 | private bool m_oarFileLoading; |
56 | private bool m_lastOarLoadedOk; | 53 | private bool m_lastOarLoadedOk; |
57 | private int m_channelNotify = -1000; | 54 | private int m_channelNotify = -1000; |
58 | private bool m_enabled = false; | 55 | private bool m_enabled = false; |
59 | private bool m_disable_logins = false; | 56 | private bool m_disable_logins; |
60 | private string m_uri = string.Empty; | 57 | private string m_uri = string.Empty; |
61 | 58 | ||
62 | Scene m_scene = null; | 59 | Scene m_scene; |
63 | 60 | ||
64 | #region INonSharedRegionModule interface | 61 | #region INonSharedRegionModule interface |
65 | 62 | ||
@@ -93,53 +90,40 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady | |||
93 | 90 | ||
94 | m_scene.RegisterModuleInterface<IRegionReadyModule>(this); | 91 | m_scene.RegisterModuleInterface<IRegionReadyModule>(this); |
95 | 92 | ||
96 | m_ScriptRez = false; | ||
97 | m_firstEmptyCompileQueue = true; | 93 | m_firstEmptyCompileQueue = true; |
98 | m_oarFileLoading = false; | 94 | m_oarFileLoading = false; |
99 | m_lastOarLoadedOk = true; | 95 | m_lastOarLoadedOk = true; |
100 | 96 | ||
101 | m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; | 97 | m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; |
102 | m_scene.EventManager.OnRezScript += OnRezScript; | ||
103 | m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; | ||
104 | 98 | ||
105 | m_log.DebugFormat("[RegionReady]: Enabled for region {0}", scene.RegionInfo.RegionName); | 99 | m_log.DebugFormat("[RegionReady]: Enabled for region {0}", scene.RegionInfo.RegionName); |
106 | 100 | ||
107 | if (m_disable_logins == true) | 101 | if (m_disable_logins) |
108 | { | 102 | { |
109 | scene.LoginLock = true; | 103 | m_scene.LoginLock = true; |
110 | scene.LoginsDisabled = true; | 104 | m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; |
111 | m_log.InfoFormat("[RegionReady]: Region {0} - logins disabled during initialization.",m_scene.RegionInfo.RegionName); | 105 | |
106 | m_log.InfoFormat("[RegionReady]: Region {0} - LOGINS DISABLED DURING INITIALIZATION.", m_scene.Name); | ||
112 | 107 | ||
113 | if(m_uri != string.Empty) | 108 | if (m_uri != string.Empty) |
114 | { | 109 | { |
115 | RRAlert("disabled"); | 110 | RRAlert("disabled"); |
116 | } | 111 | } |
117 | } | 112 | } |
118 | } | 113 | } |
119 | 114 | ||
120 | void OnRezScript (uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource) | ||
121 | { | ||
122 | if (!m_ScriptRez) | ||
123 | { | ||
124 | m_ScriptRez = true; | ||
125 | m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; | ||
126 | m_scene.EventManager.OnRezScript -= OnRezScript; | ||
127 | } | ||
128 | } | ||
129 | |||
130 | public void RemoveRegion(Scene scene) | 115 | public void RemoveRegion(Scene scene) |
131 | { | 116 | { |
132 | if (!m_enabled) | 117 | if (!m_enabled) |
133 | return; | 118 | return; |
134 | 119 | ||
135 | m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; | ||
136 | m_scene.EventManager.OnOarFileLoaded -= OnOarFileLoaded; | 120 | m_scene.EventManager.OnOarFileLoaded -= OnOarFileLoaded; |
137 | m_scene.EventManager.OnLoginsEnabled -= OnLoginsEnabled; | ||
138 | 121 | ||
139 | if(m_uri != string.Empty) | 122 | if (m_disable_logins) |
140 | { | 123 | m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; |
124 | |||
125 | if (m_uri != string.Empty) | ||
141 | RRAlert("shutdown"); | 126 | RRAlert("shutdown"); |
142 | } | ||
143 | 127 | ||
144 | m_scene = null; | 128 | m_scene = null; |
145 | } | 129 | } |
@@ -159,7 +143,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady | |||
159 | 143 | ||
160 | #endregion | 144 | #endregion |
161 | 145 | ||
162 | |||
163 | void OnEmptyScriptCompileQueue(int numScriptsFailed, string message) | 146 | void OnEmptyScriptCompileQueue(int numScriptsFailed, string message) |
164 | { | 147 | { |
165 | m_log.DebugFormat("[RegionReady]: Script compile queue empty!"); | 148 | m_log.DebugFormat("[RegionReady]: Script compile queue empty!"); |
@@ -193,75 +176,80 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady | |||
193 | m_scene.RegionInfo.RegionName, c.Message, m_channelNotify); | 176 | m_scene.RegionInfo.RegionName, c.Message, m_channelNotify); |
194 | 177 | ||
195 | m_scene.EventManager.TriggerOnChatBroadcast(this, c); | 178 | m_scene.EventManager.TriggerOnChatBroadcast(this, c); |
196 | m_scene.EventManager.TriggerLoginsEnabled(m_scene.RegionInfo.RegionName); | 179 | |
197 | m_scene.SceneGridService.InformNeighborsThatRegionisUp(m_scene.RequestModuleInterface<INeighbourService>(), m_scene.RegionInfo); | 180 | TriggerRegionReady(m_scene); |
198 | } | 181 | } |
199 | } | 182 | } |
200 | 183 | ||
201 | void OnOarFileLoaded(Guid requestId, string message) | 184 | void OnOarFileLoaded(Guid requestId, string message) |
202 | { | 185 | { |
203 | m_oarFileLoading = true; | 186 | m_oarFileLoading = true; |
187 | |||
204 | if (message==String.Empty) | 188 | if (message==String.Empty) |
205 | { | 189 | { |
206 | m_lastOarLoadedOk = true; | 190 | m_lastOarLoadedOk = true; |
207 | } else { | 191 | } |
192 | else | ||
193 | { | ||
208 | m_log.WarnFormat("[RegionReady]: Oar file load errors: {0}", message); | 194 | m_log.WarnFormat("[RegionReady]: Oar file load errors: {0}", message); |
209 | m_lastOarLoadedOk = false; | 195 | m_lastOarLoadedOk = false; |
210 | } | 196 | } |
211 | } | 197 | } |
212 | 198 | ||
213 | // This will be triggerd by Scene if we have no scripts | 199 | /// <summary> |
214 | // m_ScriptsRezzing will be false if there were none | 200 | /// This will be triggered by Scene directly if it contains no scripts on startup. Otherwise it is triggered |
215 | // else it will be true and we should wait on the | 201 | /// when the script compile queue is empty after initial region startup. |
216 | // empty compile queue | 202 | /// </summary> |
217 | void OnLoginsEnabled(string regionName) | 203 | /// <param name='scene'></param> |
204 | public void TriggerRegionReady(IScene scene) | ||
218 | { | 205 | { |
219 | if (m_disable_logins == true) | 206 | m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; |
207 | m_scene.LoginLock = false; | ||
208 | |||
209 | if (!m_scene.StartDisabled) | ||
220 | { | 210 | { |
221 | if (m_scene.StartDisabled == false) | 211 | m_scene.LoginsEnabled = true; |
222 | { | ||
223 | m_scene.LoginsDisabled = false; | ||
224 | m_scene.LoginLock = false; | ||
225 | 212 | ||
226 | m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; | 213 | // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", |
214 | // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); | ||
227 | 215 | ||
228 | // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", | 216 | m_log.InfoFormat( |
229 | // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); | 217 | "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); |
218 | } | ||
230 | 219 | ||
231 | m_log.InfoFormat( | 220 | m_scene.SceneGridService.InformNeighborsThatRegionisUp( |
232 | "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); | 221 | m_scene.RequestModuleInterface<INeighbourService>(), m_scene.RegionInfo); |
233 | 222 | ||
234 | if (m_uri != string.Empty) | 223 | if (m_uri != string.Empty) |
235 | { | 224 | { |
236 | RRAlert("enabled"); | 225 | RRAlert("enabled"); |
237 | } | ||
238 | } | ||
239 | } | 226 | } |
227 | |||
228 | m_scene.Ready = true; | ||
240 | } | 229 | } |
241 | 230 | ||
242 | public void OarLoadingAlert(string msg) | 231 | public void OarLoadingAlert(string msg) |
243 | { | 232 | { |
244 | // Let's bypass this for now until some better feedback can be established | 233 | // Let's bypass this for now until some better feedback can be established |
245 | // | 234 | // |
246 | return; | ||
247 | 235 | ||
248 | if (msg == "load") | 236 | // if (msg == "load") |
249 | { | 237 | // { |
250 | m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; | 238 | // m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; |
251 | m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; | 239 | // m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; |
252 | m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; | 240 | // m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; |
253 | m_scene.EventManager.OnRezScript += OnRezScript; | 241 | // m_scene.EventManager.OnRezScript += OnRezScript; |
254 | m_oarFileLoading = true; | 242 | // m_oarFileLoading = true; |
255 | m_firstEmptyCompileQueue = true; | 243 | // m_firstEmptyCompileQueue = true; |
256 | 244 | // | |
257 | m_scene.LoginsDisabled = true; | 245 | // m_scene.LoginsDisabled = true; |
258 | m_scene.LoginLock = true; | 246 | // m_scene.LoginLock = true; |
259 | if ( m_uri != string.Empty ) | 247 | // if ( m_uri != string.Empty ) |
260 | { | 248 | // { |
261 | RRAlert("loading oar"); | 249 | // RRAlert("loading oar"); |
262 | RRAlert("disabled"); | 250 | // RRAlert("disabled"); |
263 | } | 251 | // } |
264 | } | 252 | // } |
265 | } | 253 | } |
266 | 254 | ||
267 | public void RRAlert(string status) | 255 | public void RRAlert(string status) |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index dc0c008..09e1f0c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -41,7 +41,7 @@ public class BSCharacter : PhysicsActor | |||
41 | 41 | ||
42 | private BSScene _scene; | 42 | private BSScene _scene; |
43 | private String _avName; | 43 | private String _avName; |
44 | private bool _stopped; | 44 | // private bool _stopped; |
45 | private Vector3 _size; | 45 | private Vector3 _size; |
46 | private Vector3 _scale; | 46 | private Vector3 _scale; |
47 | private PrimitiveBaseShape _pbs; | 47 | private PrimitiveBaseShape _pbs; |
@@ -134,9 +134,9 @@ public class BSCharacter : PhysicsActor | |||
134 | { | 134 | { |
135 | base.RequestPhysicsterseUpdate(); | 135 | base.RequestPhysicsterseUpdate(); |
136 | } | 136 | } |
137 | 137 | // No one calls this method so I don't know what it could possibly mean | |
138 | public override bool Stopped { | 138 | public override bool Stopped { |
139 | get { return _stopped; } | 139 | get { return false; } |
140 | } | 140 | } |
141 | public override Vector3 Size { | 141 | public override Vector3 Size { |
142 | get { return _size; } | 142 | get { return _size; } |
@@ -391,52 +391,47 @@ public class BSCharacter : PhysicsActor | |||
391 | _mass = _density * _avatarVolume; | 391 | _mass = _density * _avatarVolume; |
392 | } | 392 | } |
393 | 393 | ||
394 | // Set to 'true' if the individual changed items should be checked | ||
395 | // (someday RequestPhysicsTerseUpdate() will take a bitmap of changed properties) | ||
396 | const bool SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES = false; | ||
397 | |||
398 | // The physics engine says that properties have updated. Update same and inform | 394 | // The physics engine says that properties have updated. Update same and inform |
399 | // the world that things have changed. | 395 | // the world that things have changed. |
400 | public void UpdateProperties(EntityProperties entprop) | 396 | public void UpdateProperties(EntityProperties entprop) |
401 | { | 397 | { |
398 | /* | ||
402 | bool changed = false; | 399 | bool changed = false; |
403 | if (SHOULD_CHECK_FOR_INDIVIDUAL_CHANGES) { | 400 | // we assign to the local variables so the normal set action does not happen |
404 | // we assign to the local variables so the normal set action does not happen | 401 | if (_position != entprop.Position) { |
405 | if (_position != entprop.Position) { | ||
406 | _position = entprop.Position; | ||
407 | changed = true; | ||
408 | } | ||
409 | if (_orientation != entprop.Rotation) { | ||
410 | _orientation = entprop.Rotation; | ||
411 | changed = true; | ||
412 | } | ||
413 | if (_velocity != entprop.Velocity) { | ||
414 | _velocity = entprop.Velocity; | ||
415 | changed = true; | ||
416 | } | ||
417 | if (_acceleration != entprop.Acceleration) { | ||
418 | _acceleration = entprop.Acceleration; | ||
419 | changed = true; | ||
420 | } | ||
421 | if (_rotationalVelocity != entprop.RotationalVelocity) { | ||
422 | _rotationalVelocity = entprop.RotationalVelocity; | ||
423 | changed = true; | ||
424 | } | ||
425 | if (changed) { | ||
426 | // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); | ||
427 | // Avatar movement is not done by generating this event. There is code in the heartbeat | ||
428 | // loop that updates avatars. | ||
429 | // base.RequestPhysicsterseUpdate(); | ||
430 | } | ||
431 | } | ||
432 | else { | ||
433 | _position = entprop.Position; | 402 | _position = entprop.Position; |
403 | changed = true; | ||
404 | } | ||
405 | if (_orientation != entprop.Rotation) { | ||
434 | _orientation = entprop.Rotation; | 406 | _orientation = entprop.Rotation; |
407 | changed = true; | ||
408 | } | ||
409 | if (_velocity != entprop.Velocity) { | ||
435 | _velocity = entprop.Velocity; | 410 | _velocity = entprop.Velocity; |
411 | changed = true; | ||
412 | } | ||
413 | if (_acceleration != entprop.Acceleration) { | ||
436 | _acceleration = entprop.Acceleration; | 414 | _acceleration = entprop.Acceleration; |
415 | changed = true; | ||
416 | } | ||
417 | if (_rotationalVelocity != entprop.RotationalVelocity) { | ||
437 | _rotationalVelocity = entprop.RotationalVelocity; | 418 | _rotationalVelocity = entprop.RotationalVelocity; |
419 | changed = true; | ||
420 | } | ||
421 | if (changed) { | ||
422 | // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); | ||
423 | // Avatar movement is not done by generating this event. There is code in the heartbeat | ||
424 | // loop that updates avatars. | ||
438 | // base.RequestPhysicsterseUpdate(); | 425 | // base.RequestPhysicsterseUpdate(); |
439 | } | 426 | } |
427 | */ | ||
428 | _position = entprop.Position; | ||
429 | _orientation = entprop.Rotation; | ||
430 | _velocity = entprop.Velocity; | ||
431 | _acceleration = entprop.Acceleration; | ||
432 | _rotationalVelocity = entprop.RotationalVelocity; | ||
433 | // Avatars don't report theirr changes the usual way. Changes are checked for in the heartbeat loop. | ||
434 | // base.RequestPhysicsterseUpdate(); | ||
440 | } | 435 | } |
441 | 436 | ||
442 | // Called by the scene when a collision with this object is reported | 437 | // Called by the scene when a collision with this object is reported |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs new file mode 100755 index 0000000..fbb9e21 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs | |||
@@ -0,0 +1,115 @@ | |||
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 | */ | ||
27 | using System; | ||
28 | using System.Collections.Generic; | ||
29 | using System.Text; | ||
30 | using OpenMetaverse; | ||
31 | |||
32 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
33 | { | ||
34 | |||
35 | public class BSConstraint : IDisposable | ||
36 | { | ||
37 | private BulletSim m_world; | ||
38 | private BulletBody m_body1; | ||
39 | private BulletBody m_body2; | ||
40 | private BulletConstraint m_constraint; | ||
41 | private bool m_enabled = false; | ||
42 | |||
43 | public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, | ||
44 | Vector3 frame1, Quaternion frame1rot, | ||
45 | Vector3 frame2, Quaternion frame2rot | ||
46 | ) | ||
47 | { | ||
48 | m_world = world; | ||
49 | m_body1 = obj1; | ||
50 | m_body2 = obj2; | ||
51 | m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, | ||
52 | frame1, frame1rot, | ||
53 | frame2, frame2rot)); | ||
54 | m_enabled = true; | ||
55 | } | ||
56 | |||
57 | public void Dispose() | ||
58 | { | ||
59 | if (m_enabled) | ||
60 | { | ||
61 | // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID); | ||
62 | BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr); | ||
63 | m_enabled = false; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | public BulletBody Body1 { get { return m_body1; } } | ||
68 | public BulletBody Body2 { get { return m_body2; } } | ||
69 | |||
70 | public bool SetLinearLimits(Vector3 low, Vector3 high) | ||
71 | { | ||
72 | bool ret = false; | ||
73 | if (m_enabled) | ||
74 | ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high); | ||
75 | return ret; | ||
76 | } | ||
77 | |||
78 | public bool SetAngularLimits(Vector3 low, Vector3 high) | ||
79 | { | ||
80 | bool ret = false; | ||
81 | if (m_enabled) | ||
82 | ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high); | ||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | public bool UseFrameOffset(bool useOffset) | ||
87 | { | ||
88 | bool ret = false; | ||
89 | float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; | ||
90 | if (m_enabled) | ||
91 | ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff); | ||
92 | return ret; | ||
93 | } | ||
94 | |||
95 | public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce) | ||
96 | { | ||
97 | bool ret = false; | ||
98 | float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; | ||
99 | if (m_enabled) | ||
100 | ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | public bool CalculateTransforms() | ||
105 | { | ||
106 | bool ret = false; | ||
107 | if (m_enabled) | ||
108 | { | ||
109 | BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); | ||
110 | ret = true; | ||
111 | } | ||
112 | return ret; | ||
113 | } | ||
114 | } | ||
115 | } | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs new file mode 100755 index 0000000..a2650fb --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs | |||
@@ -0,0 +1,178 @@ | |||
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 | */ | ||
27 | using System; | ||
28 | using System.Collections.Generic; | ||
29 | using System.Text; | ||
30 | using log4net; | ||
31 | using OpenMetaverse; | ||
32 | |||
33 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
34 | { | ||
35 | |||
36 | public class BSConstraintCollection : IDisposable | ||
37 | { | ||
38 | // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
39 | // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]"; | ||
40 | |||
41 | delegate bool ConstraintAction(BSConstraint constrain); | ||
42 | |||
43 | private List<BSConstraint> m_constraints; | ||
44 | private BulletSim m_world; | ||
45 | |||
46 | public BSConstraintCollection(BulletSim world) | ||
47 | { | ||
48 | m_world = world; | ||
49 | m_constraints = new List<BSConstraint>(); | ||
50 | } | ||
51 | |||
52 | public void Dispose() | ||
53 | { | ||
54 | this.Clear(); | ||
55 | } | ||
56 | |||
57 | public void Clear() | ||
58 | { | ||
59 | foreach (BSConstraint cons in m_constraints) | ||
60 | { | ||
61 | cons.Dispose(); | ||
62 | } | ||
63 | m_constraints.Clear(); | ||
64 | } | ||
65 | |||
66 | public BSConstraint CreateConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, | ||
67 | Vector3 frame1, Quaternion frame1rot, | ||
68 | Vector3 frame2, Quaternion frame2rot) | ||
69 | { | ||
70 | BSConstraint constrain = new BSConstraint(world, obj1, obj2, frame1, frame1rot, frame2, frame2rot); | ||
71 | |||
72 | this.AddConstraint(constrain); | ||
73 | return constrain; | ||
74 | } | ||
75 | |||
76 | public bool AddConstraint(BSConstraint cons) | ||
77 | { | ||
78 | // There is only one constraint between any bodies. Remove any old just to make sure. | ||
79 | RemoveAndDestroyConstraint(cons.Body1, cons.Body2); | ||
80 | |||
81 | m_constraints.Add(cons); | ||
82 | |||
83 | return true; | ||
84 | } | ||
85 | |||
86 | // Get the constraint between two bodies. There can be only one the way we're using them. | ||
87 | public bool TryGetConstraint(BulletBody body1, BulletBody body2, out BSConstraint returnConstraint) | ||
88 | { | ||
89 | bool found = false; | ||
90 | BSConstraint foundConstraint = null; | ||
91 | |||
92 | uint lookingID1 = body1.ID; | ||
93 | uint lookingID2 = body2.ID; | ||
94 | ForEachConstraint(delegate(BSConstraint constrain) | ||
95 | { | ||
96 | if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) | ||
97 | || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1)) | ||
98 | { | ||
99 | foundConstraint = constrain; | ||
100 | found = true; | ||
101 | } | ||
102 | return found; | ||
103 | }); | ||
104 | returnConstraint = foundConstraint; | ||
105 | return found; | ||
106 | } | ||
107 | |||
108 | public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) | ||
109 | { | ||
110 | // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID); | ||
111 | |||
112 | bool ret = false; | ||
113 | BSConstraint constrain; | ||
114 | |||
115 | if (this.TryGetConstraint(body1, body2, out constrain)) | ||
116 | { | ||
117 | // remove the constraint from our collection | ||
118 | m_constraints.Remove(constrain); | ||
119 | // tell the engine that all its structures need to be freed | ||
120 | constrain.Dispose(); | ||
121 | // we destroyed something | ||
122 | ret = true; | ||
123 | } | ||
124 | |||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | public bool RemoveAndDestroyConstraint(BulletBody body1) | ||
129 | { | ||
130 | // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID); | ||
131 | |||
132 | List<BSConstraint> toRemove = new List<BSConstraint>(); | ||
133 | uint lookingID = body1.ID; | ||
134 | ForEachConstraint(delegate(BSConstraint constrain) | ||
135 | { | ||
136 | if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) | ||
137 | { | ||
138 | toRemove.Add(constrain); | ||
139 | } | ||
140 | return false; | ||
141 | }); | ||
142 | lock (m_constraints) | ||
143 | { | ||
144 | foreach (BSConstraint constrain in toRemove) | ||
145 | { | ||
146 | m_constraints.Remove(constrain); | ||
147 | constrain.Dispose(); | ||
148 | } | ||
149 | } | ||
150 | return (toRemove.Count > 0); | ||
151 | } | ||
152 | |||
153 | public bool RecalculateAllConstraints() | ||
154 | { | ||
155 | foreach (BSConstraint constrain in m_constraints) | ||
156 | { | ||
157 | constrain.CalculateTransforms(); | ||
158 | } | ||
159 | return true; | ||
160 | } | ||
161 | |||
162 | // Lock the constraint list and loop through it. | ||
163 | // The constraint action returns 'true' if it wants the loop aborted. | ||
164 | private void ForEachConstraint(ConstraintAction action) | ||
165 | { | ||
166 | lock (m_constraints) | ||
167 | { | ||
168 | foreach (BSConstraint constrain in m_constraints) | ||
169 | { | ||
170 | if (action(constrain)) | ||
171 | break; | ||
172 | } | ||
173 | } | ||
174 | } | ||
175 | |||
176 | |||
177 | } | ||
178 | } | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index eb20eb3..c197e61 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs | |||
@@ -57,7 +57,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
57 | private int frcount = 0; // Used to limit dynamics debug output to | 57 | private int frcount = 0; // Used to limit dynamics debug output to |
58 | // every 100th frame | 58 | // every 100th frame |
59 | 59 | ||
60 | // private BSScene m_parentScene = null; | ||
61 | private BSPrim m_prim; // the prim this dynamic controller belongs to | 60 | private BSPrim m_prim; // the prim this dynamic controller belongs to |
62 | 61 | ||
63 | // Vehicle properties | 62 | // Vehicle properties |
@@ -131,8 +130,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
131 | m_type = Vehicle.TYPE_NONE; | 130 | m_type = Vehicle.TYPE_NONE; |
132 | } | 131 | } |
133 | 132 | ||
134 | internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) | 133 | internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep) |
135 | { | 134 | { |
135 | DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); | ||
136 | switch (pParam) | 136 | switch (pParam) |
137 | { | 137 | { |
138 | case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: | 138 | case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: |
@@ -229,8 +229,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
229 | } | 229 | } |
230 | }//end ProcessFloatVehicleParam | 230 | }//end ProcessFloatVehicleParam |
231 | 231 | ||
232 | internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) | 232 | internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep) |
233 | { | 233 | { |
234 | DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); | ||
234 | switch (pParam) | 235 | switch (pParam) |
235 | { | 236 | { |
236 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: | 237 | case Vehicle.ANGULAR_FRICTION_TIMESCALE: |
@@ -265,6 +266,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
265 | 266 | ||
266 | internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) | 267 | internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) |
267 | { | 268 | { |
269 | DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); | ||
268 | switch (pParam) | 270 | switch (pParam) |
269 | { | 271 | { |
270 | case Vehicle.REFERENCE_FRAME: | 272 | case Vehicle.REFERENCE_FRAME: |
@@ -278,6 +280,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
278 | 280 | ||
279 | internal void ProcessVehicleFlags(int pParam, bool remove) | 281 | internal void ProcessVehicleFlags(int pParam, bool remove) |
280 | { | 282 | { |
283 | DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); | ||
281 | if (remove) | 284 | if (remove) |
282 | { | 285 | { |
283 | if (pParam == -1) | 286 | if (pParam == -1) |
@@ -434,6 +437,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
434 | 437 | ||
435 | internal void ProcessTypeChange(Vehicle pType) | 438 | internal void ProcessTypeChange(Vehicle pType) |
436 | { | 439 | { |
440 | DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); | ||
437 | // Set Defaults For Type | 441 | // Set Defaults For Type |
438 | m_type = pType; | 442 | m_type = pType; |
439 | switch (pType) | 443 | switch (pType) |
@@ -594,11 +598,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
594 | m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); | 598 | m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); |
595 | m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); | 599 | m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); |
596 | break; | 600 | break; |
597 | |||
598 | } | 601 | } |
599 | }//end SetDefaultsForType | 602 | }//end SetDefaultsForType |
600 | 603 | ||
601 | internal void Step(float pTimestep, BSScene pParentScene) | 604 | internal void Step(float pTimestep) |
602 | { | 605 | { |
603 | if (m_type == Vehicle.TYPE_NONE) return; | 606 | if (m_type == Vehicle.TYPE_NONE) return; |
604 | 607 | ||
@@ -606,21 +609,34 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
606 | if (frcount > 100) | 609 | if (frcount > 100) |
607 | frcount = 0; | 610 | frcount = 0; |
608 | 611 | ||
609 | MoveLinear(pTimestep, pParentScene); | 612 | MoveLinear(pTimestep); |
610 | MoveAngular(pTimestep); | 613 | MoveAngular(pTimestep); |
611 | LimitRotation(pTimestep); | 614 | LimitRotation(pTimestep); |
615 | |||
616 | DetailLog("{0},Dynamics,done,pos={1},force={2},velocity={3},angvel={4}", | ||
617 | m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); | ||
612 | }// end Step | 618 | }// end Step |
613 | 619 | ||
614 | private void MoveLinear(float pTimestep, BSScene _pParentScene) | 620 | private void MoveLinear(float pTimestep) |
615 | { | 621 | { |
616 | if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) // requested m_linearMotorDirection is significant | 622 | // requested m_linearMotorDirection is significant |
623 | // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) | ||
624 | if (m_linearMotorDirection.LengthSquared() > 0.0001f) | ||
617 | { | 625 | { |
626 | Vector3 origDir = m_linearMotorDirection; | ||
627 | Vector3 origVel = m_lastLinearVelocityVector; | ||
628 | |||
618 | // add drive to body | 629 | // add drive to body |
619 | Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); | 630 | // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); |
620 | m_lastLinearVelocityVector += (addAmount*10); // lastLinearVelocityVector is the current body velocity vector? | 631 | Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale); |
632 | // lastLinearVelocityVector is the current body velocity vector? | ||
633 | // RA: Not sure what the *10 is for. A correction for pTimestep? | ||
634 | // m_lastLinearVelocityVector += (addAmount*10); | ||
635 | m_lastLinearVelocityVector += addAmount; | ||
621 | 636 | ||
622 | // This will work temporarily, but we really need to compare speed on an axis | 637 | // This will work temporarily, but we really need to compare speed on an axis |
623 | // KF: Limit body velocity to applied velocity? | 638 | // KF: Limit body velocity to applied velocity? |
639 | // Limit the velocity vector to less than the last set linear motor direction | ||
624 | if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) | 640 | if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) |
625 | m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; | 641 | m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; |
626 | if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) | 642 | if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) |
@@ -630,76 +646,93 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
630 | 646 | ||
631 | // decay applied velocity | 647 | // decay applied velocity |
632 | Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); | 648 | Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); |
633 | //Console.WriteLine("decay: " + decayfraction); | ||
634 | m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; | 649 | m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; |
635 | //Console.WriteLine("actual: " + m_linearMotorDirection); | 650 | |
651 | /* | ||
652 | Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale; | ||
653 | m_lastLinearVelocityVector += addAmount; | ||
654 | |||
655 | float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale); | ||
656 | m_linearMotorDirection *= decayfraction; | ||
657 | |||
658 | */ | ||
659 | |||
660 | DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", | ||
661 | m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); | ||
636 | } | 662 | } |
637 | else | 663 | else |
638 | { // requested is not significant | 664 | { |
639 | // if what remains of applied is small, zero it. | 665 | // if what remains of applied is small, zero it. |
640 | if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) | 666 | // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) |
641 | m_lastLinearVelocityVector = Vector3.Zero; | 667 | // m_lastLinearVelocityVector = Vector3.Zero; |
668 | m_linearMotorDirection = Vector3.Zero; | ||
669 | m_lastLinearVelocityVector = Vector3.Zero; | ||
642 | } | 670 | } |
643 | 671 | ||
644 | // convert requested object velocity to world-referenced vector | 672 | // convert requested object velocity to world-referenced vector |
645 | m_dir = m_lastLinearVelocityVector; | 673 | Quaternion rotq = m_prim.Orientation; |
646 | Quaternion rot = m_prim.Orientation; | 674 | m_dir = m_lastLinearVelocityVector * rotq; |
647 | Quaternion rotq = new Quaternion(rot.X, rot.Y, rot.Z, rot.W); // rotq = rotation of object | 675 | |
648 | m_dir *= rotq; // apply obj rotation to velocity vector | 676 | // Add the various forces into m_dir which will be our new direction vector (velocity) |
649 | 677 | ||
650 | // add Gravity andBuoyancy | 678 | // add Gravity and Buoyancy |
651 | // KF: So far I have found no good method to combine a script-requested | 679 | // KF: So far I have found no good method to combine a script-requested |
652 | // .Z velocity and gravity. Therefore only 0g will used script-requested | 680 | // .Z velocity and gravity. Therefore only 0g will used script-requested |
653 | // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. | 681 | // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. |
654 | Vector3 grav = Vector3.Zero; | 682 | Vector3 grav = Vector3.Zero; |
655 | // There is some gravity, make a gravity force vector | 683 | // There is some gravity, make a gravity force vector that is applied after object velocity. |
656 | // that is applied after object velocity. | ||
657 | float objMass = m_prim.Mass; | ||
658 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; | 684 | // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; |
659 | grav.Z = _pParentScene.DefaultGravity.Z * objMass * (1f - m_VehicleBuoyancy); | 685 | grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy); |
660 | // Preserve the current Z velocity | 686 | // Preserve the current Z velocity |
661 | Vector3 vel_now = m_prim.Velocity; | 687 | Vector3 vel_now = m_prim.Velocity; |
662 | m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity | 688 | m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity |
663 | 689 | ||
664 | Vector3 pos = m_prim.Position; | 690 | Vector3 pos = m_prim.Position; |
691 | Vector3 posChange = pos; | ||
665 | // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); | 692 | // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); |
666 | Vector3 posChange = new Vector3(); | ||
667 | posChange.X = pos.X - m_lastPositionVector.X; | ||
668 | posChange.Y = pos.Y - m_lastPositionVector.Y; | ||
669 | posChange.Z = pos.Z - m_lastPositionVector.Z; | ||
670 | double Zchange = Math.Abs(posChange.Z); | 693 | double Zchange = Math.Abs(posChange.Z); |
671 | if (m_BlockingEndPoint != Vector3.Zero) | 694 | if (m_BlockingEndPoint != Vector3.Zero) |
672 | { | 695 | { |
696 | bool changed = false; | ||
673 | if (pos.X >= (m_BlockingEndPoint.X - (float)1)) | 697 | if (pos.X >= (m_BlockingEndPoint.X - (float)1)) |
674 | { | 698 | { |
675 | pos.X -= posChange.X + 1; | 699 | pos.X -= posChange.X + 1; |
676 | m_prim.Position = pos; | 700 | changed = true; |
677 | } | 701 | } |
678 | if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) | 702 | if (pos.Y >= (m_BlockingEndPoint.Y - (float)1)) |
679 | { | 703 | { |
680 | pos.Y -= posChange.Y + 1; | 704 | pos.Y -= posChange.Y + 1; |
681 | m_prim.Position = pos; | 705 | changed = true; |
682 | } | 706 | } |
683 | if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) | 707 | if (pos.Z >= (m_BlockingEndPoint.Z - (float)1)) |
684 | { | 708 | { |
685 | pos.Z -= posChange.Z + 1; | 709 | pos.Z -= posChange.Z + 1; |
686 | m_prim.Position = pos; | 710 | changed = true; |
687 | } | 711 | } |
688 | if (pos.X <= 0) | 712 | if (pos.X <= 0) |
689 | { | 713 | { |
690 | pos.X += posChange.X + 1; | 714 | pos.X += posChange.X + 1; |
691 | m_prim.Position = pos; | 715 | changed = true; |
692 | } | 716 | } |
693 | if (pos.Y <= 0) | 717 | if (pos.Y <= 0) |
694 | { | 718 | { |
695 | pos.Y += posChange.Y + 1; | 719 | pos.Y += posChange.Y + 1; |
720 | changed = true; | ||
721 | } | ||
722 | if (changed) | ||
723 | { | ||
696 | m_prim.Position = pos; | 724 | m_prim.Position = pos; |
725 | DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", | ||
726 | m_prim.LocalID, m_BlockingEndPoint, posChange, pos); | ||
697 | } | 727 | } |
698 | } | 728 | } |
699 | if (pos.Z < _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y)) | 729 | |
730 | // If below the terrain, move us above the ground a little. | ||
731 | if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos)) | ||
700 | { | 732 | { |
701 | pos.Z = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + 2; | 733 | pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2; |
702 | m_prim.Position = pos; | 734 | m_prim.Position = pos; |
735 | DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); | ||
703 | } | 736 | } |
704 | 737 | ||
705 | // Check if hovering | 738 | // Check if hovering |
@@ -708,11 +741,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
708 | // We should hover, get the target height | 741 | // We should hover, get the target height |
709 | if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) | 742 | if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) |
710 | { | 743 | { |
711 | m_VhoverTargetHeight = _pParentScene.GetWaterLevel() + m_VhoverHeight; | 744 | m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; |
712 | } | 745 | } |
713 | if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) | 746 | if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) |
714 | { | 747 | { |
715 | m_VhoverTargetHeight = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; | 748 | m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; |
716 | } | 749 | } |
717 | if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) | 750 | if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) |
718 | { | 751 | { |
@@ -746,6 +779,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
746 | } | 779 | } |
747 | } | 780 | } |
748 | 781 | ||
782 | DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); | ||
783 | |||
749 | // m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped | 784 | // m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped |
750 | // m_VhoverTimescale = 0f; // time to acheive height | 785 | // m_VhoverTimescale = 0f; // time to acheive height |
751 | // pTimestep is time since last frame,in secs | 786 | // pTimestep is time since last frame,in secs |
@@ -774,12 +809,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
774 | { | 809 | { |
775 | grav.Z = (float)(grav.Z * 1.125); | 810 | grav.Z = (float)(grav.Z * 1.125); |
776 | } | 811 | } |
777 | float terraintemp = _pParentScene.GetTerrainHeightAtXY(pos.X, pos.Y); | 812 | float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos); |
778 | float postemp = (pos.Z - terraintemp); | 813 | float postemp = (pos.Z - terraintemp); |
779 | if (postemp > 2.5f) | 814 | if (postemp > 2.5f) |
780 | { | 815 | { |
781 | grav.Z = (float)(grav.Z * 1.037125); | 816 | grav.Z = (float)(grav.Z * 1.037125); |
782 | } | 817 | } |
818 | DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); | ||
783 | //End Experimental Values | 819 | //End Experimental Values |
784 | } | 820 | } |
785 | if ((m_flags & (VehicleFlag.NO_X)) != 0) | 821 | if ((m_flags & (VehicleFlag.NO_X)) != 0) |
@@ -800,32 +836,39 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
800 | // Apply velocity | 836 | // Apply velocity |
801 | m_prim.Velocity = m_dir; | 837 | m_prim.Velocity = m_dir; |
802 | // apply gravity force | 838 | // apply gravity force |
803 | m_prim.Force = grav; | 839 | // Why is this set here? The physics engine already does gravity. |
804 | 840 | // m_prim.AddForce(grav, false); | |
841 | // m_prim.Force = grav; | ||
805 | 842 | ||
806 | // apply friction | 843 | // Apply friction |
807 | Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); | 844 | Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); |
808 | m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; | 845 | m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; |
846 | |||
847 | DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", | ||
848 | m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); | ||
849 | |||
809 | } // end MoveLinear() | 850 | } // end MoveLinear() |
810 | 851 | ||
811 | private void MoveAngular(float pTimestep) | 852 | private void MoveAngular(float pTimestep) |
812 | { | 853 | { |
813 | /* | 854 | // m_angularMotorDirection // angular velocity requested by LSL motor |
814 | private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor | 855 | // m_angularMotorApply // application frame counter |
815 | private int m_angularMotorApply = 0; // application frame counter | 856 | // m_angularMotorVelocity // current angular motor velocity (ramps up and down) |
816 | private float m_angularMotorVelocity = 0; // current angular motor velocity (ramps up and down) | 857 | // m_angularMotorTimescale // motor angular velocity ramp up rate |
817 | private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate | 858 | // m_angularMotorDecayTimescale // motor angular velocity decay rate |
818 | private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate | 859 | // m_angularFrictionTimescale // body angular velocity decay rate |
819 | private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate | 860 | // m_lastAngularVelocity // what was last applied to body |
820 | private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body | ||
821 | */ | ||
822 | 861 | ||
823 | // Get what the body is doing, this includes 'external' influences | 862 | // Get what the body is doing, this includes 'external' influences |
824 | Vector3 angularVelocity = m_prim.RotationalVelocity; | 863 | Vector3 angularVelocity = m_prim.RotationalVelocity; |
825 | // Vector3 angularVelocity = Vector3.Zero; | ||
826 | 864 | ||
827 | if (m_angularMotorApply > 0) | 865 | if (m_angularMotorApply > 0) |
828 | { | 866 | { |
867 | // Rather than snapping the angular motor velocity from the old value to | ||
868 | // a newly set velocity, this routine steps the value from the previous | ||
869 | // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection). | ||
870 | // There are m_angularMotorApply steps. | ||
871 | Vector3 origAngularVelocity = m_angularMotorVelocity; | ||
829 | // ramp up to new value | 872 | // ramp up to new value |
830 | // current velocity += error / (time to get there / step interval) | 873 | // current velocity += error / (time to get there / step interval) |
831 | // requested speed - last motor speed | 874 | // requested speed - last motor speed |
@@ -833,23 +876,21 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
833 | m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); | 876 | m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); |
834 | m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); | 877 | m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); |
835 | 878 | ||
879 | DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", | ||
880 | m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); | ||
881 | |||
836 | m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected | 882 | m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected |
837 | // velocity may still be acheived. | 883 | // velocity may still be acheived. |
838 | } | 884 | } |
839 | else | 885 | else |
840 | { | 886 | { |
841 | // no motor recently applied, keep the body velocity | 887 | // No motor recently applied, keep the body velocity |
842 | /* m_angularMotorVelocity.X = angularVelocity.X; | ||
843 | m_angularMotorVelocity.Y = angularVelocity.Y; | ||
844 | m_angularMotorVelocity.Z = angularVelocity.Z; */ | ||
845 | |||
846 | // and decay the velocity | 888 | // and decay the velocity |
847 | m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); | 889 | m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); |
848 | } // end motor section | 890 | } // end motor section |
849 | 891 | ||
850 | // Vertical attractor section | 892 | // Vertical attractor section |
851 | Vector3 vertattr = Vector3.Zero; | 893 | Vector3 vertattr = Vector3.Zero; |
852 | |||
853 | if (m_verticalAttractionTimescale < 300) | 894 | if (m_verticalAttractionTimescale < 300) |
854 | { | 895 | { |
855 | float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); | 896 | float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); |
@@ -871,7 +912,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
871 | // Error is 0 (no error) to +/- 2 (max error) | 912 | // Error is 0 (no error) to +/- 2 (max error) |
872 | // scale it by VAservo | 913 | // scale it by VAservo |
873 | verterr = verterr * VAservo; | 914 | verterr = verterr * VAservo; |
874 | //if (frcount == 0) Console.WriteLine("VAerr=" + verterr); | ||
875 | 915 | ||
876 | // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so | 916 | // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so |
877 | // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. | 917 | // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. |
@@ -884,11 +924,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
884 | vertattr.X += bounce * angularVelocity.X; | 924 | vertattr.X += bounce * angularVelocity.X; |
885 | vertattr.Y += bounce * angularVelocity.Y; | 925 | vertattr.Y += bounce * angularVelocity.Y; |
886 | 926 | ||
927 | DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", | ||
928 | m_prim.LocalID, verterr, bounce, vertattr); | ||
929 | |||
887 | } // else vertical attractor is off | 930 | } // else vertical attractor is off |
888 | 931 | ||
889 | // m_lastVertAttractor = vertattr; | 932 | // m_lastVertAttractor = vertattr; |
890 | 933 | ||
891 | // Bank section tba | 934 | // Bank section tba |
935 | |||
892 | // Deflection section tba | 936 | // Deflection section tba |
893 | 937 | ||
894 | // Sum velocities | 938 | // Sum velocities |
@@ -898,11 +942,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
898 | { | 942 | { |
899 | m_lastAngularVelocity.X = 0; | 943 | m_lastAngularVelocity.X = 0; |
900 | m_lastAngularVelocity.Y = 0; | 944 | m_lastAngularVelocity.Y = 0; |
945 | DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); | ||
901 | } | 946 | } |
902 | 947 | ||
903 | if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) | 948 | if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) |
904 | { | 949 | { |
905 | m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. | 950 | m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. |
951 | DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); | ||
906 | } | 952 | } |
907 | 953 | ||
908 | // apply friction | 954 | // apply friction |
@@ -912,10 +958,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
912 | // Apply to the body | 958 | // Apply to the body |
913 | m_prim.RotationalVelocity = m_lastAngularVelocity; | 959 | m_prim.RotationalVelocity = m_lastAngularVelocity; |
914 | 960 | ||
961 | DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity); | ||
915 | } //end MoveAngular | 962 | } //end MoveAngular |
963 | |||
916 | internal void LimitRotation(float timestep) | 964 | internal void LimitRotation(float timestep) |
917 | { | 965 | { |
918 | Quaternion rotq = m_prim.Orientation; // rotq = rotation of object | 966 | Quaternion rotq = m_prim.Orientation; |
919 | Quaternion m_rot = rotq; | 967 | Quaternion m_rot = rotq; |
920 | bool changed = false; | 968 | bool changed = false; |
921 | if (m_RollreferenceFrame != Quaternion.Identity) | 969 | if (m_RollreferenceFrame != Quaternion.Identity) |
@@ -923,18 +971,22 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
923 | if (rotq.X >= m_RollreferenceFrame.X) | 971 | if (rotq.X >= m_RollreferenceFrame.X) |
924 | { | 972 | { |
925 | m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); | 973 | m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); |
974 | changed = true; | ||
926 | } | 975 | } |
927 | if (rotq.Y >= m_RollreferenceFrame.Y) | 976 | if (rotq.Y >= m_RollreferenceFrame.Y) |
928 | { | 977 | { |
929 | m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); | 978 | m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); |
979 | changed = true; | ||
930 | } | 980 | } |
931 | if (rotq.X <= -m_RollreferenceFrame.X) | 981 | if (rotq.X <= -m_RollreferenceFrame.X) |
932 | { | 982 | { |
933 | m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); | 983 | m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); |
984 | changed = true; | ||
934 | } | 985 | } |
935 | if (rotq.Y <= -m_RollreferenceFrame.Y) | 986 | if (rotq.Y <= -m_RollreferenceFrame.Y) |
936 | { | 987 | { |
937 | m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); | 988 | m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); |
989 | changed = true; | ||
938 | } | 990 | } |
939 | changed = true; | 991 | changed = true; |
940 | } | 992 | } |
@@ -944,8 +996,23 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
944 | m_rot.Y = 0; | 996 | m_rot.Y = 0; |
945 | changed = true; | 997 | changed = true; |
946 | } | 998 | } |
999 | if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) | ||
1000 | { | ||
1001 | m_rot.X = 0; | ||
1002 | m_rot.Y = 0; | ||
1003 | changed = true; | ||
1004 | } | ||
947 | if (changed) | 1005 | if (changed) |
948 | m_prim.Orientation = m_rot; | 1006 | m_prim.Orientation = m_rot; |
1007 | |||
1008 | DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot); | ||
1009 | } | ||
1010 | |||
1011 | // Invoke the detailed logger and output something if it's enabled. | ||
1012 | private void DetailLog(string msg, params Object[] args) | ||
1013 | { | ||
1014 | if (m_prim.Scene.VehicleLoggingEnabled) | ||
1015 | m_prim.Scene.PhysicsLogging.Write(msg, args); | ||
949 | } | 1016 | } |
950 | } | 1017 | } |
951 | } | 1018 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs new file mode 100755 index 0000000..3bc2100 --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -0,0 +1,308 @@ | |||
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 | */ | ||
27 | using System; | ||
28 | using System.Collections.Generic; | ||
29 | using System.Text; | ||
30 | |||
31 | using OMV = OpenMetaverse; | ||
32 | |||
33 | namespace OpenSim.Region.Physics.BulletSPlugin | ||
34 | { | ||
35 | public class BSLinkset | ||
36 | { | ||
37 | private static string LogHeader = "[BULLETSIM LINKSET]"; | ||
38 | |||
39 | private BSPrim m_linksetRoot; | ||
40 | public BSPrim Root { get { return m_linksetRoot; } } | ||
41 | |||
42 | private BSScene m_scene; | ||
43 | |||
44 | private List<BSPrim> m_children; | ||
45 | |||
46 | // We lock the diddling of linkset classes to prevent any badness. | ||
47 | // This locks the modification of the instances of this class. Changes | ||
48 | // to the physical representation is done via the tainting mechenism. | ||
49 | private object m_linksetActivityLock = new Object(); | ||
50 | |||
51 | // We keep the prim's mass in the linkset structure since it could be dependent on other prims | ||
52 | private float m_mass; | ||
53 | public float LinksetMass | ||
54 | { | ||
55 | get | ||
56 | { | ||
57 | m_mass = ComputeLinksetMass(); | ||
58 | return m_mass; | ||
59 | } | ||
60 | } | ||
61 | |||
62 | public OMV.Vector3 CenterOfMass | ||
63 | { | ||
64 | get { return ComputeLinksetCenterOfMass(); } | ||
65 | } | ||
66 | |||
67 | public OMV.Vector3 GeometricCenter | ||
68 | { | ||
69 | get { return ComputeLinksetGeometricCenter(); } | ||
70 | } | ||
71 | |||
72 | public BSLinkset(BSScene scene, BSPrim parent) | ||
73 | { | ||
74 | // A simple linkset of one (no children) | ||
75 | m_scene = scene; | ||
76 | m_linksetRoot = parent; | ||
77 | m_children = new List<BSPrim>(); | ||
78 | m_mass = parent.MassRaw; | ||
79 | } | ||
80 | |||
81 | // Link to a linkset where the child knows the parent. | ||
82 | // Parent changing should not happen so do some sanity checking. | ||
83 | // We return the parent's linkset so the child can track it's membership. | ||
84 | public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent) | ||
85 | { | ||
86 | lock (m_linksetActivityLock) | ||
87 | { | ||
88 | parent.Linkset.AddChildToLinkset(child); | ||
89 | } | ||
90 | return parent.Linkset; | ||
91 | } | ||
92 | |||
93 | public BSLinkset RemoveMeFromLinkset(BSPrim child) | ||
94 | { | ||
95 | lock (m_linksetActivityLock) | ||
96 | { | ||
97 | if (IsRoot(child)) | ||
98 | { | ||
99 | // if root of linkset, take the linkset apart | ||
100 | while (m_children.Count > 0) | ||
101 | { | ||
102 | // Note that we don't do a foreach because the remove routine | ||
103 | // takes it out of the list. | ||
104 | RemoveChildFromLinkset(m_children[0]); | ||
105 | } | ||
106 | m_children.Clear(); // just to make sure | ||
107 | } | ||
108 | else | ||
109 | { | ||
110 | // Just removing a child from an existing linkset | ||
111 | RemoveChildFromLinkset(child); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | // The child is down to a linkset of just itself | ||
116 | return new BSLinkset(m_scene, child); | ||
117 | } | ||
118 | |||
119 | // An existing linkset had one of its members rebuilt or something. | ||
120 | // Undo all the physical linking and rebuild the physical linkset. | ||
121 | public bool RefreshLinkset(BSPrim requestor) | ||
122 | { | ||
123 | return true; | ||
124 | } | ||
125 | |||
126 | |||
127 | // Return 'true' if the passed object is the root object of this linkset | ||
128 | public bool IsRoot(BSPrim requestor) | ||
129 | { | ||
130 | return (requestor.LocalID == m_linksetRoot.LocalID); | ||
131 | } | ||
132 | |||
133 | // Return 'true' if this linkset has any children (more than the root member) | ||
134 | public bool HasAnyChildren { get { return (m_children.Count > 0); } } | ||
135 | |||
136 | // Return 'true' if this child is in this linkset | ||
137 | public bool HasChild(BSPrim child) | ||
138 | { | ||
139 | bool ret = false; | ||
140 | foreach (BSPrim bp in m_children) | ||
141 | { | ||
142 | if (child.LocalID == bp.LocalID) | ||
143 | { | ||
144 | ret = true; | ||
145 | break; | ||
146 | } | ||
147 | } | ||
148 | return ret; | ||
149 | } | ||
150 | |||
151 | private float ComputeLinksetMass() | ||
152 | { | ||
153 | float mass = m_linksetRoot.MassRaw; | ||
154 | foreach (BSPrim bp in m_children) | ||
155 | { | ||
156 | mass += bp.MassRaw; | ||
157 | } | ||
158 | return mass; | ||
159 | } | ||
160 | |||
161 | private OMV.Vector3 ComputeLinksetCenterOfMass() | ||
162 | { | ||
163 | OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; | ||
164 | float totalMass = m_linksetRoot.MassRaw; | ||
165 | |||
166 | foreach (BSPrim bp in m_children) | ||
167 | { | ||
168 | com += bp.Position * bp.MassRaw; | ||
169 | totalMass += bp.MassRaw; | ||
170 | } | ||
171 | com /= totalMass; | ||
172 | |||
173 | return com; | ||
174 | } | ||
175 | |||
176 | private OMV.Vector3 ComputeLinksetGeometricCenter() | ||
177 | { | ||
178 | OMV.Vector3 com = m_linksetRoot.Position; | ||
179 | |||
180 | foreach (BSPrim bp in m_children) | ||
181 | { | ||
182 | com += bp.Position * bp.MassRaw; | ||
183 | } | ||
184 | com /= m_children.Count + 1; | ||
185 | |||
186 | return com; | ||
187 | } | ||
188 | |||
189 | // I am the root of a linkset and a new child is being added | ||
190 | public void AddChildToLinkset(BSPrim pchild) | ||
191 | { | ||
192 | BSPrim child = pchild; | ||
193 | if (!HasChild(child)) | ||
194 | { | ||
195 | m_children.Add(child); | ||
196 | |||
197 | m_scene.TaintedObject(delegate() | ||
198 | { | ||
199 | DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); | ||
200 | DetailLog("{0},AddChildToLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); | ||
201 | PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child | ||
202 | }); | ||
203 | } | ||
204 | return; | ||
205 | } | ||
206 | |||
207 | // I am the root of a linkset and one of my children is being removed. | ||
208 | // Safe to call even if the child is not really in my linkset. | ||
209 | public void RemoveChildFromLinkset(BSPrim pchild) | ||
210 | { | ||
211 | BSPrim child = pchild; | ||
212 | |||
213 | if (m_children.Remove(child)) | ||
214 | { | ||
215 | m_scene.TaintedObject(delegate() | ||
216 | { | ||
217 | DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); | ||
218 | DetailLog("{0},RemoveChildFromLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); | ||
219 | |||
220 | if (m_children.Count == 0) | ||
221 | { | ||
222 | // if the linkset is empty, make sure all linkages have been removed | ||
223 | PhysicallyUnlinkAllChildrenFromRoot(); | ||
224 | } | ||
225 | else | ||
226 | { | ||
227 | PhysicallyUnlinkAChildFromRoot(pchild); | ||
228 | } | ||
229 | }); | ||
230 | } | ||
231 | else | ||
232 | { | ||
233 | // This will happen if we remove the root of the linkset first. Non-fatal occurance. | ||
234 | // m_scene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); | ||
235 | } | ||
236 | return; | ||
237 | } | ||
238 | |||
239 | // Create a constraint between me (root of linkset) and the passed prim (the child). | ||
240 | // Called at taint time! | ||
241 | private void PhysicallyLinkAChildToRoot(BSPrim childPrim) | ||
242 | { | ||
243 | // Zero motion for children so they don't interpolate | ||
244 | childPrim.ZeroMotion(); | ||
245 | |||
246 | // relative position normalized to the root prim | ||
247 | OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation); | ||
248 | OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation; | ||
249 | |||
250 | // relative rotation of the child to the parent | ||
251 | OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; | ||
252 | |||
253 | // create a constraint that allows no freedom of movement between the two objects | ||
254 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | ||
255 | // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); | ||
256 | DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); | ||
257 | BSConstraint constrain = m_scene.Constraints.CreateConstraint( | ||
258 | m_scene.World, m_linksetRoot.Body, childPrim.Body, | ||
259 | childRelativePosition, | ||
260 | childRelativeRotation, | ||
261 | OMV.Vector3.Zero, | ||
262 | OMV.Quaternion.Identity); | ||
263 | constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); | ||
264 | constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); | ||
265 | |||
266 | // tweek the constraint to increase stability | ||
267 | constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset)); | ||
268 | constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor), | ||
269 | m_scene.Params.linkConstraintTransMotorMaxVel, | ||
270 | m_scene.Params.linkConstraintTransMotorMaxForce); | ||
271 | |||
272 | } | ||
273 | |||
274 | // Remove linkage between myself and a particular child | ||
275 | // Called at taint time! | ||
276 | private void PhysicallyUnlinkAChildFromRoot(BSPrim childPrim) | ||
277 | { | ||
278 | DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", | ||
279 | LogHeader, m_linksetRoot.LocalID, childPrim.LocalID); | ||
280 | DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); | ||
281 | // BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID); | ||
282 | m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body, childPrim.Body); | ||
283 | } | ||
284 | |||
285 | // Remove linkage between myself and any possible children I might have | ||
286 | // Called at taint time! | ||
287 | private void PhysicallyUnlinkAllChildrenFromRoot() | ||
288 | { | ||
289 | // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); | ||
290 | DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID); | ||
291 | m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body); | ||
292 | // BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); | ||
293 | } | ||
294 | |||
295 | // Invoke the detailed logger and output something if it's enabled. | ||
296 | private void DebugLog(string msg, params Object[] args) | ||
297 | { | ||
298 | m_scene.Logger.DebugFormat(msg, args); | ||
299 | } | ||
300 | |||
301 | // Invoke the detailed logger and output something if it's enabled. | ||
302 | private void DetailLog(string msg, params Object[] args) | ||
303 | { | ||
304 | m_scene.PhysicsLogging.Write(msg, args); | ||
305 | } | ||
306 | |||
307 | } | ||
308 | } | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 130f1ca..7590d93 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -42,6 +42,8 @@ public sealed class BSPrim : PhysicsActor | |||
42 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 42 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
43 | private static readonly string LogHeader = "[BULLETS PRIM]"; | 43 | private static readonly string LogHeader = "[BULLETS PRIM]"; |
44 | 44 | ||
45 | private void DebugLog(string mm, params Object[] xx) { if (_scene.shouldDebugLog) m_log.DebugFormat(mm, xx); } | ||
46 | |||
45 | private IMesh _mesh; | 47 | private IMesh _mesh; |
46 | private PrimitiveBaseShape _pbs; | 48 | private PrimitiveBaseShape _pbs; |
47 | private ShapeData.PhysicsShapeType _shapeType; | 49 | private ShapeData.PhysicsShapeType _shapeType; |
@@ -50,6 +52,7 @@ public sealed class BSPrim : PhysicsActor | |||
50 | private List<ConvexResult> _hulls; | 52 | private List<ConvexResult> _hulls; |
51 | 53 | ||
52 | private BSScene _scene; | 54 | private BSScene _scene; |
55 | public BSScene Scene { get { return _scene; } } | ||
53 | private String _avName; | 56 | private String _avName; |
54 | private uint _localID = 0; | 57 | private uint _localID = 0; |
55 | 58 | ||
@@ -63,7 +66,7 @@ public sealed class BSPrim : PhysicsActor | |||
63 | private bool _isSelected; | 66 | private bool _isSelected; |
64 | private bool _isVolumeDetect; | 67 | private bool _isVolumeDetect; |
65 | private OMV.Vector3 _position; | 68 | private OMV.Vector3 _position; |
66 | private float _mass; | 69 | private float _mass; // the mass of this object |
67 | private float _density; | 70 | private float _density; |
68 | private OMV.Vector3 _force; | 71 | private OMV.Vector3 _force; |
69 | private OMV.Vector3 _velocity; | 72 | private OMV.Vector3 _velocity; |
@@ -86,14 +89,22 @@ public sealed class BSPrim : PhysicsActor | |||
86 | private bool _kinematic; | 89 | private bool _kinematic; |
87 | private float _buoyancy; | 90 | private float _buoyancy; |
88 | 91 | ||
89 | private List<BSPrim> _childrenPrims; | 92 | // Membership in a linkset is controlled by this class. |
90 | private BSPrim _parentPrim; | 93 | private BSLinkset _linkset; |
94 | public BSLinkset Linkset | ||
95 | { | ||
96 | get { return _linkset; } | ||
97 | set { _linkset = value; } | ||
98 | } | ||
91 | 99 | ||
92 | private int _subscribedEventsMs = 0; | 100 | private int _subscribedEventsMs = 0; |
93 | private int _nextCollisionOkTime = 0; | 101 | private int _nextCollisionOkTime = 0; |
94 | long _collidingStep; | 102 | long _collidingStep; |
95 | long _collidingGroundStep; | 103 | long _collidingGroundStep; |
96 | 104 | ||
105 | private BulletBody m_body; | ||
106 | public BulletBody Body { get { return m_body; } } | ||
107 | |||
97 | private BSDynamics _vehicle; | 108 | private BSDynamics _vehicle; |
98 | 109 | ||
99 | private OMV.Vector3 _PIDTarget; | 110 | private OMV.Vector3 _PIDTarget; |
@@ -127,17 +138,18 @@ public sealed class BSPrim : PhysicsActor | |||
127 | _friction = _scene.Params.defaultFriction; // TODO: compute based on object material | 138 | _friction = _scene.Params.defaultFriction; // TODO: compute based on object material |
128 | _density = _scene.Params.defaultDensity; // TODO: compute based on object material | 139 | _density = _scene.Params.defaultDensity; // TODO: compute based on object material |
129 | _restitution = _scene.Params.defaultRestitution; | 140 | _restitution = _scene.Params.defaultRestitution; |
130 | _parentPrim = null; // not a child or a parent | 141 | _linkset = new BSLinkset(_scene, this); // a linkset of one |
131 | _vehicle = new BSDynamics(this); // add vehicleness | 142 | _vehicle = new BSDynamics(this); // add vehicleness |
132 | _childrenPrims = new List<BSPrim>(); | 143 | _mass = CalculateMass(); |
133 | if (_isPhysical) | ||
134 | _mass = CalculateMass(); | ||
135 | else | ||
136 | _mass = 0f; | ||
137 | // do the actual object creation at taint time | 144 | // do the actual object creation at taint time |
138 | _scene.TaintedObject(delegate() | 145 | _scene.TaintedObject(delegate() |
139 | { | 146 | { |
140 | RecreateGeomAndObject(); | 147 | RecreateGeomAndObject(); |
148 | |||
149 | // Get the pointer to the physical body for this object. | ||
150 | // At the moment, we're still letting BulletSim manage the creation and destruction | ||
151 | // of the object. Someday we'll move that into the C# code. | ||
152 | m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); | ||
141 | }); | 153 | }); |
142 | } | 154 | } |
143 | 155 | ||
@@ -145,13 +157,19 @@ public sealed class BSPrim : PhysicsActor | |||
145 | public void Destroy() | 157 | public void Destroy() |
146 | { | 158 | { |
147 | // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); | 159 | // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); |
160 | // DetailLog("{0},Destroy", LocalID); | ||
161 | |||
148 | // Undo any vehicle properties | 162 | // Undo any vehicle properties |
149 | _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); | 163 | _vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); |
150 | _scene.RemoveVehiclePrim(this); // just to make sure | 164 | _scene.RemoveVehiclePrim(this); // just to make sure |
165 | |||
151 | _scene.TaintedObject(delegate() | 166 | _scene.TaintedObject(delegate() |
152 | { | 167 | { |
168 | // Undo any links between me and any other object | ||
169 | _linkset = _linkset.RemoveMeFromLinkset(this); | ||
170 | |||
153 | // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. | 171 | // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. |
154 | BulletSimAPI.DestroyObject(_scene.WorldID, _localID); | 172 | BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); |
155 | }); | 173 | }); |
156 | } | 174 | } |
157 | 175 | ||
@@ -164,8 +182,8 @@ public sealed class BSPrim : PhysicsActor | |||
164 | _size = value; | 182 | _size = value; |
165 | _scene.TaintedObject(delegate() | 183 | _scene.TaintedObject(delegate() |
166 | { | 184 | { |
167 | if (_isPhysical) _mass = CalculateMass(); // changing size changes the mass | 185 | _mass = CalculateMass(); // changing size changes the mass |
168 | BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, _mass, _isPhysical); | 186 | BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); |
169 | RecreateGeomAndObject(); | 187 | RecreateGeomAndObject(); |
170 | }); | 188 | }); |
171 | } | 189 | } |
@@ -175,7 +193,7 @@ public sealed class BSPrim : PhysicsActor | |||
175 | _pbs = value; | 193 | _pbs = value; |
176 | _scene.TaintedObject(delegate() | 194 | _scene.TaintedObject(delegate() |
177 | { | 195 | { |
178 | if (_isPhysical) _mass = CalculateMass(); // changing the shape changes the mass | 196 | _mass = CalculateMass(); // changing the shape changes the mass |
179 | RecreateGeomAndObject(); | 197 | RecreateGeomAndObject(); |
180 | }); | 198 | }); |
181 | } | 199 | } |
@@ -202,33 +220,10 @@ public sealed class BSPrim : PhysicsActor | |||
202 | // link me to the specified parent | 220 | // link me to the specified parent |
203 | public override void link(PhysicsActor obj) { | 221 | public override void link(PhysicsActor obj) { |
204 | BSPrim parent = obj as BSPrim; | 222 | BSPrim parent = obj as BSPrim; |
205 | // m_log.DebugFormat("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); | 223 | DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); |
206 | // TODO: decide if this parent checking needs to happen at taint time | 224 | DetailLog("{0},link,parent={1}", LocalID, obj.LocalID); |
207 | if (_parentPrim == null) | 225 | |
208 | { | 226 | _linkset = _linkset.AddMeToLinkset(this, parent); |
209 | if (parent != null) | ||
210 | { | ||
211 | // I don't have a parent so I am joining a linkset | ||
212 | parent.AddChildToLinkset(this); | ||
213 | } | ||
214 | } | ||
215 | else | ||
216 | { | ||
217 | // I already have a parent, is parenting changing? | ||
218 | if (parent != _parentPrim) | ||
219 | { | ||
220 | if (parent == null) | ||
221 | { | ||
222 | // we are being removed from a linkset | ||
223 | _parentPrim.RemoveChildFromLinkset(this); | ||
224 | } | ||
225 | else | ||
226 | { | ||
227 | // asking to reparent a prim should not happen | ||
228 | m_log.ErrorFormat("{0}: Reparenting a prim. ", LogHeader); | ||
229 | } | ||
230 | } | ||
231 | } | ||
232 | return; | 227 | return; |
233 | } | 228 | } |
234 | 229 | ||
@@ -236,101 +231,92 @@ public sealed class BSPrim : PhysicsActor | |||
236 | public override void delink() { | 231 | public override void delink() { |
237 | // TODO: decide if this parent checking needs to happen at taint time | 232 | // TODO: decide if this parent checking needs to happen at taint time |
238 | // Race condition here: if link() and delink() in same simulation tick, the delink will not happen | 233 | // Race condition here: if link() and delink() in same simulation tick, the delink will not happen |
239 | // m_log.DebugFormat("{0}: delink {1}/{2}", LogHeader, _avName, _localID); | 234 | DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, |
240 | if (_parentPrim != null) | 235 | _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString()); |
241 | { | 236 | DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString()); |
242 | _parentPrim.RemoveChildFromLinkset(this); | ||
243 | } | ||
244 | return; | ||
245 | } | ||
246 | |||
247 | // I am the root of a linkset and a new child is being added | ||
248 | public void AddChildToLinkset(BSPrim pchild) | ||
249 | { | ||
250 | BSPrim child = pchild; | ||
251 | _scene.TaintedObject(delegate() | ||
252 | { | ||
253 | if (!_childrenPrims.Contains(child)) | ||
254 | { | ||
255 | _childrenPrims.Add(child); | ||
256 | child.ParentPrim = this; // the child has gained a parent | ||
257 | RecreateGeomAndObject(); // rebuild my shape with the new child added | ||
258 | } | ||
259 | }); | ||
260 | return; | ||
261 | } | ||
262 | |||
263 | // I am the root of a linkset and one of my children is being removed. | ||
264 | // Safe to call even if the child is not really in my linkset. | ||
265 | public void RemoveChildFromLinkset(BSPrim pchild) | ||
266 | { | ||
267 | BSPrim child = pchild; | ||
268 | _scene.TaintedObject(delegate() | ||
269 | { | ||
270 | if (_childrenPrims.Contains(child)) | ||
271 | { | ||
272 | BulletSimAPI.RemoveConstraint(_scene.WorldID, child.LocalID, this.LocalID); | ||
273 | _childrenPrims.Remove(child); | ||
274 | child.ParentPrim = null; // the child has lost its parent | ||
275 | RecreateGeomAndObject(); // rebuild my shape with the child removed | ||
276 | } | ||
277 | else | ||
278 | { | ||
279 | m_log.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset"); | ||
280 | } | ||
281 | }); | ||
282 | return; | ||
283 | } | ||
284 | |||
285 | public BSPrim ParentPrim | ||
286 | { | ||
287 | set { _parentPrim = value; } | ||
288 | } | ||
289 | 237 | ||
290 | // return true if we are the root of a linkset (there are children to manage) | 238 | _linkset.RemoveMeFromLinkset(this); |
291 | public bool IsRootOfLinkset | 239 | return; |
292 | { | ||
293 | get { return (_parentPrim == null && _childrenPrims.Count != 0); } | ||
294 | } | 240 | } |
295 | 241 | ||
296 | // Set motion values to zero. | 242 | // Set motion values to zero. |
297 | // Do it to the properties so the values get set in the physics engine. | 243 | // Do it to the properties so the values get set in the physics engine. |
298 | // Push the setting of the values to the viewer. | 244 | // Push the setting of the values to the viewer. |
299 | private void ZeroMotion() | 245 | // Called at taint time! |
246 | public void ZeroMotion() | ||
300 | { | 247 | { |
301 | Velocity = OMV.Vector3.Zero; | 248 | _velocity = OMV.Vector3.Zero; |
302 | _acceleration = OMV.Vector3.Zero; | 249 | _acceleration = OMV.Vector3.Zero; |
303 | RotationalVelocity = OMV.Vector3.Zero; | 250 | _rotationalVelocity = OMV.Vector3.Zero; |
304 | base.RequestPhysicsterseUpdate(); | 251 | |
252 | // Zero some other properties directly into the physics engine | ||
253 | BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero); | ||
254 | BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero); | ||
255 | BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); | ||
256 | BulletSimAPI.ClearForces2(Body.Ptr); | ||
305 | } | 257 | } |
306 | 258 | ||
307 | public override void LockAngularMotion(OMV.Vector3 axis) { return; } | 259 | public override void LockAngularMotion(OMV.Vector3 axis) |
260 | { | ||
261 | DetailLog("{0},LockAngularMotion,call,axis={1}", LocalID, axis); | ||
262 | return; | ||
263 | } | ||
308 | 264 | ||
309 | public override OMV.Vector3 Position { | 265 | public override OMV.Vector3 Position { |
310 | get { | 266 | get { |
311 | // don't do the following GetObjectPosition because this function is called a zillion times | 267 | if (!_linkset.IsRoot(this)) |
268 | // child prims move around based on their parent. Need to get the latest location | ||
269 | _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); | ||
270 | |||
271 | // don't do the GetObjectPosition for root elements because this function is called a zillion times | ||
312 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); | 272 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); |
313 | return _position; | 273 | return _position; |
314 | } | 274 | } |
315 | set { | 275 | set { |
316 | _position = value; | 276 | _position = value; |
277 | // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? | ||
317 | _scene.TaintedObject(delegate() | 278 | _scene.TaintedObject(delegate() |
318 | { | 279 | { |
280 | DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); | ||
319 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); | 281 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); |
320 | // m_log.DebugFormat("{0}: setPosition: id={1}, position={2}", LogHeader, _localID, _position); | ||
321 | }); | 282 | }); |
322 | } | 283 | } |
323 | } | 284 | } |
324 | public override float Mass { | 285 | |
325 | get { return _mass; } | 286 | // Return the effective mass of the object. |
287 | // If there are multiple items in the linkset, add them together for the root | ||
288 | public override float Mass | ||
289 | { | ||
290 | get | ||
291 | { | ||
292 | return _linkset.LinksetMass; | ||
293 | } | ||
294 | } | ||
295 | |||
296 | // used when we only want this prim's mass and not the linkset thing | ||
297 | public float MassRaw { get { return _mass; } } | ||
298 | |||
299 | // Is this used? | ||
300 | public override OMV.Vector3 CenterOfMass | ||
301 | { | ||
302 | get { return _linkset.CenterOfMass; } | ||
326 | } | 303 | } |
304 | |||
305 | // Is this used? | ||
306 | public override OMV.Vector3 GeometricCenter | ||
307 | { | ||
308 | get { return _linkset.GeometricCenter; } | ||
309 | } | ||
310 | |||
327 | public override OMV.Vector3 Force { | 311 | public override OMV.Vector3 Force { |
328 | get { return _force; } | 312 | get { return _force; } |
329 | set { | 313 | set { |
330 | _force = value; | 314 | _force = value; |
331 | _scene.TaintedObject(delegate() | 315 | _scene.TaintedObject(delegate() |
332 | { | 316 | { |
333 | BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); | 317 | DetailLog("{0},SetForce,taint,force={1}", LocalID, _force); |
318 | // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); | ||
319 | BulletSimAPI.SetObjectForce2(Body.Ptr, _force); | ||
334 | }); | 320 | }); |
335 | } | 321 | } |
336 | } | 322 | } |
@@ -341,15 +327,22 @@ public sealed class BSPrim : PhysicsActor | |||
341 | } | 327 | } |
342 | set { | 328 | set { |
343 | Vehicle type = (Vehicle)value; | 329 | Vehicle type = (Vehicle)value; |
344 | _vehicle.ProcessTypeChange(type); | ||
345 | _scene.TaintedObject(delegate() | 330 | _scene.TaintedObject(delegate() |
346 | { | 331 | { |
332 | DetailLog("{0},SetVehicleType,taint,type={1}", LocalID, type); | ||
333 | _vehicle.ProcessTypeChange(type); | ||
347 | if (type == Vehicle.TYPE_NONE) | 334 | if (type == Vehicle.TYPE_NONE) |
348 | { | 335 | { |
349 | _scene.RemoveVehiclePrim(this); | 336 | _scene.RemoveVehiclePrim(this); |
350 | } | 337 | } |
351 | else | 338 | else |
352 | { | 339 | { |
340 | _scene.TaintedObject(delegate() | ||
341 | { | ||
342 | // Tell the physics engine to clear state | ||
343 | BulletSimAPI.ClearForces2(this.Body.Ptr); | ||
344 | }); | ||
345 | |||
353 | // make it so the scene will call us each tick to do vehicle things | 346 | // make it so the scene will call us each tick to do vehicle things |
354 | _scene.AddVehiclePrim(this); | 347 | _scene.AddVehiclePrim(this); |
355 | } | 348 | } |
@@ -359,47 +352,59 @@ public sealed class BSPrim : PhysicsActor | |||
359 | } | 352 | } |
360 | public override void VehicleFloatParam(int param, float value) | 353 | public override void VehicleFloatParam(int param, float value) |
361 | { | 354 | { |
362 | _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); | 355 | _scene.TaintedObject(delegate() |
356 | { | ||
357 | _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); | ||
358 | }); | ||
363 | } | 359 | } |
364 | public override void VehicleVectorParam(int param, OMV.Vector3 value) | 360 | public override void VehicleVectorParam(int param, OMV.Vector3 value) |
365 | { | 361 | { |
366 | _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); | 362 | _scene.TaintedObject(delegate() |
363 | { | ||
364 | _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); | ||
365 | }); | ||
367 | } | 366 | } |
368 | public override void VehicleRotationParam(int param, OMV.Quaternion rotation) | 367 | public override void VehicleRotationParam(int param, OMV.Quaternion rotation) |
369 | { | 368 | { |
370 | _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); | 369 | _scene.TaintedObject(delegate() |
370 | { | ||
371 | _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); | ||
372 | }); | ||
371 | } | 373 | } |
372 | public override void VehicleFlags(int param, bool remove) | 374 | public override void VehicleFlags(int param, bool remove) |
373 | { | 375 | { |
374 | _vehicle.ProcessVehicleFlags(param, remove); | 376 | _scene.TaintedObject(delegate() |
377 | { | ||
378 | _vehicle.ProcessVehicleFlags(param, remove); | ||
379 | }); | ||
375 | } | 380 | } |
376 | // Called each simulation step to advance vehicle characteristics | 381 | |
382 | // Called each simulation step to advance vehicle characteristics. | ||
383 | // Called from Scene when doing simulation step so we're in taint processing time. | ||
377 | public void StepVehicle(float timeStep) | 384 | public void StepVehicle(float timeStep) |
378 | { | 385 | { |
379 | _vehicle.Step(timeStep, _scene); | 386 | if (IsPhysical) |
387 | _vehicle.Step(timeStep); | ||
380 | } | 388 | } |
381 | 389 | ||
382 | // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more | 390 | // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more |
383 | public override void SetVolumeDetect(int param) { | 391 | public override void SetVolumeDetect(int param) { |
384 | bool newValue = (param != 0); | 392 | bool newValue = (param != 0); |
385 | if (_isVolumeDetect != newValue) | 393 | _isVolumeDetect = newValue; |
394 | _scene.TaintedObject(delegate() | ||
386 | { | 395 | { |
387 | _isVolumeDetect = newValue; | 396 | SetObjectDynamic(); |
388 | _scene.TaintedObject(delegate() | 397 | }); |
389 | { | ||
390 | SetObjectDynamic(); | ||
391 | }); | ||
392 | } | ||
393 | return; | 398 | return; |
394 | } | 399 | } |
395 | 400 | ||
396 | public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } | ||
397 | public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } | ||
398 | public override OMV.Vector3 Velocity { | 401 | public override OMV.Vector3 Velocity { |
399 | get { return _velocity; } | 402 | get { return _velocity; } |
400 | set { _velocity = value; | 403 | set { |
404 | _velocity = value; | ||
401 | _scene.TaintedObject(delegate() | 405 | _scene.TaintedObject(delegate() |
402 | { | 406 | { |
407 | DetailLog("{0},SetVelocity,taint,vel={1}", LocalID, _velocity); | ||
403 | BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); | 408 | BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); |
404 | }); | 409 | }); |
405 | } | 410 | } |
@@ -407,6 +412,7 @@ public sealed class BSPrim : PhysicsActor | |||
407 | public override OMV.Vector3 Torque { | 412 | public override OMV.Vector3 Torque { |
408 | get { return _torque; } | 413 | get { return _torque; } |
409 | set { _torque = value; | 414 | set { _torque = value; |
415 | DetailLog("{0},SetTorque,call,torque={1}", LocalID, _torque); | ||
410 | } | 416 | } |
411 | } | 417 | } |
412 | public override float CollisionScore { | 418 | public override float CollisionScore { |
@@ -419,13 +425,21 @@ public sealed class BSPrim : PhysicsActor | |||
419 | set { _acceleration = value; } | 425 | set { _acceleration = value; } |
420 | } | 426 | } |
421 | public override OMV.Quaternion Orientation { | 427 | public override OMV.Quaternion Orientation { |
422 | get { return _orientation; } | 428 | get { |
429 | if (!_linkset.IsRoot(this)) | ||
430 | { | ||
431 | // Children move around because tied to parent. Get a fresh value. | ||
432 | _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); | ||
433 | } | ||
434 | return _orientation; | ||
435 | } | ||
423 | set { | 436 | set { |
424 | _orientation = value; | 437 | _orientation = value; |
425 | // m_log.DebugFormat("{0}: set orientation: id={1}, ori={2}", LogHeader, LocalID, _orientation); | 438 | // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? |
426 | _scene.TaintedObject(delegate() | 439 | _scene.TaintedObject(delegate() |
427 | { | 440 | { |
428 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); | 441 | // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); |
442 | DetailLog("{0},SetOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); | ||
429 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); | 443 | BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); |
430 | }); | 444 | }); |
431 | } | 445 | } |
@@ -458,25 +472,22 @@ public sealed class BSPrim : PhysicsActor | |||
458 | get { return !IsPhantom && !_isVolumeDetect; } | 472 | get { return !IsPhantom && !_isVolumeDetect; } |
459 | } | 473 | } |
460 | 474 | ||
461 | // make gravity work if the object is physical and not selected | 475 | // Make gravity work if the object is physical and not selected |
462 | // no locking here because only called when it is safe | 476 | // No locking here because only called when it is safe |
477 | // Only called at taint time so it is save to call into Bullet. | ||
463 | private void SetObjectDynamic() | 478 | private void SetObjectDynamic() |
464 | { | 479 | { |
465 | // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid); | 480 | // m_log.DebugFormat("{0}: ID={1}, SetObjectDynamic: IsStatic={2}, IsSolid={3}", LogHeader, _localID, IsStatic, IsSolid); |
466 | // non-physical things work best with a mass of zero | ||
467 | if (IsStatic) | ||
468 | { | ||
469 | _mass = 0f; | ||
470 | } | ||
471 | else | ||
472 | { | ||
473 | _mass = CalculateMass(); | ||
474 | // If it's dynamic, make sure the hull has been created for it | ||
475 | // This shouldn't do much work if the object had previously been built | ||
476 | RecreateGeomAndObject(); | ||
477 | 481 | ||
478 | } | 482 | RecreateGeomAndObject(); |
479 | BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), _mass); | 483 | |
484 | float mass = _mass; | ||
485 | // Bullet wants static objects have a mass of zero | ||
486 | if (IsStatic) | ||
487 | mass = 0f; | ||
488 | |||
489 | DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, mass); | ||
490 | BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); | ||
480 | } | 491 | } |
481 | 492 | ||
482 | // prims don't fly | 493 | // prims don't fly |
@@ -516,11 +527,24 @@ public sealed class BSPrim : PhysicsActor | |||
516 | set { _floatOnWater = value; } | 527 | set { _floatOnWater = value; } |
517 | } | 528 | } |
518 | public override OMV.Vector3 RotationalVelocity { | 529 | public override OMV.Vector3 RotationalVelocity { |
519 | get { return _rotationalVelocity; } | 530 | get { |
520 | set { _rotationalVelocity = value; | 531 | /* |
532 | OMV.Vector3 pv = OMV.Vector3.Zero; | ||
533 | // if close to zero, report zero | ||
534 | // This is copied from ODE but I'm not sure why it returns zero but doesn't | ||
535 | // zero the property in the physics engine. | ||
536 | if (_rotationalVelocity.ApproxEquals(pv, 0.2f)) | ||
537 | return pv; | ||
538 | */ | ||
539 | |||
540 | return _rotationalVelocity; | ||
541 | } | ||
542 | set { | ||
543 | _rotationalVelocity = value; | ||
521 | // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); | 544 | // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); |
522 | _scene.TaintedObject(delegate() | 545 | _scene.TaintedObject(delegate() |
523 | { | 546 | { |
547 | DetailLog("{0},SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); | ||
524 | BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); | 548 | BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); |
525 | }); | 549 | }); |
526 | } | 550 | } |
@@ -533,11 +557,13 @@ public sealed class BSPrim : PhysicsActor | |||
533 | } | 557 | } |
534 | public override float Buoyancy { | 558 | public override float Buoyancy { |
535 | get { return _buoyancy; } | 559 | get { return _buoyancy; } |
536 | set { _buoyancy = value; | 560 | set { |
537 | _scene.TaintedObject(delegate() | 561 | _buoyancy = value; |
538 | { | 562 | _scene.TaintedObject(delegate() |
539 | BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); | 563 | { |
540 | }); | 564 | DetailLog("{0},SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); |
565 | BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); | ||
566 | }); | ||
541 | } | 567 | } |
542 | } | 568 | } |
543 | 569 | ||
@@ -573,27 +599,45 @@ public sealed class BSPrim : PhysicsActor | |||
573 | public override float APIDStrength { set { return; } } | 599 | public override float APIDStrength { set { return; } } |
574 | public override float APIDDamping { set { return; } } | 600 | public override float APIDDamping { set { return; } } |
575 | 601 | ||
602 | private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); | ||
576 | public override void AddForce(OMV.Vector3 force, bool pushforce) { | 603 | public override void AddForce(OMV.Vector3 force, bool pushforce) { |
577 | if (force.IsFinite()) | 604 | if (force.IsFinite()) |
578 | { | 605 | { |
579 | _force.X += force.X; | 606 | // _force += force; |
580 | _force.Y += force.Y; | 607 | lock (m_accumulatedForces) |
581 | _force.Z += force.Z; | 608 | m_accumulatedForces.Add(new OMV.Vector3(force)); |
582 | } | 609 | } |
583 | else | 610 | else |
584 | { | 611 | { |
585 | m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); | 612 | m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); |
613 | return; | ||
586 | } | 614 | } |
587 | _scene.TaintedObject(delegate() | 615 | _scene.TaintedObject(delegate() |
588 | { | 616 | { |
589 | BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); | 617 | lock (m_accumulatedForces) |
618 | { | ||
619 | if (m_accumulatedForces.Count > 0) | ||
620 | { | ||
621 | OMV.Vector3 fSum = OMV.Vector3.Zero; | ||
622 | foreach (OMV.Vector3 v in m_accumulatedForces) | ||
623 | { | ||
624 | fSum += v; | ||
625 | } | ||
626 | m_accumulatedForces.Clear(); | ||
627 | |||
628 | DetailLog("{0},SetObjectForce,taint,force={1}", LocalID, fSum); | ||
629 | BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, fSum); | ||
630 | } | ||
631 | } | ||
590 | }); | 632 | }); |
591 | } | 633 | } |
592 | 634 | ||
593 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { | 635 | public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { |
636 | DetailLog("{0},AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); | ||
594 | // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); | 637 | // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); |
595 | } | 638 | } |
596 | public override void SetMomentum(OMV.Vector3 momentum) { | 639 | public override void SetMomentum(OMV.Vector3 momentum) { |
640 | DetailLog("{0},SetMomentum,call,mom={1}", LocalID, momentum); | ||
597 | } | 641 | } |
598 | public override void SubscribeEvents(int ms) { | 642 | public override void SubscribeEvents(int ms) { |
599 | _subscribedEventsMs = ms; | 643 | _subscribedEventsMs = ms; |
@@ -885,6 +929,9 @@ public sealed class BSPrim : PhysicsActor | |||
885 | 929 | ||
886 | returnMass = _density * volume; | 930 | returnMass = _density * volume; |
887 | 931 | ||
932 | /* | ||
933 | * This change means each object keeps its own mass and the Mass property | ||
934 | * will return the sum if we're part of a linkset. | ||
888 | if (IsRootOfLinkset) | 935 | if (IsRootOfLinkset) |
889 | { | 936 | { |
890 | foreach (BSPrim prim in _childrenPrims) | 937 | foreach (BSPrim prim in _childrenPrims) |
@@ -892,6 +939,7 @@ public sealed class BSPrim : PhysicsActor | |||
892 | returnMass += prim.CalculateMass(); | 939 | returnMass += prim.CalculateMass(); |
893 | } | 940 | } |
894 | } | 941 | } |
942 | */ | ||
895 | 943 | ||
896 | if (returnMass <= 0) | 944 | if (returnMass <= 0) |
897 | returnMass = 0.0001f; | 945 | returnMass = 0.0001f; |
@@ -907,9 +955,11 @@ public sealed class BSPrim : PhysicsActor | |||
907 | // The objects needs a hull if it's physical otherwise a mesh is enough | 955 | // The objects needs a hull if it's physical otherwise a mesh is enough |
908 | // No locking here because this is done when we know physics is not simulating | 956 | // No locking here because this is done when we know physics is not simulating |
909 | // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used | 957 | // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used |
910 | private void CreateGeom(bool forceRebuild) | 958 | // Returns 'true' if the geometry was rebuilt |
959 | private bool CreateGeom(bool forceRebuild) | ||
911 | { | 960 | { |
912 | // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. | 961 | // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. |
962 | bool ret = false; | ||
913 | if (!_scene.NeedsMeshing(_pbs)) | 963 | if (!_scene.NeedsMeshing(_pbs)) |
914 | { | 964 | { |
915 | if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) | 965 | if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) |
@@ -917,16 +967,26 @@ public sealed class BSPrim : PhysicsActor | |||
917 | if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) | 967 | if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) |
918 | { | 968 | { |
919 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); | 969 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); |
920 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; | 970 | if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE) |
921 | // Bullet native objects are scaled by the Bullet engine so pass the size in | 971 | { |
922 | _scale = _size; | 972 | DetailLog("{0},CreateGeom,sphere", LocalID); |
973 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; | ||
974 | ret = true; | ||
975 | // Bullet native objects are scaled by the Bullet engine so pass the size in | ||
976 | _scale = _size; | ||
977 | } | ||
923 | } | 978 | } |
924 | } | 979 | } |
925 | else | 980 | else |
926 | { | 981 | { |
927 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size); | 982 | // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, size={2}", LogHeader, LocalID, _size); |
928 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; | 983 | if (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX) |
929 | _scale = _size; | 984 | { |
985 | DetailLog("{0},CreateGeom,box", LocalID); | ||
986 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; | ||
987 | ret = true; | ||
988 | _scale = _size; | ||
989 | } | ||
930 | } | 990 | } |
931 | } | 991 | } |
932 | else | 992 | else |
@@ -938,6 +998,7 @@ public sealed class BSPrim : PhysicsActor | |||
938 | // physical objects require a hull for interaction. | 998 | // physical objects require a hull for interaction. |
939 | // This will create the mesh if it doesn't already exist | 999 | // This will create the mesh if it doesn't already exist |
940 | CreateGeomHull(); | 1000 | CreateGeomHull(); |
1001 | ret = true; | ||
941 | } | 1002 | } |
942 | } | 1003 | } |
943 | else | 1004 | else |
@@ -946,9 +1007,11 @@ public sealed class BSPrim : PhysicsActor | |||
946 | { | 1007 | { |
947 | // Static (non-physical) objects only need a mesh for bumping into | 1008 | // Static (non-physical) objects only need a mesh for bumping into |
948 | CreateGeomMesh(); | 1009 | CreateGeomMesh(); |
1010 | ret = true; | ||
949 | } | 1011 | } |
950 | } | 1012 | } |
951 | } | 1013 | } |
1014 | return ret; | ||
952 | } | 1015 | } |
953 | 1016 | ||
954 | // No locking here because this is done when we know physics is not simulating | 1017 | // No locking here because this is done when we know physics is not simulating |
@@ -961,10 +1024,12 @@ public sealed class BSPrim : PhysicsActor | |||
961 | // if this new shape is the same as last time, don't recreate the mesh | 1024 | // if this new shape is the same as last time, don't recreate the mesh |
962 | if (_meshKey == newMeshKey) return; | 1025 | if (_meshKey == newMeshKey) return; |
963 | 1026 | ||
1027 | DetailLog("{0},CreateGeomMesh,create,key={1}", LocalID, _meshKey); | ||
964 | // Since we're recreating new, get rid of any previously generated shape | 1028 | // Since we're recreating new, get rid of any previously generated shape |
965 | if (_meshKey != 0) | 1029 | if (_meshKey != 0) |
966 | { | 1030 | { |
967 | // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); | 1031 | // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); |
1032 | DetailLog("{0},CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); | ||
968 | BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); | 1033 | BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); |
969 | _mesh = null; | 1034 | _mesh = null; |
970 | _meshKey = 0; | 1035 | _meshKey = 0; |
@@ -981,7 +1046,6 @@ public sealed class BSPrim : PhysicsActor | |||
981 | int vi = 0; | 1046 | int vi = 0; |
982 | foreach (OMV.Vector3 vv in vertices) | 1047 | foreach (OMV.Vector3 vv in vertices) |
983 | { | 1048 | { |
984 | // m_log.DebugFormat("{0}: {1}: <{2:0.00}, {3:0.00}, {4:0.00}>", LogHeader, vi / 3, vv.X, vv.Y, vv.Z); | ||
985 | verticesAsFloats[vi++] = vv.X; | 1049 | verticesAsFloats[vi++] = vv.X; |
986 | verticesAsFloats[vi++] = vv.Y; | 1050 | verticesAsFloats[vi++] = vv.Y; |
987 | verticesAsFloats[vi++] = vv.Z; | 1051 | verticesAsFloats[vi++] = vv.Z; |
@@ -995,6 +1059,7 @@ public sealed class BSPrim : PhysicsActor | |||
995 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; | 1059 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; |
996 | // meshes are already scaled by the meshmerizer | 1060 | // meshes are already scaled by the meshmerizer |
997 | _scale = new OMV.Vector3(1f, 1f, 1f); | 1061 | _scale = new OMV.Vector3(1f, 1f, 1f); |
1062 | DetailLog("{0},CreateGeomMesh,done", LocalID); | ||
998 | return; | 1063 | return; |
999 | } | 1064 | } |
1000 | 1065 | ||
@@ -1008,13 +1073,17 @@ public sealed class BSPrim : PhysicsActor | |||
1008 | // if the hull hasn't changed, don't rebuild it | 1073 | // if the hull hasn't changed, don't rebuild it |
1009 | if (newHullKey == _hullKey) return; | 1074 | if (newHullKey == _hullKey) return; |
1010 | 1075 | ||
1076 | DetailLog("{0},CreateGeomHull,create,key={1}", LocalID, _meshKey); | ||
1077 | |||
1011 | // Since we're recreating new, get rid of any previously generated shape | 1078 | // Since we're recreating new, get rid of any previously generated shape |
1012 | if (_hullKey != 0) | 1079 | if (_hullKey != 0) |
1013 | { | 1080 | { |
1014 | // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); | 1081 | // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); |
1082 | DetailLog("{0},CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey); | ||
1015 | BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); | 1083 | BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); |
1016 | _hullKey = 0; | 1084 | _hullKey = 0; |
1017 | _hulls.Clear(); | 1085 | _hulls.Clear(); |
1086 | DetailLog("{0},CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey); | ||
1018 | BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); | 1087 | BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); |
1019 | _mesh = null; // the mesh cannot match either | 1088 | _mesh = null; // the mesh cannot match either |
1020 | _meshKey = 0; | 1089 | _meshKey = 0; |
@@ -1111,6 +1180,7 @@ public sealed class BSPrim : PhysicsActor | |||
1111 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; | 1180 | _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; |
1112 | // meshes are already scaled by the meshmerizer | 1181 | // meshes are already scaled by the meshmerizer |
1113 | _scale = new OMV.Vector3(1f, 1f, 1f); | 1182 | _scale = new OMV.Vector3(1f, 1f, 1f); |
1183 | DetailLog("{0},CreateGeomHull,done", LocalID); | ||
1114 | return; | 1184 | return; |
1115 | } | 1185 | } |
1116 | 1186 | ||
@@ -1126,45 +1196,18 @@ public sealed class BSPrim : PhysicsActor | |||
1126 | // No locking here because this is done when the physics engine is not simulating | 1196 | // No locking here because this is done when the physics engine is not simulating |
1127 | private void CreateObject() | 1197 | private void CreateObject() |
1128 | { | 1198 | { |
1129 | if (IsRootOfLinkset) | 1199 | // this routine is called when objects are rebuilt. |
1130 | { | ||
1131 | // Create a linkset around this object | ||
1132 | // CreateLinksetWithCompoundHull(); | ||
1133 | CreateLinksetWithConstraints(); | ||
1134 | } | ||
1135 | else | ||
1136 | { | ||
1137 | // simple object | ||
1138 | // the mesh or hull must have already been created in Bullet | ||
1139 | ShapeData shape; | ||
1140 | FillShapeInfo(out shape); | ||
1141 | // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); | ||
1142 | BulletSimAPI.CreateObject(_scene.WorldID, shape); | ||
1143 | } | ||
1144 | } | ||
1145 | 1200 | ||
1146 | // Create a linkset by creating a compound hull at the root prim that consists of all | 1201 | // the mesh or hull must have already been created in Bullet |
1147 | // the children. | 1202 | ShapeData shape; |
1148 | // NOTE: This does not allow proper collisions with the children prims so it is not a workable solution | 1203 | FillShapeInfo(out shape); |
1149 | void CreateLinksetWithCompoundHull() | 1204 | // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); |
1150 | { | 1205 | BulletSimAPI.CreateObject(_scene.WorldID, shape); |
1151 | // If I am the root prim of a linkset, replace my physical shape with all the | 1206 | // the CreateObject() may have recreated the rigid body. Make sure we have the latest. |
1152 | // pieces of the children. | 1207 | m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID); |
1153 | // All of the children should have called CreateGeom so they have a hull | 1208 | |
1154 | // in the physics engine already. Here we pull together all of those hulls | 1209 | // The root object could have been recreated. Make sure everything linksety is up to date. |
1155 | // into one shape. | 1210 | _linkset.RefreshLinkset(this); |
1156 | int totalPrimsInLinkset = _childrenPrims.Count + 1; | ||
1157 | // m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, totalPrimsInLinkset); | ||
1158 | ShapeData[] shapes = new ShapeData[totalPrimsInLinkset]; | ||
1159 | FillShapeInfo(out shapes[0]); | ||
1160 | int ii = 1; | ||
1161 | foreach (BSPrim prim in _childrenPrims) | ||
1162 | { | ||
1163 | // m_log.DebugFormat("{0}: CreateLinkset: adding prim {1}", LogHeader, prim.LocalID); | ||
1164 | prim.FillShapeInfo(out shapes[ii]); | ||
1165 | ii++; | ||
1166 | } | ||
1167 | BulletSimAPI.CreateLinkset(_scene.WorldID, totalPrimsInLinkset, shapes); | ||
1168 | } | 1211 | } |
1169 | 1212 | ||
1170 | // Copy prim's info into the BulletSim shape description structure | 1213 | // Copy prim's info into the BulletSim shape description structure |
@@ -1186,44 +1229,6 @@ public sealed class BSPrim : PhysicsActor | |||
1186 | shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; | 1229 | shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; |
1187 | } | 1230 | } |
1188 | 1231 | ||
1189 | // Create the linkset by putting constraints between the objects of the set so they cannot move | ||
1190 | // relative to each other. | ||
1191 | // TODO: make this more effeicient: a large linkset gets rebuilt over and over and prims are added | ||
1192 | void CreateLinksetWithConstraints() | ||
1193 | { | ||
1194 | // m_log.DebugFormat("{0}: CreateLinkset. Root prim={1}, prims={2}", LogHeader, LocalID, _childrenPrims.Count+1); | ||
1195 | |||
1196 | // remove any constraints that might be in place | ||
1197 | foreach (BSPrim prim in _childrenPrims) | ||
1198 | { | ||
1199 | // m_log.DebugFormat("{0}: CreateLinkset: RemoveConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID); | ||
1200 | BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, prim.LocalID); | ||
1201 | } | ||
1202 | // create constraints between the root prim and each of the children | ||
1203 | foreach (BSPrim prim in _childrenPrims) | ||
1204 | { | ||
1205 | // m_log.DebugFormat("{0}: CreateLinkset: AddConstraint between root prim {1} and child prim {2}", LogHeader, LocalID, prim.LocalID); | ||
1206 | |||
1207 | // Zero motion for children so they don't interpolate | ||
1208 | prim.ZeroMotion(); | ||
1209 | |||
1210 | // relative position normalized to the root prim | ||
1211 | OMV.Vector3 childRelativePosition = (prim._position - this._position) * OMV.Quaternion.Inverse(this._orientation); | ||
1212 | |||
1213 | // relative rotation of the child to the parent | ||
1214 | OMV.Quaternion relativeRotation = OMV.Quaternion.Inverse(prim._orientation) * this._orientation; | ||
1215 | |||
1216 | // this is a constraint that allows no freedom of movement between the two objects | ||
1217 | // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 | ||
1218 | BulletSimAPI.AddConstraint(_scene.WorldID, LocalID, prim.LocalID, | ||
1219 | childRelativePosition, | ||
1220 | relativeRotation, | ||
1221 | OMV.Vector3.Zero, | ||
1222 | OMV.Quaternion.Identity, | ||
1223 | OMV.Vector3.Zero, OMV.Vector3.Zero, | ||
1224 | OMV.Vector3.Zero, OMV.Vector3.Zero); | ||
1225 | } | ||
1226 | } | ||
1227 | 1232 | ||
1228 | // Rebuild the geometry and object. | 1233 | // Rebuild the geometry and object. |
1229 | // This is called when the shape changes so we need to recreate the mesh/hull. | 1234 | // This is called when the shape changes so we need to recreate the mesh/hull. |
@@ -1252,78 +1257,71 @@ public sealed class BSPrim : PhysicsActor | |||
1252 | const float POSITION_TOLERANCE = 0.05f; | 1257 | const float POSITION_TOLERANCE = 0.05f; |
1253 | const float ACCELERATION_TOLERANCE = 0.01f; | 1258 | const float ACCELERATION_TOLERANCE = 0.01f; |
1254 | const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; | 1259 | const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; |
1255 | const bool SHOULD_DAMP_UPDATES = false; | ||
1256 | 1260 | ||
1257 | public void UpdateProperties(EntityProperties entprop) | 1261 | public void UpdateProperties(EntityProperties entprop) |
1258 | { | 1262 | { |
1263 | /* | ||
1259 | UpdatedProperties changed = 0; | 1264 | UpdatedProperties changed = 0; |
1260 | if (SHOULD_DAMP_UPDATES) | 1265 | // assign to the local variables so the normal set action does not happen |
1266 | // if (_position != entprop.Position) | ||
1267 | if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE)) | ||
1261 | { | 1268 | { |
1262 | // assign to the local variables so the normal set action does not happen | 1269 | _position = entprop.Position; |
1263 | // if (_position != entprop.Position) | 1270 | changed |= UpdatedProperties.Position; |
1264 | if (!_position.ApproxEquals(entprop.Position, POSITION_TOLERANCE)) | ||
1265 | { | ||
1266 | _position = entprop.Position; | ||
1267 | // m_log.DebugFormat("{0}: UpdateProperties: id={1}, pos = {2}", LogHeader, LocalID, _position); | ||
1268 | changed |= UpdatedProperties.Position; | ||
1269 | } | ||
1270 | // if (_orientation != entprop.Rotation) | ||
1271 | if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE)) | ||
1272 | { | ||
1273 | _orientation = entprop.Rotation; | ||
1274 | // m_log.DebugFormat("{0}: UpdateProperties: id={1}, rot = {2}", LogHeader, LocalID, _orientation); | ||
1275 | changed |= UpdatedProperties.Rotation; | ||
1276 | } | ||
1277 | // if (_velocity != entprop.Velocity) | ||
1278 | if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE)) | ||
1279 | { | ||
1280 | _velocity = entprop.Velocity; | ||
1281 | // m_log.DebugFormat("{0}: UpdateProperties: velocity = {1}", LogHeader, _velocity); | ||
1282 | changed |= UpdatedProperties.Velocity; | ||
1283 | } | ||
1284 | // if (_acceleration != entprop.Acceleration) | ||
1285 | if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE)) | ||
1286 | { | ||
1287 | _acceleration = entprop.Acceleration; | ||
1288 | // m_log.DebugFormat("{0}: UpdateProperties: acceleration = {1}", LogHeader, _acceleration); | ||
1289 | changed |= UpdatedProperties.Acceleration; | ||
1290 | } | ||
1291 | // if (_rotationalVelocity != entprop.RotationalVelocity) | ||
1292 | if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE)) | ||
1293 | { | ||
1294 | _rotationalVelocity = entprop.RotationalVelocity; | ||
1295 | // m_log.DebugFormat("{0}: UpdateProperties: rotationalVelocity = {1}", LogHeader, _rotationalVelocity); | ||
1296 | changed |= UpdatedProperties.RotationalVel; | ||
1297 | } | ||
1298 | if (changed != 0) | ||
1299 | { | ||
1300 | // m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); | ||
1301 | // Only update the position of single objects and linkset roots | ||
1302 | if (this._parentPrim == null) | ||
1303 | { | ||
1304 | // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation); | ||
1305 | base.RequestPhysicsterseUpdate(); | ||
1306 | } | ||
1307 | } | ||
1308 | } | 1271 | } |
1309 | else | 1272 | // if (_orientation != entprop.Rotation) |
1273 | if (!_orientation.ApproxEquals(entprop.Rotation, ROTATION_TOLERANCE)) | ||
1310 | { | 1274 | { |
1311 | // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. | 1275 | _orientation = entprop.Rotation; |
1312 | 1276 | changed |= UpdatedProperties.Rotation; | |
1313 | // Only updates only for individual prims and for the root object of a linkset. | 1277 | } |
1278 | // if (_velocity != entprop.Velocity) | ||
1279 | if (!_velocity.ApproxEquals(entprop.Velocity, VELOCITY_TOLERANCE)) | ||
1280 | { | ||
1281 | _velocity = entprop.Velocity; | ||
1282 | changed |= UpdatedProperties.Velocity; | ||
1283 | } | ||
1284 | // if (_acceleration != entprop.Acceleration) | ||
1285 | if (!_acceleration.ApproxEquals(entprop.Acceleration, ACCELERATION_TOLERANCE)) | ||
1286 | { | ||
1287 | _acceleration = entprop.Acceleration; | ||
1288 | changed |= UpdatedProperties.Acceleration; | ||
1289 | } | ||
1290 | // if (_rotationalVelocity != entprop.RotationalVelocity) | ||
1291 | if (!_rotationalVelocity.ApproxEquals(entprop.RotationalVelocity, ROTATIONAL_VELOCITY_TOLERANCE)) | ||
1292 | { | ||
1293 | _rotationalVelocity = entprop.RotationalVelocity; | ||
1294 | changed |= UpdatedProperties.RotationalVel; | ||
1295 | } | ||
1296 | if (changed != 0) | ||
1297 | { | ||
1298 | // Only update the position of single objects and linkset roots | ||
1314 | if (this._parentPrim == null) | 1299 | if (this._parentPrim == null) |
1315 | { | 1300 | { |
1316 | // Assign to the local variables so the normal set action does not happen | ||
1317 | _position = entprop.Position; | ||
1318 | _orientation = entprop.Rotation; | ||
1319 | _velocity = entprop.Velocity; | ||
1320 | _acceleration = entprop.Acceleration; | ||
1321 | _rotationalVelocity = entprop.RotationalVelocity; | ||
1322 | // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", | ||
1323 | // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); | ||
1324 | base.RequestPhysicsterseUpdate(); | 1301 | base.RequestPhysicsterseUpdate(); |
1325 | } | 1302 | } |
1326 | } | 1303 | } |
1304 | */ | ||
1305 | |||
1306 | // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. | ||
1307 | |||
1308 | // Updates only for individual prims and for the root object of a linkset. | ||
1309 | if (_linkset.IsRoot(this)) | ||
1310 | { | ||
1311 | // Assign to the local variables so the normal set action does not happen | ||
1312 | _position = entprop.Position; | ||
1313 | _orientation = entprop.Rotation; | ||
1314 | _velocity = entprop.Velocity; | ||
1315 | _acceleration = entprop.Acceleration; | ||
1316 | _rotationalVelocity = entprop.RotationalVelocity; | ||
1317 | |||
1318 | // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", | ||
1319 | // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); | ||
1320 | DetailLog("{0},UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", | ||
1321 | LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); | ||
1322 | |||
1323 | base.RequestPhysicsterseUpdate(); | ||
1324 | } | ||
1327 | } | 1325 | } |
1328 | 1326 | ||
1329 | // I've collided with something | 1327 | // I've collided with something |
@@ -1362,5 +1360,11 @@ public sealed class BSPrim : PhysicsActor | |||
1362 | collisionCollection.Clear(); | 1360 | collisionCollection.Clear(); |
1363 | } | 1361 | } |
1364 | } | 1362 | } |
1363 | |||
1364 | // Invoke the detailed logger and output something if it's enabled. | ||
1365 | private void DetailLog(string msg, params Object[] args) | ||
1366 | { | ||
1367 | Scene.PhysicsLogging.Write(msg, args); | ||
1368 | } | ||
1365 | } | 1369 | } |
1366 | } | 1370 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 417cb5f..c6d622b 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -29,12 +29,14 @@ using System.Collections.Generic; | |||
29 | using System.Runtime.InteropServices; | 29 | using System.Runtime.InteropServices; |
30 | using System.Text; | 30 | using System.Text; |
31 | using System.Threading; | 31 | using System.Threading; |
32 | using Nini.Config; | ||
33 | using log4net; | ||
34 | using OpenSim.Framework; | 32 | using OpenSim.Framework; |
33 | using OpenSim.Region.Framework; | ||
34 | using OpenSim.Region.CoreModules; | ||
35 | using Logging = OpenSim.Region.CoreModules.Framework.Statistics.Logging; | ||
35 | using OpenSim.Region.Physics.Manager; | 36 | using OpenSim.Region.Physics.Manager; |
37 | using Nini.Config; | ||
38 | using log4net; | ||
36 | using OpenMetaverse; | 39 | using OpenMetaverse; |
37 | using OpenSim.Region.Framework; | ||
38 | 40 | ||
39 | // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) | 41 | // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) |
40 | // Debug linkset | 42 | // Debug linkset |
@@ -44,15 +46,17 @@ using OpenSim.Region.Framework; | |||
44 | // Compute physics FPS reasonably | 46 | // Compute physics FPS reasonably |
45 | // Based on material, set density and friction | 47 | // Based on material, set density and friction |
46 | // More efficient memory usage when passing hull information from BSPrim to BulletSim | 48 | // More efficient memory usage when passing hull information from BSPrim to BulletSim |
49 | // Move all logic out of the C++ code and into the C# code for easier future modifications. | ||
47 | // Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? | 50 | // Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? |
48 | // In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) | 51 | // In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) |
49 | // At the moment, physical and phantom causes object to drop through the terrain | 52 | // At the moment, physical and phantom causes object to drop through the terrain |
50 | // Physical phantom objects and related typing (collision options ) | 53 | // Physical phantom objects and related typing (collision options ) |
54 | // Use collision masks for collision with terrain and phantom objects | ||
51 | // Check out llVolumeDetect. Must do something for that. | 55 | // Check out llVolumeDetect. Must do something for that. |
52 | // Should prim.link() and prim.delink() membership checking happen at taint time? | 56 | // Should prim.link() and prim.delink() membership checking happen at taint time? |
57 | // changing the position and orientation of a linked prim must rebuild the constraint with the root. | ||
53 | // Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once | 58 | // Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once |
54 | // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect | 59 | // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect |
55 | // Use collision masks for collision with terrain and phantom objects | ||
56 | // Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) | 60 | // Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) |
57 | // Implement LockAngularMotion | 61 | // Implement LockAngularMotion |
58 | // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) | 62 | // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) |
@@ -60,9 +64,6 @@ using OpenSim.Region.Framework; | |||
60 | // Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. | 64 | // Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. |
61 | // Add PID movement operations. What does ScenePresence.MoveToTarget do? | 65 | // Add PID movement operations. What does ScenePresence.MoveToTarget do? |
62 | // Check terrain size. 128 or 127? | 66 | // Check terrain size. 128 or 127? |
63 | // Multiple contact points on collision? | ||
64 | // See code in ode::near... calls to collision_accounting_events() | ||
65 | // (This might not be a problem. ODE collects all the collisions with one object in one tick.) | ||
66 | // Raycast | 67 | // Raycast |
67 | // | 68 | // |
68 | namespace OpenSim.Region.Physics.BulletSPlugin | 69 | namespace OpenSim.Region.Physics.BulletSPlugin |
@@ -72,6 +73,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
72 | private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 73 | private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
73 | private static readonly string LogHeader = "[BULLETS SCENE]"; | 74 | private static readonly string LogHeader = "[BULLETS SCENE]"; |
74 | 75 | ||
76 | public void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); } | ||
77 | |||
75 | public string BulletSimVersion = "?"; | 78 | public string BulletSimVersion = "?"; |
76 | 79 | ||
77 | private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); | 80 | private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); |
@@ -84,6 +87,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
84 | private uint m_worldID; | 87 | private uint m_worldID; |
85 | public uint WorldID { get { return m_worldID; } } | 88 | public uint WorldID { get { return m_worldID; } } |
86 | 89 | ||
90 | // let my minuions use my logger | ||
91 | public ILog Logger { get { return m_log; } } | ||
92 | |||
87 | private bool m_initialized = false; | 93 | private bool m_initialized = false; |
88 | 94 | ||
89 | private int m_detailedStatsStep = 0; | 95 | private int m_detailedStatsStep = 0; |
@@ -100,11 +106,24 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
100 | get { return m_sculptLOD; } | 106 | get { return m_sculptLOD; } |
101 | } | 107 | } |
102 | 108 | ||
109 | private BulletSim m_worldSim; | ||
110 | public BulletSim World | ||
111 | { | ||
112 | get { return m_worldSim; } | ||
113 | } | ||
114 | private BSConstraintCollection m_constraintCollection; | ||
115 | public BSConstraintCollection Constraints | ||
116 | { | ||
117 | get { return m_constraintCollection; } | ||
118 | } | ||
119 | |||
103 | private int m_maxSubSteps; | 120 | private int m_maxSubSteps; |
104 | private float m_fixedTimeStep; | 121 | private float m_fixedTimeStep; |
105 | private long m_simulationStep = 0; | 122 | private long m_simulationStep = 0; |
106 | public long SimulationStep { get { return m_simulationStep; } } | 123 | public long SimulationStep { get { return m_simulationStep; } } |
107 | 124 | ||
125 | public float LastSimulatedTimestep { get; private set; } | ||
126 | |||
108 | // A value of the time now so all the collision and update routines do not have to get their own | 127 | // A value of the time now so all the collision and update routines do not have to get their own |
109 | // Set to 'now' just before all the prims and actors are called for collisions and updates | 128 | // Set to 'now' just before all the prims and actors are called for collisions and updates |
110 | private int m_simulationNowTime; | 129 | private int m_simulationNowTime; |
@@ -121,6 +140,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
121 | private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed | 140 | private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed |
122 | private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes | 141 | private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes |
123 | 142 | ||
143 | public float PID_D { get; private set; } // derivative | ||
144 | public float PID_P { get; private set; } // proportional | ||
145 | |||
124 | public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero | 146 | public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero |
125 | public const uint GROUNDPLANE_ID = 1; | 147 | public const uint GROUNDPLANE_ID = 1; |
126 | 148 | ||
@@ -147,8 +169,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
147 | ConfigurationParameters[] m_params; | 169 | ConfigurationParameters[] m_params; |
148 | GCHandle m_paramsHandle; | 170 | GCHandle m_paramsHandle; |
149 | 171 | ||
172 | public bool shouldDebugLog { get; private set; } | ||
173 | |||
150 | private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; | 174 | private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; |
151 | 175 | ||
176 | // Sometimes you just have to log everything. | ||
177 | public Logging.LogWriter PhysicsLogging; | ||
178 | private bool m_physicsLoggingEnabled; | ||
179 | private string m_physicsLoggingDir; | ||
180 | private string m_physicsLoggingPrefix; | ||
181 | private int m_physicsLoggingFileMinutes; | ||
182 | |||
183 | private bool m_vehicleLoggingEnabled; | ||
184 | public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } } | ||
185 | |||
152 | public BSScene(string identifier) | 186 | public BSScene(string identifier) |
153 | { | 187 | { |
154 | m_initialized = false; | 188 | m_initialized = false; |
@@ -169,17 +203,32 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
169 | m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; | 203 | m_updateArray = new EntityProperties[m_maxUpdatesPerFrame]; |
170 | m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); | 204 | m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned); |
171 | 205 | ||
206 | // Enable very detailed logging. | ||
207 | // By creating an empty logger when not logging, the log message invocation code | ||
208 | // can be left in and every call doesn't have to check for null. | ||
209 | if (m_physicsLoggingEnabled) | ||
210 | { | ||
211 | PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); | ||
212 | } | ||
213 | else | ||
214 | { | ||
215 | PhysicsLogging = new Logging.LogWriter(); | ||
216 | } | ||
217 | |||
172 | // Get the version of the DLL | 218 | // Get the version of the DLL |
173 | // TODO: this doesn't work yet. Something wrong with marshaling the returned string. | 219 | // TODO: this doesn't work yet. Something wrong with marshaling the returned string. |
174 | // BulletSimVersion = BulletSimAPI.GetVersion(); | 220 | // BulletSimVersion = BulletSimAPI.GetVersion(); |
175 | // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); | 221 | // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); |
176 | 222 | ||
177 | // if Debug, enable logging from the unmanaged code | 223 | // if Debug, enable logging from the unmanaged code |
178 | if (m_log.IsDebugEnabled) | 224 | if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) |
179 | { | 225 | { |
180 | m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); | 226 | m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); |
181 | // the handle is saved to it doesn't get freed after this call | 227 | if (PhysicsLogging.Enabled) |
182 | m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); | 228 | m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); |
229 | else | ||
230 | m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); | ||
231 | // the handle is saved in a variable to make sure it doesn't get freed after this call | ||
183 | BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); | 232 | BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); |
184 | } | 233 | } |
185 | 234 | ||
@@ -194,6 +243,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
194 | m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), | 243 | m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), |
195 | m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); | 244 | m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); |
196 | 245 | ||
246 | // Initialization to support the transition to a new API which puts most of the logic | ||
247 | // into the C# code so it is easier to modify and add to. | ||
248 | m_worldSim = new BulletSim(m_worldID, BulletSimAPI.GetSimHandle2(m_worldID)); | ||
249 | m_constraintCollection = new BSConstraintCollection(World); | ||
250 | |||
197 | m_initialized = true; | 251 | m_initialized = true; |
198 | } | 252 | } |
199 | 253 | ||
@@ -202,110 +256,27 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
202 | private void GetInitialParameterValues(IConfigSource config) | 256 | private void GetInitialParameterValues(IConfigSource config) |
203 | { | 257 | { |
204 | ConfigurationParameters parms = new ConfigurationParameters(); | 258 | ConfigurationParameters parms = new ConfigurationParameters(); |
259 | m_params[0] = parms; | ||
205 | 260 | ||
206 | _meshSculptedPrim = true; // mesh sculpted prims | 261 | SetParameterDefaultValues(); |
207 | _forceSimplePrimMeshing = false; // use complex meshing if called for | ||
208 | |||
209 | m_meshLOD = 8f; | ||
210 | m_sculptLOD = 32f; | ||
211 | |||
212 | m_detailedStatsStep = 0; // disabled | ||
213 | |||
214 | m_maxSubSteps = 10; | ||
215 | m_fixedTimeStep = 1f / 60f; | ||
216 | m_maxCollisionsPerFrame = 2048; | ||
217 | m_maxUpdatesPerFrame = 2048; | ||
218 | m_maximumObjectMass = 10000.01f; | ||
219 | |||
220 | parms.defaultFriction = 0.5f; | ||
221 | parms.defaultDensity = 10.000006836f; // Aluminum g/cm3 | ||
222 | parms.defaultRestitution = 0f; | ||
223 | parms.collisionMargin = 0.0f; | ||
224 | parms.gravity = -9.80665f; | ||
225 | |||
226 | parms.linearDamping = 0.0f; | ||
227 | parms.angularDamping = 0.0f; | ||
228 | parms.deactivationTime = 0.2f; | ||
229 | parms.linearSleepingThreshold = 0.8f; | ||
230 | parms.angularSleepingThreshold = 1.0f; | ||
231 | parms.ccdMotionThreshold = 0.0f; // set to zero to disable | ||
232 | parms.ccdSweptSphereRadius = 0.0f; | ||
233 | parms.contactProcessingThreshold = 0.1f; | ||
234 | |||
235 | parms.terrainFriction = 0.5f; | ||
236 | parms.terrainHitFraction = 0.8f; | ||
237 | parms.terrainRestitution = 0f; | ||
238 | parms.avatarFriction = 0.5f; | ||
239 | parms.avatarRestitution = 0.0f; | ||
240 | parms.avatarDensity = 60f; | ||
241 | parms.avatarCapsuleRadius = 0.37f; | ||
242 | parms.avatarCapsuleHeight = 1.5f; // 2.140599f | ||
243 | parms.avatarContactProcessingThreshold = 0.1f; | ||
244 | |||
245 | parms.maxPersistantManifoldPoolSize = 0f; | ||
246 | parms.shouldDisableContactPoolDynamicAllocation = ConfigurationParameters.numericTrue; | ||
247 | parms.shouldForceUpdateAllAabbs = ConfigurationParameters.numericFalse; | ||
248 | parms.shouldRandomizeSolverOrder = ConfigurationParameters.numericFalse; | ||
249 | parms.shouldSplitSimulationIslands = ConfigurationParameters.numericFalse; | ||
250 | parms.shouldEnableFrictionCaching = ConfigurationParameters.numericFalse; | ||
251 | parms.numberOfSolverIterations = 0f; // means use default | ||
252 | 262 | ||
253 | if (config != null) | 263 | if (config != null) |
254 | { | 264 | { |
255 | // If there are specifications in the ini file, use those values | 265 | // If there are specifications in the ini file, use those values |
256 | // WHEN ADDING OR UPDATING THIS SECTION, BE SURE TO UPDATE OpenSimDefaults.ini | ||
257 | // ALSO REMEMBER TO UPDATE THE RUNTIME SETTING OF THE PARAMETERS. | ||
258 | IConfig pConfig = config.Configs["BulletSim"]; | 266 | IConfig pConfig = config.Configs["BulletSim"]; |
259 | if (pConfig != null) | 267 | if (pConfig != null) |
260 | { | 268 | { |
261 | _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); | 269 | SetParameterConfigurationValues(pConfig); |
262 | _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing); | 270 | |
263 | 271 | // Very detailed logging for physics debugging | |
264 | m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep); | 272 | m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); |
265 | m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD); | 273 | m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); |
266 | m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD); | 274 | m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-"); |
267 | 275 | m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); | |
268 | m_maxSubSteps = pConfig.GetInt("MaxSubSteps", m_maxSubSteps); | 276 | // Very detailed logging for vehicle debugging |
269 | m_fixedTimeStep = pConfig.GetFloat("FixedTimeStep", m_fixedTimeStep); | 277 | m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); |
270 | m_maxCollisionsPerFrame = pConfig.GetInt("MaxCollisionsPerFrame", m_maxCollisionsPerFrame); | ||
271 | m_maxUpdatesPerFrame = pConfig.GetInt("MaxUpdatesPerFrame", m_maxUpdatesPerFrame); | ||
272 | m_maximumObjectMass = pConfig.GetFloat("MaxObjectMass", m_maximumObjectMass); | ||
273 | |||
274 | parms.defaultFriction = pConfig.GetFloat("DefaultFriction", parms.defaultFriction); | ||
275 | parms.defaultDensity = pConfig.GetFloat("DefaultDensity", parms.defaultDensity); | ||
276 | parms.defaultRestitution = pConfig.GetFloat("DefaultRestitution", parms.defaultRestitution); | ||
277 | parms.collisionMargin = pConfig.GetFloat("CollisionMargin", parms.collisionMargin); | ||
278 | parms.gravity = pConfig.GetFloat("Gravity", parms.gravity); | ||
279 | |||
280 | parms.linearDamping = pConfig.GetFloat("LinearDamping", parms.linearDamping); | ||
281 | parms.angularDamping = pConfig.GetFloat("AngularDamping", parms.angularDamping); | ||
282 | parms.deactivationTime = pConfig.GetFloat("DeactivationTime", parms.deactivationTime); | ||
283 | parms.linearSleepingThreshold = pConfig.GetFloat("LinearSleepingThreshold", parms.linearSleepingThreshold); | ||
284 | parms.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", parms.angularSleepingThreshold); | ||
285 | parms.ccdMotionThreshold = pConfig.GetFloat("CcdMotionThreshold", parms.ccdMotionThreshold); | ||
286 | parms.ccdSweptSphereRadius = pConfig.GetFloat("CcdSweptSphereRadius", parms.ccdSweptSphereRadius); | ||
287 | parms.contactProcessingThreshold = pConfig.GetFloat("ContactProcessingThreshold", parms.contactProcessingThreshold); | ||
288 | |||
289 | parms.terrainFriction = pConfig.GetFloat("TerrainFriction", parms.terrainFriction); | ||
290 | parms.terrainHitFraction = pConfig.GetFloat("TerrainHitFraction", parms.terrainHitFraction); | ||
291 | parms.terrainRestitution = pConfig.GetFloat("TerrainRestitution", parms.terrainRestitution); | ||
292 | parms.avatarFriction = pConfig.GetFloat("AvatarFriction", parms.avatarFriction); | ||
293 | parms.avatarRestitution = pConfig.GetFloat("AvatarRestitution", parms.avatarRestitution); | ||
294 | parms.avatarDensity = pConfig.GetFloat("AvatarDensity", parms.avatarDensity); | ||
295 | parms.avatarCapsuleRadius = pConfig.GetFloat("AvatarCapsuleRadius", parms.avatarCapsuleRadius); | ||
296 | parms.avatarCapsuleHeight = pConfig.GetFloat("AvatarCapsuleHeight", parms.avatarCapsuleHeight); | ||
297 | parms.avatarContactProcessingThreshold = pConfig.GetFloat("AvatarContactProcessingThreshold", parms.avatarContactProcessingThreshold); | ||
298 | |||
299 | parms.maxPersistantManifoldPoolSize = pConfig.GetFloat("MaxPersistantManifoldPoolSize", parms.maxPersistantManifoldPoolSize); | ||
300 | parms.shouldDisableContactPoolDynamicAllocation = ParamBoolean(pConfig, "ShouldDisableContactPoolDynamicAllocation", parms.shouldDisableContactPoolDynamicAllocation); | ||
301 | parms.shouldForceUpdateAllAabbs = ParamBoolean(pConfig, "ShouldForceUpdateAllAabbs", parms.shouldForceUpdateAllAabbs); | ||
302 | parms.shouldRandomizeSolverOrder = ParamBoolean(pConfig, "ShouldRandomizeSolverOrder", parms.shouldRandomizeSolverOrder); | ||
303 | parms.shouldSplitSimulationIslands = ParamBoolean(pConfig, "ShouldSplitSimulationIslands", parms.shouldSplitSimulationIslands); | ||
304 | parms.shouldEnableFrictionCaching = ParamBoolean(pConfig, "ShouldEnableFrictionCaching", parms.shouldEnableFrictionCaching); | ||
305 | parms.numberOfSolverIterations = pConfig.GetFloat("NumberOfSolverIterations", parms.numberOfSolverIterations); | ||
306 | } | 278 | } |
307 | } | 279 | } |
308 | m_params[0] = parms; | ||
309 | } | 280 | } |
310 | 281 | ||
311 | // A helper function that handles a true/false parameter and returns the proper float number encoding | 282 | // A helper function that handles a true/false parameter and returns the proper float number encoding |
@@ -323,12 +294,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
323 | return ret; | 294 | return ret; |
324 | } | 295 | } |
325 | 296 | ||
326 | |||
327 | // Called directly from unmanaged code so don't do much | 297 | // Called directly from unmanaged code so don't do much |
328 | private void BulletLogger(string msg) | 298 | private void BulletLogger(string msg) |
329 | { | 299 | { |
330 | m_log.Debug("[BULLETS UNMANAGED]:" + msg); | 300 | m_log.Debug("[BULLETS UNMANAGED]:" + msg); |
331 | } | 301 | } |
302 | |||
303 | // Called directly from unmanaged code so don't do much | ||
304 | private void BulletLoggerPhysLog(string msg) | ||
305 | { | ||
306 | PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); | ||
307 | } | ||
332 | 308 | ||
333 | public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) | 309 | public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) |
334 | { | 310 | { |
@@ -347,34 +323,42 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
347 | public override void RemoveAvatar(PhysicsActor actor) | 323 | public override void RemoveAvatar(PhysicsActor actor) |
348 | { | 324 | { |
349 | // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader); | 325 | // m_log.DebugFormat("{0}: RemoveAvatar", LogHeader); |
350 | if (actor is BSCharacter) | 326 | BSCharacter bsactor = actor as BSCharacter; |
351 | { | 327 | if (bsactor != null) |
352 | ((BSCharacter)actor).Destroy(); | ||
353 | } | ||
354 | try | ||
355 | { | 328 | { |
356 | lock (m_avatars) m_avatars.Remove(actor.LocalID); | 329 | try |
357 | } | 330 | { |
358 | catch (Exception e) | 331 | lock (m_avatars) m_avatars.Remove(actor.LocalID); |
359 | { | 332 | } |
360 | m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e); | 333 | catch (Exception e) |
334 | { | ||
335 | m_log.WarnFormat("{0}: Attempt to remove avatar that is not in physics scene: {1}", LogHeader, e); | ||
336 | } | ||
337 | bsactor.Destroy(); | ||
338 | // bsactor.dispose(); | ||
361 | } | 339 | } |
362 | } | 340 | } |
363 | 341 | ||
364 | public override void RemovePrim(PhysicsActor prim) | 342 | public override void RemovePrim(PhysicsActor prim) |
365 | { | 343 | { |
366 | // m_log.DebugFormat("{0}: RemovePrim", LogHeader); | 344 | BSPrim bsprim = prim as BSPrim; |
367 | if (prim is BSPrim) | 345 | if (bsprim != null) |
368 | { | 346 | { |
369 | ((BSPrim)prim).Destroy(); | 347 | m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); |
370 | } | 348 | try |
371 | try | 349 | { |
372 | { | 350 | lock (m_prims) m_prims.Remove(bsprim.LocalID); |
373 | lock (m_prims) m_prims.Remove(prim.LocalID); | 351 | } |
352 | catch (Exception e) | ||
353 | { | ||
354 | m_log.ErrorFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e); | ||
355 | } | ||
356 | bsprim.Destroy(); | ||
357 | // bsprim.dispose(); | ||
374 | } | 358 | } |
375 | catch (Exception e) | 359 | else |
376 | { | 360 | { |
377 | m_log.WarnFormat("{0}: Attempt to remove prim that is not in physics scene: {1}", LogHeader, e); | 361 | m_log.ErrorFormat("{0}: Attempt to remove prim that is not a BSPrim type.", LogHeader); |
378 | } | 362 | } |
379 | } | 363 | } |
380 | 364 | ||
@@ -400,6 +384,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
400 | int collidersCount; | 384 | int collidersCount; |
401 | IntPtr collidersPtr; | 385 | IntPtr collidersPtr; |
402 | 386 | ||
387 | LastSimulatedTimestep = timeStep; | ||
388 | |||
403 | // prevent simulation until we've been initialized | 389 | // prevent simulation until we've been initialized |
404 | if (!m_initialized) return 10.0f; | 390 | if (!m_initialized) return 10.0f; |
405 | 391 | ||
@@ -459,7 +445,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
459 | for (int ii = 0; ii < updatedEntityCount; ii++) | 445 | for (int ii = 0; ii < updatedEntityCount; ii++) |
460 | { | 446 | { |
461 | EntityProperties entprop = m_updateArray[ii]; | 447 | EntityProperties entprop = m_updateArray[ii]; |
462 | // m_log.DebugFormat("{0}: entprop[{1}]: id={2}, pos={3}", LogHeader, ii, entprop.ID, entprop.Position); | ||
463 | BSPrim prim; | 448 | BSPrim prim; |
464 | if (m_prims.TryGetValue(entprop.ID, out prim)) | 449 | if (m_prims.TryGetValue(entprop.ID, out prim)) |
465 | { | 450 | { |
@@ -532,8 +517,17 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
532 | }); | 517 | }); |
533 | } | 518 | } |
534 | 519 | ||
520 | // Someday we will have complex terrain with caves and tunnels | ||
521 | // For the moment, it's flat and convex | ||
522 | public float GetTerrainHeightAtXYZ(Vector3 loc) | ||
523 | { | ||
524 | return GetTerrainHeightAtXY(loc.X, loc.Y); | ||
525 | } | ||
526 | |||
535 | public float GetTerrainHeightAtXY(float tX, float tY) | 527 | public float GetTerrainHeightAtXY(float tX, float tY) |
536 | { | 528 | { |
529 | if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize) | ||
530 | return 30; | ||
537 | return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)]; | 531 | return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)]; |
538 | } | 532 | } |
539 | 533 | ||
@@ -555,6 +549,33 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
555 | public override void Dispose() | 549 | public override void Dispose() |
556 | { | 550 | { |
557 | // m_log.DebugFormat("{0}: Dispose()", LogHeader); | 551 | // m_log.DebugFormat("{0}: Dispose()", LogHeader); |
552 | |||
553 | // make sure no stepping happens while we're deleting stuff | ||
554 | m_initialized = false; | ||
555 | |||
556 | if (m_constraintCollection != null) | ||
557 | { | ||
558 | m_constraintCollection.Dispose(); | ||
559 | m_constraintCollection = null; | ||
560 | } | ||
561 | |||
562 | foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) | ||
563 | { | ||
564 | kvp.Value.Destroy(); | ||
565 | } | ||
566 | m_avatars.Clear(); | ||
567 | |||
568 | foreach (KeyValuePair<uint, BSPrim> kvp in m_prims) | ||
569 | { | ||
570 | kvp.Value.Destroy(); | ||
571 | } | ||
572 | m_prims.Clear(); | ||
573 | |||
574 | // Anything left in the unmanaged code should be cleaned out | ||
575 | BulletSimAPI.Shutdown(WorldID); | ||
576 | |||
577 | // Not logging any more | ||
578 | PhysicsLogging.Close(); | ||
558 | } | 579 | } |
559 | 580 | ||
560 | public override Dictionary<uint, float> GetTopColliders() | 581 | public override Dictionary<uint, float> GetTopColliders() |
@@ -680,10 +701,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
680 | } | 701 | } |
681 | 702 | ||
682 | // The calls to the PhysicsActors can't directly call into the physics engine | 703 | // The calls to the PhysicsActors can't directly call into the physics engine |
683 | // because it might be busy. We we delay changes to a known time. | 704 | // because it might be busy. We delay changes to a known time. |
684 | // We rely on C#'s closure to save and restore the context for the delegate. | 705 | // We rely on C#'s closure to save and restore the context for the delegate. |
685 | public void TaintedObject(TaintCallback callback) | 706 | public void TaintedObject(TaintCallback callback) |
686 | { | 707 | { |
708 | if (!m_initialized) return; | ||
709 | |||
687 | lock (_taintLock) | 710 | lock (_taintLock) |
688 | _taintedObjects.Add(callback); | 711 | _taintedObjects.Add(callback); |
689 | return; | 712 | return; |
@@ -757,61 +780,371 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
757 | } | 780 | } |
758 | #endregion Vehicles | 781 | #endregion Vehicles |
759 | 782 | ||
760 | #region Runtime settable parameters | 783 | #region Parameters |
761 | public static PhysParameterEntry[] SettableParameters = new PhysParameterEntry[] | 784 | |
762 | { | 785 | delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); |
763 | new PhysParameterEntry("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)"), | 786 | delegate float ParamGet(BSScene scene); |
764 | new PhysParameterEntry("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)"), | 787 | delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); |
765 | new PhysParameterEntry("MaxSubStep", "In simulation step, maximum number of substeps"), | 788 | |
766 | new PhysParameterEntry("FixedTimeStep", "In simulation step, seconds of one substep (1/60)"), | 789 | private struct ParameterDefn |
767 | new PhysParameterEntry("MaxObjectMass", "Maximum object mass (10000.01)"), | 790 | { |
768 | new PhysParameterEntry("DetailedStats", "Frames between outputting detailed phys stats. Zero is off"), | 791 | public string name; |
769 | 792 | public string desc; | |
770 | new PhysParameterEntry("DefaultFriction", "Friction factor used on new objects"), | 793 | public float defaultValue; |
771 | new PhysParameterEntry("DefaultDensity", "Density for new objects" ), | 794 | public ParamUser userParam; |
772 | new PhysParameterEntry("DefaultRestitution", "Bouncyness of an object" ), | 795 | public ParamGet getter; |
773 | // new PhysParameterEntry("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!!)" ), | 796 | public ParamSet setter; |
774 | new PhysParameterEntry("Gravity", "Vertical force of gravity (negative means down)" ), | 797 | public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) |
775 | 798 | { | |
776 | new PhysParameterEntry("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)" ), | 799 | name = n; |
777 | new PhysParameterEntry("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)" ), | 800 | desc = d; |
778 | new PhysParameterEntry("DeactivationTime", "Seconds before considering an object potentially static" ), | 801 | defaultValue = v; |
779 | new PhysParameterEntry("LinearSleepingThreshold", "Seconds to measure linear movement before considering static" ), | 802 | userParam = u; |
780 | new PhysParameterEntry("AngularSleepingThreshold", "Seconds to measure angular movement before considering static" ), | 803 | getter = g; |
781 | new PhysParameterEntry("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ), | 804 | setter = s; |
782 | new PhysParameterEntry("CcdSweptSphereRadius", "Continuious collision detection test radius" ), | 805 | } |
783 | new PhysParameterEntry("ContactProcessingThreshold", "Distance between contacts before doing collision check" ), | 806 | } |
784 | // Can only change the following at initialization time. Change the INI file and reboot. | 807 | |
785 | new PhysParameterEntry("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)"), | 808 | // List of all of the externally visible parameters. |
786 | new PhysParameterEntry("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count"), | 809 | // For each parameter, this table maps a text name to getter and setters. |
787 | new PhysParameterEntry("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step"), | 810 | // A ParameterDefn() takes the following parameters: |
788 | new PhysParameterEntry("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction"), | 811 | // -- the text name of the parameter. This is used for console input and ini file. |
789 | new PhysParameterEntry("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands"), | 812 | // -- a short text description of the parameter. This shows up in the console listing. |
790 | new PhysParameterEntry("ShouldEnableFrictionCaching", "Enable friction computation caching"), | 813 | // -- a delegate for fetching the parameter from the ini file. |
791 | new PhysParameterEntry("NumberOfSolverIterations", "Number of internal iterations (0 means default)"), | 814 | // Should handle fetching the right type from the ini file and converting it. |
792 | 815 | // -- a delegate for getting the value as a float | |
793 | new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ), | 816 | // -- a delegate for setting the value from a float |
794 | new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ), | 817 | // |
795 | 818 | // To add a new variable, it is best to find an existing definition and copy it. | |
796 | new PhysParameterEntry("Friction", "Set friction parameter for a specific object" ), | 819 | private ParameterDefn[] ParameterDefinitions = |
797 | new PhysParameterEntry("Restitution", "Set restitution parameter for a specific object" ), | 820 | { |
798 | 821 | new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", | |
799 | new PhysParameterEntry("TerrainFriction", "Factor to reduce movement against terrain surface" ), | 822 | ConfigurationParameters.numericTrue, |
800 | new PhysParameterEntry("TerrainHitFraction", "Distance to measure hit collisions" ), | 823 | (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, |
801 | new PhysParameterEntry("TerrainRestitution", "Bouncyness" ), | 824 | (s) => { return s.NumericBool(s._meshSculptedPrim); }, |
802 | new PhysParameterEntry("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation." ), | 825 | (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ), |
803 | new PhysParameterEntry("AvatarDensity", "Density of an avatar. Changed on avatar recreation." ), | 826 | new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", |
804 | new PhysParameterEntry("AvatarRestitution", "Bouncyness. Changed on avatar recreation." ), | 827 | ConfigurationParameters.numericFalse, |
805 | new PhysParameterEntry("AvatarCapsuleRadius", "Radius of space around an avatar" ), | 828 | (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, |
806 | new PhysParameterEntry("AvatarCapsuleHeight", "Default height of space around avatar" ), | 829 | (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, |
807 | new PhysParameterEntry("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions") | 830 | (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), |
831 | |||
832 | new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", | ||
833 | 8f, | ||
834 | (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); }, | ||
835 | (s) => { return (float)s.m_meshLOD; }, | ||
836 | (s,p,l,v) => { s.m_meshLOD = (int)v; } ), | ||
837 | new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", | ||
838 | 32, | ||
839 | (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, | ||
840 | (s) => { return (float)s.m_sculptLOD; }, | ||
841 | (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), | ||
842 | |||
843 | new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", | ||
844 | 10f, | ||
845 | (s,cf,p,v) => { s.m_maxSubSteps = cf.GetInt(p, (int)v); }, | ||
846 | (s) => { return (float)s.m_maxSubSteps; }, | ||
847 | (s,p,l,v) => { s.m_maxSubSteps = (int)v; } ), | ||
848 | new ParameterDefn("FixedTimeStep", "In simulation step, seconds of one substep (1/60)", | ||
849 | 1f / 60f, | ||
850 | (s,cf,p,v) => { s.m_fixedTimeStep = cf.GetFloat(p, v); }, | ||
851 | (s) => { return (float)s.m_fixedTimeStep; }, | ||
852 | (s,p,l,v) => { s.m_fixedTimeStep = v; } ), | ||
853 | new ParameterDefn("MaxCollisionsPerFrame", "Max collisions returned at end of each frame", | ||
854 | 2048f, | ||
855 | (s,cf,p,v) => { s.m_maxCollisionsPerFrame = cf.GetInt(p, (int)v); }, | ||
856 | (s) => { return (float)s.m_maxCollisionsPerFrame; }, | ||
857 | (s,p,l,v) => { s.m_maxCollisionsPerFrame = (int)v; } ), | ||
858 | new ParameterDefn("MaxUpdatesPerFrame", "Max updates returned at end of each frame", | ||
859 | 8000f, | ||
860 | (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, | ||
861 | (s) => { return (float)s.m_maxUpdatesPerFrame; }, | ||
862 | (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), | ||
863 | new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", | ||
864 | 10000.01f, | ||
865 | (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); }, | ||
866 | (s) => { return (float)s.m_maximumObjectMass; }, | ||
867 | (s,p,l,v) => { s.m_maximumObjectMass = v; } ), | ||
868 | |||
869 | new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", | ||
870 | 2200f, | ||
871 | (s,cf,p,v) => { s.PID_D = cf.GetFloat(p, v); }, | ||
872 | (s) => { return (float)s.PID_D; }, | ||
873 | (s,p,l,v) => { s.PID_D = v; } ), | ||
874 | new ParameterDefn("PID_P", "Parameteric factor for motion smoothing", | ||
875 | 900f, | ||
876 | (s,cf,p,v) => { s.PID_P = cf.GetFloat(p, v); }, | ||
877 | (s) => { return (float)s.PID_P; }, | ||
878 | (s,p,l,v) => { s.PID_P = v; } ), | ||
879 | |||
880 | new ParameterDefn("DefaultFriction", "Friction factor used on new objects", | ||
881 | 0.5f, | ||
882 | (s,cf,p,v) => { s.m_params[0].defaultFriction = cf.GetFloat(p, v); }, | ||
883 | (s) => { return s.m_params[0].defaultFriction; }, | ||
884 | (s,p,l,v) => { s.m_params[0].defaultFriction = v; } ), | ||
885 | new ParameterDefn("DefaultDensity", "Density for new objects" , | ||
886 | 10.000006836f, // Aluminum g/cm3 | ||
887 | (s,cf,p,v) => { s.m_params[0].defaultDensity = cf.GetFloat(p, v); }, | ||
888 | (s) => { return s.m_params[0].defaultDensity; }, | ||
889 | (s,p,l,v) => { s.m_params[0].defaultDensity = v; } ), | ||
890 | new ParameterDefn("DefaultRestitution", "Bouncyness of an object" , | ||
891 | 0f, | ||
892 | (s,cf,p,v) => { s.m_params[0].defaultRestitution = cf.GetFloat(p, v); }, | ||
893 | (s) => { return s.m_params[0].defaultRestitution; }, | ||
894 | (s,p,l,v) => { s.m_params[0].defaultRestitution = v; } ), | ||
895 | new ParameterDefn("CollisionMargin", "Margin around objects before collisions are calculated (must be zero!)", | ||
896 | 0f, | ||
897 | (s,cf,p,v) => { s.m_params[0].collisionMargin = cf.GetFloat(p, v); }, | ||
898 | (s) => { return s.m_params[0].collisionMargin; }, | ||
899 | (s,p,l,v) => { s.m_params[0].collisionMargin = v; } ), | ||
900 | new ParameterDefn("Gravity", "Vertical force of gravity (negative means down)", | ||
901 | -9.80665f, | ||
902 | (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); }, | ||
903 | (s) => { return s.m_params[0].gravity; }, | ||
904 | (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ), | ||
905 | |||
906 | |||
907 | new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", | ||
908 | 0f, | ||
909 | (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, | ||
910 | (s) => { return s.m_params[0].linearDamping; }, | ||
911 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ), | ||
912 | new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", | ||
913 | 0f, | ||
914 | (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, | ||
915 | (s) => { return s.m_params[0].angularDamping; }, | ||
916 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ), | ||
917 | new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", | ||
918 | 0.2f, | ||
919 | (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, | ||
920 | (s) => { return s.m_params[0].deactivationTime; }, | ||
921 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ), | ||
922 | new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", | ||
923 | 0.8f, | ||
924 | (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, | ||
925 | (s) => { return s.m_params[0].linearSleepingThreshold; }, | ||
926 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), | ||
927 | new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", | ||
928 | 1.0f, | ||
929 | (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, | ||
930 | (s) => { return s.m_params[0].angularSleepingThreshold; }, | ||
931 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), | ||
932 | new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , | ||
933 | 0f, // set to zero to disable | ||
934 | (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, | ||
935 | (s) => { return s.m_params[0].ccdMotionThreshold; }, | ||
936 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), | ||
937 | new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , | ||
938 | 0f, | ||
939 | (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, | ||
940 | (s) => { return s.m_params[0].ccdSweptSphereRadius; }, | ||
941 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), | ||
942 | new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , | ||
943 | 0.1f, | ||
944 | (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, | ||
945 | (s) => { return s.m_params[0].contactProcessingThreshold; }, | ||
946 | (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), | ||
947 | |||
948 | new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , | ||
949 | 0.5f, | ||
950 | (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, | ||
951 | (s) => { return s.m_params[0].terrainFriction; }, | ||
952 | (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ), | ||
953 | new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , | ||
954 | 0.8f, | ||
955 | (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); }, | ||
956 | (s) => { return s.m_params[0].terrainHitFraction; }, | ||
957 | (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ), | ||
958 | new ParameterDefn("TerrainRestitution", "Bouncyness" , | ||
959 | 0f, | ||
960 | (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, | ||
961 | (s) => { return s.m_params[0].terrainRestitution; }, | ||
962 | (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), | ||
963 | new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", | ||
964 | 0.5f, | ||
965 | (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, | ||
966 | (s) => { return s.m_params[0].avatarFriction; }, | ||
967 | (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ), | ||
968 | new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", | ||
969 | 60f, | ||
970 | (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, | ||
971 | (s) => { return s.m_params[0].avatarDensity; }, | ||
972 | (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ), | ||
973 | new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", | ||
974 | 0f, | ||
975 | (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, | ||
976 | (s) => { return s.m_params[0].avatarRestitution; }, | ||
977 | (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ), | ||
978 | new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", | ||
979 | 0.37f, | ||
980 | (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, | ||
981 | (s) => { return s.m_params[0].avatarCapsuleRadius; }, | ||
982 | (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), | ||
983 | new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", | ||
984 | 1.5f, | ||
985 | (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, | ||
986 | (s) => { return s.m_params[0].avatarCapsuleHeight; }, | ||
987 | (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), | ||
988 | new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", | ||
989 | 0.1f, | ||
990 | (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, | ||
991 | (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, | ||
992 | (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), | ||
993 | |||
994 | |||
995 | new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)", | ||
996 | 0f, // zero to disable | ||
997 | (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, | ||
998 | (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, | ||
999 | (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), | ||
1000 | new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", | ||
1001 | ConfigurationParameters.numericTrue, | ||
1002 | (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | ||
1003 | (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; }, | ||
1004 | (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ), | ||
1005 | new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", | ||
1006 | ConfigurationParameters.numericFalse, | ||
1007 | (s,cf,p,v) => { s.m_params[0].shouldForceUpdateAllAabbs = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | ||
1008 | (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; }, | ||
1009 | (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ), | ||
1010 | new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", | ||
1011 | ConfigurationParameters.numericFalse, | ||
1012 | (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | ||
1013 | (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, | ||
1014 | (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), | ||
1015 | new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", | ||
1016 | ConfigurationParameters.numericFalse, | ||
1017 | (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | ||
1018 | (s) => { return s.m_params[0].shouldSplitSimulationIslands; }, | ||
1019 | (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ), | ||
1020 | new ParameterDefn("ShouldEnableFrictionCaching", "Enable friction computation caching", | ||
1021 | ConfigurationParameters.numericFalse, | ||
1022 | (s,cf,p,v) => { s.m_params[0].shouldEnableFrictionCaching = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | ||
1023 | (s) => { return s.m_params[0].shouldEnableFrictionCaching; }, | ||
1024 | (s,p,l,v) => { s.m_params[0].shouldEnableFrictionCaching = v; } ), | ||
1025 | new ParameterDefn("NumberOfSolverIterations", "Number of internal iterations (0 means default)", | ||
1026 | 0f, // zero says use Bullet default | ||
1027 | (s,cf,p,v) => { s.m_params[0].numberOfSolverIterations = cf.GetFloat(p, v); }, | ||
1028 | (s) => { return s.m_params[0].numberOfSolverIterations; }, | ||
1029 | (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), | ||
1030 | |||
1031 | new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", | ||
1032 | ConfigurationParameters.numericFalse, | ||
1033 | (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | ||
1034 | (s) => { return s.m_params[0].linkConstraintUseFrameOffset; }, | ||
1035 | (s,p,l,v) => { s.m_params[0].linkConstraintUseFrameOffset = v; } ), | ||
1036 | new ParameterDefn("LinkConstraintEnableTransMotor", "Whether to enable translational motor on linkset constraints", | ||
1037 | ConfigurationParameters.numericTrue, | ||
1038 | (s,cf,p,v) => { s.m_params[0].linkConstraintEnableTransMotor = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, | ||
1039 | (s) => { return s.m_params[0].linkConstraintEnableTransMotor; }, | ||
1040 | (s,p,l,v) => { s.m_params[0].linkConstraintEnableTransMotor = v; } ), | ||
1041 | new ParameterDefn("LinkConstraintTransMotorMaxVel", "Maximum velocity to be applied by translational motor in linkset constraints", | ||
1042 | 5.0f, | ||
1043 | (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = cf.GetFloat(p, v); }, | ||
1044 | (s) => { return s.m_params[0].linkConstraintTransMotorMaxVel; }, | ||
1045 | (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxVel = v; } ), | ||
1046 | new ParameterDefn("LinkConstraintTransMotorMaxForce", "Maximum force to be applied by translational motor in linkset constraints", | ||
1047 | 0.1f, | ||
1048 | (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, | ||
1049 | (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, | ||
1050 | (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), | ||
1051 | |||
1052 | new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", | ||
1053 | 0f, | ||
1054 | (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, | ||
1055 | (s) => { return (float)s.m_detailedStatsStep; }, | ||
1056 | (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), | ||
1057 | new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements", | ||
1058 | ConfigurationParameters.numericFalse, | ||
1059 | (s,cf,p,v) => { s.shouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); }, | ||
1060 | (s) => { return s.NumericBool(s.shouldDebugLog); }, | ||
1061 | (s,p,l,v) => { s.shouldDebugLog = s.BoolNumeric(v); } ), | ||
808 | 1062 | ||
809 | }; | 1063 | }; |
810 | 1064 | ||
1065 | // Convert a boolean to our numeric true and false values | ||
1066 | public float NumericBool(bool b) | ||
1067 | { | ||
1068 | return (b ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse); | ||
1069 | } | ||
1070 | |||
1071 | // Convert numeric true and false values to a boolean | ||
1072 | public bool BoolNumeric(float b) | ||
1073 | { | ||
1074 | return (b == ConfigurationParameters.numericTrue ? true : false); | ||
1075 | } | ||
1076 | |||
1077 | // Search through the parameter definitions and return the matching | ||
1078 | // ParameterDefn structure. | ||
1079 | // Case does not matter as names are compared after converting to lower case. | ||
1080 | // Returns 'false' if the parameter is not found. | ||
1081 | private bool TryGetParameter(string paramName, out ParameterDefn defn) | ||
1082 | { | ||
1083 | bool ret = false; | ||
1084 | ParameterDefn foundDefn = new ParameterDefn(); | ||
1085 | string pName = paramName.ToLower(); | ||
1086 | |||
1087 | foreach (ParameterDefn parm in ParameterDefinitions) | ||
1088 | { | ||
1089 | if (pName == parm.name.ToLower()) | ||
1090 | { | ||
1091 | foundDefn = parm; | ||
1092 | ret = true; | ||
1093 | break; | ||
1094 | } | ||
1095 | } | ||
1096 | defn = foundDefn; | ||
1097 | return ret; | ||
1098 | } | ||
1099 | |||
1100 | // Pass through the settable parameters and set the default values | ||
1101 | private void SetParameterDefaultValues() | ||
1102 | { | ||
1103 | foreach (ParameterDefn parm in ParameterDefinitions) | ||
1104 | { | ||
1105 | parm.setter(this, parm.name, PhysParameterEntry.APPLY_TO_NONE, parm.defaultValue); | ||
1106 | } | ||
1107 | } | ||
1108 | |||
1109 | // Get user set values out of the ini file. | ||
1110 | private void SetParameterConfigurationValues(IConfig cfg) | ||
1111 | { | ||
1112 | foreach (ParameterDefn parm in ParameterDefinitions) | ||
1113 | { | ||
1114 | parm.userParam(this, cfg, parm.name, parm.defaultValue); | ||
1115 | } | ||
1116 | } | ||
1117 | |||
1118 | private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; | ||
1119 | |||
1120 | private void BuildParameterTable() | ||
1121 | { | ||
1122 | if (SettableParameters.Length < ParameterDefinitions.Length) | ||
1123 | { | ||
1124 | |||
1125 | List<PhysParameterEntry> entries = new List<PhysParameterEntry>(); | ||
1126 | for (int ii = 0; ii < ParameterDefinitions.Length; ii++) | ||
1127 | { | ||
1128 | ParameterDefn pd = ParameterDefinitions[ii]; | ||
1129 | entries.Add(new PhysParameterEntry(pd.name, pd.desc)); | ||
1130 | } | ||
1131 | |||
1132 | // make the list in alphabetical order for estetic reasons | ||
1133 | entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2) | ||
1134 | { | ||
1135 | return ppe1.name.CompareTo(ppe2.name); | ||
1136 | }); | ||
1137 | |||
1138 | SettableParameters = entries.ToArray(); | ||
1139 | } | ||
1140 | } | ||
1141 | |||
1142 | |||
811 | #region IPhysicsParameters | 1143 | #region IPhysicsParameters |
812 | // Get the list of parameters this physics engine supports | 1144 | // Get the list of parameters this physics engine supports |
813 | public PhysParameterEntry[] GetParameterList() | 1145 | public PhysParameterEntry[] GetParameterList() |
814 | { | 1146 | { |
1147 | BuildParameterTable(); | ||
815 | return SettableParameters; | 1148 | return SettableParameters; |
816 | } | 1149 | } |
817 | 1150 | ||
@@ -823,63 +1156,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
823 | // value activated ('terrainFriction' for instance). | 1156 | // value activated ('terrainFriction' for instance). |
824 | public bool SetPhysicsParameter(string parm, float val, uint localID) | 1157 | public bool SetPhysicsParameter(string parm, float val, uint localID) |
825 | { | 1158 | { |
826 | bool ret = true; | 1159 | bool ret = false; |
827 | string lparm = parm.ToLower(); | 1160 | ParameterDefn theParam; |
828 | switch (lparm) | 1161 | if (TryGetParameter(parm, out theParam)) |
829 | { | 1162 | { |
830 | case "detailedstats": m_detailedStatsStep = (int)val; break; | 1163 | theParam.setter(this, parm, localID, val); |
831 | 1164 | ret = true; | |
832 | case "meshlod": m_meshLOD = (int)val; break; | ||
833 | case "sculptlod": m_sculptLOD = (int)val; break; | ||
834 | case "maxsubstep": m_maxSubSteps = (int)val; break; | ||
835 | case "fixedtimestep": m_fixedTimeStep = val; break; | ||
836 | case "maxobjectmass": m_maximumObjectMass = val; break; | ||
837 | |||
838 | case "defaultfriction": m_params[0].defaultFriction = val; break; | ||
839 | case "defaultdensity": m_params[0].defaultDensity = val; break; | ||
840 | case "defaultrestitution": m_params[0].defaultRestitution = val; break; | ||
841 | case "collisionmargin": m_params[0].collisionMargin = val; break; | ||
842 | case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, localID, val); break; | ||
843 | |||
844 | case "lineardamping": UpdateParameterPrims(ref m_params[0].linearDamping, lparm, localID, val); break; | ||
845 | case "angulardamping": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break; | ||
846 | case "deactivationtime": UpdateParameterPrims(ref m_params[0].deactivationTime, lparm, localID, val); break; | ||
847 | case "linearsleepingthreshold": UpdateParameterPrims(ref m_params[0].linearSleepingThreshold, lparm, localID, val); break; | ||
848 | case "angularsleepingthreshold": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break; | ||
849 | case "ccdmotionthreshold": UpdateParameterPrims(ref m_params[0].ccdMotionThreshold, lparm, localID, val); break; | ||
850 | case "ccdsweptsphereradius": UpdateParameterPrims(ref m_params[0].ccdSweptSphereRadius, lparm, localID, val); break; | ||
851 | case "contactprocessingthreshold": UpdateParameterPrims(ref m_params[0].contactProcessingThreshold, lparm, localID, val); break; | ||
852 | // the following are used only at initialization time so setting them makes no sense | ||
853 | // case "maxPersistantmanifoldpoolSize": m_params[0].maxPersistantManifoldPoolSize = val; break; | ||
854 | // case "shoulddisablecontactpooldynamicallocation": m_params[0].shouldDisableContactPoolDynamicAllocation = val; break; | ||
855 | // case "shouldforceupdateallaabbs": m_params[0].shouldForceUpdateAllAabbs = val; break; | ||
856 | // case "shouldrandomizesolverorder": m_params[0].shouldRandomizeSolverOrder = val; break; | ||
857 | // case "shouldsplitsimulationislands": m_params[0].shouldSplitSimulationIslands = val; break; | ||
858 | // case "shouldenablefrictioncaching": m_params[0].shouldEnableFrictionCaching = val; break; | ||
859 | // case "numberofsolveriterations": m_params[0].numberOfSolverIterations = val; break; | ||
860 | |||
861 | case "friction": TaintedUpdateParameter(lparm, localID, val); break; | ||
862 | case "restitution": TaintedUpdateParameter(lparm, localID, val); break; | ||
863 | |||
864 | // set a terrain physical feature and cause terrain to be recalculated | ||
865 | case "terrainfriction": m_params[0].terrainFriction = val; TaintedUpdateParameter("terrain", 0, val); break; | ||
866 | case "terrainhitfraction": m_params[0].terrainHitFraction = val; TaintedUpdateParameter("terrain", 0, val); break; | ||
867 | case "terrainrestitution": m_params[0].terrainRestitution = val; TaintedUpdateParameter("terrain", 0, val); break; | ||
868 | // set an avatar physical feature and cause avatar(s) to be recalculated | ||
869 | case "avatarfriction": UpdateParameterAvatars(ref m_params[0].avatarFriction, "avatar", localID, val); break; | ||
870 | case "avatardensity": UpdateParameterAvatars(ref m_params[0].avatarDensity, "avatar", localID, val); break; | ||
871 | case "avatarrestitution": UpdateParameterAvatars(ref m_params[0].avatarRestitution, "avatar", localID, val); break; | ||
872 | case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break; | ||
873 | case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break; | ||
874 | case "avatarcontactprocessingthreshold": UpdateParameterAvatars(ref m_params[0].avatarContactProcessingThreshold, "avatar", localID, val); break; | ||
875 | |||
876 | default: ret = false; break; | ||
877 | } | 1165 | } |
878 | return ret; | 1166 | return ret; |
879 | } | 1167 | } |
880 | 1168 | ||
881 | // check to see if we are updating a parameter for a particular or all of the prims | 1169 | // check to see if we are updating a parameter for a particular or all of the prims |
882 | private void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) | 1170 | protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) |
883 | { | 1171 | { |
884 | List<uint> operateOn; | 1172 | List<uint> operateOn; |
885 | lock (m_prims) operateOn = new List<uint>(m_prims.Keys); | 1173 | lock (m_prims) operateOn = new List<uint>(m_prims.Keys); |
@@ -887,7 +1175,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
887 | } | 1175 | } |
888 | 1176 | ||
889 | // check to see if we are updating a parameter for a particular or all of the avatars | 1177 | // check to see if we are updating a parameter for a particular or all of the avatars |
890 | private void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val) | 1178 | protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val) |
891 | { | 1179 | { |
892 | List<uint> operateOn; | 1180 | List<uint> operateOn; |
893 | lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys); | 1181 | lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys); |
@@ -898,7 +1186,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
898 | // If the local ID is APPLY_TO_NONE, just change the default value | 1186 | // If the local ID is APPLY_TO_NONE, just change the default value |
899 | // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs | 1187 | // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs |
900 | // If the localID is a specific object, apply the parameter change to only that object | 1188 | // If the localID is a specific object, apply the parameter change to only that object |
901 | private void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val) | 1189 | protected void UpdateParameterSet(List<uint> lIDs, ref float defaultLoc, string parm, uint localID, float val) |
902 | { | 1190 | { |
903 | switch (localID) | 1191 | switch (localID) |
904 | { | 1192 | { |
@@ -925,7 +1213,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
925 | } | 1213 | } |
926 | 1214 | ||
927 | // schedule the actual updating of the paramter to when the phys engine is not busy | 1215 | // schedule the actual updating of the paramter to when the phys engine is not busy |
928 | private void TaintedUpdateParameter(string parm, uint localID, float val) | 1216 | protected void TaintedUpdateParameter(string parm, uint localID, float val) |
929 | { | 1217 | { |
930 | uint xlocalID = localID; | 1218 | uint xlocalID = localID; |
931 | string xparm = parm.ToLower(); | 1219 | string xparm = parm.ToLower(); |
@@ -940,50 +1228,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters | |||
940 | public bool GetPhysicsParameter(string parm, out float value) | 1228 | public bool GetPhysicsParameter(string parm, out float value) |
941 | { | 1229 | { |
942 | float val = 0f; | 1230 | float val = 0f; |
943 | bool ret = true; | 1231 | bool ret = false; |
944 | switch (parm.ToLower()) | 1232 | ParameterDefn theParam; |
945 | { | 1233 | if (TryGetParameter(parm, out theParam)) |
946 | case "detailedstats": val = (int)m_detailedStatsStep; break; | 1234 | { |
947 | case "meshlod": val = (float)m_meshLOD; break; | 1235 | val = theParam.getter(this); |
948 | case "sculptlod": val = (float)m_sculptLOD; break; | 1236 | ret = true; |
949 | case "maxsubstep": val = (float)m_maxSubSteps; break; | ||
950 | case "fixedtimestep": val = m_fixedTimeStep; break; | ||
951 | case "maxobjectmass": val = m_maximumObjectMass; break; | ||
952 | |||
953 | case "defaultfriction": val = m_params[0].defaultFriction; break; | ||
954 | case "defaultdensity": val = m_params[0].defaultDensity; break; | ||
955 | case "defaultrestitution": val = m_params[0].defaultRestitution; break; | ||
956 | case "collisionmargin": val = m_params[0].collisionMargin; break; | ||
957 | case "gravity": val = m_params[0].gravity; break; | ||
958 | |||
959 | case "lineardamping": val = m_params[0].linearDamping; break; | ||
960 | case "angulardamping": val = m_params[0].angularDamping; break; | ||
961 | case "deactivationtime": val = m_params[0].deactivationTime; break; | ||
962 | case "linearsleepingthreshold": val = m_params[0].linearSleepingThreshold; break; | ||
963 | case "angularsleepingthreshold": val = m_params[0].angularDamping; break; | ||
964 | case "ccdmotionthreshold": val = m_params[0].ccdMotionThreshold; break; | ||
965 | case "ccdsweptsphereradius": val = m_params[0].ccdSweptSphereRadius; break; | ||
966 | case "contactprocessingthreshold": val = m_params[0].contactProcessingThreshold; break; | ||
967 | case "maxPersistantmanifoldpoolSize": val = m_params[0].maxPersistantManifoldPoolSize; break; | ||
968 | case "shoulddisablecontactpooldynamicallocation": val = m_params[0].shouldDisableContactPoolDynamicAllocation; break; | ||
969 | case "shouldforceupdateallaabbs": val = m_params[0].shouldForceUpdateAllAabbs; break; | ||
970 | case "shouldrandomizesolverorder": val = m_params[0].shouldRandomizeSolverOrder; break; | ||
971 | case "shouldsplitsimulationislands": val = m_params[0].shouldSplitSimulationIslands; break; | ||
972 | case "shouldenablefrictioncaching": val = m_params[0].shouldEnableFrictionCaching; break; | ||
973 | case "numberofsolveriterations": val = m_params[0].numberOfSolverIterations; break; | ||
974 | |||
975 | case "terrainfriction": val = m_params[0].terrainFriction; break; | ||
976 | case "terrainhitfraction": val = m_params[0].terrainHitFraction; break; | ||
977 | case "terrainrestitution": val = m_params[0].terrainRestitution; break; | ||
978 | |||
979 | case "avatarfriction": val = m_params[0].avatarFriction; break; | ||
980 | case "avatardensity": val = m_params[0].avatarDensity; break; | ||
981 | case "avatarrestitution": val = m_params[0].avatarRestitution; break; | ||
982 | case "avatarcapsuleradius": val = m_params[0].avatarCapsuleRadius; break; | ||
983 | case "avatarcapsuleheight": val = m_params[0].avatarCapsuleHeight; break; | ||
984 | case "avatarcontactprocessingthreshold": val = m_params[0].avatarContactProcessingThreshold; break; | ||
985 | default: ret = false; break; | ||
986 | |||
987 | } | 1237 | } |
988 | value = val; | 1238 | value = val; |
989 | return ret; | 1239 | return ret; |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 086f0dc..65e3145 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | |||
@@ -32,6 +32,28 @@ using OpenMetaverse; | |||
32 | 32 | ||
33 | namespace OpenSim.Region.Physics.BulletSPlugin { | 33 | namespace OpenSim.Region.Physics.BulletSPlugin { |
34 | 34 | ||
35 | // Classes to allow some type checking for the API | ||
36 | public struct BulletSim | ||
37 | { | ||
38 | public BulletSim(uint id, IntPtr xx) { ID = id; Ptr = xx; } | ||
39 | public IntPtr Ptr; | ||
40 | public uint ID; | ||
41 | } | ||
42 | |||
43 | public struct BulletBody | ||
44 | { | ||
45 | public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; } | ||
46 | public IntPtr Ptr; | ||
47 | public uint ID; | ||
48 | } | ||
49 | |||
50 | public struct BulletConstraint | ||
51 | { | ||
52 | public BulletConstraint(IntPtr xx) { Ptr = xx; } | ||
53 | public IntPtr Ptr; | ||
54 | } | ||
55 | |||
56 | // =============================================================================== | ||
35 | [StructLayout(LayoutKind.Sequential)] | 57 | [StructLayout(LayoutKind.Sequential)] |
36 | public struct ConvexHull | 58 | public struct ConvexHull |
37 | { | 59 | { |
@@ -142,10 +164,32 @@ public struct ConfigurationParameters | |||
142 | public float shouldEnableFrictionCaching; | 164 | public float shouldEnableFrictionCaching; |
143 | public float numberOfSolverIterations; | 165 | public float numberOfSolverIterations; |
144 | 166 | ||
167 | public float linkConstraintUseFrameOffset; | ||
168 | public float linkConstraintEnableTransMotor; | ||
169 | public float linkConstraintTransMotorMaxVel; | ||
170 | public float linkConstraintTransMotorMaxForce; | ||
171 | |||
145 | public const float numericTrue = 1f; | 172 | public const float numericTrue = 1f; |
146 | public const float numericFalse = 0f; | 173 | public const float numericFalse = 0f; |
147 | } | 174 | } |
148 | 175 | ||
176 | // Values used by Bullet and BulletSim to control collisions | ||
177 | public enum CollisionFlags : uint | ||
178 | { | ||
179 | STATIC_OBJECT = 1 << 0, | ||
180 | KINEMATIC_OBJECT = 1 << 1, | ||
181 | NO_CONTACT_RESPONSE = 1 << 2, | ||
182 | CUSTOM_MATERIAL_CALLBACK = 1 << 3, | ||
183 | CHARACTER_OBJECT = 1 << 4, | ||
184 | DISABLE_VISUALIZE_OBJECT = 1 << 5, | ||
185 | DISABLE_SPU_COLLISION_PROCESS = 1 << 6, | ||
186 | // Following used by BulletSim to control collisions | ||
187 | VOLUME_DETECT_OBJECT = 1 << 10, | ||
188 | PHANTOM_OBJECT = 1 << 11, | ||
189 | PHYSICAL_OBJECT = 1 << 12, | ||
190 | }; | ||
191 | |||
192 | // =============================================================================== | ||
149 | static class BulletSimAPI { | 193 | static class BulletSimAPI { |
150 | 194 | ||
151 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 195 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
@@ -195,6 +239,7 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey); | |||
195 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 239 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
196 | public static extern bool CreateObject(uint worldID, ShapeData shapeData); | 240 | public static extern bool CreateObject(uint worldID, ShapeData shapeData); |
197 | 241 | ||
242 | /* Remove old functionality | ||
198 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 243 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
199 | public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); | 244 | public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); |
200 | 245 | ||
@@ -209,11 +254,15 @@ public static extern bool RemoveConstraintByID(uint worldID, uint id1); | |||
209 | 254 | ||
210 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 255 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
211 | public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); | 256 | public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); |
257 | */ | ||
212 | 258 | ||
213 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 259 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
214 | public static extern Vector3 GetObjectPosition(uint WorldID, uint id); | 260 | public static extern Vector3 GetObjectPosition(uint WorldID, uint id); |
215 | 261 | ||
216 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 262 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
263 | public static extern Quaternion GetObjectOrientation(uint WorldID, uint id); | ||
264 | |||
265 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
217 | public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation); | 266 | public static extern bool SetObjectTranslation(uint worldID, uint id, Vector3 position, Quaternion rotation); |
218 | 267 | ||
219 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 268 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
@@ -268,5 +317,175 @@ public static extern void DumpBulletStatistics(); | |||
268 | public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); | 317 | public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); |
269 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 318 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
270 | public static extern void SetDebugLogCallback(DebugLogCallback callback); | 319 | public static extern void SetDebugLogCallback(DebugLogCallback callback); |
320 | |||
321 | // =============================================================================== | ||
322 | // =============================================================================== | ||
323 | // =============================================================================== | ||
324 | // A new version of the API that enables moving all the logic out of the C++ code and into | ||
325 | // the C# code. This will make modifications easier for the next person. | ||
326 | // This interface passes the actual pointers to the objects in the unmanaged | ||
327 | // address space. All the management (calls for creation/destruction/lookup) | ||
328 | // is done in the C# code. | ||
329 | // The names have a "2" tacked on. This will be removed as the C# code gets rebuilt | ||
330 | // and the old code is removed. | ||
331 | |||
332 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
333 | public static extern IntPtr GetSimHandle2(uint worldID); | ||
334 | |||
335 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
336 | public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id); | ||
337 | |||
338 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
339 | public static extern IntPtr GetBodyHandle2(IntPtr sim, uint id); | ||
340 | |||
341 | // =============================================================================== | ||
342 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
343 | public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, | ||
344 | int maxCollisions, IntPtr collisionArray, | ||
345 | int maxUpdates, IntPtr updateArray); | ||
346 | |||
347 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
348 | public static extern bool UpdateParameter2(IntPtr sim, uint localID, String parm, float value); | ||
349 | |||
350 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
351 | public static extern void SetHeightmap2(IntPtr sim, float[] heightmap); | ||
352 | |||
353 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
354 | public static extern void Shutdown2(IntPtr sim); | ||
355 | |||
356 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
357 | public static extern int PhysicsStep2(IntPtr sim, float timeStep, int maxSubSteps, float fixedTimeStep, | ||
358 | out int updatedEntityCount, | ||
359 | out IntPtr updatedEntitiesPtr, | ||
360 | out int collidersCount, | ||
361 | out IntPtr collidersPtr); | ||
362 | |||
363 | /* | ||
364 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
365 | public static extern IntPtr CreateMesh2(IntPtr sim, int indicesCount, int* indices, int verticesCount, float* vertices ); | ||
366 | |||
367 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
368 | public static extern bool BuildHull2(IntPtr sim, IntPtr mesh); | ||
369 | |||
370 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
371 | public static extern bool ReleaseHull2(IntPtr sim, IntPtr mesh); | ||
372 | |||
373 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
374 | public static extern bool DestroyMesh2(IntPtr sim, IntPtr mesh); | ||
375 | |||
376 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
377 | public static extern IntPtr CreateObject2(IntPtr sim, ShapeData shapeData); | ||
378 | */ | ||
379 | |||
380 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
381 | public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2, | ||
382 | Vector3 frame1loc, Quaternion frame1rot, | ||
383 | Vector3 frame2loc, Quaternion frame2rot); | ||
384 | |||
385 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
386 | public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); | ||
387 | |||
388 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
389 | public static extern bool SetAngularLimits2(IntPtr constrain, Vector3 low, Vector3 hi); | ||
390 | |||
391 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
392 | public static extern bool UseFrameOffset2(IntPtr constrain, float enable); | ||
393 | |||
394 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
395 | public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce); | ||
396 | |||
397 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
398 | public static extern bool CalculateTransforms2(IntPtr constrain); | ||
399 | |||
400 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
401 | public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain); | ||
402 | |||
403 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
404 | public static extern Vector3 GetPosition2(IntPtr obj); | ||
405 | |||
406 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
407 | public static extern Quaternion GetOrientation2(IntPtr obj); | ||
408 | |||
409 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
410 | public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); | ||
411 | |||
412 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
413 | public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity); | ||
414 | |||
415 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
416 | public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); | ||
417 | |||
418 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
419 | public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); | ||
420 | |||
421 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
422 | public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); | ||
423 | |||
424 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
425 | public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val); | ||
426 | |||
427 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
428 | public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping); | ||
429 | |||
430 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
431 | public static extern bool SetDeactivationTime2(IntPtr obj, float val); | ||
432 | |||
433 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
434 | public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); | ||
435 | |||
436 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
437 | public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val); | ||
438 | |||
439 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
440 | public static extern bool SetFriction2(IntPtr obj, float val); | ||
441 | |||
442 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
443 | public static extern bool SetRestitution2(IntPtr obj, float val); | ||
444 | |||
445 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
446 | public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val); | ||
447 | |||
448 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
449 | public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); | ||
450 | |||
451 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
452 | public static extern IntPtr SetCollisionFlags2(IntPtr obj, uint flags); | ||
453 | |||
454 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
455 | public static extern IntPtr AddToCollisionFlags2(IntPtr obj, uint flags); | ||
456 | |||
457 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
458 | public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, uint flags); | ||
459 | |||
460 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
461 | public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); | ||
462 | |||
463 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
464 | public static extern bool UpdateInertiaTensor2(IntPtr obj); | ||
465 | |||
466 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
467 | public static extern bool SetGravity2(IntPtr obj, Vector3 val); | ||
468 | |||
469 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
470 | public static extern IntPtr ClearForces2(IntPtr obj); | ||
471 | |||
472 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
473 | public static extern bool SetMargin2(IntPtr obj, float val); | ||
474 | |||
475 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
476 | public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj); | ||
477 | |||
478 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
479 | public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj); | ||
480 | |||
481 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
482 | public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj); | ||
483 | |||
484 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
485 | public static extern bool DestroyObject2(IntPtr world, uint id); | ||
486 | |||
487 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
488 | public static extern void DumpPhysicsStatistics2(IntPtr sim); | ||
489 | |||
271 | } | 490 | } |
272 | } | 491 | } |
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 32e81e2..929b019 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs | |||
@@ -290,7 +290,6 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
290 | 290 | ||
291 | private readonly IntPtr contactgroup; | 291 | private readonly IntPtr contactgroup; |
292 | 292 | ||
293 | internal IntPtr LandGeom; | ||
294 | internal IntPtr WaterGeom; | 293 | internal IntPtr WaterGeom; |
295 | 294 | ||
296 | private float nmTerrainContactFriction = 255.0f; | 295 | private float nmTerrainContactFriction = 255.0f; |
@@ -489,6 +488,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
489 | /// </summary> | 488 | /// </summary> |
490 | internal Object OdeLock = new Object(); | 489 | internal Object OdeLock = new Object(); |
491 | 490 | ||
491 | private bool _worldInitialized = false; | ||
492 | |||
492 | public IMesher mesher; | 493 | public IMesher mesher; |
493 | 494 | ||
494 | private IConfigSource m_config; | 495 | private IConfigSource m_config; |
@@ -875,6 +876,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
875 | staticPrimspace[i, j] = IntPtr.Zero; | 876 | staticPrimspace[i, j] = IntPtr.Zero; |
876 | } | 877 | } |
877 | } | 878 | } |
879 | |||
880 | _worldInitialized = true; | ||
878 | } | 881 | } |
879 | 882 | ||
880 | // internal void waitForSpaceUnlock(IntPtr space) | 883 | // internal void waitForSpaceUnlock(IntPtr space) |
@@ -1508,8 +1511,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1508 | { | 1511 | { |
1509 | if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) | 1512 | if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) |
1510 | && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) | 1513 | && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) |
1511 | && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) | 1514 | && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f))) |
1512 | && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) | ||
1513 | { | 1515 | { |
1514 | if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f) | 1516 | if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f) |
1515 | { | 1517 | { |
@@ -1538,7 +1540,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1538 | //d.GeomGetAABB(contactGeom.g2, out aabb2); | 1540 | //d.GeomGetAABB(contactGeom.g2, out aabb2); |
1539 | //d.GeomGetAABB(contactGeom.g1, out aabb1); | 1541 | //d.GeomGetAABB(contactGeom.g1, out aabb1); |
1540 | //aabb1. | 1542 | //aabb1. |
1541 | if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) | 1543 | if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f))) |
1542 | { | 1544 | { |
1543 | if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z) | 1545 | if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z) |
1544 | { | 1546 | { |
@@ -2896,6 +2898,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2896 | /// <returns>The number of frames simulated over that period.</returns> | 2898 | /// <returns>The number of frames simulated over that period.</returns> |
2897 | public override float Simulate(float timeStep) | 2899 | public override float Simulate(float timeStep) |
2898 | { | 2900 | { |
2901 | if (!_worldInitialized) return 11f; | ||
2902 | |||
2899 | int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0; | 2903 | int startFrameTick = CollectStats ? Util.EnvironmentTickCount() : 0; |
2900 | int tempTick = 0, tempTick2 = 0; | 2904 | int tempTick = 0, tempTick2 = 0; |
2901 | 2905 | ||
@@ -4017,6 +4021,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
4017 | 4021 | ||
4018 | public override void Dispose() | 4022 | public override void Dispose() |
4019 | { | 4023 | { |
4024 | _worldInitialized = false; | ||
4025 | |||
4020 | m_rayCastManager.Dispose(); | 4026 | m_rayCastManager.Dispose(); |
4021 | m_rayCastManager = null; | 4027 | m_rayCastManager = null; |
4022 | 4028 | ||
@@ -4037,6 +4043,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
4037 | d.WorldDestroy(world); | 4043 | d.WorldDestroy(world); |
4038 | //d.CloseODE(); | 4044 | //d.CloseODE(); |
4039 | } | 4045 | } |
4046 | |||
4040 | } | 4047 | } |
4041 | 4048 | ||
4042 | public override Dictionary<uint, float> GetTopColliders() | 4049 | public override Dictionary<uint, float> GetTopColliders() |
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 204c4ff..3144d76 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs | |||
@@ -99,6 +99,8 @@ namespace OpenSim.Region.RegionCombinerModule | |||
99 | 99 | ||
100 | public void RemoveRegion(Scene scene) | 100 | public void RemoveRegion(Scene scene) |
101 | { | 101 | { |
102 | lock (m_startingScenes) | ||
103 | m_startingScenes.Remove(scene.RegionInfo.originRegionID); | ||
102 | } | 104 | } |
103 | 105 | ||
104 | public void RegionLoaded(Scene scene) | 106 | public void RegionLoaded(Scene scene) |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs index 693992a..94fd940 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs | |||
@@ -31,6 +31,7 @@ using System.Collections.Generic; | |||
31 | using System.Threading; | 31 | using System.Threading; |
32 | using OpenMetaverse; | 32 | using OpenMetaverse; |
33 | using OpenSim.Framework; | 33 | using OpenSim.Framework; |
34 | using OpenSim.Framework.Monitoring; | ||
34 | using OpenSim.Region.Framework.Interfaces; | 35 | using OpenSim.Region.Framework.Interfaces; |
35 | using OpenSim.Region.ScriptEngine.Interfaces; | 36 | using OpenSim.Region.ScriptEngine.Interfaces; |
36 | using OpenSim.Region.ScriptEngine.Shared; | 37 | using OpenSim.Region.ScriptEngine.Shared; |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index cd72dc2..ce1c364 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -6885,22 +6885,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6885 | if (folderID == UUID.Zero) | 6885 | if (folderID == UUID.Zero) |
6886 | return; | 6886 | return; |
6887 | 6887 | ||
6888 | byte[] bucket = new byte[1]; | ||
6889 | bucket[0] = (byte)AssetType.Folder; | ||
6890 | //byte[] objBytes = folderID.GetBytes(); | ||
6891 | //Array.Copy(objBytes, 0, bucket, 1, 16); | ||
6892 | |||
6893 | GridInstantMessage msg = new GridInstantMessage(World, | ||
6894 | m_host.OwnerID, m_host.Name, destID, | ||
6895 | (byte)InstantMessageDialog.TaskInventoryOffered, | ||
6896 | false, category+". "+m_host.Name+" is located at "+ | ||
6897 | World.RegionInfo.RegionName+" "+ | ||
6898 | m_host.AbsolutePosition.ToString(), | ||
6899 | folderID, true, m_host.AbsolutePosition, | ||
6900 | bucket); | ||
6901 | |||
6902 | if (m_TransferModule != null) | 6888 | if (m_TransferModule != null) |
6889 | { | ||
6890 | byte[] bucket = new byte[] { (byte)AssetType.Folder }; | ||
6891 | |||
6892 | GridInstantMessage msg = new GridInstantMessage(World, | ||
6893 | m_host.UUID, m_host.Name + ", an object owned by " + | ||
6894 | resolveName(m_host.OwnerID) + ",", destID, | ||
6895 | (byte)InstantMessageDialog.TaskInventoryOffered, | ||
6896 | false, category + "\n" + m_host.Name + " is located at " + | ||
6897 | World.RegionInfo.RegionName + " " + | ||
6898 | m_host.AbsolutePosition.ToString(), | ||
6899 | folderID, true, m_host.AbsolutePosition, | ||
6900 | bucket); | ||
6901 | |||
6903 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); | 6902 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); |
6903 | } | ||
6904 | } | 6904 | } |
6905 | 6905 | ||
6906 | public void llSetVehicleType(int type) | 6906 | public void llSetVehicleType(int type) |
@@ -11847,7 +11847,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11847 | break; | 11847 | break; |
11848 | case ScriptBaseClass.OBJECT_ROT: | 11848 | case ScriptBaseClass.OBJECT_ROT: |
11849 | { | 11849 | { |
11850 | Quaternion rot = Quaternion.Identity; | 11850 | Quaternion rot = Quaternion.Identity; |
11851 | 11851 | ||
11852 | if (obj.ParentGroup.RootPart == obj) | 11852 | if (obj.ParentGroup.RootPart == obj) |
11853 | rot = obj.ParentGroup.GroupRotation; | 11853 | rot = obj.ParentGroup.GroupRotation; |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index 4bd3dff..7844c75 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs | |||
@@ -200,24 +200,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
200 | for (int i = 0; i < result.Length; i++) | 200 | for (int i = 0; i < result.Length; i++) |
201 | { | 201 | { |
202 | if (result[i] is string) | 202 | if (result[i] is string) |
203 | { | ||
203 | llist[i] = new LSL_String((string)result[i]); | 204 | llist[i] = new LSL_String((string)result[i]); |
205 | } | ||
204 | else if (result[i] is int) | 206 | else if (result[i] is int) |
207 | { | ||
205 | llist[i] = new LSL_Integer((int)result[i]); | 208 | llist[i] = new LSL_Integer((int)result[i]); |
209 | } | ||
206 | else if (result[i] is float) | 210 | else if (result[i] is float) |
211 | { | ||
207 | llist[i] = new LSL_Float((float)result[i]); | 212 | llist[i] = new LSL_Float((float)result[i]); |
213 | } | ||
214 | else if (result[i] is UUID) | ||
215 | { | ||
216 | llist[i] = new LSL_Key(result[i].ToString()); | ||
217 | } | ||
208 | else if (result[i] is OpenMetaverse.Vector3) | 218 | else if (result[i] is OpenMetaverse.Vector3) |
209 | { | 219 | { |
210 | OpenMetaverse.Vector3 vresult = (OpenMetaverse.Vector3)result[i]; | 220 | OpenMetaverse.Vector3 vresult = (OpenMetaverse.Vector3)result[i]; |
211 | llist[i] = new LSL_Vector(vresult.X,vresult.Y,vresult.Z); | 221 | llist[i] = new LSL_Vector(vresult.X, vresult.Y, vresult.Z); |
212 | } | 222 | } |
213 | else if (result[i] is OpenMetaverse.Quaternion) | 223 | else if (result[i] is OpenMetaverse.Quaternion) |
214 | { | 224 | { |
215 | OpenMetaverse.Quaternion qresult = (OpenMetaverse.Quaternion)result[i]; | 225 | OpenMetaverse.Quaternion qresult = (OpenMetaverse.Quaternion)result[i]; |
216 | llist[i] = new LSL_Rotation(qresult.X,qresult.Y,qresult.Z,qresult.W); | 226 | llist[i] = new LSL_Rotation(qresult.X, qresult.Y, qresult.Z, qresult.W); |
217 | } | 227 | } |
218 | else | 228 | else |
219 | { | 229 | { |
220 | MODError(String.Format("unknown list element returned by {0}",fname)); | 230 | MODError(String.Format("unknown list element {1} returned by {0}", fname, result[i].GetType().Name)); |
221 | } | 231 | } |
222 | } | 232 | } |
223 | 233 | ||
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 29d0342..1181c10 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | |||
@@ -3290,8 +3290,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3290 | ((LSL_Api)m_LSL_Api).llSay(0, string.Format("Unable to attach, item '{0}' is not an object.", itemName)); | 3290 | ((LSL_Api)m_LSL_Api).llSay(0, string.Format("Unable to attach, item '{0}' is not an object.", itemName)); |
3291 | 3291 | ||
3292 | throw new Exception(String.Format("The inventory item '{0}' is not an object", itemName)); | 3292 | throw new Exception(String.Format("The inventory item '{0}' is not an object", itemName)); |
3293 | |||
3294 | return; | ||
3295 | } | 3293 | } |
3296 | 3294 | ||
3297 | ScenePresence sp = World.GetScenePresence(avatarId); | 3295 | ScenePresence sp = World.GetScenePresence(avatarId); |
@@ -3322,5 +3320,47 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3322 | InitLSL(); | 3320 | InitLSL(); |
3323 | ((LSL_Api)m_LSL_Api).DetachFromAvatar(); | 3321 | ((LSL_Api)m_LSL_Api).DetachFromAvatar(); |
3324 | } | 3322 | } |
3323 | |||
3324 | /// <summary> | ||
3325 | /// Checks if thing is a UUID. | ||
3326 | /// </summary> | ||
3327 | /// <param name="thing"></param> | ||
3328 | /// <returns>1 if thing is a valid UUID, 0 otherwise</returns> | ||
3329 | public LSL_Integer osIsUUID(string thing) | ||
3330 | { | ||
3331 | CheckThreatLevel(ThreatLevel.None, "osIsUUID"); | ||
3332 | m_host.AddScriptLPS(1); | ||
3333 | |||
3334 | UUID test; | ||
3335 | return UUID.TryParse(thing, out test) ? 1 : 0; | ||
3336 | } | ||
3337 | |||
3338 | /// <summary> | ||
3339 | /// Wraps to Math.Min() | ||
3340 | /// </summary> | ||
3341 | /// <param name="a"></param> | ||
3342 | /// <param name="b"></param> | ||
3343 | /// <returns></returns> | ||
3344 | public LSL_Float osMin(double a, double b) | ||
3345 | { | ||
3346 | CheckThreatLevel(ThreatLevel.None, "osMin"); | ||
3347 | m_host.AddScriptLPS(1); | ||
3348 | |||
3349 | return Math.Min(a, b); | ||
3350 | } | ||
3351 | |||
3352 | /// <summary> | ||
3353 | /// Wraps to Math.max() | ||
3354 | /// </summary> | ||
3355 | /// <param name="a"></param> | ||
3356 | /// <param name="b"></param> | ||
3357 | /// <returns></returns> | ||
3358 | public LSL_Float osMax(double a, double b) | ||
3359 | { | ||
3360 | CheckThreatLevel(ThreatLevel.None, "osMax"); | ||
3361 | m_host.AddScriptLPS(1); | ||
3362 | |||
3363 | return Math.Max(a, b); | ||
3364 | } | ||
3325 | } | 3365 | } |
3326 | } | 3366 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 1facc96..aba66d3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | |||
@@ -276,5 +276,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | |||
276 | 276 | ||
277 | void osSetTerrainTexture(int level, LSL_Key texture); | 277 | void osSetTerrainTexture(int level, LSL_Key texture); |
278 | void osSetTerrainTextureHeight(int corner, double low, double high); | 278 | void osSetTerrainTextureHeight(int corner, double low, double high); |
279 | |||
280 | /// <summary> | ||
281 | /// Checks if thing is a UUID. | ||
282 | /// </summary> | ||
283 | /// <param name="thing"></param> | ||
284 | /// <returns>1 if thing is a valid UUID, 0 otherwise</returns> | ||
285 | LSL_Integer osIsUUID(string thing); | ||
286 | |||
287 | /// <summary> | ||
288 | /// Wraps to Math.Min() | ||
289 | /// </summary> | ||
290 | /// <param name="a"></param> | ||
291 | /// <param name="b"></param> | ||
292 | /// <returns></returns> | ||
293 | LSL_Float osMin(double a, double b); | ||
294 | |||
295 | /// <summary> | ||
296 | /// Wraps to Math.max() | ||
297 | /// </summary> | ||
298 | /// <param name="a"></param> | ||
299 | /// <param name="b"></param> | ||
300 | /// <returns></returns> | ||
301 | LSL_Float osMax(double a, double b); | ||
279 | } | 302 | } |
280 | } | 303 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index b40bdf0..53daa13 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs | |||
@@ -930,5 +930,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase | |||
930 | { | 930 | { |
931 | m_OSSL_Functions.osSetTerrainTextureHeight(corner, low, high); | 931 | m_OSSL_Functions.osSetTerrainTextureHeight(corner, low, high); |
932 | } | 932 | } |
933 | |||
934 | public LSL_Integer osIsUUID(string thing) | ||
935 | { | ||
936 | return m_OSSL_Functions.osIsUUID(thing); | ||
937 | } | ||
938 | |||
939 | public LSL_Float osMin(double a, double b) | ||
940 | { | ||
941 | return m_OSSL_Functions.osMin(a, b); | ||
942 | } | ||
943 | |||
944 | public LSL_Float osMax(double a, double b) | ||
945 | { | ||
946 | return m_OSSL_Functions.osMax(a, b); | ||
947 | } | ||
933 | } | 948 | } |
934 | } | 949 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs index 5c9d30f..9e5fb24 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs | |||
@@ -36,6 +36,7 @@ using OpenSim.Framework; | |||
36 | using OpenSim.Region.CoreModules; | 36 | using OpenSim.Region.CoreModules; |
37 | using OpenSim.Region.Framework.Scenes; | 37 | using OpenSim.Region.Framework.Scenes; |
38 | using OpenSim.Services.Interfaces; | 38 | using OpenSim.Services.Interfaces; |
39 | using OpenSim.Region.Framework.Interfaces; | ||
39 | 40 | ||
40 | namespace OpenSim.Region.ScriptEngine.Shared | 41 | namespace OpenSim.Region.ScriptEngine.Shared |
41 | { | 42 | { |
@@ -83,6 +84,12 @@ namespace OpenSim.Region.ScriptEngine.Shared | |||
83 | 84 | ||
84 | public class DetectParams | 85 | public class DetectParams |
85 | { | 86 | { |
87 | public const int AGENT = 1; | ||
88 | public const int ACTIVE = 2; | ||
89 | public const int PASSIVE = 4; | ||
90 | public const int SCRIPTED = 8; | ||
91 | public const int OS_NPC = 0x01000000; | ||
92 | |||
86 | public DetectParams() | 93 | public DetectParams() |
87 | { | 94 | { |
88 | Key = UUID.Zero; | 95 | Key = UUID.Zero; |
@@ -199,8 +206,27 @@ namespace OpenSim.Region.ScriptEngine.Shared | |||
199 | Type = 0x01; // Avatar | 206 | Type = 0x01; // Avatar |
200 | if (presence.PresenceType == PresenceType.Npc) | 207 | if (presence.PresenceType == PresenceType.Npc) |
201 | Type = 0x20; | 208 | Type = 0x20; |
209 | |||
210 | // Cope Impl. We don't use OS_NPC. | ||
211 | //if (presence.PresenceType != PresenceType.Npc) | ||
212 | //{ | ||
213 | // Type = AGENT; | ||
214 | //} | ||
215 | //else | ||
216 | //{ | ||
217 | // Type = OS_NPC; | ||
218 | |||
219 | // INPCModule npcModule = scene.RequestModuleInterface<INPCModule>(); | ||
220 | // INPC npcData = npcModule.GetNPC(presence.UUID, presence.Scene); | ||
221 | |||
222 | // if (npcData.SenseAsAgent) | ||
223 | // { | ||
224 | // Type |= AGENT; | ||
225 | // } | ||
226 | //} | ||
227 | |||
202 | if (presence.Velocity != Vector3.Zero) | 228 | if (presence.Velocity != Vector3.Zero) |
203 | Type |= 0x02; // Active | 229 | Type |= ACTIVE; |
204 | 230 | ||
205 | Group = presence.ControllingClient.ActiveGroupId; | 231 | Group = presence.ControllingClient.ActiveGroupId; |
206 | 232 | ||
@@ -215,15 +241,15 @@ namespace OpenSim.Region.ScriptEngine.Shared | |||
215 | Name = part.Name; | 241 | Name = part.Name; |
216 | Owner = part.OwnerID; | 242 | Owner = part.OwnerID; |
217 | if (part.Velocity == Vector3.Zero) | 243 | if (part.Velocity == Vector3.Zero) |
218 | Type = 0x04; // Passive | 244 | Type = PASSIVE; |
219 | else | 245 | else |
220 | Type = 0x02; // Passive | 246 | Type = ACTIVE; |
221 | 247 | ||
222 | foreach (SceneObjectPart p in part.ParentGroup.Parts) | 248 | foreach (SceneObjectPart p in part.ParentGroup.Parts) |
223 | { | 249 | { |
224 | if (p.Inventory.ContainsScripts()) | 250 | if (p.Inventory.ContainsScripts()) |
225 | { | 251 | { |
226 | Type |= 0x08; // Scripted | 252 | Type |= SCRIPTED; // Scripted |
227 | break; | 253 | break; |
228 | } | 254 | } |
229 | } | 255 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 983eed2..771db0c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | |||
@@ -312,11 +312,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
312 | part.SetScriptEvents(ItemID, | 312 | part.SetScriptEvents(ItemID, |
313 | (int)m_Script.GetStateEventFlags(State)); | 313 | (int)m_Script.GetStateEventFlags(State)); |
314 | 314 | ||
315 | Running = false; | 315 | if (!Running) |
316 | |||
317 | if (ShuttingDown) | ||
318 | m_startOnInit = false; | 316 | m_startOnInit = false; |
319 | 317 | ||
318 | Running = false; | ||
319 | |||
320 | // we get new rez events on sim restart, too | 320 | // we get new rez events on sim restart, too |
321 | // but if there is state, then we fire the change | 321 | // but if there is state, then we fire the change |
322 | // event | 322 | // event |
@@ -352,12 +352,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
352 | 352 | ||
353 | public void Init() | 353 | public void Init() |
354 | { | 354 | { |
355 | if (!m_startOnInit) | 355 | if (ShuttingDown) |
356 | return; | 356 | return; |
357 | 357 | ||
358 | if (m_startedFromSavedState) | 358 | if (m_startedFromSavedState) |
359 | { | 359 | { |
360 | Start(); | 360 | if (m_startOnInit) |
361 | Start(); | ||
361 | if (m_postOnRez) | 362 | if (m_postOnRez) |
362 | { | 363 | { |
363 | PostEvent(new EventParams("on_rez", | 364 | PostEvent(new EventParams("on_rez", |
@@ -389,7 +390,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
389 | } | 390 | } |
390 | else | 391 | else |
391 | { | 392 | { |
392 | Start(); | 393 | if (m_startOnInit) |
394 | Start(); | ||
393 | PostEvent(new EventParams("state_entry", | 395 | PostEvent(new EventParams("state_entry", |
394 | new Object[0], new DetectParams[0])); | 396 | new Object[0], new DetectParams[0])); |
395 | if (m_postOnRez) | 397 | if (m_postOnRez) |
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 35a0200..f6cb7df 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | |||
@@ -109,6 +109,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
109 | private bool m_KillTimedOutScripts; | 109 | private bool m_KillTimedOutScripts; |
110 | private string m_ScriptEnginesPath = null; | 110 | private string m_ScriptEnginesPath = null; |
111 | 111 | ||
112 | private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>(); | ||
113 | |||
112 | /// <summary> | 114 | /// <summary> |
113 | /// Is the entire simulator in the process of shutting down? | 115 | /// Is the entire simulator in the process of shutting down? |
114 | /// </summary> | 116 | /// </summary> |
@@ -715,6 +717,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
715 | m_Scene.EventManager.OnGetScriptRunning += OnGetScriptRunning; | 717 | m_Scene.EventManager.OnGetScriptRunning += OnGetScriptRunning; |
716 | m_Scene.EventManager.OnShutdown += OnShutdown; | 718 | m_Scene.EventManager.OnShutdown += OnShutdown; |
717 | 719 | ||
720 | // If region ready has been triggered, then the region had no scripts to compile and completed its other | ||
721 | // work. | ||
722 | m_Scene.EventManager.OnRegionReadyStatusChange += s => { if (s.Ready) m_InitialStartup = false; }; | ||
723 | |||
718 | if (m_SleepTime > 0) | 724 | if (m_SleepTime > 0) |
719 | { | 725 | { |
720 | m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoMaintenance), | 726 | m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoMaintenance), |
@@ -1269,7 +1275,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1269 | 1275 | ||
1270 | if (instance!=null) | 1276 | if (instance!=null) |
1271 | instance.Init(); | 1277 | instance.Init(); |
1272 | 1278 | ||
1279 | bool runIt; | ||
1280 | if (m_runFlags.TryGetValue(itemID, out runIt)) | ||
1281 | { | ||
1282 | if (!runIt) | ||
1283 | StopScript(itemID); | ||
1284 | m_runFlags.Remove(itemID); | ||
1285 | } | ||
1286 | |||
1273 | return true; | 1287 | return true; |
1274 | } | 1288 | } |
1275 | 1289 | ||
@@ -1660,6 +1674,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1660 | IScriptInstance instance = GetInstance(itemID); | 1674 | IScriptInstance instance = GetInstance(itemID); |
1661 | if (instance != null) | 1675 | if (instance != null) |
1662 | instance.Start(); | 1676 | instance.Start(); |
1677 | else | ||
1678 | m_runFlags.AddOrUpdate(itemID, true, 240); | ||
1663 | } | 1679 | } |
1664 | 1680 | ||
1665 | public void StopScript(UUID itemID) | 1681 | public void StopScript(UUID itemID) |
@@ -1671,6 +1687,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
1671 | // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort. | 1687 | // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort. |
1672 | instance.Stop(1000); | 1688 | instance.Stop(1000); |
1673 | } | 1689 | } |
1690 | else | ||
1691 | { | ||
1692 | m_runFlags.AddOrUpdate(itemID, false, 240); | ||
1693 | } | ||
1674 | } | 1694 | } |
1675 | 1695 | ||
1676 | public DetectParams GetDetectParams(UUID itemID, int idx) | 1696 | public DetectParams GetDetectParams(UUID itemID, int idx) |
diff --git a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs index dcbd717..3243a9a 100644 --- a/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs +++ b/OpenSim/Region/UserStatistics/ActiveConnectionsAJAX.cs | |||
@@ -34,7 +34,7 @@ using Mono.Data.SqliteClient; | |||
34 | using OpenMetaverse; | 34 | using OpenMetaverse; |
35 | using OpenSim.Framework; | 35 | using OpenSim.Framework; |
36 | using OpenSim.Region.Framework.Scenes; | 36 | using OpenSim.Region.Framework.Scenes; |
37 | using OpenSim.Framework.Statistics; | 37 | using OpenSim.Framework.Monitoring; |
38 | 38 | ||
39 | namespace OpenSim.Region.UserStatistics | 39 | namespace OpenSim.Region.UserStatistics |
40 | { | 40 | { |
diff --git a/OpenSim/Region/UserStatistics/Default_Report.cs b/OpenSim/Region/UserStatistics/Default_Report.cs index 0e17630..cdc615c 100644 --- a/OpenSim/Region/UserStatistics/Default_Report.cs +++ b/OpenSim/Region/UserStatistics/Default_Report.cs | |||
@@ -33,7 +33,7 @@ using System.Text; | |||
33 | using Mono.Data.SqliteClient; | 33 | using Mono.Data.SqliteClient; |
34 | using OpenMetaverse; | 34 | using OpenMetaverse; |
35 | using OpenSim.Region.Framework.Scenes; | 35 | using OpenSim.Region.Framework.Scenes; |
36 | using OpenSim.Framework.Statistics; | 36 | using OpenSim.Framework.Monitoring; |
37 | 37 | ||
38 | 38 | ||
39 | namespace OpenSim.Region.UserStatistics | 39 | namespace OpenSim.Region.UserStatistics |
diff --git a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs index 811baba..74de46b 100644 --- a/OpenSim/Region/UserStatistics/LogLinesAJAX.cs +++ b/OpenSim/Region/UserStatistics/LogLinesAJAX.cs | |||
@@ -34,7 +34,7 @@ using System.Text.RegularExpressions; | |||
34 | using Mono.Data.SqliteClient; | 34 | using Mono.Data.SqliteClient; |
35 | using OpenMetaverse; | 35 | using OpenMetaverse; |
36 | using OpenSim.Region.Framework.Scenes; | 36 | using OpenSim.Region.Framework.Scenes; |
37 | using OpenSim.Framework.Statistics; | 37 | using OpenSim.Framework.Monitoring; |
38 | 38 | ||
39 | namespace OpenSim.Region.UserStatistics | 39 | namespace OpenSim.Region.UserStatistics |
40 | { | 40 | { |
diff --git a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs index 8c04e71..28051fb 100644 --- a/OpenSim/Region/UserStatistics/SimStatsAJAX.cs +++ b/OpenSim/Region/UserStatistics/SimStatsAJAX.cs | |||
@@ -33,7 +33,7 @@ using System.Text; | |||
33 | using Mono.Data.SqliteClient; | 33 | using Mono.Data.SqliteClient; |
34 | using OpenMetaverse; | 34 | using OpenMetaverse; |
35 | using OpenSim.Region.Framework.Scenes; | 35 | using OpenSim.Region.Framework.Scenes; |
36 | using OpenSim.Framework.Statistics; | 36 | using OpenSim.Framework.Monitoring; |
37 | 37 | ||
38 | namespace OpenSim.Region.UserStatistics | 38 | namespace OpenSim.Region.UserStatistics |
39 | { | 39 | { |
diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs index 769de83..7598cc3 100644 --- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs | |||
@@ -190,7 +190,7 @@ namespace OpenSim.Tests.Common | |||
190 | = physicsPluginManager.GetPhysicsScene("basicphysics", "ZeroMesher", new IniConfigSource(), "test"); | 190 | = physicsPluginManager.GetPhysicsScene("basicphysics", "ZeroMesher", new IniConfigSource(), "test"); |
191 | 191 | ||
192 | testScene.RegionInfo.EstateSettings = new EstateSettings(); | 192 | testScene.RegionInfo.EstateSettings = new EstateSettings(); |
193 | testScene.LoginsDisabled = false; | 193 | testScene.LoginsEnabled = true; |
194 | testScene.RegisterRegionWithGrid(); | 194 | testScene.RegisterRegionWithGrid(); |
195 | 195 | ||
196 | SceneManager.Add(testScene); | 196 | SceneManager.Add(testScene); |
diff --git a/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs index fba03ab..0a2b30a 100644 --- a/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/TaskInventoryHelpers.cs | |||
@@ -80,8 +80,26 @@ namespace OpenSim.Tests.Common | |||
80 | /// <returns>The item that was added</returns> | 80 | /// <returns>The item that was added</returns> |
81 | public static TaskInventoryItem AddScript(Scene scene, SceneObjectPart part) | 81 | public static TaskInventoryItem AddScript(Scene scene, SceneObjectPart part) |
82 | { | 82 | { |
83 | return AddScript(scene, part, "scriptItem", "default { state_entry() { llSay(0, \"Hello World\"); } }"); | ||
84 | } | ||
85 | |||
86 | /// <summary> | ||
87 | /// Add a simple script to the given part. | ||
88 | /// </summary> | ||
89 | /// <remarks> | ||
90 | /// TODO: Accept input for item and asset IDs to avoid mysterious script failures that try to use any of these | ||
91 | /// functions more than once in a test. | ||
92 | /// </remarks> | ||
93 | /// <param name="scene"></param> | ||
94 | /// <param name="part"></param> | ||
95 | /// <param name="scriptName">Name of the script to add</param> | ||
96 | /// <param name="scriptSource">LSL script source</param> | ||
97 | /// <returns>The item that was added</returns> | ||
98 | public static TaskInventoryItem AddScript( | ||
99 | Scene scene, SceneObjectPart part, string scriptName, string scriptSource) | ||
100 | { | ||
83 | AssetScriptText ast = new AssetScriptText(); | 101 | AssetScriptText ast = new AssetScriptText(); |
84 | ast.Source = "default { state_entry() { llSay(0, \"Hello World\"); } }"; | 102 | ast.Source = scriptSource; |
85 | ast.Encode(); | 103 | ast.Encode(); |
86 | 104 | ||
87 | UUID assetUuid = new UUID("00000000-0000-0000-1000-000000000000"); | 105 | UUID assetUuid = new UUID("00000000-0000-0000-1000-000000000000"); |
@@ -91,7 +109,7 @@ namespace OpenSim.Tests.Common | |||
91 | scene.AssetService.Store(asset); | 109 | scene.AssetService.Store(asset); |
92 | TaskInventoryItem item | 110 | TaskInventoryItem item |
93 | = new TaskInventoryItem | 111 | = new TaskInventoryItem |
94 | { Name = "scriptItem", AssetID = assetUuid, ItemID = itemUuid, | 112 | { Name = scriptName, AssetID = assetUuid, ItemID = itemUuid, |
95 | Type = (int)AssetType.LSLText, InvType = (int)InventoryType.LSL }; | 113 | Type = (int)AssetType.LSLText, InvType = (int)InventoryType.LSL }; |
96 | part.Inventory.AddInventoryItem(item, true); | 114 | part.Inventory.AddInventoryItem(item, true); |
97 | 115 | ||