diff --git a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs index 3f29f5b36d..17f42e1f0b 100644 --- a/OpenSim/Data/MSSQL/MSSQLSimulationData.cs +++ b/OpenSim/Data/MSSQL/MSSQLSimulationData.cs @@ -2202,5 +2202,18 @@ VALUES } } } + + public void SaveExtra(UUID regionID, string name, string value) + { + } + + public void RemoveExtra(UUID regionID, string name) + { + } + + public Dictionary GetExtra(UUID regionID) + { + return null; + } } } diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs index 1a2e11333a..3fc04ee461 100644 --- a/OpenSim/Data/MySQL/MySQLSimulationData.cs +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -1966,5 +1966,74 @@ namespace OpenSim.Data.MySQL } } } + + public void SaveExtra(UUID regionID, string name, string val) + { + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "replace into regionextra values (?RegionID, ?Name, ?value)"; + cmd.Parameters.AddWithValue("?RegionID", regionID.ToString()); + cmd.Parameters.AddWithValue("?Name", name); + cmd.Parameters.AddWithValue("?value", val); + + cmd.ExecuteNonQuery(); + } + } + } + } + + public void RemoveExtra(UUID regionID, string name) + { + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "delete from regionextra where RegionID=?RegionID and Name=?Name"; + cmd.Parameters.AddWithValue("?RegionID", regionID.ToString()); + cmd.Parameters.AddWithValue("?Name", name); + + cmd.ExecuteNonQuery(); + } + } + } + } + + public Dictionary GetExtra(UUID regionID) + { + Dictionary ret = new Dictionary(); + + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "select * from regionextra where RegionID=?RegionID"; + cmd.Parameters.AddWithValue("?RegionID", regionID.ToString()); + using (IDataReader r = cmd.ExecuteReader()) + { + while (r.Read()) + { + ret[r["Name"].ToString()] = r["value"].ToString(); + } + } + } + } + } + + return ret; + } } } diff --git a/OpenSim/Data/MySQL/Resources/RegionStore.migrations b/OpenSim/Data/MySQL/Resources/RegionStore.migrations index 4a925fb9bd..5b59779050 100644 --- a/OpenSim/Data/MySQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/MySQL/Resources/RegionStore.migrations @@ -895,3 +895,10 @@ CREATE TABLE `regionenvironment` ( COMMIT; +:VERSION 45 + +BEGIN; + +CREATE TABLE `regionextra` (`RegionID` char(36) not null, `Name` varchar(32) not null, `value` text, primary key(`RegionID`, `Name`)); + +COMMIT; diff --git a/OpenSim/Data/Null/NullSimulationData.cs b/OpenSim/Data/Null/NullSimulationData.cs index 8f2314ff1f..4979cf6d61 100644 --- a/OpenSim/Data/Null/NullSimulationData.cs +++ b/OpenSim/Data/Null/NullSimulationData.cs @@ -151,5 +151,18 @@ namespace OpenSim.Data.Null public void Shutdown() { } + + public void SaveExtra(UUID regionID, string name, string value) + { + } + + public void RemoveExtra(UUID regionID, string name) + { + } + + public Dictionary GetExtra(UUID regionID) + { + return null; + } } } diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs index f40e86644c..56df3cbbdd 100644 --- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs +++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs @@ -2890,5 +2890,17 @@ namespace OpenSim.Data.SQLite } } + public void SaveExtra(UUID regionID, string name, string value) + { + } + + public void RemoveExtra(UUID regionID, string name) + { + } + + public Dictionary GetExtra(UUID regionID) + { + return null; + } } } diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 79e20fc88e..31cab4a021 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -199,7 +199,14 @@ namespace OpenSim.Framework // public class Cache { + /// + /// Must only be accessed under lock. + /// private List m_Index = new List(); + + /// + /// Must only be accessed under m_Index lock. + /// private Dictionary m_Lookup = new Dictionary(); @@ -320,19 +327,19 @@ namespace OpenSim.Framework { if (m_Lookup.ContainsKey(index)) item = m_Lookup[index]; - } - if (item == null) - { + if (item == null) + { + Expire(true); + return null; + } + + item.hits++; + item.lastUsed = DateTime.Now; + Expire(true); - return null; } - item.hits++; - item.lastUsed = DateTime.Now; - - Expire(true); - return item; } @@ -385,7 +392,10 @@ namespace OpenSim.Framework // public Object Find(Predicate d) { - CacheItemBase item = m_Index.Find(d); + CacheItemBase item; + + lock (m_Index) + item = m_Index.Find(d); if (item == null) return null; @@ -419,12 +429,12 @@ namespace OpenSim.Framework public virtual void Store(string index, Object data, Type container, Object[] parameters) { - Expire(false); - CacheItemBase item; lock (m_Index) { + Expire(false); + if (m_Index.Contains(new CacheItemBase(index))) { if ((m_Flags & CacheFlags.AllowUpdate) != 0) @@ -450,9 +460,17 @@ namespace OpenSim.Framework m_Index.Add(item); m_Lookup[index] = item; } + item.Store(data); } + /// + /// Expire items as appropriate. + /// + /// + /// Callers must lock m_Index. + /// + /// protected virtual void Expire(bool getting) { if (getting && (m_Strategy == CacheStrategy.Aggressive)) @@ -475,12 +493,10 @@ namespace OpenSim.Framework switch (m_Strategy) { - case CacheStrategy.Aggressive: - if (Count < Size) - return; + case CacheStrategy.Aggressive: + if (Count < Size) + return; - lock (m_Index) - { m_Index.Sort(new SortLRU()); m_Index.Reverse(); @@ -490,7 +506,7 @@ namespace OpenSim.Framework ExpireDelegate doExpire = OnExpire; - if (doExpire != null) + if (doExpire != null) { List candidates = m_Index.GetRange(target, Count - target); @@ -513,27 +529,34 @@ namespace OpenSim.Framework foreach (CacheItemBase item in m_Index) m_Lookup[item.uuid] = item; } - } - break; - default: - break; + + break; + + default: + break; } } public void Invalidate(string uuid) { - if (!m_Lookup.ContainsKey(uuid)) - return; + lock (m_Index) + { + if (!m_Lookup.ContainsKey(uuid)) + return; - CacheItemBase item = m_Lookup[uuid]; - m_Lookup.Remove(uuid); - m_Index.Remove(item); + CacheItemBase item = m_Lookup[uuid]; + m_Lookup.Remove(uuid); + m_Index.Remove(item); + } } public void Clear() { - m_Index.Clear(); - m_Lookup.Clear(); + lock (m_Index) + { + m_Index.Clear(); + m_Lookup.Clear(); + } } } -} +} \ No newline at end of file diff --git a/OpenSim/Framework/Console/CommandConsole.cs b/OpenSim/Framework/Console/CommandConsole.cs index 87bdacd2da..bd23d1cb62 100644 --- a/OpenSim/Framework/Console/CommandConsole.cs +++ b/OpenSim/Framework/Console/CommandConsole.cs @@ -678,6 +678,8 @@ namespace OpenSim.Framework.Console { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + public event OnOutputDelegate OnOutput; + public ICommands Commands { get; private set; } public CommandConsole(string defaultPrompt) : base(defaultPrompt) @@ -697,6 +699,13 @@ namespace OpenSim.Framework.Console Output(s); } + protected void FireOnOutput(string text) + { + OnOutputDelegate onOutput = OnOutput; + if (onOutput != null) + onOutput(text); + } + /// /// Display a command prompt on the console and wait for user input /// diff --git a/OpenSim/Framework/Console/LocalConsole.cs b/OpenSim/Framework/Console/LocalConsole.cs index f65813b9ee..d41481fb1c 100644 --- a/OpenSim/Framework/Console/LocalConsole.cs +++ b/OpenSim/Framework/Console/LocalConsole.cs @@ -319,6 +319,8 @@ namespace OpenSim.Framework.Console public override void Output(string text, string level) { + FireOnOutput(text); + lock (m_commandLine) { if (m_cursorYPosition == -1) @@ -509,4 +511,4 @@ namespace OpenSim.Framework.Console } } } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/Console/MockConsole.cs b/OpenSim/Framework/Console/MockConsole.cs index 4d8751f5f6..b489f93b69 100644 --- a/OpenSim/Framework/Console/MockConsole.cs +++ b/OpenSim/Framework/Console/MockConsole.cs @@ -40,6 +40,8 @@ namespace OpenSim.Framework.Console /// public class MockConsole : ICommandConsole { + public event OnOutputDelegate OnOutput; + private MockCommands m_commands = new MockCommands(); public ICommands Commands { get { return m_commands; } } @@ -76,4 +78,4 @@ namespace OpenSim.Framework.Console public string[] Resolve(string[] cmd) { return null; } public XmlElement GetXml(XmlDocument doc) { return null; } } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/Console/RemoteConsole.cs b/OpenSim/Framework/Console/RemoteConsole.cs index eabb62dd01..27edd4b0fe 100644 --- a/OpenSim/Framework/Console/RemoteConsole.cs +++ b/OpenSim/Framework/Console/RemoteConsole.cs @@ -100,6 +100,7 @@ namespace OpenSim.Framework.Console m_LineNumber++; m_Scrollback.Add(String.Format("{0}", m_LineNumber)+":"+level+":"+text); } + FireOnOutput(text.Trim()); System.Console.WriteLine(text.Trim()); } diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index d5952c4b4c..8a63bff9f5 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -1033,7 +1033,21 @@ namespace OpenSim.Framework void InPacket(object NewPack); void ProcessInPacket(Packet NewPack); + + /// + /// Close this client + /// void Close(); + + /// + /// Close this client + /// + /// + /// If true, attempts the close without checking active status. You do not want to try this except as a last + /// ditch attempt where Active == false but the ScenePresence still exists. + /// + void Close(bool force); + void Kick(string message); /// diff --git a/OpenSim/Framework/ICommandConsole.cs b/OpenSim/Framework/ICommandConsole.cs index ca0ff936ca..8cd20da4ee 100644 --- a/OpenSim/Framework/ICommandConsole.cs +++ b/OpenSim/Framework/ICommandConsole.cs @@ -74,8 +74,12 @@ namespace OpenSim.Framework XmlElement GetXml(XmlDocument doc); } + public delegate void OnOutputDelegate(string message); + public interface ICommandConsole : IConsole { + event OnOutputDelegate OnOutput; + ICommands Commands { get; } /// @@ -87,4 +91,4 @@ namespace OpenSim.Framework string ReadLine(string p, bool isCommand, bool e); } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs index d4cf02fe41..7964f28944 100644 --- a/OpenSim/Framework/Monitoring/Watchdog.cs +++ b/OpenSim/Framework/Monitoring/Watchdog.cs @@ -89,6 +89,17 @@ namespace OpenSim.Framework.Monitoring FirstTick = Environment.TickCount & Int32.MaxValue; LastTick = FirstTick; } + + public ThreadWatchdogInfo(ThreadWatchdogInfo previousTwi) + { + Thread = previousTwi.Thread; + FirstTick = previousTwi.FirstTick; + LastTick = previousTwi.LastTick; + Timeout = previousTwi.Timeout; + IsTimedOut = previousTwi.IsTimedOut; + AlarmIfTimeout = previousTwi.AlarmIfTimeout; + AlarmMethod = previousTwi.AlarmMethod; + } } /// @@ -97,6 +108,32 @@ namespace OpenSim.Framework.Monitoring /// /summary> public static event Action OnWatchdogTimeout; + /// + /// Is this watchdog active? + /// + public static bool Enabled + { + get { return m_enabled; } + set + { +// m_log.DebugFormat("[MEMORY WATCHDOG]: Setting MemoryWatchdog.Enabled to {0}", value); + + if (value == m_enabled) + return; + + m_enabled = value; + + if (m_enabled) + { + // Set now so we don't get alerted on the first run + LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue; + } + + m_watchdogTimer.Enabled = m_enabled; + } + } + private static bool m_enabled; + private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static Dictionary m_threads; private static System.Timers.Timer m_watchdogTimer; @@ -115,11 +152,6 @@ namespace OpenSim.Framework.Monitoring m_watchdogTimer = new System.Timers.Timer(WATCHDOG_INTERVAL_MS); m_watchdogTimer.AutoReset = false; m_watchdogTimer.Elapsed += WatchdogTimerElapsed; - - // Set now so we don't get alerted on the first run - LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue; - - m_watchdogTimer.Start(); } /// @@ -314,7 +346,9 @@ namespace OpenSim.Framework.Monitoring if (callbackInfos == null) callbackInfos = new List(); - callbackInfos.Add(threadInfo); + // Send a copy of the watchdog info to prevent race conditions where the watchdog + // thread updates the monitoring info after an alarm has been sent out. + callbackInfos.Add(new ThreadWatchdogInfo(threadInfo)); } } } diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index 2080a1682e..81310894dd 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -120,7 +120,9 @@ namespace OpenSim.Framework public UUID lastMapUUID = UUID.Zero; public string lastMapRefresh = "0"; + private float m_nonphysPrimMin = 0; private int m_nonphysPrimMax = 0; + private float m_physPrimMin = 0; private int m_physPrimMax = 0; private bool m_clampPrimSize = false; private int m_objectCapacity = 0; @@ -285,11 +287,21 @@ namespace OpenSim.Framework set { m_windlight = value; } } + public float NonphysPrimMin + { + get { return m_nonphysPrimMin; } + } + public int NonphysPrimMax { get { return m_nonphysPrimMax; } } + public float PhysPrimMin + { + get { return m_physPrimMin; } + } + public int PhysPrimMax { get { return m_physPrimMax; } @@ -623,16 +635,28 @@ namespace OpenSim.Framework m_regionType = config.GetString("RegionType", String.Empty); allKeys.Remove("RegionType"); - // Prim stuff - // + #region Prim stuff + + m_nonphysPrimMin = config.GetFloat("NonphysicalPrimMin", 0); + allKeys.Remove("NonphysicalPrimMin"); + m_nonphysPrimMax = config.GetInt("NonphysicalPrimMax", 0); allKeys.Remove("NonphysicalPrimMax"); + + m_physPrimMin = config.GetFloat("PhysicalPrimMin", 0); + allKeys.Remove("PhysicalPrimMin"); + m_physPrimMax = config.GetInt("PhysicalPrimMax", 0); allKeys.Remove("PhysicalPrimMax"); + m_clampPrimSize = config.GetBoolean("ClampPrimSize", false); allKeys.Remove("ClampPrimSize"); + m_objectCapacity = config.GetInt("MaxPrims", 15000); allKeys.Remove("MaxPrims"); + + #endregion + m_agentCapacity = config.GetInt("MaxAgents", 100); allKeys.Remove("MaxAgents"); @@ -668,10 +692,18 @@ namespace OpenSim.Framework config.Set("ExternalHostName", m_externalHostName); + if (m_nonphysPrimMin != 0) + config.Set("NonphysicalPrimMax", m_nonphysPrimMin); + if (m_nonphysPrimMax != 0) config.Set("NonphysicalPrimMax", m_nonphysPrimMax); + + if (m_physPrimMin != 0) + config.Set("PhysicalPrimMax", m_physPrimMin); + if (m_physPrimMax != 0) config.Set("PhysicalPrimMax", m_physPrimMax); + config.Set("ClampPrimSize", m_clampPrimSize.ToString()); if (m_objectCapacity != 0) @@ -754,9 +786,15 @@ namespace OpenSim.Framework configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true); + configMember.addConfigurationOption("nonphysical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, + "Minimum size for nonphysical prims", m_nonphysPrimMin.ToString(), true); + configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32, "Maximum size for nonphysical prims", m_nonphysPrimMax.ToString(), true); + configMember.addConfigurationOption("physical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, + "Minimum size for nonphysical prims", m_physPrimMin.ToString(), true); + configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32, "Maximum size for physical prims", m_physPrimMax.ToString(), true); diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 8cc29eed36..38cb3a6380 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -850,6 +850,12 @@ namespace OpenSim.Framework return Math.Min(Math.Max(x, min), max); } + public static Vector3 Clip(Vector3 vec, float min, float max) + { + return new Vector3(Clip(vec.X, min, max), Clip(vec.Y, min, max), + Clip(vec.Z, min, max)); + } + /// /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens. /// diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 6bbab35ad0..769eea85db 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -35,6 +35,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Timers; using log4net; +using NDesk.Options; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -310,8 +311,11 @@ namespace OpenSim "Change the scale of a named prim", HandleEditScale); m_console.Commands.AddCommand("Users", false, "kick user", - "kick user [message]", - "Kick a user off the simulator", KickUserCommand); + "kick user [--force] [message]", + "Kick a user off the simulator", + "The --force option will kick the user without any checks to see whether it's already in the process of closing\n" + + "Only use this option if you are sure the avatar is inactive and a normal kick user operation does not removed them", + KickUserCommand); m_console.Commands.AddCommand("Users", false, "show users", "show users [full]", @@ -416,6 +420,7 @@ namespace OpenSim { RunCommandScript(m_shutdownCommandsFile); } + base.ShutdownSpecific(); } @@ -453,11 +458,17 @@ namespace OpenSim /// name of avatar to kick private void KickUserCommand(string module, string[] cmdparams) { - if (cmdparams.Length < 4) + bool force = false; + + OptionSet options = new OptionSet().Add("f|force", delegate (string v) { force = v != null; }); + + List mainParams = options.Parse(cmdparams); + + if (mainParams.Count < 4) return; string alert = null; - if (cmdparams.Length > 4) + if (mainParams.Count > 4) alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); IList agents = SceneManager.GetCurrentSceneAvatars(); @@ -466,8 +477,8 @@ namespace OpenSim { RegionInfo regionInfo = presence.Scene.RegionInfo; - if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) && - presence.Lastname.ToLower().Contains(cmdparams[3].ToLower())) + if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) && + presence.Lastname.ToLower().Contains(mainParams[3].ToLower())) { MainConsole.Instance.Output( String.Format( @@ -480,7 +491,7 @@ namespace OpenSim else presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n"); - presence.Scene.IncomingCloseAgent(presence.UUID); + presence.Scene.IncomingCloseAgent(presence.UUID, force); } } diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 37cfe1d25f..f78439860a 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -305,8 +305,13 @@ namespace OpenSim m_httpServerPort = m_networkServersInfo.HttpListenerPort; SceneManager.OnRestartSim += handleRestartRegion; - // Only start the memory watchdog once all regions are ready - SceneManager.OnRegionsReadyStatusChange += sm => MemoryWatchdog.Enabled = sm.AllRegionsReady; + // Only enable the watchdogs when all regions are ready. Otherwise we get false positives when cpu is + // heavily used during initial startup. + // + // FIXME: It's also possible that region ready status should be flipped during an OAR load since this + // also makes heavy use of the CPU. + SceneManager.OnRegionsReadyStatusChange + += sm => { MemoryWatchdog.Enabled = sm.AllRegionsReady; Watchdog.Enabled = sm.AllRegionsReady; }; } /// diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs index cd70410680..d604cf6f51 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs @@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests UUID spId = TestHelpers.ParseTail(0x1); SceneHelpers.AddScenePresence(m_scene, spId); - m_scene.IncomingCloseAgent(spId); + m_scene.IncomingCloseAgent(spId, false); // TODO: Add more assertions for the other aspects of event queues Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs new file mode 100644 index 0000000000..36af55f0f3 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs @@ -0,0 +1,234 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Drawing; +using System.Drawing.Imaging; +using System.Reflection; +using System.IO; +using System.Web; +using log4net; +using Nini.Config; +using Mono.Addins; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenMetaverse.Imaging; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; +using OpenSim.Capabilities.Handlers; + +namespace OpenSim.Region.ClientStack.Linden +{ + + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RegionConsoleModule")] + public class RegionConsoleModule : INonSharedRegionModule, IRegionConsole + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + private IEventQueue m_eventQueue; + private Commands m_commands = new Commands(); + public ICommands Commands { get { return m_commands; } } + + public void Initialise(IConfigSource source) + { + m_commands.AddCommand( "Help", false, "help", "help []", "Display help on a particular command or on a list of commands in a category", Help); + } + + public void AddRegion(Scene s) + { + m_scene = s; + m_scene.RegisterModuleInterface(this); + } + + public void RemoveRegion(Scene s) + { + m_scene.EventManager.OnRegisterCaps -= RegisterCaps; + m_scene = null; + } + + public void RegionLoaded(Scene s) + { + m_scene.EventManager.OnRegisterCaps += RegisterCaps; + m_eventQueue = m_scene.RequestModuleInterface(); + } + + public void PostInitialise() + { + } + + public void Close() { } + + public string Name { get { return "RegionConsoleModule"; } } + + public Type ReplaceableInterface + { + get { return null; } + } + + public void RegisterCaps(UUID agentID, Caps caps) + { + if (!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(agentID)) + return; + + UUID capID = UUID.Random(); + + m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); + caps.RegisterHandler( + "SimConsoleAsync", + new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene)); + } + + public void SendConsoleOutput(UUID agentID, string message) + { + OSD osd = OSD.FromString(message); + + m_eventQueue.Enqueue(EventQueueHelper.BuildEvent("SimConsoleResponse", osd), agentID); + } + + public bool RunCommand(string command, UUID invokerID) + { + string[] parts = Parser.Parse(command); + Array.Resize(ref parts, parts.Length + 1); + parts[parts.Length - 1] = invokerID.ToString(); + + if (m_commands.Resolve(parts).Length == 0) + return false; + + return true; + } + + private void Help(string module, string[] cmd) + { + UUID agentID = new UUID(cmd[cmd.Length - 1]); + Array.Resize(ref cmd, cmd.Length - 1); + + List help = Commands.GetHelp(cmd); + + string reply = String.Empty; + + foreach (string s in help) + { + reply += s + "\n"; + } + + SendConsoleOutput(agentID, reply); + } + + public void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn) + { + m_commands.AddCommand(module, shared, command, help, longhelp, fn); + } + } + + public class ConsoleHandler : BaseStreamHandler + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private RegionConsoleModule m_consoleModule; + private UUID m_agentID; + private bool m_isGod; + private Scene m_scene; + private bool m_consoleIsOn = false; + + public ConsoleHandler(string path, string name, UUID agentID, RegionConsoleModule module, Scene scene) + :base("POST", path, name, agentID.ToString()) + { + m_agentID = agentID; + m_consoleModule = module; + m_scene = scene; + + m_isGod = m_scene.Permissions.IsGod(agentID); + } + + public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + StreamReader reader = new StreamReader(request); + string message = reader.ReadToEnd(); + + OSD osd = OSDParser.DeserializeLLSDXml(message); + + string cmd = osd.AsString(); + if (cmd == "set console on") + { + if (m_isGod) + { + MainConsole.Instance.OnOutput += ConsoleSender; + m_consoleIsOn = true; + m_consoleModule.SendConsoleOutput(m_agentID, "Console is now on"); + } + return new byte[0]; + } + else if (cmd == "set console off") + { + MainConsole.Instance.OnOutput -= ConsoleSender; + m_consoleIsOn = false; + m_consoleModule.SendConsoleOutput(m_agentID, "Console is now off"); + return new byte[0]; + } + + if (m_consoleIsOn == false && m_consoleModule.RunCommand(osd.AsString().Trim(), m_agentID)) + return new byte[0]; + + if (m_isGod && m_consoleIsOn) + { + MainConsole.Instance.RunCommand(osd.AsString().Trim()); + } + else + { + m_consoleModule.SendConsoleOutput(m_agentID, "Unknown command"); + } + + return new byte[0]; + } + + private void ConsoleSender(string text) + { + m_consoleModule.SendConsoleOutput(m_agentID, text); + } + + private void OnMakeChildAgent(ScenePresence presence) + { + if (presence.UUID == m_agentID) + { + MainConsole.Instance.OnOutput -= ConsoleSender; + m_consoleIsOn = false; + } + } + } +} diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 01ceeeda98..148d0e0357 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -487,16 +487,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Client Methods - /// - /// Close down the client view - /// public void Close() + { + Close(false); + } + + public void Close(bool force) { // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. lock (CloseSyncLock) { - if (!IsActive) + // We still perform a force close inside the sync lock since this is intended to attempt close where + // there is some unidentified connection problem, not where we have issues due to deadlock + if (!IsActive && !force) return; IsActive = false; @@ -5810,7 +5814,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP args.Channel = ch; args.From = String.Empty; args.Message = Utils.BytesToString(msg); - args.Type = ChatTypeEnum.Shout; + args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance args.Position = new Vector3(); args.Scene = Scene; args.Sender = this; @@ -11989,7 +11993,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { Kick(reason); Thread.Sleep(1000); - Close(); + Disconnect(); } public void Disconnect() diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index f107be17fa..d6ad07e62a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -458,10 +458,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) { - // As per Linden spec, detach (take) is disabled for temp attachs - if (so.FromItemID == UUID.Zero) - return; - lock (sp.AttachmentsSyncLock) { // Save avatar attachment information @@ -976,7 +972,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); - if (sp != null && group != null) + if (sp != null && group != null && group.FromItemID != UUID.Zero) DetachSingleAttachmentToInv(sp, group); } @@ -994,7 +990,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments foreach (SceneObjectGroup group in attachments) { - if (group.FromItemID == itemID) + if (group.FromItemID == itemID && group.FromItemID != UUID.Zero) { DetachSingleAttachmentToInv(sp, group); return; diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 1d13f753f6..82c63901f6 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -461,7 +461,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; - scene.IncomingCloseAgent(presence.UUID); + scene.IncomingCloseAgent(presence.UUID, false); // Check that we can't retrieve this attachment from the scene. Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 46738f687d..c63b0a4d0e 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -644,7 +644,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // an agent cannot teleport back to this region if it has teleported away. Thread.Sleep(2000); - sp.Scene.IncomingCloseAgent(sp.UUID); + sp.Scene.IncomingCloseAgent(sp.UUID, false); } else { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index 09a3bd604f..1e52d3705c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs @@ -312,7 +312,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation // "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", // s.RegionInfo.RegionName, destination.RegionHandle); - Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); }); + Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); }); return true; } diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 2b61800c94..433166d848 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -97,6 +97,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver } } + /// + /// Used to cache lookups for valid groups. + /// + private IDictionary m_validGroupUuids = new Dictionary(); + + private IGroupsModule m_groupsModule; + public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) { m_scene = scene; @@ -120,6 +127,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; + + m_groupsModule = m_scene.RequestModuleInterface(); } public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) @@ -132,6 +141,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; + + m_groupsModule = m_scene.RequestModuleInterface(); } /// @@ -302,6 +313,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (!ResolveUserUuid(part.LastOwnerID)) part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveGroupUuid(part.GroupID)) + part.GroupID = UUID.Zero; + // And zap any troublesome sit target information // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); // part.SitTargetPosition = new Vector3(0, 0, 0); @@ -318,13 +332,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver { kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; } + if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) { if (!ResolveUserUuid(kvp.Value.CreatorID)) kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; } + if (UserManager != null) UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); + + if (!ResolveGroupUuid(kvp.Value.GroupID)) + kvp.Value.GroupID = UUID.Zero; } } } @@ -364,9 +383,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (string serialisedParcel in serialisedParcels) { LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); + + // Validate User and Group UUID's + if (!ResolveUserUuid(parcel.OwnerID)) parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - + + if (!ResolveGroupUuid(parcel.GroupID)) + { + parcel.GroupID = UUID.Zero; + parcel.IsGroupOwned = false; + } + + List accessList = new List(); + foreach (LandAccessEntry entry in parcel.ParcelAccessList) + { + if (ResolveUserUuid(entry.AgentID)) + accessList.Add(entry); + // else, drop this access rule + } + parcel.ParcelAccessList = accessList; + // m_log.DebugFormat( // "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", // parcel.Name, parcel.LocalID, parcel.Area); @@ -401,6 +438,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver } /// + /// Look up the given group id to check whether it's one that is valid for this grid. + /// + /// + /// + private bool ResolveGroupUuid(UUID uuid) + { + if (uuid == UUID.Zero) + return true; // this means the object has no group + + if (!m_validGroupUuids.ContainsKey(uuid)) + { + bool exists; + + if (m_groupsModule == null) + exists = false; + else + exists = (m_groupsModule.GetGroupRecord(uuid) != null); + + m_validGroupUuids.Add(uuid, exists); + } + + return m_validGroupUuids[uuid]; + } + /// Load an asset /// /// diff --git a/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs b/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs new file mode 100644 index 0000000000..4d261d6655 --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs @@ -0,0 +1,39 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Region.Framework.Interfaces +{ + public interface IRegionConsole + { + bool RunCommand(string command, UUID invokerID); + void SendConsoleOutput(UUID agentID, string message); + void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn); + } +} diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs index 0fcafcc515..085b5caf69 100644 --- a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs +++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs @@ -116,5 +116,10 @@ namespace OpenSim.Region.Framework.Interfaces /// the region UUID void RemoveRegionEnvironmentSettings(UUID regionUUID); + void SaveExtra(UUID regionID, string name, string value); + + void RemoveExtra(UUID regionID, string name); + + Dictionary GetExtra(UUID regionID); } } diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs index e424976226..3787ca0f36 100644 --- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs +++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs @@ -127,6 +127,12 @@ namespace OpenSim.Region.Framework.Interfaces /// the region UUID void RemoveRegionEnvironmentSettings(UUID regionUUID); + void SaveExtra(UUID regionID, string name, string val); + + void RemoveExtra(UUID regionID, string name); + + Dictionary GetExtra(UUID regionID); + void Shutdown(); } } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 6dea2f0cd1..4d65be9056 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -213,6 +213,9 @@ namespace OpenSim.Region.Framework.Scenes /// public event NewScript OnNewScript; + public delegate void ExtraSettingChangedDelegate(Scene scene, string name, string value); + public event ExtraSettingChangedDelegate OnExtraSettingChanged; + public virtual void TriggerNewScript(UUID clientID, SceneObjectPart part, UUID itemID) { NewScript handlerNewScript = OnNewScript; @@ -2591,5 +2594,25 @@ namespace OpenSim.Region.Framework.Scenes } } + public void TriggerExtraSettingChanged(Scene scene, string name, string val) + { + ExtraSettingChangedDelegate handler = OnExtraSettingChanged; + + if (handler != null) + { + foreach (ExtraSettingChangedDelegate d in handler.GetInvocationList()) + { + try + { + d(scene, name, val); + } + catch (Exception e) + { + m_log.ErrorFormat("[EVENT MANAGER]: Delegate for ExtraSettingChanged failed - continuing {0} - {1}", + e.Message, e.StackTrace); + } + } + } + } } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 0967c3427e..ad7418970c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -103,8 +103,26 @@ namespace OpenSim.Region.Framework.Scenes /// public bool CollidablePrims { get; private set; } + /// + /// Minimum value of the size of a non-physical prim in each axis + /// + public float m_minNonphys = 0.01f; + + /// + /// Maximum value of the size of a non-physical prim in each axis + /// public float m_maxNonphys = 256; + + /// + /// Minimum value of the size of a physical prim in each axis + /// + public float m_minPhys = 0.01f; + + /// + /// Maximum value of the size of a physical prim in each axis + /// public float m_maxPhys = 10; + public bool m_clampPrimSize; public bool m_trustBinaries; public bool m_allowScriptCrossings; @@ -174,6 +192,8 @@ namespace OpenSim.Region.Framework.Scenes protected ICapabilitiesModule m_capsModule; protected IGroupsModule m_groupsModule; + private Dictionary m_extraSettings; + /// /// Current scene frame number /// @@ -635,6 +655,8 @@ namespace OpenSim.Region.Framework.Scenes // FIXME: It shouldn't be up to the database plugins to create this data - we should do it when a new // region is set up and avoid these gyrations. RegionSettings rs = simDataService.LoadRegionSettings(RegionInfo.RegionID); + m_extraSettings = simDataService.GetExtra(RegionInfo.RegionID); + bool updatedTerrainTextures = false; if (rs.TerrainTexture1 == UUID.Zero) { @@ -717,14 +739,25 @@ namespace OpenSim.Region.Framework.Scenes PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); + m_minNonphys = startupConfig.GetFloat("NonphysicalPrimMin", m_minNonphys); + if (RegionInfo.NonphysPrimMin > 0) + { + m_minNonphys = RegionInfo.NonphysPrimMin; + } + m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys); if (RegionInfo.NonphysPrimMax > 0) { m_maxNonphys = RegionInfo.NonphysPrimMax; } - m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); + m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys); + if (RegionInfo.PhysPrimMin > 0) + { + m_minPhys = RegionInfo.PhysPrimMin; + } + m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); if (RegionInfo.PhysPrimMax > 0) { m_maxPhys = RegionInfo.PhysPrimMax; @@ -4083,16 +4116,19 @@ namespace OpenSim.Region.Framework.Scenes /// /// Tell a single agent to disconnect from the region. /// - /// /// - public bool IncomingCloseAgent(UUID agentID) + /// + /// Force the agent to close even if it might be in the middle of some other operation. You do not want to + /// force unless you are absolutely sure that the agent is dead and a normal close is not working. + /// + public bool IncomingCloseAgent(UUID agentID, bool force) { //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); if (presence != null) { - presence.ControllingClient.Close(); + presence.ControllingClient.Close(force); return true; } @@ -5443,5 +5479,44 @@ namespace OpenSim.Region.Framework.Scenes callback(asset); } + + public string GetExtraSetting(string name) + { + string val; + + if (!m_extraSettings.TryGetValue(name, out val)) + return String.Empty; + + return val; + } + + public void StoreExtraSetting(string name, string val) + { + string oldVal; + + if (m_extraSettings.TryGetValue(name, out oldVal)) + { + if (oldVal == val) + return; + } + + m_extraSettings[name] = val; + + m_SimulationDataService.SaveExtra(RegionInfo.RegionID, name, val); + + m_eventManager.TriggerExtraSettingChanged(this, name, val); + } + + public void RemoveExtraSetting(string name) + { + if (!m_extraSettings.ContainsKey(name)) + return; + + m_extraSettings.Remove(name); + + m_SimulationDataService.RemoveExtra(RegionInfo.RegionID, name); + + m_eventManager.TriggerExtraSettingChanged(this, name, String.Empty); + } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 13842ad85d..b6339fb636 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -375,12 +375,9 @@ namespace OpenSim.Region.Framework.Scenes { Vector3 scale = part.Shape.Scale; - if (scale.X > m_parentScene.m_maxNonphys) - scale.X = m_parentScene.m_maxNonphys; - if (scale.Y > m_parentScene.m_maxNonphys) - scale.Y = m_parentScene.m_maxNonphys; - if (scale.Z > m_parentScene.m_maxNonphys) - scale.Z = m_parentScene.m_maxNonphys; + scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); + scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); + scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); part.Shape.Scale = scale; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 5f90035b1d..f6c725ba50 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2674,17 +2674,17 @@ namespace OpenSim.Region.Framework.Scenes RootPart.StoreUndoState(true); - scale.X = Math.Min(scale.X, Scene.m_maxNonphys); - scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); - scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); + scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); + scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y)); + scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z)); PhysicsActor pa = m_rootPart.PhysActor; if (pa != null && pa.IsPhysical) { - scale.X = Math.Min(scale.X, Scene.m_maxPhys); - scale.Y = Math.Min(scale.Y, Scene.m_maxPhys); - scale.Z = Math.Min(scale.Z, Scene.m_maxPhys); + scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X)); + scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y)); + scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z)); } float x = (scale.X / RootPart.Scale.X); @@ -2716,6 +2716,14 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } + else if (oldSize.X * x < m_scene.m_minPhys) + { + f = m_scene.m_minPhys / oldSize.X; + a = f / x; + x *= a; + y *= a; + z *= a; + } if (oldSize.Y * y > m_scene.m_maxPhys) { @@ -2725,6 +2733,14 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } + else if (oldSize.Y * y < m_scene.m_minPhys) + { + f = m_scene.m_minPhys / oldSize.Y; + a = f / y; + x *= a; + y *= a; + z *= a; + } if (oldSize.Z * z > m_scene.m_maxPhys) { @@ -2734,6 +2750,14 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } + else if (oldSize.Z * z < m_scene.m_minPhys) + { + f = m_scene.m_minPhys / oldSize.Z; + a = f / z; + x *= a; + y *= a; + z *= a; + } } else { @@ -2745,6 +2769,14 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } + else if (oldSize.X * x < m_scene.m_minNonphys) + { + f = m_scene.m_minNonphys / oldSize.X; + a = f / x; + x *= a; + y *= a; + z *= a; + } if (oldSize.Y * y > m_scene.m_maxNonphys) { @@ -2754,6 +2786,14 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } + else if (oldSize.Y * y < m_scene.m_minNonphys) + { + f = m_scene.m_minNonphys / oldSize.Y; + a = f / y; + x *= a; + y *= a; + z *= a; + } if (oldSize.Z * z > m_scene.m_maxNonphys) { @@ -2763,6 +2803,14 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } + else if (oldSize.Z * z < m_scene.m_minNonphys) + { + f = m_scene.m_minNonphys / oldSize.Z; + a = f / z; + x *= a; + y *= a; + z *= a; + } } // obPart.IgnoreUndoUpdate = false; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 4c87639f94..2a9ee3a5d4 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -733,7 +733,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); + m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e); } } @@ -2368,17 +2368,16 @@ namespace OpenSim.Region.Framework.Scenes /// public void Resize(Vector3 scale) { - scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys); - scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys); - scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys); + scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); + scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); + scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z)); PhysicsActor pa = PhysActor; - if (pa != null && pa.IsPhysical) { - scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys); - scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys); - scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys); + scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); + scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); + scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); } // m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); @@ -2852,23 +2851,32 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Set the color of prim faces + /// Set the color & alpha of prim faces /// - /// /// - public void SetFaceColor(Vector3 color, int face) + /// + /// + public void SetFaceColorAlpha(int face, Vector3 color, double ?alpha) { + Vector3 clippedColor = Util.Clip(color, 0.0f, 1.0f); + float clippedAlpha = alpha.HasValue ? + Util.Clip((float)alpha.Value, 0.0f, 1.0f) : 0; + // The only way to get a deep copy/ If we don't do this, we can - // mever detect color changes further down. + // never detect color changes further down. Byte[] buf = Shape.Textures.GetBytes(); Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); Color4 texcolor; if (face >= 0 && face < GetNumberOfSides()) { texcolor = tex.CreateFace((uint)face).RGBA; - texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); - texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); - texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); + texcolor.R = clippedColor.X; + texcolor.G = clippedColor.Y; + texcolor.B = clippedColor.Z; + if (alpha.HasValue) + { + texcolor.A = clippedAlpha; + } tex.FaceTextures[face].RGBA = texcolor; UpdateTextureEntry(tex.GetBytes()); return; @@ -2880,15 +2888,23 @@ namespace OpenSim.Region.Framework.Scenes if (tex.FaceTextures[i] != null) { texcolor = tex.FaceTextures[i].RGBA; - texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); - texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); - texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); + texcolor.R = clippedColor.X; + texcolor.G = clippedColor.Y; + texcolor.B = clippedColor.Z; + if (alpha.HasValue) + { + texcolor.A = clippedAlpha; + } tex.FaceTextures[i].RGBA = texcolor; } texcolor = tex.DefaultTexture.RGBA; - texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); - texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); - texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); + texcolor.R = clippedColor.X; + texcolor.G = clippedColor.Y; + texcolor.B = clippedColor.Z; + if (alpha.HasValue) + { + texcolor.A = clippedAlpha; + } tex.DefaultTexture.RGBA = texcolor; } UpdateTextureEntry(tex.GetBytes()); @@ -4237,6 +4253,57 @@ namespace OpenSim.Region.Framework.Scenes ScheduleFullUpdate(); } + public void UpdateSlice(float begin, float end) + { + if (end < begin) + { + float temp = begin; + begin = end; + end = temp; + } + end = Math.Min(1f, Math.Max(0f, end)); + begin = Math.Min(Math.Min(1f, Math.Max(0f, begin)), end - 0.02f); + if (begin < 0.02f && end < 0.02f) + { + begin = 0f; + end = 0.02f; + } + + ushort uBegin = (ushort)(50000.0 * begin); + ushort uEnd = (ushort)(50000.0 * (1f - end)); + bool updatePossiblyNeeded = false; + PrimType primType = GetPrimType(); + if (primType == PrimType.SPHERE || primType == PrimType.TORUS || primType == PrimType.TUBE || primType == PrimType.RING) + { + if (m_shape.ProfileBegin != uBegin || m_shape.ProfileEnd != uEnd) + { + m_shape.ProfileBegin = uBegin; + m_shape.ProfileEnd = uEnd; + updatePossiblyNeeded = true; + } + } + else if (m_shape.PathBegin != uBegin || m_shape.PathEnd != uEnd) + { + m_shape.PathBegin = uBegin; + m_shape.PathEnd = uEnd; + updatePossiblyNeeded = true; + } + + if (updatePossiblyNeeded && ParentGroup != null) + { + ParentGroup.HasGroupChanged = true; + } + if (updatePossiblyNeeded && PhysActor != null) + { + PhysActor.Shape = m_shape; + ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); + } + if (updatePossiblyNeeded) + { + ScheduleFullUpdate(); + } + } + /// /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics /// engine can use it. diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 548dfd36a0..65d526fd4e 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1385,17 +1385,22 @@ namespace OpenSim.Region.Framework.Scenes bool DCFlagKeyPressed = false; Vector3 agent_control_v3 = Vector3.Zero; - bool oldflying = Flying; + bool newFlying = actor.Flying; if (ForceFly) - actor.Flying = true; + newFlying = true; else if (FlyDisabled) - actor.Flying = false; + newFlying = false; else - actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); + newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); - if (actor.Flying != oldflying) + if (actor.Flying != newFlying) + { + // Note: ScenePresence.Flying is actually fetched from the physical actor + // so setting PhysActor.Flying here also sets the ScenePresence's value. + actor.Flying = newFlying; update_movementflag = true; + } if (ParentID == 0) { diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index 5758869e7a..5faf131caf 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs @@ -141,7 +141,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests TestScene scene = new SceneHelpers().SetupScene(); ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); - scene.IncomingCloseAgent(sp.UUID); + scene.IncomingCloseAgent(sp.UUID, false); Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index bae25cdf7b..e93bd7cb1d 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -885,6 +885,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } public void Close() + { + Close(false); + } + + public void Close(bool force) { Disconnect(); } diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs index 27ba5c93ea..cb89cd1133 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs @@ -43,15 +43,13 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.OptionalModules.Avatar.Attachments { - /// - /// A module that just holds commands for inspecting avatar appearance. - /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TempAttachmentsModule")] public class TempAttachmentsModule : INonSharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private Scene m_scene; + private IRegionConsole m_console; public void Initialise(IConfigSource configSource) { @@ -74,6 +72,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments { comms.RegisterScriptInvocation( this, "llAttachToAvatarTemp"); m_log.DebugFormat("[TEMP ATTACHS]: Registered script functions"); + m_console = scene.RequestModuleInterface(); + + if (m_console != null) + { + m_console.AddCommand("TempATtachModule", false, "set auto_grant_attach_perms", "set auto_grant_attach_perms true|false", "Allow objects owned by the region owner os estate managers to obtain attach permissions without asking the user", SetAutoGrantAttachPerms); + } } else { @@ -95,6 +99,37 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments get { return "TempAttachmentsModule"; } } + private void SendConsoleOutput(UUID agentID, string text) + { + if (m_console == null) + return; + + m_console.SendConsoleOutput(agentID, text); + } + + private void SetAutoGrantAttachPerms(string module, string[] parms) + { + UUID agentID = new UUID(parms[parms.Length - 1]); + Array.Resize(ref parms, parms.Length - 1); + + if (parms.Length != 3) + { + SendConsoleOutput(agentID, "Command parameter error"); + return; + } + + string val = parms[2]; + if (val != "true" && val != "false") + { + SendConsoleOutput(agentID, "Command parameter error"); + return; + } + + m_scene.StoreExtraSetting("auto_grant_attach_perms", val); + + SendConsoleOutput(agentID, String.Format("auto_grant_attach_perms set to {0}", val)); + } + private void llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) { SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host); diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 67989ba752..a8e4d9060d 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -900,6 +900,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC } public void Close() + { + Close(false); + } + + public void Close(bool force) { // Remove ourselves from the scene m_scene.RemoveClient(AgentId, false); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs index 72df6b9427..683bc51163 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs @@ -37,7 +37,8 @@ public class BS6DofConstraint : BSConstraint // Create a btGeneric6DofConstraint public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, Vector3 frame1, Quaternion frame1rot, - Vector3 frame2, Quaternion frame2rot ) + Vector3 frame2, Quaternion frame2rot, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) { m_world = world; m_body1 = obj1; @@ -46,16 +47,45 @@ public class BS6DofConstraint : BSConstraint BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, frame1, frame1rot, frame2, frame2rot, - true /*useLinearReferenceFrameA*/, true /*disableCollisionsBetweenLinkedBodies*/)); + useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); m_enabled = true; } + public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 joinPoint, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + m_constraint = new BulletConstraint( + BulletSimAPI.Create6DofConstraintToPoint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, + joinPoint, + useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + m_enabled = true; + } + + public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) + { + bool ret = false; + if (m_enabled) + { + BulletSimAPI.SetFrames2(m_constraint.Ptr, frameA, frameArot, frameB, frameBrot); + ret = true; + } + return ret; + } + public bool SetCFMAndERP(float cfm, float erp) { - bool ret = true; - BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); - BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); - BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + bool ret = false; + if (m_enabled) + { + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + ret = true; + } return ret; } @@ -76,5 +106,13 @@ public class BS6DofConstraint : BSConstraint ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); return ret; } + + public bool SetBreakingImpulseThreshold(float threshold) + { + bool ret = false; + if (m_enabled) + ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold); + return ret; + } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index f164afeeff..1b23a3696c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -124,10 +124,14 @@ public class BSCharacter : PhysicsActor // do actual create at taint time _scene.TaintedObject("BSCharacter.create", delegate() { + DetailLog("{0},BSCharacter.create", _localID); BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); + // Set the buoyancy for flying. This will be refactored when all the settings happen in C# + BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); + m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); - // avatars get all collisions no matter what + // avatars get all collisions no matter what (makes walking on ground and such work) BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); @@ -137,7 +141,7 @@ public class BSCharacter : PhysicsActor // called when this character is being destroyed and the resources should be released public void Destroy() { - // DetailLog("{0},Destroy", LocalID); + DetailLog("{0},BSCharacter.Destroy", LocalID); _scene.TaintedObject("BSCharacter.destroy", delegate() { BulletSimAPI.DestroyObject(_scene.WorldID, _localID); @@ -209,7 +213,7 @@ public class BSCharacter : PhysicsActor _scene.TaintedObject("BSCharacter.setPosition", delegate() { - DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); + DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); }); } @@ -226,7 +230,7 @@ public class BSCharacter : PhysicsActor float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); if (_position.Z < terrainHeight) { - DetailLog("{0},PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); + DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); _position.Z = terrainHeight + 2.0f; ret = true; } @@ -319,14 +323,13 @@ public class BSCharacter : PhysicsActor public override bool Flying { get { return _flying; } set { - if (_flying != value) - { - _flying = value; - // simulate flying by changing the effect of gravity - this.Buoyancy = ComputeBuoyancyFromFlying(_flying); - } + _flying = value; + // simulate flying by changing the effect of gravity + this.Buoyancy = ComputeBuoyancyFromFlying(_flying); } } + // Flying is implimented by changing the avatar's buoyancy. + // Would this be done better with a vehicle type? private float ComputeBuoyancyFromFlying(bool ifFlying) { return ifFlying ? 1f : 0f; } @@ -368,7 +371,7 @@ public class BSCharacter : PhysicsActor set { _buoyancy = value; _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() { - DetailLog("{0},setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); + DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); }); } @@ -415,7 +418,7 @@ public class BSCharacter : PhysicsActor // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); _scene.TaintedObject("BSCharacter.AddForce", delegate() { - DetailLog("{0},setAddForce,taint,addedForce={1}", LocalID, _force); + DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); BulletSimAPI.AddObjectForce2(Body.Ptr, _force); }); } @@ -507,6 +510,7 @@ public class BSCharacter : PhysicsActor { _collidingGroundStep = _scene.SimulationStep; } + // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith); // throttle collisions to the rate specified in the subscription if (_subscribedEventsMs != 0) { @@ -535,7 +539,10 @@ public class BSCharacter : PhysicsActor if (collisionCollection == null) collisionCollection = new CollisionEventUpdate(); base.SendCollisionUpdate(collisionCollection); - collisionCollection.Clear(); + // If there were any collisions in the collection, make sure we don't use the + // same instance next time. + if (collisionCollection.Count > 0) + collisionCollection = null; // End kludge } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index da26b721ec..25084d80ac 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -80,10 +80,33 @@ public abstract class BSConstraint : IDisposable bool ret = false; if (m_enabled) { + // Recompute the internal transforms BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); ret = true; } return ret; } + + // Reset this constraint making sure it has all its internal structures + // recomputed and is enabled and ready to go. + public virtual bool RecomputeConstraintVariables(float mass) + { + bool ret = false; + if (m_enabled) + { + ret = CalculateTransforms(); + if (ret) + { + // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}", + // BSScene.DetailLogZero, Body1.ID, Body2.ID); + BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); + } + else + { + m_world.scene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID); + } + } + return ret; + } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs index 3df2ddc007..22ea3671fc 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs @@ -56,21 +56,25 @@ public class BSConstraintCollection : IDisposable public void Clear() { - foreach (BSConstraint cons in m_constraints) + lock (m_constraints) { - cons.Dispose(); + foreach (BSConstraint cons in m_constraints) + { + cons.Dispose(); + } + m_constraints.Clear(); } - m_constraints.Clear(); } public bool AddConstraint(BSConstraint cons) { - // There is only one constraint between any bodies. Remove any old just to make sure. - RemoveAndDestroyConstraint(cons.Body1, cons.Body2); + lock (m_constraints) + { + // There is only one constraint between any bodies. Remove any old just to make sure. + RemoveAndDestroyConstraint(cons.Body1, cons.Body2); - m_world.scene.DetailLog("{0},BSConstraintCollection.AddConstraint,call,body1={1},body2={2}", BSScene.DetailLogZero, cons.Body1.ID, cons.Body2.ID); - - m_constraints.Add(cons); + m_constraints.Add(cons); + } return true; } @@ -84,16 +88,19 @@ public class BSConstraintCollection : IDisposable uint lookingID1 = body1.ID; uint lookingID2 = body2.ID; - ForEachConstraint(delegate(BSConstraint constrain) + lock (m_constraints) { - if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) - || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1)) + foreach (BSConstraint constrain in m_constraints) { - foundConstraint = constrain; - found = true; + if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) + || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1)) + { + foundConstraint = constrain; + found = true; + break; + } } - return found; - }); + } returnConstraint = foundConstraint; return found; } @@ -103,25 +110,35 @@ public class BSConstraintCollection : IDisposable // Return 'true' if a constraint was found and destroyed. public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) { - // return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID); - bool ret = false; - BSConstraint constrain; - - if (this.TryGetConstraint(body1, body2, out constrain)) + lock (m_constraints) { - m_world.scene.DetailLog("{0},BSConstraintCollection.RemoveAndDestroyConstraint,taint,body1={1},body2={2}", BSScene.DetailLogZero, body1.ID, body2.ID); - // remove the constraint from our collection - m_constraints.Remove(constrain); - // tell the engine that all its structures need to be freed - constrain.Dispose(); - // we destroyed something - ret = true; + BSConstraint constrain; + if (this.TryGetConstraint(body1, body2, out constrain)) + { + // remove the constraint from our collection + RemoveAndDestroyConstraint(constrain); + ret = true; + } } return ret; } + // The constraint MUST exist in the collection + public bool RemoveAndDestroyConstraint(BSConstraint constrain) + { + lock (m_constraints) + { + // remove the constraint from our collection + m_constraints.Remove(constrain); + } + // tell the engine that all its structures need to be freed + constrain.Dispose(); + // we destroyed something + return true; + } + // Remove all constraints that reference the passed body. // Return 'true' if any constraints were destroyed. public bool RemoveAndDestroyConstraint(BulletBody body1) @@ -130,16 +147,15 @@ public class BSConstraintCollection : IDisposable List toRemove = new List(); uint lookingID = body1.ID; - ForEachConstraint(delegate(BSConstraint constrain) - { - if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) - { - toRemove.Add(constrain); - } - return false; - }); lock (m_constraints) { + foreach (BSConstraint constrain in m_constraints) + { + if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) + { + toRemove.Add(constrain); + } + } foreach (BSConstraint constrain in toRemove) { m_constraints.Remove(constrain); @@ -151,28 +167,16 @@ public class BSConstraintCollection : IDisposable public bool RecalculateAllConstraints() { - ForEachConstraint(delegate(BSConstraint constrain) - { - constrain.CalculateTransforms(); - return false; - }); - return true; - } - - // Lock the constraint list and loop through it. - // The constraint action returns 'true' if it wants the loop aborted. - private void ForEachConstraint(ConstraintAction action) - { + bool ret = false; lock (m_constraints) { foreach (BSConstraint constrain in m_constraints) { - if (action(constrain)) - break; + constrain.CalculateTransforms(); + ret = true; } } + return ret; } - - } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index c197e61ee8..d7213fc66a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -57,6 +57,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin private int frcount = 0; // Used to limit dynamics debug output to // every 100th frame + private BSScene m_physicsScene; private BSPrim m_prim; // the prim this dynamic controller belongs to // Vehicle properties @@ -74,7 +75,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin // HOVER_UP_ONLY // LIMIT_MOTOR_UP // LIMIT_ROLL_ONLY - private VehicleFlag m_Hoverflags = (VehicleFlag)0; private Vector3 m_BlockingEndPoint = Vector3.Zero; private Quaternion m_RollreferenceFrame = Quaternion.Identity; // Linear properties @@ -124,15 +124,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin private float m_verticalAttractionEfficiency = 1.0f; // damped private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. - public BSDynamics(BSPrim myPrim) + public BSDynamics(BSScene myScene, BSPrim myPrim) { + m_physicsScene = myScene; m_prim = myPrim; m_type = Vehicle.TYPE_NONE; } internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep) { - DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); + VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: @@ -231,7 +232,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep) { - DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); + VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.ANGULAR_FRICTION_TIMESCALE: @@ -266,7 +267,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) { - DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); + VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.REFERENCE_FRAME: @@ -280,164 +281,27 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessVehicleFlags(int pParam, bool remove) { - DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); + VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); + VehicleFlag parm = (VehicleFlag)pParam; if (remove) { if (pParam == -1) { m_flags = (VehicleFlag)0; - m_Hoverflags = (VehicleFlag)0; - return; } - if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) + else { - if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.HOVER_GLOBAL_HEIGHT); - } - if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY) - { - if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY); - } - if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY) - { - if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.HOVER_UP_ONLY); - } - if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY) - { - if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY); - } - if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP) - { - if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.LIMIT_MOTOR_UP); - } - if ((pParam & (int)VehicleFlag.LIMIT_ROLL_ONLY) == (int)VehicleFlag.LIMIT_ROLL_ONLY) - { - if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); - } - if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) - { - if ((m_flags & VehicleFlag.MOUSELOOK_BANK) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.MOUSELOOK_BANK); - } - if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER) - { - if ((m_flags & VehicleFlag.MOUSELOOK_STEER) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.MOUSELOOK_STEER); - } - if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP) - { - if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP); - } - if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED) - { - if ((m_flags & VehicleFlag.CAMERA_DECOUPLED) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.CAMERA_DECOUPLED); - } - if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X) - { - if ((m_flags & VehicleFlag.NO_X) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_X); - } - if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y) - { - if ((m_flags & VehicleFlag.NO_Y) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_Y); - } - if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z) - { - if ((m_flags & VehicleFlag.NO_Z) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_Z); - } - if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT) - { - if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != (VehicleFlag)0) - m_Hoverflags &= ~(VehicleFlag.LOCK_HOVER_HEIGHT); - } - if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION) - { - if ((m_flags & VehicleFlag.NO_DEFLECTION) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.NO_DEFLECTION); - } - if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION) - { - if ((m_flags & VehicleFlag.LOCK_ROTATION) != (VehicleFlag)0) - m_flags &= ~(VehicleFlag.LOCK_ROTATION); + m_flags &= ~parm; } } - else - { - if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) - { - m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT | m_flags); - } - if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY) - { - m_Hoverflags |= (VehicleFlag.HOVER_TERRAIN_ONLY | m_flags); - } - if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY) - { - m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY | m_flags); - } - if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY) - { - m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY | m_flags); - } - if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP) - { - m_flags |= (VehicleFlag.LIMIT_MOTOR_UP | m_flags); - } - if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) - { - m_flags |= (VehicleFlag.MOUSELOOK_BANK | m_flags); - } - if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER) - { - m_flags |= (VehicleFlag.MOUSELOOK_STEER | m_flags); - } - if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP) - { - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | m_flags); - } - if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED) - { - m_flags |= (VehicleFlag.CAMERA_DECOUPLED | m_flags); - } - if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X) - { - m_flags |= (VehicleFlag.NO_X); - } - if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y) - { - m_flags |= (VehicleFlag.NO_Y); - } - if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z) - { - m_flags |= (VehicleFlag.NO_Z); - } - if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT) - { - m_Hoverflags |= (VehicleFlag.LOCK_HOVER_HEIGHT); - } - if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION) - { - m_flags |= (VehicleFlag.NO_DEFLECTION); - } - if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION) - { - m_flags |= (VehicleFlag.LOCK_ROTATION); - } + else { + m_flags |= parm; } }//end ProcessVehicleFlags - internal void ProcessTypeChange(Vehicle pType) + internal void ProcessTypeChange(Vehicle pType, float stepSize) { - DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); + VDetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); // Set Defaults For Type m_type = pType; switch (pType) @@ -478,10 +342,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 1; // m_bankingTimescale = 10; // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); break; case Vehicle.TYPE_CAR: m_linearFrictionTimescale = new Vector3(100, 2, 1000); @@ -506,10 +370,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 1; // m_bankingTimescale = 1; // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); - m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY); + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); + m_flags |= (VehicleFlag.HOVER_UP_ONLY); break; case Vehicle.TYPE_BOAT: m_linearFrictionTimescale = new Vector3(10, 3, 2); @@ -534,12 +398,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 0.8f; // m_bankingTimescale = 1; // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | + m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); - m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY); + m_flags |= (VehicleFlag.HOVER_WATER_ONLY); break; case Vehicle.TYPE_AIRPLANE: m_linearFrictionTimescale = new Vector3(200, 10, 5); @@ -564,7 +428,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 0.7f; // m_bankingTimescale = 2; // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); @@ -592,11 +456,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_bankingMix = 0.7f; // m_bankingTimescale = 5; // m_referenceFrame = Quaternion.Identity; - m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_UP_ONLY); m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); - m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); + m_flags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); break; } }//end SetDefaultsForType @@ -613,7 +477,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin MoveAngular(pTimestep); LimitRotation(pTimestep); - DetailLog("{0},Dynamics,done,pos={1},force={2},velocity={3},angvel={4}", + VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); }// end Step @@ -657,7 +521,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin */ - DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", + VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); } else @@ -669,7 +533,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_lastLinearVelocityVector = Vector3.Zero; } - // convert requested object velocity to world-referenced vector + // convert requested object velocity to object relative vector Quaternion rotq = m_prim.Orientation; m_dir = m_lastLinearVelocityVector * rotq; @@ -722,7 +586,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (changed) { m_prim.Position = pos; - DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", + VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", m_prim.LocalID, m_BlockingEndPoint, posChange, pos); } } @@ -732,32 +596,32 @@ namespace OpenSim.Region.Physics.BulletSPlugin { pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2; m_prim.Position = pos; - DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); + VDetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); } // Check if hovering - if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) + if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) { // We should hover, get the target height - if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) + if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) { m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; } - if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) + if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) { m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; } - if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) + if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) { m_VhoverTargetHeight = m_VhoverHeight; } - if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0) + if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) { // If body is aready heigher, use its height as target height if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; } - if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) + if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) { if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) { @@ -779,7 +643,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin } } - DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); + VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); // m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped // m_VhoverTimescale = 0f; // time to acheive height @@ -815,7 +679,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { grav.Z = (float)(grav.Z * 1.037125); } - DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); + VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); //End Experimental Values } if ((m_flags & (VehicleFlag.NO_X)) != 0) @@ -844,7 +708,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; - DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", + VDetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); } // end MoveLinear() @@ -870,13 +734,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin // There are m_angularMotorApply steps. Vector3 origAngularVelocity = m_angularMotorVelocity; // ramp up to new value - // current velocity += error / (time to get there / step interval) + // current velocity += error / (time to get there / step interval) // requested speed - last motor speed m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); - DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", + VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected @@ -887,6 +751,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin // No motor recently applied, keep the body velocity // and decay the velocity m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); + if (m_angularMotorVelocity.LengthSquared() < 0.00001) + m_angularMotorVelocity = Vector3.Zero; } // end motor section // Vertical attractor section @@ -924,7 +790,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin vertattr.X += bounce * angularVelocity.X; vertattr.Y += bounce * angularVelocity.Y; - DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", + VDetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", m_prim.LocalID, verterr, bounce, vertattr); } // else vertical attractor is off @@ -942,13 +808,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin { m_lastAngularVelocity.X = 0; m_lastAngularVelocity.Y = 0; - DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); + VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); } if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) { m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. - DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); + VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); } // apply friction @@ -958,7 +824,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Apply to the body m_prim.RotationalVelocity = m_lastAngularVelocity; - DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity); + VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity); } //end MoveAngular internal void LimitRotation(float timestep) @@ -1005,11 +871,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (changed) m_prim.Orientation = m_rot; - DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot); + VDetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot); } // Invoke the detailed logger and output something if it's enabled. - private void DetailLog(string msg, params Object[] args) + private void VDetailLog(string msg, params Object[] args) { if (m_prim.Scene.VehicleLoggingEnabled) m_prim.Scene.PhysicsLogging.Write(msg, args); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs new file mode 100755 index 0000000000..d68048bd0a --- /dev/null +++ b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs @@ -0,0 +1,55 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyrightD + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +using System; +using System.Collections.Generic; +using System.Text; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ + +class BSHingeConstraint : BSConstraint +{ + public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 pivotInA, Vector3 pivotInB, + Vector3 axisInA, Vector3 axisInB, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + m_constraint = new BulletConstraint( + BulletSimAPI.CreateHingeConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, + pivotInA, pivotInB, + axisInA, axisInB, + useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + m_enabled = true; + } + +} + +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 4a71612f1a..9e3f0db689 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -37,11 +37,15 @@ public class BSLinkset private static string LogHeader = "[BULLETSIM LINKSET]"; private BSPrim m_linksetRoot; - public BSPrim Root { get { return m_linksetRoot; } } + public BSPrim LinksetRoot { get { return m_linksetRoot; } } - private BSScene m_scene; - public BSScene Scene { get { return m_scene; } } + private BSScene m_physicsScene; + public BSScene PhysicsScene { get { return m_physicsScene; } } + static int m_nextLinksetID = 1; + public int LinksetID { get; private set; } + + // The children under the root in this linkset private List m_children; // We lock the diddling of linkset classes to prevent any badness. @@ -73,7 +77,11 @@ public class BSLinkset public BSLinkset(BSScene scene, BSPrim parent) { // A simple linkset of one (no children) - m_scene = scene; + LinksetID = m_nextLinksetID++; + // We create LOTS of linksets. + if (m_nextLinksetID < 0) + m_nextLinksetID = 1; + m_physicsScene = scene; m_linksetRoot = parent; m_children = new List(); m_mass = parent.MassRaw; @@ -91,6 +99,9 @@ public class BSLinkset return this; } + // Remove a child from a linkset. + // Returns a new linkset for the child which is a linkset of one (just the + // orphened child). public BSLinkset RemoveMeFromLinkset(BSPrim child) { lock (m_linksetActivityLock) @@ -114,60 +125,9 @@ public class BSLinkset } // The child is down to a linkset of just itself - return new BSLinkset(Scene, child); + return new BSLinkset(PhysicsScene, child); } - /* DEPRECATED: this is really bad in that it trys to unlink other prims. - // An existing linkset had one of its members rebuilt or something. - // Go through the linkset and rebuild the pointers to the bodies of the linkset members. - public BSLinkset RefreshLinkset(BSPrim requestor) - { - BSLinkset ret = requestor.Linkset; - - lock (m_linksetActivityLock) - { - // The body pointer is refetched in case anything has moved. - System.IntPtr aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, m_linksetRoot.LocalID); - if (aPtr == System.IntPtr.Zero) - { - // That's odd. We can't find the root of the linkset. - // The linkset is somehow dead. The requestor is now a member of a linkset of one. - DetailLog("{0},RefreshLinkset.RemoveRoot,child={1}", m_linksetRoot.LocalID, m_linksetRoot.LocalID); - ret = RemoveMeFromLinkset(m_linksetRoot); - } - else - { - // Reconstruct the pointer to the body of the linkset root. - DetailLog("{0},RefreshLinkset.RebuildRoot,rootID={1},ptr={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, aPtr); - m_linksetRoot.Body = new BulletBody(m_linksetRoot.LocalID, aPtr); - - List toRemove = new List(); - foreach (BSPrim bsp in m_children) - { - aPtr = BulletSimAPI.GetBodyHandle2(m_scene.World.Ptr, bsp.LocalID); - if (aPtr == System.IntPtr.Zero) - { - toRemove.Add(bsp); - } - else - { - // Reconstruct the pointer to the body of the linkset root. - DetailLog("{0},RefreshLinkset.RebuildChild,rootID={1},ptr={2}", bsp.LocalID, m_linksetRoot.LocalID, aPtr); - bsp.Body = new BulletBody(bsp.LocalID, aPtr); - } - } - foreach (BSPrim bsp in toRemove) - { - RemoveChildFromOtherLinkset(bsp); - } - } - } - - return ret; - } - */ - - // Return 'true' if the passed object is the root object of this linkset public bool IsRoot(BSPrim requestor) { @@ -183,12 +143,15 @@ public class BSLinkset public bool HasChild(BSPrim child) { bool ret = false; - foreach (BSPrim bp in m_children) + lock (m_linksetActivityLock) { - if (child.LocalID == bp.LocalID) + foreach (BSPrim bp in m_children) { - ret = true; - break; + if (child.LocalID == bp.LocalID) + { + ret = true; + break; + } } } return ret; @@ -209,13 +172,16 @@ public class BSLinkset OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; float totalMass = m_linksetRoot.MassRaw; - foreach (BSPrim bp in m_children) + lock (m_linksetActivityLock) { - com += bp.Position * bp.MassRaw; - totalMass += bp.MassRaw; + foreach (BSPrim bp in m_children) + { + com += bp.Position * bp.MassRaw; + totalMass += bp.MassRaw; + } + if (totalMass != 0f) + com /= totalMass; } - if (totalMass != 0f) - com /= totalMass; return com; } @@ -224,29 +190,83 @@ public class BSLinkset { OMV.Vector3 com = m_linksetRoot.Position; - foreach (BSPrim bp in m_children) + lock (m_linksetActivityLock) { - com += bp.Position * bp.MassRaw; + foreach (BSPrim bp in m_children) + { + com += bp.Position * bp.MassRaw; + } + com /= (m_children.Count + 1); } - com /= (m_children.Count + 1); return com; } + // When physical properties are changed the linkset needs to recalculate + // its internal properties. + public void Refresh(BSPrim requestor) + { + // If there are no children, there aren't any constraints to recompute + if (!HasAnyChildren) + return; + + // Only the root does the recomputation + if (IsRoot(requestor)) + { + PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() + { + RecomputeLinksetConstraintVariables(); + }); + } + } + + // Call each of the constraints that make up this linkset and recompute the + // various transforms and variables. Used when objects are added or removed + // from a linkset to make sure the constraints know about the new mass and + // geometry. + // Must only be called at taint time!! + private bool RecomputeLinksetConstraintVariables() + { + float linksetMass = LinksetMass; + lock (m_linksetActivityLock) + { + foreach (BSPrim child in m_children) + { + BSConstraint constrain; + if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain)) + { + // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", + // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); + constrain.RecomputeConstraintVariables(linksetMass); + } + else + { + // Non-fatal error that can happen when children are being added to the linkset but + // their constraints have not been created yet. + // Caused by the fact that m_children is built at run time but building constraints + // happens at taint time. + // m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}", + // m_linksetRoot.Body.ID, child.Body.ID); + } + } + } + return false; + } + // I am the root of a linkset and a new child is being added // Called while LinkActivity is locked. - public void AddChildToLinkset(BSPrim child) + private void AddChildToLinkset(BSPrim child) { if (!HasChild(child)) { m_children.Add(child); - BSPrim root = Root; // capture the root as of now - m_scene.TaintedObject("AddChildToLinkset", delegate() + BSPrim rootx = LinksetRoot; // capture the root as of now + BSPrim childx = child; + m_physicsScene.TaintedObject("AddChildToLinkset", delegate() { - DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); - PhysicallyLinkAChildToRoot(root, child); // build the physical binding between me and the child + PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child }); } return; @@ -257,31 +277,33 @@ public class BSLinkset // it's still connected to the linkset. // Normal OpenSimulator operation will never do this because other SceneObjectPart information // has to be updated also (like pointer to prim's parent). - public void RemoveChildFromOtherLinkset(BSPrim pchild) + private void RemoveChildFromOtherLinkset(BSPrim pchild) { - pchild.Linkset = new BSLinkset(m_scene, pchild); + pchild.Linkset = new BSLinkset(m_physicsScene, pchild); RemoveChildFromLinkset(pchild); } // I am the root of a linkset and one of my children is being removed. // Safe to call even if the child is not really in my linkset. - public void RemoveChildFromLinkset(BSPrim child) + private void RemoveChildFromLinkset(BSPrim child) { if (m_children.Remove(child)) { - BSPrim root = Root; // capture the root as of now - m_scene.TaintedObject("RemoveChildFromLinkset", delegate() + BSPrim rootx = LinksetRoot; // capture the root as of now + BSPrim childx = child; + m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() { - DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); - PhysicallyUnlinkAChildFromRoot(root, child); + PhysicallyUnlinkAChildFromRoot(rootx, childx); }); + + RecomputeLinksetConstraintVariables(); } else { // This will happen if we remove the root of the linkset first. Non-fatal occurance. - // m_scene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); + // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); } return; } @@ -293,48 +315,81 @@ public class BSLinkset // Zero motion for children so they don't interpolate childPrim.ZeroMotion(); + // Relative position normalized to the root prim + // Essentually a vector pointing from center of rootPrim to center of childPrim + OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; + + // real world coordinate of midpoint between the two objects + OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); + + // create a constraint that allows no freedom of movement between the two objects + // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 + DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}", + rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint); + BS6DofConstraint constrain = new BS6DofConstraint( + m_physicsScene.World, rootPrim.Body, childPrim.Body, + midPoint, + true, + true + ); + /* NOTE: below is an attempt to build constraint with full frame computation, etc. + * Using the midpoint is easier since it lets the Bullet code use the transforms + * of the objects. + * Code left as a warning to future programmers. + // ================================================================================== // relative position normalized to the root prim OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; // relative rotation of the child to the parent OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; + OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); // create a constraint that allows no freedom of movement between the two objects // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); BS6DofConstraint constrain = new BS6DofConstraint( - m_scene.World, rootPrim.Body, childPrim.Body, - childRelativePosition, - childRelativeRotation, + PhysicsScene.World, rootPrim.Body, childPrim.Body, OMV.Vector3.Zero, - -childRelativeRotation + OMV.Quaternion.Inverse(rootPrim.Orientation), + OMV.Vector3.Zero, + OMV.Quaternion.Inverse(childPrim.Orientation), + // A point half way between the parent and child + // childRelativePosition/2, + // childRelativeRotation, + // childRelativePosition/2, + // inverseChildRelativeRotation, + true, + true ); - m_scene.Constraints.AddConstraint(constrain); + // ================================================================================== + */ + + m_physicsScene.Constraints.AddConstraint(constrain); // zero linear and angular limits makes the objects unable to move in relation to each other constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); // tweek the constraint to increase stability - constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset)); - constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor), - m_scene.Params.linkConstraintTransMotorMaxVel, - m_scene.Params.linkConstraintTransMotorMaxForce); - constrain.SetCFMAndERP(m_scene.Params.linkConstraintCFM, m_scene.Params.linkConstraintERP); + constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); + constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), + PhysicsScene.Params.linkConstraintTransMotorMaxVel, + PhysicsScene.Params.linkConstraintTransMotorMaxForce); + constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); + RecomputeLinksetConstraintVariables(); } // Remove linkage between myself and a particular child // Called at taint time! private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim) { - // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", - // LogHeader, rootPrim.LocalID, childPrim.LocalID); DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); - m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body); + // Find the constraint for this link and get rid of it from the overall collection and from my list + m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body); + // Make the child refresh its location BulletSimAPI.PushUpdate2(childPrim.Body.Ptr); } @@ -343,23 +398,15 @@ public class BSLinkset // Called at taint time! private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim) { - // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); - m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); - } - - // Invoke the detailed logger and output something if it's enabled. - private void DebugLog(string msg, params Object[] args) - { - if (m_scene.ShouldDebugLog) - m_scene.Logger.DebugFormat(msg, args); + m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); } // Invoke the detailed logger and output something if it's enabled. private void DetailLog(string msg, params Object[] args) { - m_scene.PhysicsLogging.Write(msg, args); + m_physicsScene.PhysicsLogging.Write(msg, args); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 05cc8227a3..d3f1e9c17f 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -42,8 +42,6 @@ public sealed class BSPrim : PhysicsActor private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS PRIM]"; - private void DebugLog(string mm, params Object[] xx) { if (_scene.ShouldDebugLog) m_log.DebugFormat(mm, xx); } - private IMesh _mesh; private PrimitiveBaseShape _pbs; private ShapeData.PhysicsShapeType _shapeType; @@ -141,8 +139,8 @@ public sealed class BSPrim : PhysicsActor _friction = _scene.Params.defaultFriction; // TODO: compute based on object material _density = _scene.Params.defaultDensity; // TODO: compute based on object material _restitution = _scene.Params.defaultRestitution; - _linkset = new BSLinkset(_scene, this); // a linkset of one - _vehicle = new BSDynamics(this); // add vehicleness + _linkset = new BSLinkset(Scene, this); // a linkset of one + _vehicle = new BSDynamics(Scene, this); // add vehicleness _mass = CalculateMass(); // do the actual object creation at taint time DetailLog("{0},BSPrim.constructor,call", LocalID); @@ -163,13 +161,13 @@ public sealed class BSPrim : PhysicsActor // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); // Undo any links between me and any other object - BSPrim parentBefore = _linkset.Root; + BSPrim parentBefore = _linkset.LinksetRoot; int childrenBefore = _linkset.NumberOfChildren; _linkset = _linkset.RemoveMeFromLinkset(this); DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", - LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren); + LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); // Undo any vehicle properties this.VehicleType = (int)Vehicle.TYPE_NONE; @@ -193,7 +191,7 @@ public sealed class BSPrim : PhysicsActor { _mass = CalculateMass(); // changing size changes the mass BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); - // DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); + DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); RecreateGeomAndObject(); }); } @@ -232,14 +230,13 @@ public sealed class BSPrim : PhysicsActor BSPrim parent = obj as BSPrim; if (parent != null) { - DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); - BSPrim parentBefore = _linkset.Root; + BSPrim parentBefore = _linkset.LinksetRoot; int childrenBefore = _linkset.NumberOfChildren; _linkset = parent.Linkset.AddMeToLinkset(this); DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", - LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren); + LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); } return; } @@ -248,16 +245,14 @@ public sealed class BSPrim : PhysicsActor public override void delink() { // TODO: decide if this parent checking needs to happen at taint time // Race condition here: if link() and delink() in same simulation tick, the delink will not happen - DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, - _linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString()); - BSPrim parentBefore = _linkset.Root; + BSPrim parentBefore = _linkset.LinksetRoot; int childrenBefore = _linkset.NumberOfChildren; _linkset = _linkset.RemoveMeFromLinkset(this); DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", - LocalID, parentBefore.LocalID, childrenBefore, _linkset.Root.LocalID, _linkset.NumberOfChildren); + LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); return; } @@ -354,7 +349,7 @@ public sealed class BSPrim : PhysicsActor { // Done at taint time so we're sure the physics engine is not using the variables // Vehicle code changes the parameters for this vehicle type. - _vehicle.ProcessTypeChange(type); + _vehicle.ProcessTypeChange(type, Scene.LastSimulatedTimestep); // Tell the scene about the vehicle so it will get processing each frame. _scene.VehicleInSceneTypeChanged(this, type); }); @@ -486,17 +481,17 @@ public sealed class BSPrim : PhysicsActor // No locking here because only called when it is safe private void SetObjectDynamic() { - // RA: remove this for the moment. - // The problem is that dynamic objects are hulls so if we are becoming physical - // the shape has to be checked and possibly built. - // Maybe a VerifyCorrectPhysicalShape() routine? - // RecreateGeomAndObject(); + // If it's becoming dynamic, it will need hullness + VerifyCorrectPhysicalShape(); // Bullet wants static objects to have a mass of zero float mass = IsStatic ? 0f : _mass; BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); + // recompute any linkset parameters + _linkset.Refresh(this); + CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); } @@ -504,7 +499,9 @@ public sealed class BSPrim : PhysicsActor // prims don't fly public override bool Flying { get { return _flying; } - set { _flying = value; } + set { + _flying = value; + } } public override bool SetAlwaysRun { get { return _setAlwaysRun; } @@ -1039,7 +1036,14 @@ public sealed class BSPrim : PhysicsActor // No locking here because this is done when we know physics is not simulating private void CreateGeomMesh() { - float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; + // level of detail based on size and type of the object + float lod = _scene.MeshLOD; + if (_pbs.SculptEntry) + lod = _scene.SculptLOD; + float maxAxis = Math.Max(_size.X, Math.Max(_size.Y, _size.Z)); + if (maxAxis > _scene.MeshMegaPrimThreshold) + lod = _scene.MeshMegaPrimLOD; + ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod); // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); @@ -1095,28 +1099,21 @@ public sealed class BSPrim : PhysicsActor // if the hull hasn't changed, don't rebuild it if (newHullKey == _hullKey) return; - DetailLog("{0},BSPrim.CreateGeomHull,create,key={1}", LocalID, _meshKey); + DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); // Since we're recreating new, get rid of any previously generated shape if (_hullKey != 0) { // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); - DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _meshKey); + DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey); BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); _hullKey = 0; - _hulls.Clear(); - DetailLog("{0},BSPrim.CreateGeomHull,deleteOldMesh,key={1}", LocalID, _meshKey); - BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); - _mesh = null; // the mesh cannot match either - _meshKey = 0; } _hullKey = newHullKey; - if (_meshKey != _hullKey) - { - // if the underlying mesh has changed, rebuild it - CreateGeomMesh(); - } + + // Make sure the underlying mesh exists and is correct + CreateGeomMesh(); int[] indices = _mesh.getIndexListAsInt(); List vertices = _mesh.getVertexList(); @@ -1142,7 +1139,7 @@ public sealed class BSPrim : PhysicsActor // create the hull into the _hulls variable convexBuilder.process(dcomp); - // Convert the vertices and indices for passing to unmanaged + // Convert the vertices and indices for passing to unmanaged. // The hull information is passed as a large floating point array. // The format is: // convHulls[0] = number of hulls @@ -1214,6 +1211,27 @@ public sealed class BSPrim : PhysicsActor return; } + private void VerifyCorrectPhysicalShape() + { + if (IsStatic) + { + // if static, we don't need a hull so, if there is one, rebuild without it + if (_hullKey != 0) + { + RecreateGeomAndObject(); + } + } + else + { + // if not static, it will need a hull to efficiently collide with things + if (_hullKey == 0) + { + RecreateGeomAndObject(); + } + + } + } + // Create an object in Bullet if it has not already been created // No locking here because this is done when the physics engine is not simulating // Returns 'true' if an object was actually created. @@ -1338,13 +1356,12 @@ public sealed class BSPrim : PhysicsActor _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; - // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", - // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); base.RequestPhysicsterseUpdate(); } + /* else { // For debugging, we also report the movement of children @@ -1352,10 +1369,12 @@ public sealed class BSPrim : PhysicsActor LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); } + */ } // I've collided with something - CollisionEventUpdate collisionCollection = null; + // Called at taint time from within the Step() function + CollisionEventUpdate collisionCollection; public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) { // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); @@ -1367,6 +1386,17 @@ public sealed class BSPrim : PhysicsActor _collidingGroundStep = _scene.SimulationStep; } + // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith); + BSPrim collidingWithPrim; + if (_scene.Prims.TryGetValue(collidingWith, out collidingWithPrim)) + { + // prims in the same linkset cannot collide with each other + if (this.Linkset.LinksetID == collidingWithPrim.Linkset.LinksetID) + { + return; + } + } + // if someone is subscribed to collision events.... if (_subscribedEventsMs != 0) { // throttle the collisions to the number of milliseconds specified in the subscription @@ -1387,7 +1417,9 @@ public sealed class BSPrim : PhysicsActor if (collisionCollection != null && collisionCollection.Count > 0) { base.SendCollisionUpdate(collisionCollection); - collisionCollection.Clear(); + // The collisionCollection structure is passed around in the simulator. + // Make sure we don't have a handle to that one and that a new one is used next time. + collisionCollection = null; } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index beaea1f32c..56924aa61e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -73,15 +73,22 @@ public class BSScene : PhysicsScene, IPhysicsParameters private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS SCENE]"; - public void DebugLog(string mm, params Object[] xx) { if (ShouldDebugLog) m_log.DebugFormat(mm, xx); } + // The name of the region we're working for. + public string RegionName { get; private set; } public string BulletSimVersion = "?"; private Dictionary m_avatars = new Dictionary(); + public Dictionary Characters { get { return m_avatars; } } + private Dictionary m_prims = new Dictionary(); + public Dictionary Prims { get { return m_prims; } } + private HashSet m_avatarsWithCollisions = new HashSet(); private HashSet m_primsWithCollisions = new HashSet(); + private List m_vehicles = new List(); + private float[] m_heightMap; private float m_waterLevel; private uint m_worldID; @@ -95,16 +102,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters private int m_detailedStatsStep = 0; public IMesher mesher; - private float m_meshLOD; - public float MeshLOD - { - get { return m_meshLOD; } - } - private float m_sculptLOD; - public float SculptLOD - { - get { return m_sculptLOD; } - } + // Level of Detail values kept as float because that's what the Meshmerizer wants + public float MeshLOD { get; private set; } + public float MeshMegaPrimLOD { get; private set; } + public float MeshMegaPrimThreshold { get; private set; } + public float SculptLOD { get; private set; } private BulletSim m_worldSim; public BulletSim World @@ -179,8 +181,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters ConfigurationParameters[] m_params; GCHandle m_paramsHandle; - public bool ShouldDebugLog { get; private set; } - + // Handle to the callback used by the unmanaged code to call into the managed code. + // Used for debug logging. + // Need to store the handle in a persistant variable so it won't be freed. private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; // Sometimes you just have to log everything. @@ -196,6 +199,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters public BSScene(string identifier) { m_initialized = false; + // we are passed the name of the region we're working for. + RegionName = identifier; } public override void Initialise(IMesher meshmerizer, IConfigSource config) @@ -281,10 +286,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters // Very detailed logging for physics debugging m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); - m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-"); + m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-"); m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); // Very detailed logging for vehicle debugging m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); + + // Do any replacements in the parameters + m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); } } } @@ -413,7 +421,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters // prevent simulation until we've been initialized if (!m_initialized) return 10.0f; - long simulateStartTime = Util.EnvironmentTickCount(); + int simulateStartTime = Util.EnvironmentTickCount(); // update the prim states while we know the physics engine is not busy ProcessTaints(); @@ -434,8 +442,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters catch (Exception e) { m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); - DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); - // updatedEntityCount = 0; + // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); + updatedEntityCount = 0; collidersCount = 0; } @@ -511,8 +519,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); // return (timeStep * (float)simulateTotalTime); - // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. - return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; + // TODO: FIX THIS: fps calculation possibly wrong. + // This calculation says 1/timeStep is the ideal frame rate. Any time added to + // that by the physics simulation gives a slower frame rate. + long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime); + if (totalSimulationTime >= timeStep) + return 0; + return 1f / (timeStep + totalSimulationTime); } // Something has collided @@ -529,6 +542,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters else if (m_avatars.ContainsKey(collidingWith)) type = ActorTypes.Agent; + // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); + BSPrim prim; if (m_prims.TryGetValue(localID, out prim)) { prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration); @@ -590,12 +605,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters // make sure no stepping happens while we're deleting stuff m_initialized = false; - if (m_constraintCollection != null) - { - m_constraintCollection.Dispose(); - m_constraintCollection = null; - } - foreach (KeyValuePair kvp in m_avatars) { kvp.Value.Destroy(); @@ -608,6 +617,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters } m_prims.Clear(); + // Now that the prims are all cleaned up, there should be no constraints left + if (m_constraintCollection != null) + { + m_constraintCollection.Dispose(); + m_constraintCollection = null; + } + // Anything left in the unmanaged code should be cleaned out BulletSimAPI.Shutdown(WorldID); @@ -891,16 +907,26 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), - new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", + new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 8f, - (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_meshLOD; }, - (s,p,l,v) => { s.m_meshLOD = (int)v; } ), - new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", + (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); }, + (s) => { return s.MeshLOD; }, + (s,p,l,v) => { s.MeshLOD = v; } ), + new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters", + 16f, + (s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); }, + (s) => { return s.MeshMegaPrimLOD; }, + (s,p,l,v) => { s.MeshMegaPrimLOD = v; } ), + new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD", + 10f, + (s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); }, + (s) => { return s.MeshMegaPrimThreshold; }, + (s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ), + new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", 32f, - (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_sculptLOD; }, - (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), + (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); }, + (s) => { return s.SculptLOD; }, + (s,p,l,v) => { s.SculptLOD = v; } ), new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", 10f, @@ -1131,12 +1157,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, (s) => { return (float)s.m_detailedStatsStep; }, (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), - new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements", - ConfigurationParameters.numericFalse, - (s,cf,p,v) => { s.ShouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); }, - (s) => { return s.NumericBool(s.ShouldDebugLog); }, - (s,p,l,v) => { s.ShouldDebugLog = s.BoolNumeric(v); } ), - }; // Convert a boolean to our numeric true and false values diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 6800b96977..504bd3c41c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -415,6 +415,27 @@ public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, Int Vector3 frame2loc, Quaternion frame2rot, bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr obj1, IntPtr obj2, + Vector3 joinPoint, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, + Vector3 pivotinA, Vector3 pivotinB, + Vector3 axisInA, Vector3 axisInB, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetFrames2(IntPtr constrain, + Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot); + [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); @@ -427,6 +448,9 @@ public static extern bool UseFrameOffset2(IntPtr constrain, float enable); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce); +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold); + [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool CalculateTransforms2(IntPtr constrain); @@ -517,6 +541,9 @@ public static extern bool SetGravity2(IntPtr obj, Vector3 val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr ClearForces2(IntPtr obj); +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern IntPtr ClearAllForces2(IntPtr obj); + [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool SetMargin2(IntPtr obj, float val); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 1287709f4d..8140416b80 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -243,33 +243,38 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } public List GetLinkParts(int linkType) + { + return GetLinkParts(m_host, linkType); + } + + private List GetLinkParts(SceneObjectPart part, int linkType) { List ret = new List(); - ret.Add(m_host); + ret.Add(part); switch (linkType) { case ScriptBaseClass.LINK_SET: - return new List(m_host.ParentGroup.Parts); + return new List(part.ParentGroup.Parts); case ScriptBaseClass.LINK_ROOT: ret = new List(); - ret.Add(m_host.ParentGroup.RootPart); + ret.Add(part.ParentGroup.RootPart); return ret; case ScriptBaseClass.LINK_ALL_OTHERS: - ret = new List(m_host.ParentGroup.Parts); + ret = new List(part.ParentGroup.Parts); - if (ret.Contains(m_host)) - ret.Remove(m_host); + if (ret.Contains(part)) + ret.Remove(part); return ret; case ScriptBaseClass.LINK_ALL_CHILDREN: - ret = new List(m_host.ParentGroup.Parts); + ret = new List(part.ParentGroup.Parts); - if (ret.Contains(m_host.ParentGroup.RootPart)) - ret.Remove(m_host.ParentGroup.RootPart); + if (ret.Contains(part.ParentGroup.RootPart)) + ret.Remove(part.ParentGroup.RootPart); return ret; case ScriptBaseClass.LINK_THIS: @@ -279,7 +284,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (linkType < 0) return new List(); - SceneObjectPart target = m_host.ParentGroup.GetLinkNumPart(linkType); + SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType); if (target == null) return new List(); ret = new List(); @@ -325,14 +330,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return key; } - // convert a LSL_Rotation to a Quaternion - public static Quaternion Rot2Quaternion(LSL_Rotation r) - { - Quaternion q = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); - q.Normalize(); - return q; - } - //These are the implementations of the various ll-functions used by the LSL scripts. public LSL_Float llSin(double f) { @@ -1092,9 +1089,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Float llGround(LSL_Vector offset) { m_host.AddScriptLPS(1); - Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, - (float)offset.y, - (float)offset.z); + Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; //Get the slope normal. This gives us the equation of the plane tangent to the slope. LSL_Vector vsn = llGroundNormal(offset); @@ -1338,31 +1333,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (part == null || part.ParentGroup.IsDeleted) return; - if (scale.x < 0.01) - scale.x = 0.01; - if (scale.y < 0.01) - scale.y = 0.01; - if (scale.z < 0.01) - scale.z = 0.01; - + // First we need to check whether or not we need to clamp the size of a physics-enabled prim PhysicsActor pa = part.ParentGroup.RootPart.PhysActor; - if (pa != null && pa.IsPhysical) { - if (scale.x > World.m_maxPhys) - scale.x = World.m_maxPhys; - if (scale.y > World.m_maxPhys) - scale.y = World.m_maxPhys; - if (scale.z > World.m_maxPhys) - scale.z = World.m_maxPhys; + scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x)); + scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y)); + scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z)); } - if (scale.x > World.m_maxNonphys) - scale.x = World.m_maxNonphys; - if (scale.y > World.m_maxNonphys) - scale.y = World.m_maxNonphys; - if (scale.z > World.m_maxNonphys) - scale.z = World.m_maxNonphys; + // Next we clamp the scale to the non-physical min/max + scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x)); + scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y)); + scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z)); Vector3 tmp = part.Scale; tmp.X = (float)scale.x; @@ -1394,7 +1377,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (face == ScriptBaseClass.ALL_SIDES) face = SceneObjectPart.ALL_SIDES; - m_host.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); + m_host.SetFaceColorAlpha(face, color, null); } public void SetTexGen(SceneObjectPart part, int face,int style) @@ -1981,7 +1964,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api bool sameParcel = here.GlobalID == there.GlobalID; - if (!sameParcel && !World.Permissions.CanRezObject(m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, new Vector3((float)pos.x, (float)pos.y, (float)pos.z))) + if (!sameParcel && !World.Permissions.CanRezObject( + m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos)) { return 0; } @@ -2041,13 +2025,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) targetPos.z = ground; SceneObjectGroup parent = part.ParentGroup; - LSL_Vector real_vec = !adjust ? targetPos : SetPosAdjust(currentPos, targetPos); - parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z)); + parent.UpdateGroupPosition(!adjust ? targetPos : + SetPosAdjust(currentPos, targetPos)); } else { - LSL_Vector rel_vec = !adjust ? targetPos : SetPosAdjust(currentPos, targetPos); - part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z); + part.OffsetPosition = !adjust ? targetPos : + SetPosAdjust(currentPos, targetPos); SceneObjectGroup parent = part.ParentGroup; parent.HasGroupChanged = true; parent.ScheduleGroupForTerseUpdate(); @@ -2091,7 +2075,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); - return new LSL_Vector(pos.X, pos.Y, pos.Z); + return new LSL_Vector(pos); } public void llSetRot(LSL_Rotation rot) @@ -2102,7 +2086,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_host.ParentID == 0) { // special case: If we are root, rotate complete SOG to new rotation - SetRot(m_host, Rot2Quaternion(rot)); + SetRot(m_host, rot); } else { @@ -2110,7 +2094,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api SceneObjectPart rootPart = m_host.ParentGroup.RootPart; if (rootPart != null) // better safe than sorry { - SetRot(m_host, rootPart.RotationOffset * Rot2Quaternion(rot)); + SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot); } } @@ -2120,7 +2104,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetLocalRot(LSL_Rotation rot) { m_host.AddScriptLPS(1); - SetRot(m_host, Rot2Quaternion(rot)); + SetRot(m_host, rot); ScriptSleep(200); } @@ -2205,7 +2189,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (local != 0) force *= llGetRot(); - m_host.ParentGroup.RootPart.SetForce(new Vector3((float)force.x, (float)force.y, (float)force.z)); + m_host.ParentGroup.RootPart.SetForce(force); } } @@ -2217,10 +2201,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_host.ParentGroup.IsDeleted) { - Vector3 tmpForce = m_host.ParentGroup.RootPart.GetForce(); - force.x = tmpForce.X; - force.y = tmpForce.Y; - force.z = tmpForce.Z; + force = m_host.ParentGroup.RootPart.GetForce(); } return force; @@ -2229,8 +2210,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llTarget(LSL_Vector position, double range) { m_host.AddScriptLPS(1); - return m_host.ParentGroup.registerTargetWaypoint( - new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range); + return m_host.ParentGroup.registerTargetWaypoint(position, + (float)range); } public void llTargetRemove(int number) @@ -2242,8 +2223,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llRotTarget(LSL_Rotation rot, double error) { m_host.AddScriptLPS(1); - return m_host.ParentGroup.registerRotTargetWaypoint( - new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), (float)error); + return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error); } public void llRotTargetRemove(int number) @@ -2255,7 +2235,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llMoveToTarget(LSL_Vector target, double tau) { m_host.AddScriptLPS(1); - m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau); + m_host.MoveToTarget(target, (float)tau); } public void llStopMoveToTarget() @@ -2268,7 +2248,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); //No energy force yet - Vector3 v = new Vector3((float)force.x, (float)force.y, (float)force.z); + Vector3 v = force; if (v.Length() > 20000.0f) { v.Normalize(); @@ -2280,13 +2260,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llApplyRotationalImpulse(LSL_Vector force, int local) { m_host.AddScriptLPS(1); - m_host.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); + m_host.ApplyAngularImpulse(force, local != 0); } public void llSetTorque(LSL_Vector torque, int local) { m_host.AddScriptLPS(1); - m_host.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); + m_host.SetAngularImpulse(torque, local != 0); } public LSL_Vector llGetTorque() @@ -2837,13 +2817,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); - Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z); - // need the magnitude later // float velmag = (float)Util.GetMagnitude(llvel); - SceneObjectGroup new_group = World.RezObject(m_host, item, llpos, Rot2Quaternion(rot), llvel, param); + SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param); // If either of these are null, then there was an unknown error. if (new_group == null) @@ -2864,10 +2841,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api PhysicsActor pa = new_group.RootPart.PhysActor; - if (pa != null && pa.IsPhysical && llvel != Vector3.Zero) + if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) { //Recoil. - llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0); + llApplyImpulse(vel * groupmass, 0); } // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) }); @@ -2912,7 +2889,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); + m_host.StartLookAt(rot, (float)strength, (float)damping); } } @@ -3307,7 +3284,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping); + m_host.RotLookAt(target, (float)strength, (float)damping); } } @@ -3388,7 +3365,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) { - part.UpdateAngularVelocity(new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate))); + part.UpdateAngularVelocity(axis * spinrate); } public LSL_Integer llGetStartParameter() @@ -3424,53 +3401,61 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); + int implicitPerms = 0; + if (m_host.ParentGroup.IsAttachment && (UUID)agent == m_host.ParentGroup.AttachedAvatar) { // When attached, certain permissions are implicit if requested from owner - int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | + implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | ScriptBaseClass.PERMISSION_CONTROL_CAMERA | ScriptBaseClass.PERMISSION_ATTACH; - - if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms + } + else + { + bool sitting = false; + if (m_host.SitTargetAvatar == agentID) { - lock (m_host.TaskInventory) + sitting = true; + } + else + { + foreach (SceneObjectPart p in m_host.ParentGroup.Parts) { - m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; - m_host.TaskInventory[m_item.ItemID].PermsMask = perm; + if (p.SitTargetAvatar == agentID) + sitting = true; } + } - m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( - "run_time_permissions", new Object[] { - new LSL_Integer(perm) }, - new DetectParams[0])); - - return; + if (sitting) + { + // When agent is sitting, certain permissions are implicit if requested from sitting agent + implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | + ScriptBaseClass.PERMISSION_CONTROL_CAMERA | + ScriptBaseClass.PERMISSION_TRACK_CAMERA | + ScriptBaseClass.PERMISSION_TAKE_CONTROLS; + } + else + { + if (World.GetExtraSetting("auto_grant_attach_perms") == "true") + implicitPerms = ScriptBaseClass.PERMISSION_ATTACH; } } - else if (m_host.SitTargetAvatar == agentID) // Sitting avatar + + if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms { - // When agent is sitting, certain permissions are implicit if requested from sitting agent - int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | - ScriptBaseClass.PERMISSION_CONTROL_CAMERA | - ScriptBaseClass.PERMISSION_TRACK_CAMERA | - ScriptBaseClass.PERMISSION_TAKE_CONTROLS; - - if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms + lock (m_host.TaskInventory) { - lock (m_host.TaskInventory) - { - m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; - m_host.TaskInventory[m_item.ItemID].PermsMask = perm; - } - - m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( - "run_time_permissions", new Object[] { - new LSL_Integer(perm) }, - new DetectParams[0])); - - return; + m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; + m_host.TaskInventory[m_item.ItemID].PermsMask = perm; } + + m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( + "run_time_permissions", new Object[] { + new LSL_Integer(perm) }, + new DetectParams[0])); + + return; } ScenePresence presence = World.GetScenePresence(agentID); @@ -3587,7 +3572,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) - part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); + part.SetFaceColorAlpha(face, color, null); } public void llCreateLink(string target, int parent) @@ -4018,9 +4003,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetText(string text, LSL_Vector color, double alpha) { m_host.AddScriptLPS(1); - Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f), - Util.Clip((float)color.y, 0.0f, 1.0f), - Util.Clip((float)color.z, 0.0f, 1.0f)); + Vector3 av3 = Util.Clip(color, 0.0f, 1.0f); m_host.SetText(text.Length > 254 ? text.Remove(254) : text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); //m_host.ParentGroup.HasGroupChanged = true; //m_host.ParentGroup.ScheduleGroupForFullUpdate(); @@ -4217,14 +4200,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(5000); } - public void llTeleportAgent(string agent, string destination, LSL_Vector pos, LSL_Vector lookAt) + public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt) { m_host.AddScriptLPS(1); UUID agentId = new UUID(); - Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); - Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z); - if (UUID.TryParse(agent, out agentId)) { ScenePresence presence = World.GetScenePresence(agentId); @@ -4253,15 +4233,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector pos, LSL_Vector lookAt) + public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt) { m_host.AddScriptLPS(1); UUID agentId = new UUID(); ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y); - Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); - Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z); if (UUID.TryParse(agent, out agentId)) { ScenePresence presence = World.GetScenePresence(agentId); @@ -4545,7 +4523,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api distance_attenuation = 1f / normalized_units; } - Vector3 applied_linear_impulse = new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z); + Vector3 applied_linear_impulse = impulse; { float impulse_length = applied_linear_impulse.Length(); @@ -6044,9 +6022,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api //Plug the x,y coordinates of the slope normal into the equation of the plane to get //the height of that point on the plane. The resulting vector gives the slope. - Vector3 vsl = new Vector3(); - vsl.X = (float)vsn.x; - vsl.Y = (float)vsn.y; + Vector3 vsl = vsn; vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z)); vsl.Normalize(); //Normalization might be overkill here @@ -6057,9 +6033,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector llGroundNormal(LSL_Vector offset) { m_host.AddScriptLPS(1); - Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, - (float)offset.y, - (float)offset.z); + Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; // Clamp to valid position if (pos.X < 0) pos.X = 0; @@ -6512,8 +6486,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_host.ParentGroup.IsDeleted) { - m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, - new Vector3((float)vec.x, (float)vec.y, (float)vec.z)); + m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec); } } @@ -6525,7 +6498,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_host.ParentGroup.IsDeleted) { - m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, Rot2Quaternion(rot)); + m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, rot); } } @@ -6551,12 +6524,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot) { - // LSL quaternions can normalize to 0, normal Quaternions can't. - if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) - rot.z = 1; // ZERO_ROTATION = 0,0,0,1 - - part.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z); - part.SitTargetOrientation = Rot2Quaternion(rot); + part.SitTargetPosition = offset; + part.SitTargetOrientation = rot; part.ParentGroup.HasGroupChanged = true; } @@ -6659,13 +6628,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetCameraEyeOffset(LSL_Vector offset) { m_host.AddScriptLPS(1); - m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); + m_host.SetCameraEyeOffset(offset); } public void llSetCameraAtOffset(LSL_Vector offset) { m_host.AddScriptLPS(1); - m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); + m_host.SetCameraAtOffset(offset); } public LSL_String llDumpList2String(LSL_List src, string seperator) @@ -6687,7 +6656,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llScriptDanger(LSL_Vector pos) { m_host.AddScriptLPS(1); - bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z)); + bool result = World.ScriptDanger(m_host.LocalId, pos); if (result) { return 1; @@ -7246,7 +7215,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetPrimitiveParams(LSL_List rules) { m_host.AddScriptLPS(1); - SetPrimParams(m_host, rules); + + setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules); ScriptSleep(200); } @@ -7271,11 +7241,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { List parts = GetLinkParts(linknumber); + LSL_List remaining = null; + foreach (SceneObjectPart part in parts) - SetPrimParams(part, rules); + remaining = SetPrimParams(part, rules); + + while(remaining != null && remaining.Length > 2) + { + linknumber = remaining.GetLSLIntegerItem(0); + rules = remaining.GetSublist(1,-1); + parts = GetLinkParts(linknumber); + + foreach (SceneObjectPart part in parts) + remaining = SetPrimParams(part, rules); + } } - protected void SetPrimParams(SceneObjectPart part, LSL_List rules) + protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules) { int idx = 0; @@ -7298,7 +7280,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_POSITION: case (int)ScriptBaseClass.PRIM_POS_LOCAL: if (remain < 1) - return; + return null; v=rules.GetVector3Item(idx++); positionChanged = true; @@ -7307,7 +7289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api break; case (int)ScriptBaseClass.PRIM_SIZE: if (remain < 1) - return; + return null; v=rules.GetVector3Item(idx++); SetScale(part, v); @@ -7315,27 +7297,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api break; case (int)ScriptBaseClass.PRIM_ROTATION: if (remain < 1) - return; + return null; LSL_Rotation q = rules.GetQuaternionItem(idx++); // try to let this work as in SL... if (part.ParentID == 0) { // special case: If we are root, rotate complete SOG to new rotation - SetRot(part, Rot2Quaternion(q)); + SetRot(part, q); } else { // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. SceneObjectPart rootPart = part.ParentGroup.RootPart; - SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q)); + SetRot(part, rootPart.RotationOffset * (Quaternion)q); } break; case (int)ScriptBaseClass.PRIM_TYPE: if (remain < 3) - return; + return null; code = (int)rules.GetLSLIntegerItem(idx++); @@ -7354,7 +7336,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { case (int)ScriptBaseClass.PRIM_TYPE_BOX: if (remain < 6) - return; + return null; face = (int)rules.GetLSLIntegerItem(idx++); v = rules.GetVector3Item(idx++); // cut @@ -7369,7 +7351,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: if (remain < 6) - return; + return null; face = (int)rules.GetLSLIntegerItem(idx++); // holeshape v = rules.GetVector3Item(idx++); // cut @@ -7383,7 +7365,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TYPE_PRISM: if (remain < 6) - return; + return null; face = (int)rules.GetLSLIntegerItem(idx++); // holeshape v = rules.GetVector3Item(idx++); //cut @@ -7397,7 +7379,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: if (remain < 5) - return; + return null; face = (int)rules.GetLSLIntegerItem(idx++); // holeshape v = rules.GetVector3Item(idx++); // cut @@ -7410,7 +7392,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TYPE_TORUS: if (remain < 11) - return; + return null; face = (int)rules.GetLSLIntegerItem(idx++); // holeshape v = rules.GetVector3Item(idx++); //cut @@ -7429,7 +7411,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TYPE_TUBE: if (remain < 11) - return; + return null; face = (int)rules.GetLSLIntegerItem(idx++); // holeshape v = rules.GetVector3Item(idx++); //cut @@ -7448,7 +7430,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TYPE_RING: if (remain < 11) - return; + return null; face = (int)rules.GetLSLIntegerItem(idx++); // holeshape v = rules.GetVector3Item(idx++); //cut @@ -7467,7 +7449,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: if (remain < 2) - return; + return null; string map = rules.Data[idx++].ToString(); face = (int)rules.GetLSLIntegerItem(idx++); // type @@ -7479,7 +7461,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXTURE: if (remain < 5) - return; + return null; face=(int)rules.GetLSLIntegerItem(idx++); string tex=rules.Data[idx++].ToString(); @@ -7496,20 +7478,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_COLOR: if (remain < 3) - return; + return null; face=(int)rules.GetLSLIntegerItem(idx++); LSL_Vector color=rules.GetVector3Item(idx++); double alpha=(double)rules.GetLSLFloatItem(idx++); - part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); - SetAlpha(part, alpha, face); + part.SetFaceColorAlpha(face, color, alpha); break; case (int)ScriptBaseClass.PRIM_FLEXIBLE: if (remain < 7) - return; + return null; bool flexi = rules.GetLSLIntegerItem(idx++); int softness = rules.GetLSLIntegerItem(idx++); @@ -7525,7 +7506,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_POINT_LIGHT: if (remain < 5) - return; + return null; bool light = rules.GetLSLIntegerItem(idx++); LSL_Vector lightcolor = rules.GetVector3Item(idx++); float intensity = (float)rules.GetLSLFloatItem(idx++); @@ -7538,7 +7519,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_GLOW: if (remain < 2) - return; + return null; face = rules.GetLSLIntegerItem(idx++); float glow = (float)rules.GetLSLFloatItem(idx++); @@ -7548,7 +7529,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_BUMP_SHINY: if (remain < 3) - return; + return null; face = (int)rules.GetLSLIntegerItem(idx++); int shiny = (int)rules.GetLSLIntegerItem(idx++); Bumpiness bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++); @@ -7559,7 +7540,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_FULLBRIGHT: if (remain < 2) - return; + return null; face = rules.GetLSLIntegerItem(idx++); bool st = rules.GetLSLIntegerItem(idx++); SetFullBright(part, face , st); @@ -7567,17 +7548,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_MATERIAL: if (remain < 1) - return; + return null; int mat = rules.GetLSLIntegerItem(idx++); if (mat < 0 || mat > 7) - return; + return null; part.Material = Convert.ToByte(mat); break; case (int)ScriptBaseClass.PRIM_PHANTOM: if (remain < 1) - return; + return null; string ph = rules.Data[idx++].ToString(); m_host.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1")); @@ -7586,7 +7567,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_PHYSICS: if (remain < 1) - return; + return null; string phy = rules.Data[idx++].ToString(); bool physics; @@ -7600,7 +7581,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: if (remain < 1) - return; + return null; string temp = rules.Data[idx++].ToString(); m_host.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); @@ -7609,7 +7590,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXGEN: if (remain < 2) - return; + return null; //face,type face = rules.GetLSLIntegerItem(idx++); int style = rules.GetLSLIntegerItem(idx++); @@ -7617,53 +7598,57 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api break; case (int)ScriptBaseClass.PRIM_TEXT: if (remain < 3) - return; + return null; string primText = rules.GetLSLStringItem(idx++); LSL_Vector primTextColor = rules.GetVector3Item(idx++); LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); - Vector3 av3 = new Vector3(Util.Clip((float)primTextColor.x, 0.0f, 1.0f), - Util.Clip((float)primTextColor.y, 0.0f, 1.0f), - Util.Clip((float)primTextColor.z, 0.0f, 1.0f)); + Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f); part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); break; case (int)ScriptBaseClass.PRIM_NAME: if (remain < 1) - return; + return null; string primName = rules.GetLSLStringItem(idx++); part.Name = primName; break; case (int)ScriptBaseClass.PRIM_DESC: if (remain < 1) - return; + return null; string primDesc = rules.GetLSLStringItem(idx++); part.Description = primDesc; break; case (int)ScriptBaseClass.PRIM_ROT_LOCAL: if (remain < 1) - return; - LSL_Rotation lr = rules.GetQuaternionItem(idx++); - SetRot(part, Rot2Quaternion(lr)); + return null; + SetRot(part, rules.GetQuaternionItem(idx++)); break; case (int)ScriptBaseClass.PRIM_OMEGA: if (remain < 3) - return; + return null; LSL_Vector axis = rules.GetVector3Item(idx++); LSL_Float spinrate = rules.GetLSLFloatItem(idx++); LSL_Float gain = rules.GetLSLFloatItem(idx++); TargetOmega(part, axis, (double)spinrate, (double)gain); break; + case (int)ScriptBaseClass.PRIM_SLICE: + if (remain < 1) + return null; + LSL_Vector slice = rules.GetVector3Item(idx++); + part.UpdateSlice((float)slice.x, (float)slice.y); + break; case (int)ScriptBaseClass.PRIM_LINK_TARGET: if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. - return; - LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); - LSL_List new_rules = rules.GetSublist(idx, -1); - setLinkPrimParams((int)new_linknumber, new_rules); + return null; - return; + return rules.GetSublist(idx, -1); } } } + catch (InvalidCastException e) + { + ShoutError(e.Message); + } finally { if (positionChanged) @@ -7671,17 +7656,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (part.ParentGroup.RootPart == part) { SceneObjectGroup parent = part.ParentGroup; - parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); + parent.UpdateGroupPosition(currentPosition); } else { - part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z); + part.OffsetPosition = currentPosition; SceneObjectGroup parent = part.ParentGroup; parent.HasGroupChanged = true; parent.ScheduleGroupForTerseUpdate(); } } } + return null; } public LSL_String llStringToBase64(string str) @@ -7911,8 +7897,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (part != null) { Vector3 halfSize = part.Scale / 2.0f; - LSL_Vector lower = new LSL_Vector(halfSize.X * -1.0f, halfSize.Y * -1.0f, halfSize.Z * -1.0f); - LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); + LSL_Vector lower = (new LSL_Vector(halfSize)) * -1.0f; + LSL_Vector upper = new LSL_Vector(halfSize); result.Add(lower); result.Add(upper); return result; @@ -8325,6 +8311,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_POS_LOCAL: res.Add(new LSL_Vector(GetPartLocalPos(part))); break; + case (int)ScriptBaseClass.PRIM_SLICE: + PrimType prim_type = part.GetPrimType(); + bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING); + res.Add(new LSL_Vector( + (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0, + 1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0, + 0 + )); + break; } } return res; @@ -9913,9 +9908,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence avatar = World.GetScenePresence(detectedParams.Key); if (avatar != null) { - avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, simname, - new Vector3((float)pos.x, (float)pos.y, (float)pos.z), - new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); + avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, + simname, pos, lookAt); } ScriptSleep(1000); } @@ -10522,12 +10516,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api else rot = obj.GetWorldRotation(); - LSL_Rotation objrot = new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W); + LSL_Rotation objrot = new LSL_Rotation(rot); ret.Add(objrot); } break; case ScriptBaseClass.OBJECT_VELOCITY: - ret.Add(new LSL_Vector(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z)); + ret.Add(new LSL_Vector(obj.Velocity)); break; case ScriptBaseClass.OBJECT_OWNER: ret.Add(new LSL_String(obj.OwnerID.ToString())); @@ -10754,7 +10748,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (obj.OwnerID != m_host.OwnerID) return; - SetPrimParams(obj, rules); + LSL_List remaining = SetPrimParams(obj, rules); + + while ((object)remaining != null && remaining.Length > 2) + { + LSL_Integer newLink = remaining.GetLSLIntegerItem(0); + LSL_List newrules = remaining.GetSublist(1, -1); + foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){ + remaining = SetPrimParams(part, newrules); + } + } } public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules) @@ -11104,8 +11107,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); - Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z); - Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z); + Vector3 rayStart = start; + Vector3 rayEnd = end; Vector3 dir = rayEnd - rayStart; float dist = Vector3.Mag(dir); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs index 795de802bb..ceb4660f96 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs @@ -304,7 +304,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: idx++; iV = rules.GetVector3Item(idx); - wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + wl.cloudDetailXYDensity = iV; break; case (int)ScriptBaseClass.WL_CLOUD_SCALE: idx++; @@ -329,7 +329,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: idx++; iV = rules.GetVector3Item(idx); - wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + wl.cloudXYDensity = iV; break; case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: idx++; @@ -384,7 +384,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: idx++; iV = rules.GetVector3Item(idx); - wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + wl.reflectionWaveletScale = iV; break; case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: idx++; @@ -422,7 +422,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_WATER_COLOR: idx++; iV = rules.GetVector3Item(idx); - wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); + wl.waterColor = iV; break; case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: idx++; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index 7844c75155..84cf6cab65 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -333,8 +333,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (type == typeof(OpenMetaverse.Quaternion)) { - LSL_Rotation rot = (LSL_Rotation)lslparm; - return new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s); + return (OpenMetaverse.Quaternion)((LSL_Rotation)lslparm); } } @@ -343,8 +342,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (type == typeof(OpenMetaverse.Vector3)) { - LSL_Vector vect = (LSL_Vector)lslparm; - return new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z); + return (OpenMetaverse.Vector3)((LSL_Vector)lslparm); } } @@ -367,13 +365,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api result[i] = new UUID((LSL_Key)plist[i]); else if (plist[i] is LSL_Rotation) { - LSL_Rotation rot = (LSL_Rotation)plist[i]; - result[i] = new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s); + result[i] = (OpenMetaverse.Quaternion)( + (LSL_Rotation)plist[i]); } else if (plist[i] is LSL_Vector) { - LSL_Vector vect = (LSL_Vector)plist[i]; - result[i] = new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z); + result[i] = (OpenMetaverse.Vector3)( + (LSL_Vector)plist[i]); } else MODError("unknown LSL list element type"); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 859ee93d5b..1e8b51be80 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -773,10 +773,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // We will launch the teleport on a new thread so that when the script threads are terminated // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. - Util.FireAndForget( - o => World.RequestTeleportLocation(presence.ControllingClient, regionName, - new Vector3((float)position.x, (float)position.y, (float)position.z), - new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation)); + Util.FireAndForget(o => World.RequestTeleportLocation( + presence.ControllingClient, regionName, position, + lookat, (uint)TPFlags.ViaLocation)); ScriptSleep(5000); @@ -819,10 +818,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // We will launch the teleport on a new thread so that when the script threads are terminated // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. - Util.FireAndForget( - o => World.RequestTeleportLocation(presence.ControllingClient, regionHandle, - new Vector3((float)position.x, (float)position.y, (float)position.z), - new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation)); + Util.FireAndForget(o => World.RequestTeleportLocation( + presence.ControllingClient, regionHandle, + position, lookat, (uint)TPFlags.ViaLocation)); ScriptSleep(5000); @@ -2329,7 +2327,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ownerID = m_host.OwnerID; UUID x = module.CreateNPC(firstname, lastname, - new Vector3((float) position.x, (float) position.y, (float) position.z), + position, ownerID, senseAsAgent, World, @@ -2446,7 +2444,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_Vector(0, 0, 0); } - public void osNpcMoveTo(LSL_Key npc, LSL_Vector position) + public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos) { CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo"); m_host.AddScriptLPS(1); @@ -2461,7 +2459,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!module.CheckPermissions(npcId, m_host.OwnerID)) return; - Vector3 pos = new Vector3((float) position.x, (float) position.y, (float) position.z); module.MoveToTarget(npcId, World, pos, false, true, false); } } @@ -2481,11 +2478,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!module.CheckPermissions(npcId, m_host.OwnerID)) return; - Vector3 pos = new Vector3((float)target.x, (float)target.y, (float)target.z); module.MoveToTarget( new UUID(npc.m_string), World, - pos, + target, (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0, (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0, (options & ScriptBaseClass.OS_NPC_RUNNING) != 0); @@ -2537,7 +2533,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence sp = World.GetScenePresence(npcId); if (sp != null) - sp.Rotation = LSL_Api.Rot2Quaternion(rotation); + sp.Rotation = rotation; } } @@ -2881,7 +2877,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api avatar.SpeedModifier = (float)SpeedModifier; } - public void osKickAvatar(string FirstName,string SurName,string alert) + public void osKickAvatar(string FirstName, string SurName, string alert) { CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); m_host.AddScriptLPS(1); @@ -2895,7 +2891,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api sp.ControllingClient.Kick(alert); // ...and close on our side - sp.Scene.IncomingCloseAgent(sp.UUID); + sp.Scene.IncomingCloseAgent(sp.UUID, false); } }); } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index a626be8211..24cceeaaac 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -351,7 +351,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins q = avatar.Rotation * q; } - LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); + LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); @@ -428,9 +428,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins try { Vector3 diff = toRegionPos - fromRegionPos; - LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); - double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); - double mag_obj = LSL_Types.Vector3.Mag(obj_dir); + double dot = LSL_Types.Vector3.Dot(forward_dir, diff); + double mag_obj = LSL_Types.Vector3.Mag(diff); ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); } catch @@ -479,7 +478,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins q = avatar.Rotation * q; } - LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); + LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0); @@ -560,8 +559,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins double ang_obj = 0; try { - Vector3 diff = toRegionPos - fromRegionPos; - LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); + LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3( + toRegionPos - fromRegionPos); double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); double mag_obj = LSL_Types.Vector3.Mag(obj_dir); ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index c3eada047b..cad8518473 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -226,6 +226,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int ATTACH_BELLY = 28; public const int ATTACH_RPEC = 29; public const int ATTACH_LPEC = 30; + public const int ATTACH_LEFT_PEC = 29; // Same value as ATTACH_RPEC, see https://jira.secondlife.com/browse/SVC-580 + public const int ATTACH_RIGHT_PEC = 30; // Same value as ATTACH_LPEC, see https://jira.secondlife.com/browse/SVC-580 public const int ATTACH_HUD_CENTER_2 = 31; public const int ATTACH_HUD_TOP_RIGHT = 32; public const int ATTACH_HUD_TOP_CENTER = 33; @@ -326,6 +328,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int PRIM_OMEGA = 32; public const int PRIM_POS_LOCAL = 33; public const int PRIM_LINK_TARGET = 34; + public const int PRIM_SLICE = 35; public const int PRIM_TEXGEN_DEFAULT = 0; public const int PRIM_TEXGEN_PLANAR = 1; diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index 17a0d69838..03be2abf07 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs @@ -546,6 +546,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools "OpenSim.Region.ScriptEngine.Shared.dll")); parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll")); + parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, + "OpenMetaverseTypes.dll")); if (lang == enumCompileType.yp) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs index 0108f447f3..5a58f734ff 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs @@ -160,11 +160,11 @@ namespace OpenSim.Region.ScriptEngine.Shared else { // Set the values from the touch data provided by the client - touchST = new LSL_Types.Vector3(value.STCoord.X, value.STCoord.Y, value.STCoord.Z); - touchUV = new LSL_Types.Vector3(value.UVCoord.X, value.UVCoord.Y, value.UVCoord.Z); - touchNormal = new LSL_Types.Vector3(value.Normal.X, value.Normal.Y, value.Normal.Z); - touchBinormal = new LSL_Types.Vector3(value.Binormal.X, value.Binormal.Y, value.Binormal.Z); - touchPos = new LSL_Types.Vector3(value.Position.X, value.Position.Y, value.Position.Z); + touchST = new LSL_Types.Vector3(value.STCoord); + touchUV = new LSL_Types.Vector3(value.UVCoord); + touchNormal = new LSL_Types.Vector3(value.Normal); + touchBinormal = new LSL_Types.Vector3(value.Binormal); + touchPos = new LSL_Types.Vector3(value.Position); touchFace = value.FaceIndex; } } @@ -181,19 +181,13 @@ namespace OpenSim.Region.ScriptEngine.Shared Name = presence.Firstname + " " + presence.Lastname; Owner = Key; - Position = new LSL_Types.Vector3( - presence.AbsolutePosition.X, - presence.AbsolutePosition.Y, - presence.AbsolutePosition.Z); + Position = new LSL_Types.Vector3(presence.AbsolutePosition); Rotation = new LSL_Types.Quaternion( presence.Rotation.X, presence.Rotation.Y, presence.Rotation.Z, presence.Rotation.W); - Velocity = new LSL_Types.Vector3( - presence.Velocity.X, - presence.Velocity.Y, - presence.Velocity.Z); + Velocity = new LSL_Types.Vector3(presence.Velocity); if (presence.PresenceType != PresenceType.Npc) { @@ -241,16 +235,12 @@ namespace OpenSim.Region.ScriptEngine.Shared } } - Position = new LSL_Types.Vector3(part.AbsolutePosition.X, - part.AbsolutePosition.Y, - part.AbsolutePosition.Z); + Position = new LSL_Types.Vector3(part.AbsolutePosition); Quaternion wr = part.ParentGroup.GroupRotation; Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W); - Velocity = new LSL_Types.Vector3(part.Velocity.X, - part.Velocity.Y, - part.Velocity.Z); + Velocity = new LSL_Types.Vector3(part.Velocity); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index d848b2a62b..9d9df9c4e6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -31,6 +31,11 @@ using System.Globalization; using System.Text.RegularExpressions; using OpenSim.Framework; +using OpenMetaverse; +using OMV_Vector3 = OpenMetaverse.Vector3; +using OMV_Vector3d = OpenMetaverse.Vector3d; +using OMV_Quaternion = OpenMetaverse.Quaternion; + namespace OpenSim.Region.ScriptEngine.Shared { [Serializable] @@ -54,6 +59,20 @@ namespace OpenSim.Region.ScriptEngine.Shared z = (float)vector.z; } + public Vector3(OMV_Vector3 vector) + { + x = vector.X; + y = vector.Y; + z = vector.Z; + } + + public Vector3(OMV_Vector3d vector) + { + x = vector.X; + y = vector.Y; + z = vector.Z; + } + public Vector3(double X, double Y, double Z) { x = X; @@ -109,6 +128,26 @@ namespace OpenSim.Region.ScriptEngine.Shared return new list(new object[] { vec }); } + public static implicit operator OMV_Vector3(Vector3 vec) + { + return new OMV_Vector3((float)vec.x, (float)vec.y, (float)vec.z); + } + + public static implicit operator Vector3(OMV_Vector3 vec) + { + return new Vector3(vec); + } + + public static implicit operator OMV_Vector3d(Vector3 vec) + { + return new OMV_Vector3d(vec.x, vec.y, vec.z); + } + + public static implicit operator Vector3(OMV_Vector3d vec) + { + return new Vector3(vec); + } + public static bool operator ==(Vector3 lhs, Vector3 rhs) { return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); @@ -322,6 +361,14 @@ namespace OpenSim.Region.ScriptEngine.Shared s = 1; } + public Quaternion(OMV_Quaternion rot) + { + x = rot.X; + y = rot.Y; + z = rot.Z; + s = rot.W; + } + #endregion #region Overriders @@ -368,6 +415,21 @@ namespace OpenSim.Region.ScriptEngine.Shared return new list(new object[] { r }); } + public static implicit operator OMV_Quaternion(Quaternion rot) + { + // LSL quaternions can normalize to 0, normal Quaternions can't. + if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) + rot.z = 1; // ZERO_ROTATION = 0,0,0,1 + OMV_Quaternion omvrot = new OMV_Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); + omvrot.Normalize(); + return omvrot; + } + + public static implicit operator Quaternion(OMV_Quaternion rot) + { + return new Quaternion(rot); + } + public static bool operator ==(Quaternion lhs, Quaternion rhs) { // Return true if the fields match: @@ -560,12 +622,23 @@ namespace OpenSim.Region.ScriptEngine.Shared else if (m_data[itemIndex] is LSL_Types.LSLString) return new LSLInteger(m_data[itemIndex].ToString()); else - throw new InvalidCastException(); + throw new InvalidCastException(string.Format( + "{0} expected but {1} given", + typeof(LSL_Types.LSLInteger).Name, + m_data[itemIndex] != null ? + m_data[itemIndex].GetType().Name : "null")); } public LSL_Types.Vector3 GetVector3Item(int itemIndex) { - return (LSL_Types.Vector3)m_data[itemIndex]; + if(m_data[itemIndex] is LSL_Types.Vector3) + return (LSL_Types.Vector3)m_data[itemIndex]; + else + throw new InvalidCastException(string.Format( + "{0} expected but {1} given", + typeof(LSL_Types.Vector3).Name, + m_data[itemIndex] != null ? + m_data[itemIndex].GetType().Name : "null")); } public LSL_Types.Quaternion GetQuaternionItem(int itemIndex) diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs index 5c4174e4e7..cee10df54a 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs @@ -152,9 +152,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine det[0] = new DetectParams(); det[0].Key = remoteClient.AgentId; det[0].Populate(myScriptEngine.World); - det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X, - offsetPos.Y, - offsetPos.Z); + det[0].OffsetPos = offsetPos; if (originalID == 0) { @@ -298,9 +296,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine foreach (DetectedObject detobj in col.Colliders) { DetectParams d = new DetectParams(); - d.Position = new LSL_Types.Vector3(detobj.posVector.X, - detobj.posVector.Y, - detobj.posVector.Z); + d.Position = detobj.posVector; d.Populate(myScriptEngine.World); det.Add(d); myScriptEngine.PostObjectEvent(localID, new EventParams( @@ -318,9 +314,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine foreach (DetectedObject detobj in col.Colliders) { DetectParams d = new DetectParams(); - d.Position = new LSL_Types.Vector3(detobj.posVector.X, - detobj.posVector.Y, - detobj.posVector.Z); + d.Position = detobj.posVector; d.Populate(myScriptEngine.World); det.Add(d); myScriptEngine.PostObjectEvent(localID, new EventParams( @@ -337,9 +331,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine foreach (DetectedObject detobj in col.Colliders) { DetectParams d = new DetectParams(); - d.Position = new LSL_Types.Vector3(detobj.posVector.X, - detobj.posVector.Y, - detobj.posVector.Z); + d.Position = detobj.posVector; d.Populate(myScriptEngine.World); det.Add(d); myScriptEngine.PostObjectEvent(localID, new EventParams( @@ -381,8 +373,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine myScriptEngine.PostObjectEvent(localID, new EventParams( "at_target", new object[] { new LSL_Types.LSLInteger(handle), - new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z), - new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) }, + new LSL_Types.Vector3(targetpos), + new LSL_Types.Vector3(atpos) }, new DetectParams[0])); } @@ -399,8 +391,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine myScriptEngine.PostObjectEvent(localID, new EventParams( "at_rot_target", new object[] { new LSL_Types.LSLInteger(handle), - new LSL_Types.Quaternion(targetrot.X,targetrot.Y,targetrot.Z,targetrot.W), - new LSL_Types.Quaternion(atrot.X,atrot.Y,atrot.Z,atrot.W) }, + new LSL_Types.Quaternion(targetrot), + new LSL_Types.Quaternion(atrot) }, new DetectParams[0])); } diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 2dba029307..53f899abcd 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -982,10 +982,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine return false; } - UUID assetID = item.AssetID; + m_log.DebugFormat( + "[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", + part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, + part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); - //m_log.DebugFormat("[XEngine] Compiling script {0} ({1} on object {2})", - // item.Name, itemID.ToString(), part.ParentGroup.RootPart.Name); + UUID assetID = item.AssetID; ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); @@ -1164,10 +1166,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine stateSource, m_MaxScriptQueue); // if (DebugLevel >= 1) - m_log.DebugFormat( - "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", - part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, - part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); +// m_log.DebugFormat( +// "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", +// part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, +// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); if (presence != null) { @@ -1465,9 +1467,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine else if (p[i] is string) lsl_p[i] = new LSL_Types.LSLString((string)p[i]); else if (p[i] is Vector3) - lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); + lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]); else if (p[i] is Quaternion) - lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); + lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]); else if (p[i] is float) lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); else @@ -1491,9 +1493,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine else if (p[i] is string) lsl_p[i] = new LSL_Types.LSLString((string)p[i]); else if (p[i] is Vector3) - lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); + lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]); else if (p[i] is Quaternion) - lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); + lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]); else if (p[i] is float) lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); else diff --git a/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs b/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs index c9cbbfa500..504fcaf1e9 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationDataService.cs @@ -164,5 +164,19 @@ namespace OpenSim.Services.Connectors m_database.RemoveRegionEnvironmentSettings(regionUUID); } + public void SaveExtra(UUID regionID, string name, string val) + { + m_database.SaveExtra(regionID, name, val); + } + + public void RemoveExtra(UUID regionID, string name) + { + m_database.RemoveExtra(regionID, name); + } + + public Dictionary GetExtra(UUID regionID) + { + return m_database.GetExtra(regionID); + } } } diff --git a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs index 1845eb94f3..ed29c39378 100644 --- a/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs +++ b/OpenSim/Tests/Common/Mock/MockRegionDataPlugin.cs @@ -127,6 +127,19 @@ namespace OpenSim.Data.Null { m_store.RemoveRegionEnvironmentSettings(regionUUID); } + + public void SaveExtra(UUID regionID, string name, string value) + { + } + + public void RemoveExtra(UUID regionID, string name) + { + } + + public Dictionary GetExtra(UUID regionID) + { + return null; + } } /// @@ -318,5 +331,18 @@ namespace OpenSim.Data.Null public void Shutdown() { } + + public void SaveExtra(UUID regionID, string name, string value) + { + } + + public void RemoveExtra(UUID regionID, string name) + { + } + + public Dictionary GetExtra(UUID regionID) + { + return null; + } } } diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 89c4f110db..bb8b9358c0 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -933,6 +933,11 @@ namespace OpenSim.Tests.Common.Mock } public void Close() + { + Close(false); + } + + public void Close(bool force) { // Fire the callback for this connection closing // This is necesary to get the presence detector to notice that a client has logged out. diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 9c68b6546c..eac30b85a8 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -87,10 +87,18 @@ ;; from the selected region_info_source. ; allow_regionless = false + ;# {NonPhysicalPrimMin} {} {Minimum size of nonphysical prims?} {} 0.01 + ;; Minimum size for non-physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMin!). + ; NonphysicalPrimMin = 0.01 + ;# {NonPhysicalPrimMax} {} {Maximum size of nonphysical prims?} {} 256 ;; Maximum size for non-physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMax!). ; NonphysicalPrimMax = 256 + ;# {PhysicalPrimMin} {} {Minimum size of physical prims?} {} 10 + ;; Maximum size where a prim can be physical. Affects resizing of existing prims. This can be overriden in the region config file. + ; PhysicalPrimMin = 0.01 + ;# {PhysicalPrimMax} {} {Maximum size of physical prims?} {} 10 ;; Maximum size where a prim can be physical. Affects resizing of existing prims. This can be overriden in the region config file. ; PhysicalPrimMax = 10 @@ -675,7 +683,9 @@ ;; Maximum number of events to queue for a script (excluding timers) ; MaxScriptEventQueue = 300 - ;; Stack size per thread created + ;; Stack size per script engine thread in bytes. + ;; If you are experiencing StackOverflowExceptions you may want to increase this (e.g. double it). + ;; The trade-off may be increased memory usage by the script engine. ; ThreadStackSize = 262144 ;# {DeleteScriptsOnStartup} {} {Delete previously compiled script DLLs on startup?} (true false) true diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index dcbd90cee0..b2fca0c0a9 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -894,7 +894,7 @@ AvatarDensity = 60.0 AvatarCapsuleRadius = 0.37 AvatarCapsuleHeight = 1.5 - AvatarContactProcessingThreshold = 0.1; + AvatarContactProcessingThreshold = 0.1 MaxObjectMass = 10000.01 @@ -908,19 +908,19 @@ CcdSweptSphereRadius = 0.0 ContactProcessingThreshold = 0.1 ; If setting a pool size, also disable dynamic allocation (default pool size is 4096 with dynamic alloc) - MaxPersistantManifoldPoolSize = 0; - ShouldDisableContactPoolDynamicAllocation = False; - ShouldForceUpdateAllAabbs = False; - ShouldRandomizeSolverOrder = False; - ShouldSplitSimulationIslands = False; - ShouldEnableFrictionCaching = False; + MaxPersistantManifoldPoolSize = 0 + ShouldDisableContactPoolDynamicAllocation = False + ShouldForceUpdateAllAabbs = False + ShouldRandomizeSolverOrder = False + ShouldSplitSimulationIslands = False + ShouldEnableFrictionCaching = False NumberOfSolverIterations = 0; ; Linkset constraint parameters - LinkConstraintUseFrameOffset = False; - LinkConstraintEnableTransMotor = True; - LinkConstraintTransMotorMaxVel = 5.0; - LinkConstraintTransMotorMaxForce = 0.1; + LinkConstraintUseFrameOffset = False + LinkConstraintEnableTransMotor = True + LinkConstraintTransMotorMaxVel = 5.0 + LinkConstraintTransMotorMaxForce = 0.1 ; Whether to mesh sculpties @@ -931,16 +931,24 @@ ; level of detail for physical meshes. 32,16,8 or 4 with 32 being full detail MeshLevelOfDetail = 8 + ; if mesh size is > threshold meters, we need to add more detail because people will notice + MeshLevelOfDetailMegaPrimThreshold = 10 + MeshLevelOfDetailMegaPrim = 16 ; number^2 non-physical level of detail of the sculpt texture. 32x32 - 1024 verticies SculptLevelOfDetail = 32 ; Bullet step parameters - MaxSubSteps = 10; + MaxSubSteps = 10 FixedTimeStep = .01667 MaxCollisionsPerFrame = 2048 MaxUpdatesPerFrame = 8192 + ; Detailed physics debug logging + PhysicsLoggingEnabled = False + PhysicsLoggingDir = "." + VehicleLoggingEnabled = False + [RemoteAdmin] enabled = false diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll index f4953f9031..cc55f00919 100755 Binary files a/bin/lib32/BulletSim.dll and b/bin/lib32/BulletSim.dll differ diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so index 2b5702d823..26ad52ba23 100755 Binary files a/bin/lib32/libBulletSim.so and b/bin/lib32/libBulletSim.so differ diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll index be191c0b54..94dae95849 100755 Binary files a/bin/lib64/BulletSim.dll and b/bin/lib64/BulletSim.dll differ diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so index fc51b39759..52e9960274 100755 Binary files a/bin/lib64/libBulletSim.so and b/bin/lib64/libBulletSim.so differ diff --git a/prebuild.xml b/prebuild.xml index 6ed41a0ac7..c626ae7493 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1799,6 +1799,7 @@ +