Merge branch 'master' of /home/opensim/var/repo/opensim

integration
BlueWall 2012-08-21 14:06:35 -04:00
commit 0b2e8421ce
69 changed files with 1946 additions and 837 deletions

View File

@ -2202,5 +2202,18 @@ VALUES
} }
} }
} }
public void SaveExtra(UUID regionID, string name, string value)
{
}
public void RemoveExtra(UUID regionID, string name)
{
}
public Dictionary<string, string> GetExtra(UUID regionID)
{
return null;
}
} }
} }

View File

@ -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<string, string> GetExtra(UUID regionID)
{
Dictionary<string, string> ret = new Dictionary<string, string>();
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;
}
} }
} }

View File

@ -895,3 +895,10 @@ CREATE TABLE `regionenvironment` (
COMMIT; COMMIT;
:VERSION 45
BEGIN;
CREATE TABLE `regionextra` (`RegionID` char(36) not null, `Name` varchar(32) not null, `value` text, primary key(`RegionID`, `Name`));
COMMIT;

View File

@ -151,5 +151,18 @@ namespace OpenSim.Data.Null
public void Shutdown() public void Shutdown()
{ {
} }
public void SaveExtra(UUID regionID, string name, string value)
{
}
public void RemoveExtra(UUID regionID, string name)
{
}
public Dictionary<string, string> GetExtra(UUID regionID)
{
return null;
}
} }
} }

View File

@ -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<string, string> GetExtra(UUID regionID)
{
return null;
}
} }
} }

View File

@ -199,7 +199,14 @@ namespace OpenSim.Framework
// //
public class Cache public class Cache
{ {
/// <summary>
/// Must only be accessed under lock.
/// </summary>
private List<CacheItemBase> m_Index = new List<CacheItemBase>(); private List<CacheItemBase> m_Index = new List<CacheItemBase>();
/// <summary>
/// Must only be accessed under m_Index lock.
/// </summary>
private Dictionary<string, CacheItemBase> m_Lookup = private Dictionary<string, CacheItemBase> m_Lookup =
new Dictionary<string, CacheItemBase>(); new Dictionary<string, CacheItemBase>();
@ -320,7 +327,6 @@ namespace OpenSim.Framework
{ {
if (m_Lookup.ContainsKey(index)) if (m_Lookup.ContainsKey(index))
item = m_Lookup[index]; item = m_Lookup[index];
}
if (item == null) if (item == null)
{ {
@ -332,6 +338,7 @@ namespace OpenSim.Framework
item.lastUsed = DateTime.Now; item.lastUsed = DateTime.Now;
Expire(true); Expire(true);
}
return item; return item;
} }
@ -385,7 +392,10 @@ namespace OpenSim.Framework
// //
public Object Find(Predicate<CacheItemBase> d) public Object Find(Predicate<CacheItemBase> d)
{ {
CacheItemBase item = m_Index.Find(d); CacheItemBase item;
lock (m_Index)
item = m_Index.Find(d);
if (item == null) if (item == null)
return null; return null;
@ -419,12 +429,12 @@ namespace OpenSim.Framework
public virtual void Store(string index, Object data, Type container, public virtual void Store(string index, Object data, Type container,
Object[] parameters) Object[] parameters)
{ {
Expire(false);
CacheItemBase item; CacheItemBase item;
lock (m_Index) lock (m_Index)
{ {
Expire(false);
if (m_Index.Contains(new CacheItemBase(index))) if (m_Index.Contains(new CacheItemBase(index)))
{ {
if ((m_Flags & CacheFlags.AllowUpdate) != 0) if ((m_Flags & CacheFlags.AllowUpdate) != 0)
@ -450,9 +460,17 @@ namespace OpenSim.Framework
m_Index.Add(item); m_Index.Add(item);
m_Lookup[index] = item; m_Lookup[index] = item;
} }
item.Store(data); item.Store(data);
} }
/// <summary>
/// Expire items as appropriate.
/// </summary>
/// <remarks>
/// Callers must lock m_Index.
/// </remarks>
/// <param name='getting'></param>
protected virtual void Expire(bool getting) protected virtual void Expire(bool getting)
{ {
if (getting && (m_Strategy == CacheStrategy.Aggressive)) if (getting && (m_Strategy == CacheStrategy.Aggressive))
@ -479,8 +497,6 @@ namespace OpenSim.Framework
if (Count < Size) if (Count < Size)
return; return;
lock (m_Index)
{
m_Index.Sort(new SortLRU()); m_Index.Sort(new SortLRU());
m_Index.Reverse(); m_Index.Reverse();
@ -513,14 +529,17 @@ namespace OpenSim.Framework
foreach (CacheItemBase item in m_Index) foreach (CacheItemBase item in m_Index)
m_Lookup[item.uuid] = item; m_Lookup[item.uuid] = item;
} }
}
break; break;
default: default:
break; break;
} }
} }
public void Invalidate(string uuid) public void Invalidate(string uuid)
{
lock (m_Index)
{ {
if (!m_Lookup.ContainsKey(uuid)) if (!m_Lookup.ContainsKey(uuid))
return; return;
@ -529,11 +548,15 @@ namespace OpenSim.Framework
m_Lookup.Remove(uuid); m_Lookup.Remove(uuid);
m_Index.Remove(item); m_Index.Remove(item);
} }
}
public void Clear() public void Clear()
{
lock (m_Index)
{ {
m_Index.Clear(); m_Index.Clear();
m_Lookup.Clear(); m_Lookup.Clear();
} }
} }
} }
}

View File

@ -678,6 +678,8 @@ namespace OpenSim.Framework.Console
{ {
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public event OnOutputDelegate OnOutput;
public ICommands Commands { get; private set; } public ICommands Commands { get; private set; }
public CommandConsole(string defaultPrompt) : base(defaultPrompt) public CommandConsole(string defaultPrompt) : base(defaultPrompt)
@ -697,6 +699,13 @@ namespace OpenSim.Framework.Console
Output(s); Output(s);
} }
protected void FireOnOutput(string text)
{
OnOutputDelegate onOutput = OnOutput;
if (onOutput != null)
onOutput(text);
}
/// <summary> /// <summary>
/// Display a command prompt on the console and wait for user input /// Display a command prompt on the console and wait for user input
/// </summary> /// </summary>

View File

@ -319,6 +319,8 @@ namespace OpenSim.Framework.Console
public override void Output(string text, string level) public override void Output(string text, string level)
{ {
FireOnOutput(text);
lock (m_commandLine) lock (m_commandLine)
{ {
if (m_cursorYPosition == -1) if (m_cursorYPosition == -1)

View File

@ -40,6 +40,8 @@ namespace OpenSim.Framework.Console
/// </summary> /// </summary>
public class MockConsole : ICommandConsole public class MockConsole : ICommandConsole
{ {
public event OnOutputDelegate OnOutput;
private MockCommands m_commands = new MockCommands(); private MockCommands m_commands = new MockCommands();
public ICommands Commands { get { return m_commands; } } public ICommands Commands { get { return m_commands; } }

View File

@ -100,6 +100,7 @@ namespace OpenSim.Framework.Console
m_LineNumber++; m_LineNumber++;
m_Scrollback.Add(String.Format("{0}", m_LineNumber)+":"+level+":"+text); m_Scrollback.Add(String.Format("{0}", m_LineNumber)+":"+level+":"+text);
} }
FireOnOutput(text.Trim());
System.Console.WriteLine(text.Trim()); System.Console.WriteLine(text.Trim());
} }

View File

@ -1033,7 +1033,21 @@ namespace OpenSim.Framework
void InPacket(object NewPack); void InPacket(object NewPack);
void ProcessInPacket(Packet NewPack); void ProcessInPacket(Packet NewPack);
/// <summary>
/// Close this client
/// </summary>
void Close(); void Close();
/// <summary>
/// Close this client
/// </summary>
/// <param name='force'>
/// 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.
/// </param>
void Close(bool force);
void Kick(string message); void Kick(string message);
/// <summary> /// <summary>

View File

@ -74,8 +74,12 @@ namespace OpenSim.Framework
XmlElement GetXml(XmlDocument doc); XmlElement GetXml(XmlDocument doc);
} }
public delegate void OnOutputDelegate(string message);
public interface ICommandConsole : IConsole public interface ICommandConsole : IConsole
{ {
event OnOutputDelegate OnOutput;
ICommands Commands { get; } ICommands Commands { get; }
/// <summary> /// <summary>

View File

@ -89,6 +89,17 @@ namespace OpenSim.Framework.Monitoring
FirstTick = Environment.TickCount & Int32.MaxValue; FirstTick = Environment.TickCount & Int32.MaxValue;
LastTick = FirstTick; 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;
}
} }
/// <summary> /// <summary>
@ -97,6 +108,32 @@ namespace OpenSim.Framework.Monitoring
/// /summary> /// /summary>
public static event Action<ThreadWatchdogInfo> OnWatchdogTimeout; public static event Action<ThreadWatchdogInfo> OnWatchdogTimeout;
/// <summary>
/// Is this watchdog active?
/// </summary>
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 readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private static Dictionary<int, ThreadWatchdogInfo> m_threads; private static Dictionary<int, ThreadWatchdogInfo> m_threads;
private static System.Timers.Timer m_watchdogTimer; 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 = new System.Timers.Timer(WATCHDOG_INTERVAL_MS);
m_watchdogTimer.AutoReset = false; m_watchdogTimer.AutoReset = false;
m_watchdogTimer.Elapsed += WatchdogTimerElapsed; m_watchdogTimer.Elapsed += WatchdogTimerElapsed;
// Set now so we don't get alerted on the first run
LastWatchdogThreadTick = Environment.TickCount & Int32.MaxValue;
m_watchdogTimer.Start();
} }
/// <summary> /// <summary>
@ -314,7 +346,9 @@ namespace OpenSim.Framework.Monitoring
if (callbackInfos == null) if (callbackInfos == null)
callbackInfos = new List<ThreadWatchdogInfo>(); callbackInfos = new List<ThreadWatchdogInfo>();
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));
} }
} }
} }

View File

@ -120,7 +120,9 @@ namespace OpenSim.Framework
public UUID lastMapUUID = UUID.Zero; public UUID lastMapUUID = UUID.Zero;
public string lastMapRefresh = "0"; public string lastMapRefresh = "0";
private float m_nonphysPrimMin = 0;
private int m_nonphysPrimMax = 0; private int m_nonphysPrimMax = 0;
private float m_physPrimMin = 0;
private int m_physPrimMax = 0; private int m_physPrimMax = 0;
private bool m_clampPrimSize = false; private bool m_clampPrimSize = false;
private int m_objectCapacity = 0; private int m_objectCapacity = 0;
@ -285,11 +287,21 @@ namespace OpenSim.Framework
set { m_windlight = value; } set { m_windlight = value; }
} }
public float NonphysPrimMin
{
get { return m_nonphysPrimMin; }
}
public int NonphysPrimMax public int NonphysPrimMax
{ {
get { return m_nonphysPrimMax; } get { return m_nonphysPrimMax; }
} }
public float PhysPrimMin
{
get { return m_physPrimMin; }
}
public int PhysPrimMax public int PhysPrimMax
{ {
get { return m_physPrimMax; } get { return m_physPrimMax; }
@ -623,16 +635,28 @@ namespace OpenSim.Framework
m_regionType = config.GetString("RegionType", String.Empty); m_regionType = config.GetString("RegionType", String.Empty);
allKeys.Remove("RegionType"); allKeys.Remove("RegionType");
// Prim stuff #region Prim stuff
//
m_nonphysPrimMin = config.GetFloat("NonphysicalPrimMin", 0);
allKeys.Remove("NonphysicalPrimMin");
m_nonphysPrimMax = config.GetInt("NonphysicalPrimMax", 0); m_nonphysPrimMax = config.GetInt("NonphysicalPrimMax", 0);
allKeys.Remove("NonphysicalPrimMax"); allKeys.Remove("NonphysicalPrimMax");
m_physPrimMin = config.GetFloat("PhysicalPrimMin", 0);
allKeys.Remove("PhysicalPrimMin");
m_physPrimMax = config.GetInt("PhysicalPrimMax", 0); m_physPrimMax = config.GetInt("PhysicalPrimMax", 0);
allKeys.Remove("PhysicalPrimMax"); allKeys.Remove("PhysicalPrimMax");
m_clampPrimSize = config.GetBoolean("ClampPrimSize", false); m_clampPrimSize = config.GetBoolean("ClampPrimSize", false);
allKeys.Remove("ClampPrimSize"); allKeys.Remove("ClampPrimSize");
m_objectCapacity = config.GetInt("MaxPrims", 15000); m_objectCapacity = config.GetInt("MaxPrims", 15000);
allKeys.Remove("MaxPrims"); allKeys.Remove("MaxPrims");
#endregion
m_agentCapacity = config.GetInt("MaxAgents", 100); m_agentCapacity = config.GetInt("MaxAgents", 100);
allKeys.Remove("MaxAgents"); allKeys.Remove("MaxAgents");
@ -668,10 +692,18 @@ namespace OpenSim.Framework
config.Set("ExternalHostName", m_externalHostName); config.Set("ExternalHostName", m_externalHostName);
if (m_nonphysPrimMin != 0)
config.Set("NonphysicalPrimMax", m_nonphysPrimMin);
if (m_nonphysPrimMax != 0) if (m_nonphysPrimMax != 0)
config.Set("NonphysicalPrimMax", m_nonphysPrimMax); config.Set("NonphysicalPrimMax", m_nonphysPrimMax);
if (m_physPrimMin != 0)
config.Set("PhysicalPrimMax", m_physPrimMin);
if (m_physPrimMax != 0) if (m_physPrimMax != 0)
config.Set("PhysicalPrimMax", m_physPrimMax); config.Set("PhysicalPrimMax", m_physPrimMax);
config.Set("ClampPrimSize", m_clampPrimSize.ToString()); config.Set("ClampPrimSize", m_clampPrimSize.ToString());
if (m_objectCapacity != 0) if (m_objectCapacity != 0)
@ -754,9 +786,15 @@ namespace OpenSim.Framework
configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
"Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true); "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, configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
"Maximum size for nonphysical prims", m_nonphysPrimMax.ToString(), true); "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, configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
"Maximum size for physical prims", m_physPrimMax.ToString(), true); "Maximum size for physical prims", m_physPrimMax.ToString(), true);

View File

@ -850,6 +850,12 @@ namespace OpenSim.Framework
return Math.Min(Math.Max(x, min), max); 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));
}
/// <summary> /// <summary>
/// Convert an UUID to a raw uuid string. Right now this is a string without hyphens. /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens.
/// </summary> /// </summary>

View File

@ -35,6 +35,7 @@ using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Timers; using System.Timers;
using log4net; using log4net;
using NDesk.Options;
using Nini.Config; using Nini.Config;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
@ -310,8 +311,11 @@ namespace OpenSim
"Change the scale of a named prim", HandleEditScale); "Change the scale of a named prim", HandleEditScale);
m_console.Commands.AddCommand("Users", false, "kick user", m_console.Commands.AddCommand("Users", false, "kick user",
"kick user <first> <last> [message]", "kick user <first> <last> [--force] [message]",
"Kick a user off the simulator", KickUserCommand); "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", m_console.Commands.AddCommand("Users", false, "show users",
"show users [full]", "show users [full]",
@ -416,6 +420,7 @@ namespace OpenSim
{ {
RunCommandScript(m_shutdownCommandsFile); RunCommandScript(m_shutdownCommandsFile);
} }
base.ShutdownSpecific(); base.ShutdownSpecific();
} }
@ -453,11 +458,17 @@ namespace OpenSim
/// <param name="cmdparams">name of avatar to kick</param> /// <param name="cmdparams">name of avatar to kick</param>
private void KickUserCommand(string module, string[] cmdparams) 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<string> mainParams = options.Parse(cmdparams);
if (mainParams.Count < 4)
return; return;
string alert = null; string alert = null;
if (cmdparams.Length > 4) if (mainParams.Count > 4)
alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4));
IList agents = SceneManager.GetCurrentSceneAvatars(); IList agents = SceneManager.GetCurrentSceneAvatars();
@ -466,8 +477,8 @@ namespace OpenSim
{ {
RegionInfo regionInfo = presence.Scene.RegionInfo; RegionInfo regionInfo = presence.Scene.RegionInfo;
if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) && if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) &&
presence.Lastname.ToLower().Contains(cmdparams[3].ToLower())) presence.Lastname.ToLower().Contains(mainParams[3].ToLower()))
{ {
MainConsole.Instance.Output( MainConsole.Instance.Output(
String.Format( String.Format(
@ -480,7 +491,7 @@ namespace OpenSim
else else
presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n"); presence.ControllingClient.Kick("\nThe OpenSim manager kicked you out.\n");
presence.Scene.IncomingCloseAgent(presence.UUID); presence.Scene.IncomingCloseAgent(presence.UUID, force);
} }
} }

View File

@ -305,8 +305,13 @@ namespace OpenSim
m_httpServerPort = m_networkServersInfo.HttpListenerPort; m_httpServerPort = m_networkServersInfo.HttpListenerPort;
SceneManager.OnRestartSim += handleRestartRegion; SceneManager.OnRestartSim += handleRestartRegion;
// Only start the memory watchdog once all regions are ready // Only enable the watchdogs when all regions are ready. Otherwise we get false positives when cpu is
SceneManager.OnRegionsReadyStatusChange += sm => MemoryWatchdog.Enabled = sm.AllRegionsReady; // 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; };
} }
/// <summary> /// <summary>

View File

@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
UUID spId = TestHelpers.ParseTail(0x1); UUID spId = TestHelpers.ParseTail(0x1);
SceneHelpers.AddScenePresence(m_scene, spId); 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 // TODO: Add more assertions for the other aspects of event queues
Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0));

View File

@ -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 [<item>]", "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<IRegionConsole>(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<IEventQueue>();
}
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<string> 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;
}
}
}
}

View File

@ -487,16 +487,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
#region Client Methods #region Client Methods
/// <summary>
/// Close down the client view
/// </summary>
public void Close() 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. // 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. // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
lock (CloseSyncLock) 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; return;
IsActive = false; IsActive = false;
@ -5810,7 +5814,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
args.Channel = ch; args.Channel = ch;
args.From = String.Empty; args.From = String.Empty;
args.Message = Utils.BytesToString(msg); 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.Position = new Vector3();
args.Scene = Scene; args.Scene = Scene;
args.Sender = this; args.Sender = this;
@ -11989,7 +11993,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{ {
Kick(reason); Kick(reason);
Thread.Sleep(1000); Thread.Sleep(1000);
Close(); Disconnect();
} }
public void Disconnect() public void Disconnect()

View File

@ -458,10 +458,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
public void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup so) 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) lock (sp.AttachmentsSyncLock)
{ {
// Save avatar attachment information // Save avatar attachment information
@ -976,7 +972,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
if (sp != null && group != null) if (sp != null && group != null && group.FromItemID != UUID.Zero)
DetachSingleAttachmentToInv(sp, group); DetachSingleAttachmentToInv(sp, group);
} }
@ -994,7 +990,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
foreach (SceneObjectGroup group in attachments) foreach (SceneObjectGroup group in attachments)
{ {
if (group.FromItemID == itemID) if (group.FromItemID == itemID && group.FromItemID != UUID.Zero)
{ {
DetachSingleAttachmentToInv(sp, group); DetachSingleAttachmentToInv(sp, group);
return; return;

View File

@ -461,7 +461,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; 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. // Check that we can't retrieve this attachment from the scene.
Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);

View File

@ -644,7 +644,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
// an agent cannot teleport back to this region if it has teleported away. // an agent cannot teleport back to this region if it has teleported away.
Thread.Sleep(2000); Thread.Sleep(2000);
sp.Scene.IncomingCloseAgent(sp.UUID); sp.Scene.IncomingCloseAgent(sp.UUID, false);
} }
else else
{ {

View File

@ -312,7 +312,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation
// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", // "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate",
// s.RegionInfo.RegionName, destination.RegionHandle); // 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; return true;
} }

View File

@ -97,6 +97,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
} }
} }
/// <summary>
/// Used to cache lookups for valid groups.
/// </summary>
private IDictionary<UUID, bool> m_validGroupUuids = new Dictionary<UUID, bool>();
private IGroupsModule m_groupsModule;
public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId)
{ {
m_scene = scene; m_scene = scene;
@ -120,6 +127,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// Zero can never be a valid user id // Zero can never be a valid user id
m_validUserUuids[UUID.Zero] = false; m_validUserUuids[UUID.Zero] = false;
m_groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
} }
public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) 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 // Zero can never be a valid user id
m_validUserUuids[UUID.Zero] = false; m_validUserUuids[UUID.Zero] = false;
m_groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
} }
/// <summary> /// <summary>
@ -302,6 +313,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
if (!ResolveUserUuid(part.LastOwnerID)) if (!ResolveUserUuid(part.LastOwnerID))
part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
if (!ResolveGroupUuid(part.GroupID))
part.GroupID = UUID.Zero;
// And zap any troublesome sit target information // And zap any troublesome sit target information
// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
// part.SitTargetPosition = new Vector3(0, 0, 0); // 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; kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
} }
if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty)
{ {
if (!ResolveUserUuid(kvp.Value.CreatorID)) if (!ResolveUserUuid(kvp.Value.CreatorID))
kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
} }
if (UserManager != null) if (UserManager != null)
UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); 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) foreach (string serialisedParcel in serialisedParcels)
{ {
LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
// Validate User and Group UUID's
if (!ResolveUserUuid(parcel.OwnerID)) if (!ResolveUserUuid(parcel.OwnerID))
parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
if (!ResolveGroupUuid(parcel.GroupID))
{
parcel.GroupID = UUID.Zero;
parcel.IsGroupOwned = false;
}
List<LandAccessEntry> accessList = new List<LandAccessEntry>();
foreach (LandAccessEntry entry in parcel.ParcelAccessList)
{
if (ResolveUserUuid(entry.AgentID))
accessList.Add(entry);
// else, drop this access rule
}
parcel.ParcelAccessList = accessList;
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", // "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}",
// parcel.Name, parcel.LocalID, parcel.Area); // parcel.Name, parcel.LocalID, parcel.Area);
@ -401,6 +438,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver
} }
/// <summary> /// <summary>
/// Look up the given group id to check whether it's one that is valid for this grid.
/// </summary>
/// <param name="uuid"></param>
/// <returns></returns>
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 /// Load an asset
/// </summary> /// </summary>
/// <param name="assetFilename"></param> /// <param name="assetFilename"></param>

View File

@ -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);
}
}

View File

@ -116,5 +116,10 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="regionUUID">the region UUID</param> /// <param name="regionUUID">the region UUID</param>
void RemoveRegionEnvironmentSettings(UUID regionUUID); void RemoveRegionEnvironmentSettings(UUID regionUUID);
void SaveExtra(UUID regionID, string name, string value);
void RemoveExtra(UUID regionID, string name);
Dictionary<string, string> GetExtra(UUID regionID);
} }
} }

View File

@ -127,6 +127,12 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="regionUUID">the region UUID</param> /// <param name="regionUUID">the region UUID</param>
void RemoveRegionEnvironmentSettings(UUID regionUUID); void RemoveRegionEnvironmentSettings(UUID regionUUID);
void SaveExtra(UUID regionID, string name, string val);
void RemoveExtra(UUID regionID, string name);
Dictionary<string, string> GetExtra(UUID regionID);
void Shutdown(); void Shutdown();
} }
} }

View File

@ -213,6 +213,9 @@ namespace OpenSim.Region.Framework.Scenes
/// </remarks> /// </remarks>
public event NewScript OnNewScript; 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) public virtual void TriggerNewScript(UUID clientID, SceneObjectPart part, UUID itemID)
{ {
NewScript handlerNewScript = OnNewScript; 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);
}
}
}
}
} }
} }

View File

@ -103,8 +103,26 @@ namespace OpenSim.Region.Framework.Scenes
/// </summary> /// </summary>
public bool CollidablePrims { get; private set; } public bool CollidablePrims { get; private set; }
/// <summary>
/// Minimum value of the size of a non-physical prim in each axis
/// </summary>
public float m_minNonphys = 0.01f;
/// <summary>
/// Maximum value of the size of a non-physical prim in each axis
/// </summary>
public float m_maxNonphys = 256; public float m_maxNonphys = 256;
/// <summary>
/// Minimum value of the size of a physical prim in each axis
/// </summary>
public float m_minPhys = 0.01f;
/// <summary>
/// Maximum value of the size of a physical prim in each axis
/// </summary>
public float m_maxPhys = 10; public float m_maxPhys = 10;
public bool m_clampPrimSize; public bool m_clampPrimSize;
public bool m_trustBinaries; public bool m_trustBinaries;
public bool m_allowScriptCrossings; public bool m_allowScriptCrossings;
@ -174,6 +192,8 @@ namespace OpenSim.Region.Framework.Scenes
protected ICapabilitiesModule m_capsModule; protected ICapabilitiesModule m_capsModule;
protected IGroupsModule m_groupsModule; protected IGroupsModule m_groupsModule;
private Dictionary<string, string> m_extraSettings;
/// <summary> /// <summary>
/// Current scene frame number /// Current scene frame number
/// </summary> /// </summary>
@ -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 // 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. // region is set up and avoid these gyrations.
RegionSettings rs = simDataService.LoadRegionSettings(RegionInfo.RegionID); RegionSettings rs = simDataService.LoadRegionSettings(RegionInfo.RegionID);
m_extraSettings = simDataService.GetExtra(RegionInfo.RegionID);
bool updatedTerrainTextures = false; bool updatedTerrainTextures = false;
if (rs.TerrainTexture1 == UUID.Zero) if (rs.TerrainTexture1 == UUID.Zero)
{ {
@ -717,14 +739,25 @@ namespace OpenSim.Region.Framework.Scenes
PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims);
CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); 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); m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
if (RegionInfo.NonphysPrimMax > 0) if (RegionInfo.NonphysPrimMax > 0)
{ {
m_maxNonphys = RegionInfo.NonphysPrimMax; 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) if (RegionInfo.PhysPrimMax > 0)
{ {
m_maxPhys = RegionInfo.PhysPrimMax; m_maxPhys = RegionInfo.PhysPrimMax;
@ -4083,16 +4116,19 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Tell a single agent to disconnect from the region. /// Tell a single agent to disconnect from the region.
/// </summary> /// </summary>
/// <param name="regionHandle"></param>
/// <param name="agentID"></param> /// <param name="agentID"></param>
public bool IncomingCloseAgent(UUID agentID) /// <param name="force">
/// 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.
/// </param>
public bool IncomingCloseAgent(UUID agentID, bool force)
{ {
//m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); ScenePresence presence = m_sceneGraph.GetScenePresence(agentID);
if (presence != null) if (presence != null)
{ {
presence.ControllingClient.Close(); presence.ControllingClient.Close(force);
return true; return true;
} }
@ -5443,5 +5479,44 @@ namespace OpenSim.Region.Framework.Scenes
callback(asset); 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);
}
} }
} }

View File

@ -375,12 +375,9 @@ namespace OpenSim.Region.Framework.Scenes
{ {
Vector3 scale = part.Shape.Scale; Vector3 scale = part.Shape.Scale;
if (scale.X > m_parentScene.m_maxNonphys) scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X));
scale.X = m_parentScene.m_maxNonphys; scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y));
if (scale.Y > m_parentScene.m_maxNonphys) scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z));
scale.Y = m_parentScene.m_maxNonphys;
if (scale.Z > m_parentScene.m_maxNonphys)
scale.Z = m_parentScene.m_maxNonphys;
part.Shape.Scale = scale; part.Shape.Scale = scale;
} }

View File

@ -2674,17 +2674,17 @@ namespace OpenSim.Region.Framework.Scenes
RootPart.StoreUndoState(true); RootPart.StoreUndoState(true);
scale.X = Math.Min(scale.X, Scene.m_maxNonphys); scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X));
scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y));
scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z));
PhysicsActor pa = m_rootPart.PhysActor; PhysicsActor pa = m_rootPart.PhysActor;
if (pa != null && pa.IsPhysical) if (pa != null && pa.IsPhysical)
{ {
scale.X = Math.Min(scale.X, Scene.m_maxPhys); scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X));
scale.Y = Math.Min(scale.Y, Scene.m_maxPhys); scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y));
scale.Z = Math.Min(scale.Z, Scene.m_maxPhys); scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z));
} }
float x = (scale.X / RootPart.Scale.X); float x = (scale.X / RootPart.Scale.X);
@ -2716,6 +2716,14 @@ namespace OpenSim.Region.Framework.Scenes
y *= a; y *= a;
z *= 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) if (oldSize.Y * y > m_scene.m_maxPhys)
{ {
@ -2725,6 +2733,14 @@ namespace OpenSim.Region.Framework.Scenes
y *= a; y *= a;
z *= 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) if (oldSize.Z * z > m_scene.m_maxPhys)
{ {
@ -2734,6 +2750,14 @@ namespace OpenSim.Region.Framework.Scenes
y *= a; y *= a;
z *= 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 else
{ {
@ -2745,6 +2769,14 @@ namespace OpenSim.Region.Framework.Scenes
y *= a; y *= a;
z *= 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) if (oldSize.Y * y > m_scene.m_maxNonphys)
{ {
@ -2754,6 +2786,14 @@ namespace OpenSim.Region.Framework.Scenes
y *= a; y *= a;
z *= 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) if (oldSize.Z * z > m_scene.m_maxNonphys)
{ {
@ -2763,6 +2803,14 @@ namespace OpenSim.Region.Framework.Scenes
y *= a; y *= a;
z *= 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; // obPart.IgnoreUndoUpdate = false;

View File

@ -733,7 +733,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
catch (Exception e) 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
/// <param name="scale"></param> /// <param name="scale"></param>
public void Resize(Vector3 scale) public void Resize(Vector3 scale)
{ {
scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys); scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X));
scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys); scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y));
scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys); scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z));
PhysicsActor pa = PhysActor; PhysicsActor pa = PhysActor;
if (pa != null && pa.IsPhysical) if (pa != null && pa.IsPhysical)
{ {
scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys); scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X));
scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys); scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y));
scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys); 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); // m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
@ -2852,23 +2851,32 @@ namespace OpenSim.Region.Framework.Scenes
} }
/// <summary> /// <summary>
/// Set the color of prim faces /// Set the color & alpha of prim faces
/// </summary> /// </summary>
/// <param name="color"></param>
/// <param name="face"></param> /// <param name="face"></param>
public void SetFaceColor(Vector3 color, int face) /// <param name="color"></param>
/// <param name="alpha"></param>
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 // 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(); Byte[] buf = Shape.Textures.GetBytes();
Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length);
Color4 texcolor; Color4 texcolor;
if (face >= 0 && face < GetNumberOfSides()) if (face >= 0 && face < GetNumberOfSides())
{ {
texcolor = tex.CreateFace((uint)face).RGBA; texcolor = tex.CreateFace((uint)face).RGBA;
texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); texcolor.R = clippedColor.X;
texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); texcolor.G = clippedColor.Y;
texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); texcolor.B = clippedColor.Z;
if (alpha.HasValue)
{
texcolor.A = clippedAlpha;
}
tex.FaceTextures[face].RGBA = texcolor; tex.FaceTextures[face].RGBA = texcolor;
UpdateTextureEntry(tex.GetBytes()); UpdateTextureEntry(tex.GetBytes());
return; return;
@ -2880,15 +2888,23 @@ namespace OpenSim.Region.Framework.Scenes
if (tex.FaceTextures[i] != null) if (tex.FaceTextures[i] != null)
{ {
texcolor = tex.FaceTextures[i].RGBA; texcolor = tex.FaceTextures[i].RGBA;
texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); texcolor.R = clippedColor.X;
texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); texcolor.G = clippedColor.Y;
texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); texcolor.B = clippedColor.Z;
if (alpha.HasValue)
{
texcolor.A = clippedAlpha;
}
tex.FaceTextures[i].RGBA = texcolor; tex.FaceTextures[i].RGBA = texcolor;
} }
texcolor = tex.DefaultTexture.RGBA; texcolor = tex.DefaultTexture.RGBA;
texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); texcolor.R = clippedColor.X;
texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); texcolor.G = clippedColor.Y;
texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); texcolor.B = clippedColor.Z;
if (alpha.HasValue)
{
texcolor.A = clippedAlpha;
}
tex.DefaultTexture.RGBA = texcolor; tex.DefaultTexture.RGBA = texcolor;
} }
UpdateTextureEntry(tex.GetBytes()); UpdateTextureEntry(tex.GetBytes());
@ -4237,6 +4253,57 @@ namespace OpenSim.Region.Framework.Scenes
ScheduleFullUpdate(); 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();
}
}
/// <summary> /// <summary>
/// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics /// 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. /// engine can use it.

View File

@ -1385,17 +1385,22 @@ namespace OpenSim.Region.Framework.Scenes
bool DCFlagKeyPressed = false; bool DCFlagKeyPressed = false;
Vector3 agent_control_v3 = Vector3.Zero; Vector3 agent_control_v3 = Vector3.Zero;
bool oldflying = Flying; bool newFlying = actor.Flying;
if (ForceFly) if (ForceFly)
actor.Flying = true; newFlying = true;
else if (FlyDisabled) else if (FlyDisabled)
actor.Flying = false; newFlying = false;
else 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; update_movementflag = true;
}
if (ParentID == 0) if (ParentID == 0)
{ {

View File

@ -141,7 +141,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
TestScene scene = new SceneHelpers().SetupScene(); TestScene scene = new SceneHelpers().SetupScene();
ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 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.GetScenePresence(sp.UUID), Is.Null);
Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null);

View File

@ -885,6 +885,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
} }
public void Close() public void Close()
{
Close(false);
}
public void Close(bool force)
{ {
Disconnect(); Disconnect();
} }

View File

@ -43,15 +43,13 @@ using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.OptionalModules.Avatar.Attachments namespace OpenSim.Region.OptionalModules.Avatar.Attachments
{ {
/// <summary>
/// A module that just holds commands for inspecting avatar appearance.
/// </summary>
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TempAttachmentsModule")] [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TempAttachmentsModule")]
public class TempAttachmentsModule : INonSharedRegionModule public class TempAttachmentsModule : INonSharedRegionModule
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene; private Scene m_scene;
private IRegionConsole m_console;
public void Initialise(IConfigSource configSource) public void Initialise(IConfigSource configSource)
{ {
@ -74,6 +72,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
{ {
comms.RegisterScriptInvocation( this, "llAttachToAvatarTemp"); comms.RegisterScriptInvocation( this, "llAttachToAvatarTemp");
m_log.DebugFormat("[TEMP ATTACHS]: Registered script functions"); m_log.DebugFormat("[TEMP ATTACHS]: Registered script functions");
m_console = scene.RequestModuleInterface<IRegionConsole>();
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 else
{ {
@ -95,6 +99,37 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
get { return "TempAttachmentsModule"; } 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) private void llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint)
{ {
SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host); SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host);

View File

@ -900,6 +900,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
} }
public void Close() public void Close()
{
Close(false);
}
public void Close(bool force)
{ {
// Remove ourselves from the scene // Remove ourselves from the scene
m_scene.RemoveClient(AgentId, false); m_scene.RemoveClient(AgentId, false);

View File

@ -37,7 +37,8 @@ public class BS6DofConstraint : BSConstraint
// Create a btGeneric6DofConstraint // Create a btGeneric6DofConstraint
public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
Vector3 frame1, Quaternion frame1rot, Vector3 frame1, Quaternion frame1rot,
Vector3 frame2, Quaternion frame2rot ) Vector3 frame2, Quaternion frame2rot,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
{ {
m_world = world; m_world = world;
m_body1 = obj1; m_body1 = obj1;
@ -46,16 +47,45 @@ public class BS6DofConstraint : BSConstraint
BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
frame1, frame1rot, frame1, frame1rot,
frame2, frame2rot, frame2, frame2rot,
true /*useLinearReferenceFrameA*/, true /*disableCollisionsBetweenLinkedBodies*/)); useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
m_enabled = true; 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) public bool SetCFMAndERP(float cfm, float erp)
{ {
bool ret = true; 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_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_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
ret = true;
}
return ret; return ret;
} }
@ -76,5 +106,13 @@ public class BS6DofConstraint : BSConstraint
ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
return ret; return ret;
} }
public bool SetBreakingImpulseThreshold(float threshold)
{
bool ret = false;
if (m_enabled)
ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold);
return ret;
}
} }
} }

View File

@ -124,10 +124,14 @@ public class BSCharacter : PhysicsActor
// do actual create at taint time // do actual create at taint time
_scene.TaintedObject("BSCharacter.create", delegate() _scene.TaintedObject("BSCharacter.create", delegate()
{ {
DetailLog("{0},BSCharacter.create", _localID);
BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); 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)); 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); 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 // called when this character is being destroyed and the resources should be released
public void Destroy() public void Destroy()
{ {
// DetailLog("{0},Destroy", LocalID); DetailLog("{0},BSCharacter.Destroy", LocalID);
_scene.TaintedObject("BSCharacter.destroy", delegate() _scene.TaintedObject("BSCharacter.destroy", delegate()
{ {
BulletSimAPI.DestroyObject(_scene.WorldID, _localID); BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
@ -209,7 +213,7 @@ public class BSCharacter : PhysicsActor
_scene.TaintedObject("BSCharacter.setPosition", delegate() _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); BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
}); });
} }
@ -226,7 +230,7 @@ public class BSCharacter : PhysicsActor
float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position);
if (_position.Z < terrainHeight) 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; _position.Z = terrainHeight + 2.0f;
ret = true; ret = true;
} }
@ -319,14 +323,13 @@ public class BSCharacter : PhysicsActor
public override bool Flying { public override bool Flying {
get { return _flying; } get { return _flying; }
set { set {
if (_flying != value)
{
_flying = value; _flying = value;
// simulate flying by changing the effect of gravity // simulate flying by changing the effect of gravity
this.Buoyancy = ComputeBuoyancyFromFlying(_flying); 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) { private float ComputeBuoyancyFromFlying(bool ifFlying) {
return ifFlying ? 1f : 0f; return ifFlying ? 1f : 0f;
} }
@ -368,7 +371,7 @@ public class BSCharacter : PhysicsActor
set { _buoyancy = value; set { _buoyancy = value;
_scene.TaintedObject("BSCharacter.setBuoyancy", delegate() _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); 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); // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
_scene.TaintedObject("BSCharacter.AddForce", delegate() _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); BulletSimAPI.AddObjectForce2(Body.Ptr, _force);
}); });
} }
@ -507,6 +510,7 @@ public class BSCharacter : PhysicsActor
{ {
_collidingGroundStep = _scene.SimulationStep; _collidingGroundStep = _scene.SimulationStep;
} }
// DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
// throttle collisions to the rate specified in the subscription // throttle collisions to the rate specified in the subscription
if (_subscribedEventsMs != 0) { if (_subscribedEventsMs != 0) {
@ -535,7 +539,10 @@ public class BSCharacter : PhysicsActor
if (collisionCollection == null) if (collisionCollection == null)
collisionCollection = new CollisionEventUpdate(); collisionCollection = new CollisionEventUpdate();
base.SendCollisionUpdate(collisionCollection); 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 // End kludge
} }

View File

@ -80,10 +80,33 @@ public abstract class BSConstraint : IDisposable
bool ret = false; bool ret = false;
if (m_enabled) if (m_enabled)
{ {
// Recompute the internal transforms
BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); BulletSimAPI.CalculateTransforms2(m_constraint.Ptr);
ret = true; ret = true;
} }
return ret; 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;
}
} }
} }

View File

@ -55,6 +55,8 @@ public class BSConstraintCollection : IDisposable
} }
public void Clear() public void Clear()
{
lock (m_constraints)
{ {
foreach (BSConstraint cons in m_constraints) foreach (BSConstraint cons in m_constraints)
{ {
@ -62,15 +64,17 @@ public class BSConstraintCollection : IDisposable
} }
m_constraints.Clear(); m_constraints.Clear();
} }
}
public bool AddConstraint(BSConstraint cons) public bool AddConstraint(BSConstraint cons)
{
lock (m_constraints)
{ {
// There is only one constraint between any bodies. Remove any old just to make sure. // There is only one constraint between any bodies. Remove any old just to make sure.
RemoveAndDestroyConstraint(cons.Body1, cons.Body2); 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; return true;
} }
@ -84,16 +88,19 @@ public class BSConstraintCollection : IDisposable
uint lookingID1 = body1.ID; uint lookingID1 = body1.ID;
uint lookingID2 = body2.ID; uint lookingID2 = body2.ID;
ForEachConstraint(delegate(BSConstraint constrain) lock (m_constraints)
{
foreach (BSConstraint constrain in m_constraints)
{ {
if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
|| (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1)) || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
{ {
foundConstraint = constrain; foundConstraint = constrain;
found = true; found = true;
break;
}
}
} }
return found;
});
returnConstraint = foundConstraint; returnConstraint = foundConstraint;
return found; return found;
} }
@ -103,25 +110,35 @@ public class BSConstraintCollection : IDisposable
// Return 'true' if a constraint was found and destroyed. // Return 'true' if a constraint was found and destroyed.
public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2) public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2)
{ {
// return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID);
bool ret = false; bool ret = false;
lock (m_constraints)
{
BSConstraint constrain; BSConstraint constrain;
if (this.TryGetConstraint(body1, body2, out constrain)) if (this.TryGetConstraint(body1, body2, out constrain))
{ {
m_world.scene.DetailLog("{0},BSConstraintCollection.RemoveAndDestroyConstraint,taint,body1={1},body2={2}", BSScene.DetailLogZero, body1.ID, body2.ID);
// remove the constraint from our collection // remove the constraint from our collection
m_constraints.Remove(constrain); RemoveAndDestroyConstraint(constrain);
// tell the engine that all its structures need to be freed
constrain.Dispose();
// we destroyed something
ret = true; ret = true;
} }
}
return ret; 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. // Remove all constraints that reference the passed body.
// Return 'true' if any constraints were destroyed. // Return 'true' if any constraints were destroyed.
public bool RemoveAndDestroyConstraint(BulletBody body1) public bool RemoveAndDestroyConstraint(BulletBody body1)
@ -130,16 +147,15 @@ public class BSConstraintCollection : IDisposable
List<BSConstraint> toRemove = new List<BSConstraint>(); List<BSConstraint> toRemove = new List<BSConstraint>();
uint lookingID = body1.ID; uint lookingID = body1.ID;
ForEachConstraint(delegate(BSConstraint constrain) lock (m_constraints)
{
foreach (BSConstraint constrain in m_constraints)
{ {
if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID) if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
{ {
toRemove.Add(constrain); toRemove.Add(constrain);
} }
return false; }
});
lock (m_constraints)
{
foreach (BSConstraint constrain in toRemove) foreach (BSConstraint constrain in toRemove)
{ {
m_constraints.Remove(constrain); m_constraints.Remove(constrain);
@ -151,28 +167,16 @@ public class BSConstraintCollection : IDisposable
public bool RecalculateAllConstraints() public bool RecalculateAllConstraints()
{ {
ForEachConstraint(delegate(BSConstraint constrain) bool ret = false;
{
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)
{
lock (m_constraints) lock (m_constraints)
{ {
foreach (BSConstraint constrain in m_constraints) foreach (BSConstraint constrain in m_constraints)
{ {
if (action(constrain)) constrain.CalculateTransforms();
break; ret = true;
}
}
return ret;
} }
} }
} }
}
}

View File

@ -57,6 +57,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
private int frcount = 0; // Used to limit dynamics debug output to private int frcount = 0; // Used to limit dynamics debug output to
// every 100th frame // every 100th frame
private BSScene m_physicsScene;
private BSPrim m_prim; // the prim this dynamic controller belongs to private BSPrim m_prim; // the prim this dynamic controller belongs to
// Vehicle properties // Vehicle properties
@ -74,7 +75,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// HOVER_UP_ONLY // HOVER_UP_ONLY
// LIMIT_MOTOR_UP // LIMIT_MOTOR_UP
// LIMIT_ROLL_ONLY // LIMIT_ROLL_ONLY
private VehicleFlag m_Hoverflags = (VehicleFlag)0;
private Vector3 m_BlockingEndPoint = Vector3.Zero; private Vector3 m_BlockingEndPoint = Vector3.Zero;
private Quaternion m_RollreferenceFrame = Quaternion.Identity; private Quaternion m_RollreferenceFrame = Quaternion.Identity;
// Linear properties // Linear properties
@ -124,15 +124,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
private float m_verticalAttractionEfficiency = 1.0f; // damped private float m_verticalAttractionEfficiency = 1.0f; // damped
private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. 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_prim = myPrim;
m_type = Vehicle.TYPE_NONE; m_type = Vehicle.TYPE_NONE;
} }
internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep) 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) switch (pParam)
{ {
case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
@ -231,7 +232,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep) 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) switch (pParam)
{ {
case Vehicle.ANGULAR_FRICTION_TIMESCALE: case Vehicle.ANGULAR_FRICTION_TIMESCALE:
@ -266,7 +267,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) 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) switch (pParam)
{ {
case Vehicle.REFERENCE_FRAME: case Vehicle.REFERENCE_FRAME:
@ -280,164 +281,27 @@ namespace OpenSim.Region.Physics.BulletSPlugin
internal void ProcessVehicleFlags(int pParam, bool remove) 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 (remove)
{ {
if (pParam == -1) if (pParam == -1)
{ {
m_flags = (VehicleFlag)0; m_flags = (VehicleFlag)0;
m_Hoverflags = (VehicleFlag)0;
return;
}
if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT)
{
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);
}
} }
else else
{ {
if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) m_flags &= ~parm;
{
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 }//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 // Set Defaults For Type
m_type = pType; m_type = pType;
switch (pType) switch (pType)
@ -478,10 +342,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// m_bankingMix = 1; // m_bankingMix = 1;
// m_bankingTimescale = 10; // m_bankingTimescale = 10;
// m_referenceFrame = Quaternion.Identity; // 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_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
break; break;
case Vehicle.TYPE_CAR: case Vehicle.TYPE_CAR:
m_linearFrictionTimescale = new Vector3(100, 2, 1000); m_linearFrictionTimescale = new Vector3(100, 2, 1000);
@ -506,10 +370,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// m_bankingMix = 1; // m_bankingMix = 1;
// m_bankingTimescale = 1; // m_bankingTimescale = 1;
// m_referenceFrame = Quaternion.Identity; // 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 | m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
VehicleFlag.LIMIT_MOTOR_UP); 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; break;
case Vehicle.TYPE_BOAT: case Vehicle.TYPE_BOAT:
m_linearFrictionTimescale = new Vector3(10, 3, 2); m_linearFrictionTimescale = new Vector3(10, 3, 2);
@ -534,12 +398,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// m_bankingMix = 0.8f; // m_bankingMix = 0.8f;
// m_bankingTimescale = 1; // m_bankingTimescale = 1;
// m_referenceFrame = Quaternion.Identity; // m_referenceFrame = Quaternion.Identity;
m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY);
m_flags |= (VehicleFlag.NO_DEFLECTION_UP | m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
VehicleFlag.LIMIT_MOTOR_UP); VehicleFlag.LIMIT_MOTOR_UP);
m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY); m_flags |= (VehicleFlag.HOVER_WATER_ONLY);
break; break;
case Vehicle.TYPE_AIRPLANE: case Vehicle.TYPE_AIRPLANE:
m_linearFrictionTimescale = new Vector3(200, 10, 5); m_linearFrictionTimescale = new Vector3(200, 10, 5);
@ -564,7 +428,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// m_bankingMix = 0.7f; // m_bankingMix = 0.7f;
// m_bankingTimescale = 2; // m_bankingTimescale = 2;
// m_referenceFrame = Quaternion.Identity; // 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); VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
@ -592,11 +456,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// m_bankingMix = 0.7f; // m_bankingMix = 0.7f;
// m_bankingTimescale = 5; // m_bankingTimescale = 5;
// m_referenceFrame = Quaternion.Identity; // 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); VehicleFlag.HOVER_UP_ONLY);
m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); m_flags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT);
break; break;
} }
}//end SetDefaultsForType }//end SetDefaultsForType
@ -613,7 +477,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
MoveAngular(pTimestep); MoveAngular(pTimestep);
LimitRotation(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); m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity);
}// end Step }// 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); m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector);
} }
else else
@ -669,7 +533,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_lastLinearVelocityVector = Vector3.Zero; 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; Quaternion rotq = m_prim.Orientation;
m_dir = m_lastLinearVelocityVector * rotq; m_dir = m_lastLinearVelocityVector * rotq;
@ -722,7 +586,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
if (changed) if (changed)
{ {
m_prim.Position = pos; 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); m_prim.LocalID, m_BlockingEndPoint, posChange, pos);
} }
} }
@ -732,32 +596,32 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{ {
pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2; pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2;
m_prim.Position = pos; 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 // 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 // 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; 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; 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; 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 body is aready heigher, use its height as target height
if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; 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) 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_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
// m_VhoverTimescale = 0f; // time to acheive height // m_VhoverTimescale = 0f; // time to acheive height
@ -815,7 +679,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{ {
grav.Z = (float)(grav.Z * 1.037125); 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 //End Experimental Values
} }
if ((m_flags & (VehicleFlag.NO_X)) != 0) if ((m_flags & (VehicleFlag.NO_X)) != 0)
@ -844,7 +708,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; 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); m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount);
} // end MoveLinear() } // end MoveLinear()
@ -876,7 +740,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (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); 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_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 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 // No motor recently applied, keep the body velocity
// and decay the velocity // and decay the velocity
m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep);
if (m_angularMotorVelocity.LengthSquared() < 0.00001)
m_angularMotorVelocity = Vector3.Zero;
} // end motor section } // end motor section
// Vertical attractor section // Vertical attractor section
@ -924,7 +790,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
vertattr.X += bounce * angularVelocity.X; vertattr.X += bounce * angularVelocity.X;
vertattr.Y += bounce * angularVelocity.Y; 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); m_prim.LocalID, verterr, bounce, vertattr);
} // else vertical attractor is off } // else vertical attractor is off
@ -942,13 +808,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{ {
m_lastAngularVelocity.X = 0; m_lastAngularVelocity.X = 0;
m_lastAngularVelocity.Y = 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)) if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
{ {
m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. 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 // apply friction
@ -958,7 +824,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Apply to the body // Apply to the body
m_prim.RotationalVelocity = m_lastAngularVelocity; 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 } //end MoveAngular
internal void LimitRotation(float timestep) internal void LimitRotation(float timestep)
@ -1005,11 +871,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
if (changed) if (changed)
m_prim.Orientation = m_rot; 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. // 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) if (m_prim.Scene.VehicleLoggingEnabled)
m_prim.Scene.PhysicsLogging.Write(msg, args); m_prim.Scene.PhysicsLogging.Write(msg, args);

View File

@ -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;
}
}
}

View File

@ -37,11 +37,15 @@ public class BSLinkset
private static string LogHeader = "[BULLETSIM LINKSET]"; private static string LogHeader = "[BULLETSIM LINKSET]";
private BSPrim m_linksetRoot; private BSPrim m_linksetRoot;
public BSPrim Root { get { return m_linksetRoot; } } public BSPrim LinksetRoot { get { return m_linksetRoot; } }
private BSScene m_scene; private BSScene m_physicsScene;
public BSScene Scene { get { return m_scene; } } 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<BSPrim> m_children; private List<BSPrim> m_children;
// We lock the diddling of linkset classes to prevent any badness. // We lock the diddling of linkset classes to prevent any badness.
@ -73,7 +77,11 @@ public class BSLinkset
public BSLinkset(BSScene scene, BSPrim parent) public BSLinkset(BSScene scene, BSPrim parent)
{ {
// A simple linkset of one (no children) // 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_linksetRoot = parent;
m_children = new List<BSPrim>(); m_children = new List<BSPrim>();
m_mass = parent.MassRaw; m_mass = parent.MassRaw;
@ -91,6 +99,9 @@ public class BSLinkset
return this; 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) public BSLinkset RemoveMeFromLinkset(BSPrim child)
{ {
lock (m_linksetActivityLock) lock (m_linksetActivityLock)
@ -114,60 +125,9 @@ public class BSLinkset
} }
// The child is down to a linkset of just itself // 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<BSPrim> toRemove = new List<BSPrim>();
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 // Return 'true' if the passed object is the root object of this linkset
public bool IsRoot(BSPrim requestor) public bool IsRoot(BSPrim requestor)
{ {
@ -183,6 +143,8 @@ public class BSLinkset
public bool HasChild(BSPrim child) public bool HasChild(BSPrim child)
{ {
bool ret = false; bool ret = false;
lock (m_linksetActivityLock)
{
foreach (BSPrim bp in m_children) foreach (BSPrim bp in m_children)
{ {
if (child.LocalID == bp.LocalID) if (child.LocalID == bp.LocalID)
@ -191,6 +153,7 @@ public class BSLinkset
break; break;
} }
} }
}
return ret; return ret;
} }
@ -209,6 +172,8 @@ public class BSLinkset
OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw;
float totalMass = m_linksetRoot.MassRaw; float totalMass = m_linksetRoot.MassRaw;
lock (m_linksetActivityLock)
{
foreach (BSPrim bp in m_children) foreach (BSPrim bp in m_children)
{ {
com += bp.Position * bp.MassRaw; com += bp.Position * bp.MassRaw;
@ -216,6 +181,7 @@ public class BSLinkset
} }
if (totalMass != 0f) if (totalMass != 0f)
com /= totalMass; com /= totalMass;
}
return com; return com;
} }
@ -224,29 +190,83 @@ public class BSLinkset
{ {
OMV.Vector3 com = m_linksetRoot.Position; OMV.Vector3 com = m_linksetRoot.Position;
lock (m_linksetActivityLock)
{
foreach (BSPrim bp in m_children) foreach (BSPrim bp in m_children)
{ {
com += bp.Position * bp.MassRaw; com += bp.Position * bp.MassRaw;
} }
com /= (m_children.Count + 1); com /= (m_children.Count + 1);
}
return com; 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 // I am the root of a linkset and a new child is being added
// Called while LinkActivity is locked. // Called while LinkActivity is locked.
public void AddChildToLinkset(BSPrim child) private void AddChildToLinkset(BSPrim child)
{ {
if (!HasChild(child)) if (!HasChild(child))
{ {
m_children.Add(child); m_children.Add(child);
BSPrim root = Root; // capture the root as of now BSPrim rootx = LinksetRoot; // capture the root as of now
m_scene.TaintedObject("AddChildToLinkset", delegate() 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); 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; return;
@ -257,31 +277,33 @@ public class BSLinkset
// it's still connected to the linkset. // it's still connected to the linkset.
// Normal OpenSimulator operation will never do this because other SceneObjectPart information // Normal OpenSimulator operation will never do this because other SceneObjectPart information
// has to be updated also (like pointer to prim's parent). // 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); RemoveChildFromLinkset(pchild);
} }
// I am the root of a linkset and one of my children is being removed. // 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. // 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)) if (m_children.Remove(child))
{ {
BSPrim root = Root; // capture the root as of now BSPrim rootx = LinksetRoot; // capture the root as of now
m_scene.TaintedObject("RemoveChildFromLinkset", delegate() 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); DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
PhysicallyUnlinkAChildFromRoot(root, child); PhysicallyUnlinkAChildFromRoot(rootx, childx);
}); });
RecomputeLinksetConstraintVariables();
} }
else else
{ {
// This will happen if we remove the root of the linkset first. Non-fatal occurance. // 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; return;
} }
@ -293,48 +315,81 @@ public class BSLinkset
// Zero motion for children so they don't interpolate // Zero motion for children so they don't interpolate
childPrim.ZeroMotion(); 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 // relative position normalized to the root prim
OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
// relative rotation of the child to the parent // relative rotation of the child to the parent
OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; 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 // create a constraint that allows no freedom of movement between the two objects
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 // 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); DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
BS6DofConstraint constrain = new BS6DofConstraint( BS6DofConstraint constrain = new BS6DofConstraint(
m_scene.World, rootPrim.Body, childPrim.Body, PhysicsScene.World, rootPrim.Body, childPrim.Body,
childRelativePosition,
childRelativeRotation,
OMV.Vector3.Zero, 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 // 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.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
// tweek the constraint to increase stability // tweek the constraint to increase stability
constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset)); constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset));
constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor), constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor),
m_scene.Params.linkConstraintTransMotorMaxVel, PhysicsScene.Params.linkConstraintTransMotorMaxVel,
m_scene.Params.linkConstraintTransMotorMaxForce); PhysicsScene.Params.linkConstraintTransMotorMaxForce);
constrain.SetCFMAndERP(m_scene.Params.linkConstraintCFM, m_scene.Params.linkConstraintERP); constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
RecomputeLinksetConstraintVariables();
} }
// Remove linkage between myself and a particular child // Remove linkage between myself and a particular child
// Called at taint time! // Called at taint time!
private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim) 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); 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 // Make the child refresh its location
BulletSimAPI.PushUpdate2(childPrim.Body.Ptr); BulletSimAPI.PushUpdate2(childPrim.Body.Ptr);
} }
@ -343,23 +398,15 @@ public class BSLinkset
// Called at taint time! // Called at taint time!
private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim) private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim)
{ {
// DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
m_scene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); m_physicsScene.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);
} }
// Invoke the detailed logger and output something if it's enabled. // Invoke the detailed logger and output something if it's enabled.
private void DetailLog(string msg, params Object[] args) private void DetailLog(string msg, params Object[] args)
{ {
m_scene.PhysicsLogging.Write(msg, args); m_physicsScene.PhysicsLogging.Write(msg, args);
} }
} }

View File

@ -42,8 +42,6 @@ public sealed class BSPrim : PhysicsActor
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[BULLETS PRIM]"; 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 IMesh _mesh;
private PrimitiveBaseShape _pbs; private PrimitiveBaseShape _pbs;
private ShapeData.PhysicsShapeType _shapeType; private ShapeData.PhysicsShapeType _shapeType;
@ -141,8 +139,8 @@ public sealed class BSPrim : PhysicsActor
_friction = _scene.Params.defaultFriction; // TODO: compute based on object material _friction = _scene.Params.defaultFriction; // TODO: compute based on object material
_density = _scene.Params.defaultDensity; // TODO: compute based on object material _density = _scene.Params.defaultDensity; // TODO: compute based on object material
_restitution = _scene.Params.defaultRestitution; _restitution = _scene.Params.defaultRestitution;
_linkset = new BSLinkset(_scene, this); // a linkset of one _linkset = new BSLinkset(Scene, this); // a linkset of one
_vehicle = new BSDynamics(this); // add vehicleness _vehicle = new BSDynamics(Scene, this); // add vehicleness
_mass = CalculateMass(); _mass = CalculateMass();
// do the actual object creation at taint time // do the actual object creation at taint time
DetailLog("{0},BSPrim.constructor,call", LocalID); DetailLog("{0},BSPrim.constructor,call", LocalID);
@ -163,13 +161,13 @@ public sealed class BSPrim : PhysicsActor
// m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
// Undo any links between me and any other object // Undo any links between me and any other object
BSPrim parentBefore = _linkset.Root; BSPrim parentBefore = _linkset.LinksetRoot;
int childrenBefore = _linkset.NumberOfChildren; int childrenBefore = _linkset.NumberOfChildren;
_linkset = _linkset.RemoveMeFromLinkset(this); _linkset = _linkset.RemoveMeFromLinkset(this);
DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", 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 // Undo any vehicle properties
this.VehicleType = (int)Vehicle.TYPE_NONE; this.VehicleType = (int)Vehicle.TYPE_NONE;
@ -193,7 +191,7 @@ public sealed class BSPrim : PhysicsActor
{ {
_mass = CalculateMass(); // changing size changes the mass _mass = CalculateMass(); // changing size changes the mass
BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); 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(); RecreateGeomAndObject();
}); });
} }
@ -232,14 +230,13 @@ public sealed class BSPrim : PhysicsActor
BSPrim parent = obj as BSPrim; BSPrim parent = obj as BSPrim;
if (parent != null) if (parent != null)
{ {
DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); BSPrim parentBefore = _linkset.LinksetRoot;
BSPrim parentBefore = _linkset.Root;
int childrenBefore = _linkset.NumberOfChildren; int childrenBefore = _linkset.NumberOfChildren;
_linkset = parent.Linkset.AddMeToLinkset(this); _linkset = parent.Linkset.AddMeToLinkset(this);
DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", 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; return;
} }
@ -248,16 +245,14 @@ public sealed class BSPrim : PhysicsActor
public override void delink() { public override void delink() {
// TODO: decide if this parent checking needs to happen at taint time // 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 // 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; int childrenBefore = _linkset.NumberOfChildren;
_linkset = _linkset.RemoveMeFromLinkset(this); _linkset = _linkset.RemoveMeFromLinkset(this);
DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", 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; 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 // 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 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. // Tell the scene about the vehicle so it will get processing each frame.
_scene.VehicleInSceneTypeChanged(this, type); _scene.VehicleInSceneTypeChanged(this, type);
}); });
@ -486,17 +481,17 @@ public sealed class BSPrim : PhysicsActor
// No locking here because only called when it is safe // No locking here because only called when it is safe
private void SetObjectDynamic() private void SetObjectDynamic()
{ {
// RA: remove this for the moment. // If it's becoming dynamic, it will need hullness
// The problem is that dynamic objects are hulls so if we are becoming physical VerifyCorrectPhysicalShape();
// the shape has to be checked and possibly built.
// Maybe a VerifyCorrectPhysicalShape() routine?
// RecreateGeomAndObject();
// Bullet wants static objects to have a mass of zero // Bullet wants static objects to have a mass of zero
float mass = IsStatic ? 0f : _mass; float mass = IsStatic ? 0f : _mass;
BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass);
// recompute any linkset parameters
_linkset.Refresh(this);
CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr);
DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); 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 // prims don't fly
public override bool Flying { public override bool Flying {
get { return _flying; } get { return _flying; }
set { _flying = value; } set {
_flying = value;
}
} }
public override bool SetAlwaysRun { public override bool SetAlwaysRun {
get { return _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 // No locking here because this is done when we know physics is not simulating
private void CreateGeomMesh() 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); ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod);
// m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); // 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 the hull hasn't changed, don't rebuild it
if (newHullKey == _hullKey) return; 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 // Since we're recreating new, get rid of any previously generated shape
if (_hullKey != 0) if (_hullKey != 0)
{ {
// m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); // 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); BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey);
_hullKey = 0; _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; _hullKey = newHullKey;
if (_meshKey != _hullKey)
{ // Make sure the underlying mesh exists and is correct
// if the underlying mesh has changed, rebuild it
CreateGeomMesh(); CreateGeomMesh();
}
int[] indices = _mesh.getIndexListAsInt(); int[] indices = _mesh.getIndexListAsInt();
List<OMV.Vector3> vertices = _mesh.getVertexList(); List<OMV.Vector3> vertices = _mesh.getVertexList();
@ -1142,7 +1139,7 @@ public sealed class BSPrim : PhysicsActor
// create the hull into the _hulls variable // create the hull into the _hulls variable
convexBuilder.process(dcomp); 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 hull information is passed as a large floating point array.
// The format is: // The format is:
// convHulls[0] = number of hulls // convHulls[0] = number of hulls
@ -1214,6 +1211,27 @@ public sealed class BSPrim : PhysicsActor
return; 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 // 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 // No locking here because this is done when the physics engine is not simulating
// Returns 'true' if an object was actually created. // Returns 'true' if an object was actually created.
@ -1338,13 +1356,12 @@ public sealed class BSPrim : PhysicsActor
_acceleration = entprop.Acceleration; _acceleration = entprop.Acceleration;
_rotationalVelocity = entprop.RotationalVelocity; _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}", DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
base.RequestPhysicsterseUpdate(); base.RequestPhysicsterseUpdate();
} }
/*
else else
{ {
// For debugging, we also report the movement of children // 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, LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
entprop.Acceleration, entprop.RotationalVelocity); entprop.Acceleration, entprop.RotationalVelocity);
} }
*/
} }
// I've collided with something // 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) 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); // 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; _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 someone is subscribed to collision events....
if (_subscribedEventsMs != 0) { if (_subscribedEventsMs != 0) {
// throttle the collisions to the number of milliseconds specified in the subscription // 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) if (collisionCollection != null && collisionCollection.Count > 0)
{ {
base.SendCollisionUpdate(collisionCollection); 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;
} }
} }

View File

@ -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 ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private static readonly string LogHeader = "[BULLETS SCENE]"; 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 = "?"; public string BulletSimVersion = "?";
private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>(); private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>();
public Dictionary<uint, BSCharacter> Characters { get { return m_avatars; } }
private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>(); private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>();
public Dictionary<uint, BSPrim> Prims { get { return m_prims; } }
private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>(); private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>();
private HashSet<BSPrim> m_primsWithCollisions = new HashSet<BSPrim>(); private HashSet<BSPrim> m_primsWithCollisions = new HashSet<BSPrim>();
private List<BSPrim> m_vehicles = new List<BSPrim>(); private List<BSPrim> m_vehicles = new List<BSPrim>();
private float[] m_heightMap; private float[] m_heightMap;
private float m_waterLevel; private float m_waterLevel;
private uint m_worldID; private uint m_worldID;
@ -95,16 +102,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
private int m_detailedStatsStep = 0; private int m_detailedStatsStep = 0;
public IMesher mesher; public IMesher mesher;
private float m_meshLOD; // Level of Detail values kept as float because that's what the Meshmerizer wants
public float MeshLOD public float MeshLOD { get; private set; }
{ public float MeshMegaPrimLOD { get; private set; }
get { return m_meshLOD; } public float MeshMegaPrimThreshold { get; private set; }
} public float SculptLOD { get; private set; }
private float m_sculptLOD;
public float SculptLOD
{
get { return m_sculptLOD; }
}
private BulletSim m_worldSim; private BulletSim m_worldSim;
public BulletSim World public BulletSim World
@ -179,8 +181,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
ConfigurationParameters[] m_params; ConfigurationParameters[] m_params;
GCHandle m_paramsHandle; 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; private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
// Sometimes you just have to log everything. // Sometimes you just have to log everything.
@ -196,6 +199,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
public BSScene(string identifier) public BSScene(string identifier)
{ {
m_initialized = false; 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) public override void Initialise(IMesher meshmerizer, IConfigSource config)
@ -281,10 +286,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
// Very detailed logging for physics debugging // Very detailed logging for physics debugging
m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-"); m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
// Very detailed logging for vehicle debugging // Very detailed logging for vehicle debugging
m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); 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 // prevent simulation until we've been initialized
if (!m_initialized) return 10.0f; 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 // update the prim states while we know the physics engine is not busy
ProcessTaints(); ProcessTaints();
@ -434,8 +442,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
catch (Exception e) catch (Exception e)
{ {
m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, 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); // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
// updatedEntityCount = 0; updatedEntityCount = 0;
collidersCount = 0; collidersCount = 0;
} }
@ -511,8 +519,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
// long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
// return (timeStep * (float)simulateTotalTime); // return (timeStep * (float)simulateTotalTime);
// TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. // TODO: FIX THIS: fps calculation possibly wrong.
return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; // 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 // Something has collided
@ -529,6 +542,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
else if (m_avatars.ContainsKey(collidingWith)) else if (m_avatars.ContainsKey(collidingWith))
type = ActorTypes.Agent; type = ActorTypes.Agent;
// DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
BSPrim prim; BSPrim prim;
if (m_prims.TryGetValue(localID, out prim)) { if (m_prims.TryGetValue(localID, out prim)) {
prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration); 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 // make sure no stepping happens while we're deleting stuff
m_initialized = false; m_initialized = false;
if (m_constraintCollection != null)
{
m_constraintCollection.Dispose();
m_constraintCollection = null;
}
foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars) foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
{ {
kvp.Value.Destroy(); kvp.Value.Destroy();
@ -608,6 +617,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
} }
m_prims.Clear(); 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 // Anything left in the unmanaged code should be cleaned out
BulletSimAPI.Shutdown(WorldID); BulletSimAPI.Shutdown(WorldID);
@ -891,16 +907,26 @@ public class BSScene : PhysicsScene, IPhysicsParameters
(s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, (s) => { return s.NumericBool(s._forceSimplePrimMeshing); },
(s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), (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, 8f,
(s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); }, (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); },
(s) => { return (float)s.m_meshLOD; }, (s) => { return s.MeshLOD; },
(s,p,l,v) => { s.m_meshLOD = (int)v; } ), (s,p,l,v) => { s.MeshLOD = v; } ),
new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", 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, 32f,
(s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); },
(s) => { return (float)s.m_sculptLOD; }, (s) => { return s.SculptLOD; },
(s,p,l,v) => { s.m_sculptLOD = (int)v; } ), (s,p,l,v) => { s.SculptLOD = v; } ),
new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
10f, 10f,
@ -1131,12 +1157,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
(s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); },
(s) => { return (float)s.m_detailedStatsStep; }, (s) => { return (float)s.m_detailedStatsStep; },
(s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), (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 // Convert a boolean to our numeric true and false values

View File

@ -415,6 +415,27 @@ public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, Int
Vector3 frame2loc, Quaternion frame2rot, Vector3 frame2loc, Quaternion frame2rot,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies); 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] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi); 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] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce); 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] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool CalculateTransforms2(IntPtr constrain); 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] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr ClearForces2(IntPtr obj); 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] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetMargin2(IntPtr obj, float val); public static extern bool SetMargin2(IntPtr obj, float val);

View File

@ -243,33 +243,38 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
public List<SceneObjectPart> GetLinkParts(int linkType) public List<SceneObjectPart> GetLinkParts(int linkType)
{
return GetLinkParts(m_host, linkType);
}
private List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
{ {
List<SceneObjectPart> ret = new List<SceneObjectPart>(); List<SceneObjectPart> ret = new List<SceneObjectPart>();
ret.Add(m_host); ret.Add(part);
switch (linkType) switch (linkType)
{ {
case ScriptBaseClass.LINK_SET: case ScriptBaseClass.LINK_SET:
return new List<SceneObjectPart>(m_host.ParentGroup.Parts); return new List<SceneObjectPart>(part.ParentGroup.Parts);
case ScriptBaseClass.LINK_ROOT: case ScriptBaseClass.LINK_ROOT:
ret = new List<SceneObjectPart>(); ret = new List<SceneObjectPart>();
ret.Add(m_host.ParentGroup.RootPart); ret.Add(part.ParentGroup.RootPart);
return ret; return ret;
case ScriptBaseClass.LINK_ALL_OTHERS: case ScriptBaseClass.LINK_ALL_OTHERS:
ret = new List<SceneObjectPart>(m_host.ParentGroup.Parts); ret = new List<SceneObjectPart>(part.ParentGroup.Parts);
if (ret.Contains(m_host)) if (ret.Contains(part))
ret.Remove(m_host); ret.Remove(part);
return ret; return ret;
case ScriptBaseClass.LINK_ALL_CHILDREN: case ScriptBaseClass.LINK_ALL_CHILDREN:
ret = new List<SceneObjectPart>(m_host.ParentGroup.Parts); ret = new List<SceneObjectPart>(part.ParentGroup.Parts);
if (ret.Contains(m_host.ParentGroup.RootPart)) if (ret.Contains(part.ParentGroup.RootPart))
ret.Remove(m_host.ParentGroup.RootPart); ret.Remove(part.ParentGroup.RootPart);
return ret; return ret;
case ScriptBaseClass.LINK_THIS: case ScriptBaseClass.LINK_THIS:
@ -279,7 +284,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (linkType < 0) if (linkType < 0)
return new List<SceneObjectPart>(); return new List<SceneObjectPart>();
SceneObjectPart target = m_host.ParentGroup.GetLinkNumPart(linkType); SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType);
if (target == null) if (target == null)
return new List<SceneObjectPart>(); return new List<SceneObjectPart>();
ret = new List<SceneObjectPart>(); ret = new List<SceneObjectPart>();
@ -325,14 +330,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return key; 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. //These are the implementations of the various ll-functions used by the LSL scripts.
public LSL_Float llSin(double f) public LSL_Float llSin(double f)
{ {
@ -1092,9 +1089,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Float llGround(LSL_Vector offset) public LSL_Float llGround(LSL_Vector offset)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
(float)offset.y,
(float)offset.z);
//Get the slope normal. This gives us the equation of the plane tangent to the slope. //Get the slope normal. This gives us the equation of the plane tangent to the slope.
LSL_Vector vsn = llGroundNormal(offset); LSL_Vector vsn = llGroundNormal(offset);
@ -1338,31 +1333,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (part == null || part.ParentGroup.IsDeleted) if (part == null || part.ParentGroup.IsDeleted)
return; return;
if (scale.x < 0.01) // First we need to check whether or not we need to clamp the size of a physics-enabled prim
scale.x = 0.01;
if (scale.y < 0.01)
scale.y = 0.01;
if (scale.z < 0.01)
scale.z = 0.01;
PhysicsActor pa = part.ParentGroup.RootPart.PhysActor; PhysicsActor pa = part.ParentGroup.RootPart.PhysActor;
if (pa != null && pa.IsPhysical) if (pa != null && pa.IsPhysical)
{ {
if (scale.x > World.m_maxPhys) scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x));
scale.x = World.m_maxPhys; scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y));
if (scale.y > World.m_maxPhys) scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z));
scale.y = World.m_maxPhys;
if (scale.z > World.m_maxPhys)
scale.z = World.m_maxPhys;
} }
if (scale.x > World.m_maxNonphys) // Next we clamp the scale to the non-physical min/max
scale.x = World.m_maxNonphys; scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x));
if (scale.y > World.m_maxNonphys) scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y));
scale.y = World.m_maxNonphys; scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z));
if (scale.z > World.m_maxNonphys)
scale.z = World.m_maxNonphys;
Vector3 tmp = part.Scale; Vector3 tmp = part.Scale;
tmp.X = (float)scale.x; tmp.X = (float)scale.x;
@ -1394,7 +1377,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (face == ScriptBaseClass.ALL_SIDES) if (face == ScriptBaseClass.ALL_SIDES)
face = SceneObjectPart.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) 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; 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; return 0;
} }
@ -2041,13 +2025,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
targetPos.z = ground; targetPos.z = ground;
SceneObjectGroup parent = part.ParentGroup; SceneObjectGroup parent = part.ParentGroup;
LSL_Vector real_vec = !adjust ? targetPos : SetPosAdjust(currentPos, targetPos); parent.UpdateGroupPosition(!adjust ? targetPos :
parent.UpdateGroupPosition(new Vector3((float)real_vec.x, (float)real_vec.y, (float)real_vec.z)); SetPosAdjust(currentPos, targetPos));
} }
else else
{ {
LSL_Vector rel_vec = !adjust ? targetPos : SetPosAdjust(currentPos, targetPos); part.OffsetPosition = !adjust ? targetPos :
part.OffsetPosition = new Vector3((float)rel_vec.x, (float)rel_vec.y, (float)rel_vec.z); SetPosAdjust(currentPos, targetPos);
SceneObjectGroup parent = part.ParentGroup; SceneObjectGroup parent = part.ParentGroup;
parent.HasGroupChanged = true; parent.HasGroupChanged = true;
parent.ScheduleGroupForTerseUpdate(); parent.ScheduleGroupForTerseUpdate();
@ -2091,7 +2075,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); // 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) public void llSetRot(LSL_Rotation rot)
@ -2102,7 +2086,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (m_host.ParentID == 0) if (m_host.ParentID == 0)
{ {
// special case: If we are root, rotate complete SOG to new rotation // special case: If we are root, rotate complete SOG to new rotation
SetRot(m_host, Rot2Quaternion(rot)); SetRot(m_host, rot);
} }
else else
{ {
@ -2110,7 +2094,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
SceneObjectPart rootPart = m_host.ParentGroup.RootPart; SceneObjectPart rootPart = m_host.ParentGroup.RootPart;
if (rootPart != null) // better safe than sorry 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) public void llSetLocalRot(LSL_Rotation rot)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
SetRot(m_host, Rot2Quaternion(rot)); SetRot(m_host, rot);
ScriptSleep(200); ScriptSleep(200);
} }
@ -2205,7 +2189,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (local != 0) if (local != 0)
force *= llGetRot(); 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) if (!m_host.ParentGroup.IsDeleted)
{ {
Vector3 tmpForce = m_host.ParentGroup.RootPart.GetForce(); force = m_host.ParentGroup.RootPart.GetForce();
force.x = tmpForce.X;
force.y = tmpForce.Y;
force.z = tmpForce.Z;
} }
return force; return force;
@ -2229,8 +2210,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Integer llTarget(LSL_Vector position, double range) public LSL_Integer llTarget(LSL_Vector position, double range)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
return m_host.ParentGroup.registerTargetWaypoint( return m_host.ParentGroup.registerTargetWaypoint(position,
new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range); (float)range);
} }
public void llTargetRemove(int number) public void llTargetRemove(int number)
@ -2242,8 +2223,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Integer llRotTarget(LSL_Rotation rot, double error) public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
return m_host.ParentGroup.registerRotTargetWaypoint( return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error);
new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), (float)error);
} }
public void llRotTargetRemove(int number) public void llRotTargetRemove(int number)
@ -2255,7 +2235,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llMoveToTarget(LSL_Vector target, double tau) public void llMoveToTarget(LSL_Vector target, double tau)
{ {
m_host.AddScriptLPS(1); 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() public void llStopMoveToTarget()
@ -2268,7 +2248,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
//No energy force yet //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) if (v.Length() > 20000.0f)
{ {
v.Normalize(); v.Normalize();
@ -2280,13 +2260,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llApplyRotationalImpulse(LSL_Vector force, int local) public void llApplyRotationalImpulse(LSL_Vector force, int local)
{ {
m_host.AddScriptLPS(1); 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) public void llSetTorque(LSL_Vector torque, int local)
{ {
m_host.AddScriptLPS(1); 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() public LSL_Vector llGetTorque()
@ -2837,13 +2817,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return; 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 // need the magnitude later
// float velmag = (float)Util.GetMagnitude(llvel); // 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 either of these are null, then there was an unknown error.
if (new_group == null) if (new_group == null)
@ -2864,10 +2841,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
PhysicsActor pa = new_group.RootPart.PhysActor; PhysicsActor pa = new_group.RootPart.PhysActor;
if (pa != null && pa.IsPhysical && llvel != Vector3.Zero) if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
{ {
//Recoil. //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) // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
}); });
@ -2912,7 +2889,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
else 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 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) 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() public LSL_Integer llGetStartParameter()
@ -3424,37 +3401,46 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
int implicitPerms = 0;
if (m_host.ParentGroup.IsAttachment && (UUID)agent == m_host.ParentGroup.AttachedAvatar) if (m_host.ParentGroup.IsAttachment && (UUID)agent == m_host.ParentGroup.AttachedAvatar)
{ {
// When attached, certain permissions are implicit if requested from owner // 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_TRIGGER_ANIMATION |
ScriptBaseClass.PERMISSION_CONTROL_CAMERA | ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
ScriptBaseClass.PERMISSION_ATTACH; ScriptBaseClass.PERMISSION_ATTACH;
}
if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms else
{ {
lock (m_host.TaskInventory) bool sitting = false;
if (m_host.SitTargetAvatar == agentID)
{ {
m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; sitting = true;
m_host.TaskInventory[m_item.ItemID].PermsMask = perm; }
else
{
foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
{
if (p.SitTargetAvatar == agentID)
sitting = true;
}
} }
m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( if (sitting)
"run_time_permissions", new Object[] {
new LSL_Integer(perm) },
new DetectParams[0]));
return;
}
}
else if (m_host.SitTargetAvatar == agentID) // Sitting avatar
{ {
// When agent is sitting, certain permissions are implicit if requested from sitting agent // When agent is sitting, certain permissions are implicit if requested from sitting agent
int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
ScriptBaseClass.PERMISSION_CONTROL_CAMERA | ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
ScriptBaseClass.PERMISSION_TRACK_CAMERA | ScriptBaseClass.PERMISSION_TRACK_CAMERA |
ScriptBaseClass.PERMISSION_TAKE_CONTROLS; ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
}
else
{
if (World.GetExtraSetting("auto_grant_attach_perms") == "true")
implicitPerms = ScriptBaseClass.PERMISSION_ATTACH;
}
}
if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
{ {
@ -3471,7 +3457,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return; return;
} }
}
ScenePresence presence = World.GetScenePresence(agentID); ScenePresence presence = World.GetScenePresence(agentID);
if (presence != null) if (presence != null)
@ -3587,7 +3572,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
List<SceneObjectPart> parts = GetLinkParts(linknumber); List<SceneObjectPart> parts = GetLinkParts(linknumber);
foreach (SceneObjectPart part in parts) 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) 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) public void llSetText(string text, LSL_Vector color, double alpha)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f), Vector3 av3 = Util.Clip(color, 0.0f, 1.0f);
Util.Clip((float)color.y, 0.0f, 1.0f),
Util.Clip((float)color.z, 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.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.HasGroupChanged = true;
//m_host.ParentGroup.ScheduleGroupForFullUpdate(); //m_host.ParentGroup.ScheduleGroupForFullUpdate();
@ -4217,14 +4200,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
ScriptSleep(5000); 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); m_host.AddScriptLPS(1);
UUID agentId = new UUID(); 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)) if (UUID.TryParse(agent, out agentId))
{ {
ScenePresence presence = World.GetScenePresence(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); m_host.AddScriptLPS(1);
UUID agentId = new UUID(); UUID agentId = new UUID();
ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y); 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)) if (UUID.TryParse(agent, out agentId))
{ {
ScenePresence presence = World.GetScenePresence(agentId); ScenePresence presence = World.GetScenePresence(agentId);
@ -4545,7 +4523,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
distance_attenuation = 1f / normalized_units; 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(); 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 //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. //the height of that point on the plane. The resulting vector gives the slope.
Vector3 vsl = new Vector3(); Vector3 vsl = vsn;
vsl.X = (float)vsn.x;
vsl.Y = (float)vsn.y;
vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z)); vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z));
vsl.Normalize(); vsl.Normalize();
//Normalization might be overkill here //Normalization might be overkill here
@ -6057,9 +6033,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public LSL_Vector llGroundNormal(LSL_Vector offset) public LSL_Vector llGroundNormal(LSL_Vector offset)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
(float)offset.y,
(float)offset.z);
// Clamp to valid position // Clamp to valid position
if (pos.X < 0) if (pos.X < 0)
pos.X = 0; pos.X = 0;
@ -6512,8 +6486,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (!m_host.ParentGroup.IsDeleted) if (!m_host.ParentGroup.IsDeleted)
{ {
m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec);
new Vector3((float)vec.x, (float)vec.y, (float)vec.z));
} }
} }
@ -6525,7 +6498,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (!m_host.ParentGroup.IsDeleted) 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) protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot)
{ {
// LSL quaternions can normalize to 0, normal Quaternions can't. part.SitTargetPosition = offset;
if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) part.SitTargetOrientation = rot;
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.ParentGroup.HasGroupChanged = true; part.ParentGroup.HasGroupChanged = true;
} }
@ -6659,13 +6628,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llSetCameraEyeOffset(LSL_Vector offset) public void llSetCameraEyeOffset(LSL_Vector offset)
{ {
m_host.AddScriptLPS(1); 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) public void llSetCameraAtOffset(LSL_Vector offset)
{ {
m_host.AddScriptLPS(1); 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) 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) public LSL_Integer llScriptDanger(LSL_Vector pos)
{ {
m_host.AddScriptLPS(1); 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) if (result)
{ {
return 1; return 1;
@ -7246,7 +7215,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llSetPrimitiveParams(LSL_List rules) public void llSetPrimitiveParams(LSL_List rules)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
SetPrimParams(m_host, rules);
setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules);
ScriptSleep(200); ScriptSleep(200);
} }
@ -7271,11 +7241,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
List<SceneObjectPart> parts = GetLinkParts(linknumber); List<SceneObjectPart> parts = GetLinkParts(linknumber);
LSL_List remaining = null;
foreach (SceneObjectPart part in parts) 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; int idx = 0;
@ -7298,7 +7280,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_POSITION: case (int)ScriptBaseClass.PRIM_POSITION:
case (int)ScriptBaseClass.PRIM_POS_LOCAL: case (int)ScriptBaseClass.PRIM_POS_LOCAL:
if (remain < 1) if (remain < 1)
return; return null;
v=rules.GetVector3Item(idx++); v=rules.GetVector3Item(idx++);
positionChanged = true; positionChanged = true;
@ -7307,7 +7289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break; break;
case (int)ScriptBaseClass.PRIM_SIZE: case (int)ScriptBaseClass.PRIM_SIZE:
if (remain < 1) if (remain < 1)
return; return null;
v=rules.GetVector3Item(idx++); v=rules.GetVector3Item(idx++);
SetScale(part, v); SetScale(part, v);
@ -7315,27 +7297,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break; break;
case (int)ScriptBaseClass.PRIM_ROTATION: case (int)ScriptBaseClass.PRIM_ROTATION:
if (remain < 1) if (remain < 1)
return; return null;
LSL_Rotation q = rules.GetQuaternionItem(idx++); LSL_Rotation q = rules.GetQuaternionItem(idx++);
// try to let this work as in SL... // try to let this work as in SL...
if (part.ParentID == 0) if (part.ParentID == 0)
{ {
// special case: If we are root, rotate complete SOG to new rotation // special case: If we are root, rotate complete SOG to new rotation
SetRot(part, Rot2Quaternion(q)); SetRot(part, q);
} }
else 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. // 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; SceneObjectPart rootPart = part.ParentGroup.RootPart;
SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q)); SetRot(part, rootPart.RotationOffset * (Quaternion)q);
} }
break; break;
case (int)ScriptBaseClass.PRIM_TYPE: case (int)ScriptBaseClass.PRIM_TYPE:
if (remain < 3) if (remain < 3)
return; return null;
code = (int)rules.GetLSLIntegerItem(idx++); code = (int)rules.GetLSLIntegerItem(idx++);
@ -7354,7 +7336,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
case (int)ScriptBaseClass.PRIM_TYPE_BOX: case (int)ScriptBaseClass.PRIM_TYPE_BOX:
if (remain < 6) if (remain < 6)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); face = (int)rules.GetLSLIntegerItem(idx++);
v = rules.GetVector3Item(idx++); // cut v = rules.GetVector3Item(idx++); // cut
@ -7369,7 +7351,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
if (remain < 6) if (remain < 6)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); // holeshape face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
v = rules.GetVector3Item(idx++); // cut v = rules.GetVector3Item(idx++); // cut
@ -7383,7 +7365,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_PRISM: case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
if (remain < 6) if (remain < 6)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); // holeshape face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
v = rules.GetVector3Item(idx++); //cut v = rules.GetVector3Item(idx++); //cut
@ -7397,7 +7379,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
if (remain < 5) if (remain < 5)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); // holeshape face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
v = rules.GetVector3Item(idx++); // cut v = rules.GetVector3Item(idx++); // cut
@ -7410,7 +7392,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_TORUS: case (int)ScriptBaseClass.PRIM_TYPE_TORUS:
if (remain < 11) if (remain < 11)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); // holeshape face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
v = rules.GetVector3Item(idx++); //cut v = rules.GetVector3Item(idx++); //cut
@ -7429,7 +7411,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_TUBE: case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
if (remain < 11) if (remain < 11)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); // holeshape face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
v = rules.GetVector3Item(idx++); //cut v = rules.GetVector3Item(idx++); //cut
@ -7448,7 +7430,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_RING: case (int)ScriptBaseClass.PRIM_TYPE_RING:
if (remain < 11) if (remain < 11)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); // holeshape face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
v = rules.GetVector3Item(idx++); //cut v = rules.GetVector3Item(idx++); //cut
@ -7467,7 +7449,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
if (remain < 2) if (remain < 2)
return; return null;
string map = rules.Data[idx++].ToString(); string map = rules.Data[idx++].ToString();
face = (int)rules.GetLSLIntegerItem(idx++); // type face = (int)rules.GetLSLIntegerItem(idx++); // type
@ -7479,7 +7461,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TEXTURE: case (int)ScriptBaseClass.PRIM_TEXTURE:
if (remain < 5) if (remain < 5)
return; return null;
face=(int)rules.GetLSLIntegerItem(idx++); face=(int)rules.GetLSLIntegerItem(idx++);
string tex=rules.Data[idx++].ToString(); string tex=rules.Data[idx++].ToString();
@ -7496,20 +7478,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_COLOR: case (int)ScriptBaseClass.PRIM_COLOR:
if (remain < 3) if (remain < 3)
return; return null;
face=(int)rules.GetLSLIntegerItem(idx++); face=(int)rules.GetLSLIntegerItem(idx++);
LSL_Vector color=rules.GetVector3Item(idx++); LSL_Vector color=rules.GetVector3Item(idx++);
double alpha=(double)rules.GetLSLFloatItem(idx++); double alpha=(double)rules.GetLSLFloatItem(idx++);
part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); part.SetFaceColorAlpha(face, color, alpha);
SetAlpha(part, alpha, face);
break; break;
case (int)ScriptBaseClass.PRIM_FLEXIBLE: case (int)ScriptBaseClass.PRIM_FLEXIBLE:
if (remain < 7) if (remain < 7)
return; return null;
bool flexi = rules.GetLSLIntegerItem(idx++); bool flexi = rules.GetLSLIntegerItem(idx++);
int softness = rules.GetLSLIntegerItem(idx++); int softness = rules.GetLSLIntegerItem(idx++);
@ -7525,7 +7506,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_POINT_LIGHT: case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
if (remain < 5) if (remain < 5)
return; return null;
bool light = rules.GetLSLIntegerItem(idx++); bool light = rules.GetLSLIntegerItem(idx++);
LSL_Vector lightcolor = rules.GetVector3Item(idx++); LSL_Vector lightcolor = rules.GetVector3Item(idx++);
float intensity = (float)rules.GetLSLFloatItem(idx++); float intensity = (float)rules.GetLSLFloatItem(idx++);
@ -7538,7 +7519,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_GLOW: case (int)ScriptBaseClass.PRIM_GLOW:
if (remain < 2) if (remain < 2)
return; return null;
face = rules.GetLSLIntegerItem(idx++); face = rules.GetLSLIntegerItem(idx++);
float glow = (float)rules.GetLSLFloatItem(idx++); float glow = (float)rules.GetLSLFloatItem(idx++);
@ -7548,7 +7529,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_BUMP_SHINY: case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
if (remain < 3) if (remain < 3)
return; return null;
face = (int)rules.GetLSLIntegerItem(idx++); face = (int)rules.GetLSLIntegerItem(idx++);
int shiny = (int)rules.GetLSLIntegerItem(idx++); int shiny = (int)rules.GetLSLIntegerItem(idx++);
Bumpiness bump = (Bumpiness)(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: case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
if (remain < 2) if (remain < 2)
return; return null;
face = rules.GetLSLIntegerItem(idx++); face = rules.GetLSLIntegerItem(idx++);
bool st = rules.GetLSLIntegerItem(idx++); bool st = rules.GetLSLIntegerItem(idx++);
SetFullBright(part, face , st); SetFullBright(part, face , st);
@ -7567,17 +7548,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_MATERIAL: case (int)ScriptBaseClass.PRIM_MATERIAL:
if (remain < 1) if (remain < 1)
return; return null;
int mat = rules.GetLSLIntegerItem(idx++); int mat = rules.GetLSLIntegerItem(idx++);
if (mat < 0 || mat > 7) if (mat < 0 || mat > 7)
return; return null;
part.Material = Convert.ToByte(mat); part.Material = Convert.ToByte(mat);
break; break;
case (int)ScriptBaseClass.PRIM_PHANTOM: case (int)ScriptBaseClass.PRIM_PHANTOM:
if (remain < 1) if (remain < 1)
return; return null;
string ph = rules.Data[idx++].ToString(); string ph = rules.Data[idx++].ToString();
m_host.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1")); m_host.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1"));
@ -7586,7 +7567,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_PHYSICS: case (int)ScriptBaseClass.PRIM_PHYSICS:
if (remain < 1) if (remain < 1)
return; return null;
string phy = rules.Data[idx++].ToString(); string phy = rules.Data[idx++].ToString();
bool physics; bool physics;
@ -7600,7 +7581,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
if (remain < 1) if (remain < 1)
return; return null;
string temp = rules.Data[idx++].ToString(); string temp = rules.Data[idx++].ToString();
m_host.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); m_host.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1"));
@ -7609,7 +7590,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TEXGEN: case (int)ScriptBaseClass.PRIM_TEXGEN:
if (remain < 2) if (remain < 2)
return; return null;
//face,type //face,type
face = rules.GetLSLIntegerItem(idx++); face = rules.GetLSLIntegerItem(idx++);
int style = rules.GetLSLIntegerItem(idx++); int style = rules.GetLSLIntegerItem(idx++);
@ -7617,53 +7598,57 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
break; break;
case (int)ScriptBaseClass.PRIM_TEXT: case (int)ScriptBaseClass.PRIM_TEXT:
if (remain < 3) if (remain < 3)
return; return null;
string primText = rules.GetLSLStringItem(idx++); string primText = rules.GetLSLStringItem(idx++);
LSL_Vector primTextColor = rules.GetVector3Item(idx++); LSL_Vector primTextColor = rules.GetVector3Item(idx++);
LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++);
Vector3 av3 = new Vector3(Util.Clip((float)primTextColor.x, 0.0f, 1.0f), Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f);
Util.Clip((float)primTextColor.y, 0.0f, 1.0f),
Util.Clip((float)primTextColor.z, 0.0f, 1.0f));
part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f));
break; break;
case (int)ScriptBaseClass.PRIM_NAME: case (int)ScriptBaseClass.PRIM_NAME:
if (remain < 1) if (remain < 1)
return; return null;
string primName = rules.GetLSLStringItem(idx++); string primName = rules.GetLSLStringItem(idx++);
part.Name = primName; part.Name = primName;
break; break;
case (int)ScriptBaseClass.PRIM_DESC: case (int)ScriptBaseClass.PRIM_DESC:
if (remain < 1) if (remain < 1)
return; return null;
string primDesc = rules.GetLSLStringItem(idx++); string primDesc = rules.GetLSLStringItem(idx++);
part.Description = primDesc; part.Description = primDesc;
break; break;
case (int)ScriptBaseClass.PRIM_ROT_LOCAL: case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
if (remain < 1) if (remain < 1)
return; return null;
LSL_Rotation lr = rules.GetQuaternionItem(idx++); SetRot(part, rules.GetQuaternionItem(idx++));
SetRot(part, Rot2Quaternion(lr));
break; break;
case (int)ScriptBaseClass.PRIM_OMEGA: case (int)ScriptBaseClass.PRIM_OMEGA:
if (remain < 3) if (remain < 3)
return; return null;
LSL_Vector axis = rules.GetVector3Item(idx++); LSL_Vector axis = rules.GetVector3Item(idx++);
LSL_Float spinrate = rules.GetLSLFloatItem(idx++); LSL_Float spinrate = rules.GetLSLFloatItem(idx++);
LSL_Float gain = rules.GetLSLFloatItem(idx++); LSL_Float gain = rules.GetLSLFloatItem(idx++);
TargetOmega(part, axis, (double)spinrate, (double)gain); TargetOmega(part, axis, (double)spinrate, (double)gain);
break; 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: 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. 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; return null;
LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
LSL_List new_rules = rules.GetSublist(idx, -1);
setLinkPrimParams((int)new_linknumber, new_rules);
return; return rules.GetSublist(idx, -1);
} }
} }
} }
catch (InvalidCastException e)
{
ShoutError(e.Message);
}
finally finally
{ {
if (positionChanged) if (positionChanged)
@ -7671,17 +7656,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (part.ParentGroup.RootPart == part) if (part.ParentGroup.RootPart == part)
{ {
SceneObjectGroup parent = part.ParentGroup; SceneObjectGroup parent = part.ParentGroup;
parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); parent.UpdateGroupPosition(currentPosition);
} }
else else
{ {
part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z); part.OffsetPosition = currentPosition;
SceneObjectGroup parent = part.ParentGroup; SceneObjectGroup parent = part.ParentGroup;
parent.HasGroupChanged = true; parent.HasGroupChanged = true;
parent.ScheduleGroupForTerseUpdate(); parent.ScheduleGroupForTerseUpdate();
} }
} }
} }
return null;
} }
public LSL_String llStringToBase64(string str) public LSL_String llStringToBase64(string str)
@ -7911,8 +7897,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (part != null) if (part != null)
{ {
Vector3 halfSize = part.Scale / 2.0f; 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 lower = (new LSL_Vector(halfSize)) * -1.0f;
LSL_Vector upper = new LSL_Vector(halfSize.X, halfSize.Y, halfSize.Z); LSL_Vector upper = new LSL_Vector(halfSize);
result.Add(lower); result.Add(lower);
result.Add(upper); result.Add(upper);
return result; return result;
@ -8325,6 +8311,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_POS_LOCAL: case (int)ScriptBaseClass.PRIM_POS_LOCAL:
res.Add(new LSL_Vector(GetPartLocalPos(part))); res.Add(new LSL_Vector(GetPartLocalPos(part)));
break; 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; return res;
@ -9913,9 +9908,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
ScenePresence avatar = World.GetScenePresence(detectedParams.Key); ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
if (avatar != null) if (avatar != null)
{ {
avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, simname, avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name,
new Vector3((float)pos.x, (float)pos.y, (float)pos.z), simname, pos, lookAt);
new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z));
} }
ScriptSleep(1000); ScriptSleep(1000);
} }
@ -10522,12 +10516,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
else else
rot = obj.GetWorldRotation(); 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); ret.Add(objrot);
} }
break; break;
case ScriptBaseClass.OBJECT_VELOCITY: 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; break;
case ScriptBaseClass.OBJECT_OWNER: case ScriptBaseClass.OBJECT_OWNER:
ret.Add(new LSL_String(obj.OwnerID.ToString())); ret.Add(new LSL_String(obj.OwnerID.ToString()));
@ -10754,7 +10748,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (obj.OwnerID != m_host.OwnerID) if (obj.OwnerID != m_host.OwnerID)
return; 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) public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
@ -11104,8 +11107,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z); Vector3 rayStart = start;
Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z); Vector3 rayEnd = end;
Vector3 dir = rayEnd - rayStart; Vector3 dir = rayEnd - rayStart;
float dist = Vector3.Mag(dir); float dist = Vector3.Mag(dir);

View File

@ -304,7 +304,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY:
idx++; idx++;
iV = rules.GetVector3Item(idx); iV = rules.GetVector3Item(idx);
wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); wl.cloudDetailXYDensity = iV;
break; break;
case (int)ScriptBaseClass.WL_CLOUD_SCALE: case (int)ScriptBaseClass.WL_CLOUD_SCALE:
idx++; idx++;
@ -329,7 +329,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY:
idx++; idx++;
iV = rules.GetVector3Item(idx); iV = rules.GetVector3Item(idx);
wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); wl.cloudXYDensity = iV;
break; break;
case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER:
idx++; idx++;
@ -384,7 +384,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE:
idx++; idx++;
iV = rules.GetVector3Item(idx); iV = rules.GetVector3Item(idx);
wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); wl.reflectionWaveletScale = iV;
break; break;
case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE:
idx++; idx++;
@ -422,7 +422,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.WL_WATER_COLOR: case (int)ScriptBaseClass.WL_WATER_COLOR:
idx++; idx++;
iV = rules.GetVector3Item(idx); iV = rules.GetVector3Item(idx);
wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); wl.waterColor = iV;
break; break;
case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT:
idx++; idx++;

View File

@ -333,8 +333,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
if (type == typeof(OpenMetaverse.Quaternion)) if (type == typeof(OpenMetaverse.Quaternion))
{ {
LSL_Rotation rot = (LSL_Rotation)lslparm; return (OpenMetaverse.Quaternion)((LSL_Rotation)lslparm);
return new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s);
} }
} }
@ -343,8 +342,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
if (type == typeof(OpenMetaverse.Vector3)) if (type == typeof(OpenMetaverse.Vector3))
{ {
LSL_Vector vect = (LSL_Vector)lslparm; return (OpenMetaverse.Vector3)((LSL_Vector)lslparm);
return new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z);
} }
} }
@ -367,13 +365,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
result[i] = new UUID((LSL_Key)plist[i]); result[i] = new UUID((LSL_Key)plist[i]);
else if (plist[i] is LSL_Rotation) else if (plist[i] is LSL_Rotation)
{ {
LSL_Rotation rot = (LSL_Rotation)plist[i]; result[i] = (OpenMetaverse.Quaternion)(
result[i] = new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s); (LSL_Rotation)plist[i]);
} }
else if (plist[i] is LSL_Vector) else if (plist[i] is LSL_Vector)
{ {
LSL_Vector vect = (LSL_Vector)plist[i]; result[i] = (OpenMetaverse.Vector3)(
result[i] = new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z); (LSL_Vector)plist[i]);
} }
else else
MODError("unknown LSL list element type"); MODError("unknown LSL list element type");

View File

@ -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 // 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. // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
Util.FireAndForget( Util.FireAndForget(o => World.RequestTeleportLocation(
o => World.RequestTeleportLocation(presence.ControllingClient, regionName, presence.ControllingClient, regionName, position,
new Vector3((float)position.x, (float)position.y, (float)position.z), lookat, (uint)TPFlags.ViaLocation));
new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
ScriptSleep(5000); 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 // 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. // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
Util.FireAndForget( Util.FireAndForget(o => World.RequestTeleportLocation(
o => World.RequestTeleportLocation(presence.ControllingClient, regionHandle, presence.ControllingClient, regionHandle,
new Vector3((float)position.x, (float)position.y, (float)position.z), position, lookat, (uint)TPFlags.ViaLocation));
new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
ScriptSleep(5000); ScriptSleep(5000);
@ -2329,7 +2327,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
ownerID = m_host.OwnerID; ownerID = m_host.OwnerID;
UUID x = module.CreateNPC(firstname, UUID x = module.CreateNPC(firstname,
lastname, lastname,
new Vector3((float) position.x, (float) position.y, (float) position.z), position,
ownerID, ownerID,
senseAsAgent, senseAsAgent,
World, World,
@ -2446,7 +2444,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return new LSL_Vector(0, 0, 0); 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"); CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo");
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
@ -2461,7 +2459,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (!module.CheckPermissions(npcId, m_host.OwnerID)) if (!module.CheckPermissions(npcId, m_host.OwnerID))
return; return;
Vector3 pos = new Vector3((float) position.x, (float) position.y, (float) position.z);
module.MoveToTarget(npcId, World, pos, false, true, false); 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)) if (!module.CheckPermissions(npcId, m_host.OwnerID))
return; return;
Vector3 pos = new Vector3((float)target.x, (float)target.y, (float)target.z);
module.MoveToTarget( module.MoveToTarget(
new UUID(npc.m_string), new UUID(npc.m_string),
World, World,
pos, target,
(options & ScriptBaseClass.OS_NPC_NO_FLY) != 0, (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0,
(options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0, (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0,
(options & ScriptBaseClass.OS_NPC_RUNNING) != 0); (options & ScriptBaseClass.OS_NPC_RUNNING) != 0);
@ -2537,7 +2533,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
ScenePresence sp = World.GetScenePresence(npcId); ScenePresence sp = World.GetScenePresence(npcId);
if (sp != null) if (sp != null)
sp.Rotation = LSL_Api.Rot2Quaternion(rotation); sp.Rotation = rotation;
} }
} }
@ -2895,7 +2891,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
sp.ControllingClient.Kick(alert); sp.ControllingClient.Kick(alert);
// ...and close on our side // ...and close on our side
sp.Scene.IncomingCloseAgent(sp.UUID); sp.Scene.IncomingCloseAgent(sp.UUID, false);
} }
}); });
} }

View File

@ -351,7 +351,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
q = avatar.Rotation * q; 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); LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
@ -428,9 +428,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
try try
{ {
Vector3 diff = toRegionPos - fromRegionPos; 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, diff);
double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); double mag_obj = LSL_Types.Vector3.Mag(diff);
double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
} }
catch catch
@ -479,7 +478,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
q = avatar.Rotation * q; 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); LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0); bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0);
@ -560,8 +559,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
double ang_obj = 0; double ang_obj = 0;
try try
{ {
Vector3 diff = toRegionPos - fromRegionPos; LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(
LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); toRegionPos - fromRegionPos);
double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir);
double mag_obj = LSL_Types.Vector3.Mag(obj_dir); double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));

View File

@ -226,6 +226,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
public const int ATTACH_BELLY = 28; public const int ATTACH_BELLY = 28;
public const int ATTACH_RPEC = 29; public const int ATTACH_RPEC = 29;
public const int ATTACH_LPEC = 30; 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_CENTER_2 = 31;
public const int ATTACH_HUD_TOP_RIGHT = 32; public const int ATTACH_HUD_TOP_RIGHT = 32;
public const int ATTACH_HUD_TOP_CENTER = 33; 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_OMEGA = 32;
public const int PRIM_POS_LOCAL = 33; public const int PRIM_POS_LOCAL = 33;
public const int PRIM_LINK_TARGET = 34; 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_DEFAULT = 0;
public const int PRIM_TEXGEN_PLANAR = 1; public const int PRIM_TEXGEN_PLANAR = 1;

View File

@ -546,6 +546,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
"OpenSim.Region.ScriptEngine.Shared.dll")); "OpenSim.Region.ScriptEngine.Shared.dll"));
parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
"OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll")); "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll"));
parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
"OpenMetaverseTypes.dll"));
if (lang == enumCompileType.yp) if (lang == enumCompileType.yp)
{ {

View File

@ -160,11 +160,11 @@ namespace OpenSim.Region.ScriptEngine.Shared
else else
{ {
// Set the values from the touch data provided by the client // 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); touchST = new LSL_Types.Vector3(value.STCoord);
touchUV = new LSL_Types.Vector3(value.UVCoord.X, value.UVCoord.Y, value.UVCoord.Z); touchUV = new LSL_Types.Vector3(value.UVCoord);
touchNormal = new LSL_Types.Vector3(value.Normal.X, value.Normal.Y, value.Normal.Z); touchNormal = new LSL_Types.Vector3(value.Normal);
touchBinormal = new LSL_Types.Vector3(value.Binormal.X, value.Binormal.Y, value.Binormal.Z); touchBinormal = new LSL_Types.Vector3(value.Binormal);
touchPos = new LSL_Types.Vector3(value.Position.X, value.Position.Y, value.Position.Z); touchPos = new LSL_Types.Vector3(value.Position);
touchFace = value.FaceIndex; touchFace = value.FaceIndex;
} }
} }
@ -181,19 +181,13 @@ namespace OpenSim.Region.ScriptEngine.Shared
Name = presence.Firstname + " " + presence.Lastname; Name = presence.Firstname + " " + presence.Lastname;
Owner = Key; Owner = Key;
Position = new LSL_Types.Vector3( Position = new LSL_Types.Vector3(presence.AbsolutePosition);
presence.AbsolutePosition.X,
presence.AbsolutePosition.Y,
presence.AbsolutePosition.Z);
Rotation = new LSL_Types.Quaternion( Rotation = new LSL_Types.Quaternion(
presence.Rotation.X, presence.Rotation.X,
presence.Rotation.Y, presence.Rotation.Y,
presence.Rotation.Z, presence.Rotation.Z,
presence.Rotation.W); presence.Rotation.W);
Velocity = new LSL_Types.Vector3( Velocity = new LSL_Types.Vector3(presence.Velocity);
presence.Velocity.X,
presence.Velocity.Y,
presence.Velocity.Z);
if (presence.PresenceType != PresenceType.Npc) if (presence.PresenceType != PresenceType.Npc)
{ {
@ -241,16 +235,12 @@ namespace OpenSim.Region.ScriptEngine.Shared
} }
} }
Position = new LSL_Types.Vector3(part.AbsolutePosition.X, Position = new LSL_Types.Vector3(part.AbsolutePosition);
part.AbsolutePosition.Y,
part.AbsolutePosition.Z);
Quaternion wr = part.ParentGroup.GroupRotation; Quaternion wr = part.ParentGroup.GroupRotation;
Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W); Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W);
Velocity = new LSL_Types.Vector3(part.Velocity.X, Velocity = new LSL_Types.Vector3(part.Velocity);
part.Velocity.Y,
part.Velocity.Z);
} }
} }

View File

@ -31,6 +31,11 @@ using System.Globalization;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using OpenSim.Framework; 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 namespace OpenSim.Region.ScriptEngine.Shared
{ {
[Serializable] [Serializable]
@ -54,6 +59,20 @@ namespace OpenSim.Region.ScriptEngine.Shared
z = (float)vector.z; 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) public Vector3(double X, double Y, double Z)
{ {
x = X; x = X;
@ -109,6 +128,26 @@ namespace OpenSim.Region.ScriptEngine.Shared
return new list(new object[] { vec }); 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) public static bool operator ==(Vector3 lhs, Vector3 rhs)
{ {
return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z);
@ -322,6 +361,14 @@ namespace OpenSim.Region.ScriptEngine.Shared
s = 1; s = 1;
} }
public Quaternion(OMV_Quaternion rot)
{
x = rot.X;
y = rot.Y;
z = rot.Z;
s = rot.W;
}
#endregion #endregion
#region Overriders #region Overriders
@ -368,6 +415,21 @@ namespace OpenSim.Region.ScriptEngine.Shared
return new list(new object[] { r }); 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) public static bool operator ==(Quaternion lhs, Quaternion rhs)
{ {
// Return true if the fields match: // Return true if the fields match:
@ -560,12 +622,23 @@ namespace OpenSim.Region.ScriptEngine.Shared
else if (m_data[itemIndex] is LSL_Types.LSLString) else if (m_data[itemIndex] is LSL_Types.LSLString)
return new LSLInteger(m_data[itemIndex].ToString()); return new LSLInteger(m_data[itemIndex].ToString());
else 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) public LSL_Types.Vector3 GetVector3Item(int itemIndex)
{ {
if(m_data[itemIndex] is LSL_Types.Vector3)
return (LSL_Types.Vector3)m_data[itemIndex]; 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) public LSL_Types.Quaternion GetQuaternionItem(int itemIndex)

View File

@ -152,9 +152,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
det[0] = new DetectParams(); det[0] = new DetectParams();
det[0].Key = remoteClient.AgentId; det[0].Key = remoteClient.AgentId;
det[0].Populate(myScriptEngine.World); det[0].Populate(myScriptEngine.World);
det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X, det[0].OffsetPos = offsetPos;
offsetPos.Y,
offsetPos.Z);
if (originalID == 0) if (originalID == 0)
{ {
@ -298,9 +296,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
foreach (DetectedObject detobj in col.Colliders) foreach (DetectedObject detobj in col.Colliders)
{ {
DetectParams d = new DetectParams(); DetectParams d = new DetectParams();
d.Position = new LSL_Types.Vector3(detobj.posVector.X, d.Position = detobj.posVector;
detobj.posVector.Y,
detobj.posVector.Z);
d.Populate(myScriptEngine.World); d.Populate(myScriptEngine.World);
det.Add(d); det.Add(d);
myScriptEngine.PostObjectEvent(localID, new EventParams( myScriptEngine.PostObjectEvent(localID, new EventParams(
@ -318,9 +314,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
foreach (DetectedObject detobj in col.Colliders) foreach (DetectedObject detobj in col.Colliders)
{ {
DetectParams d = new DetectParams(); DetectParams d = new DetectParams();
d.Position = new LSL_Types.Vector3(detobj.posVector.X, d.Position = detobj.posVector;
detobj.posVector.Y,
detobj.posVector.Z);
d.Populate(myScriptEngine.World); d.Populate(myScriptEngine.World);
det.Add(d); det.Add(d);
myScriptEngine.PostObjectEvent(localID, new EventParams( myScriptEngine.PostObjectEvent(localID, new EventParams(
@ -337,9 +331,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
foreach (DetectedObject detobj in col.Colliders) foreach (DetectedObject detobj in col.Colliders)
{ {
DetectParams d = new DetectParams(); DetectParams d = new DetectParams();
d.Position = new LSL_Types.Vector3(detobj.posVector.X, d.Position = detobj.posVector;
detobj.posVector.Y,
detobj.posVector.Z);
d.Populate(myScriptEngine.World); d.Populate(myScriptEngine.World);
det.Add(d); det.Add(d);
myScriptEngine.PostObjectEvent(localID, new EventParams( myScriptEngine.PostObjectEvent(localID, new EventParams(
@ -381,8 +373,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
myScriptEngine.PostObjectEvent(localID, new EventParams( myScriptEngine.PostObjectEvent(localID, new EventParams(
"at_target", new object[] { "at_target", new object[] {
new LSL_Types.LSLInteger(handle), new LSL_Types.LSLInteger(handle),
new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z), new LSL_Types.Vector3(targetpos),
new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) }, new LSL_Types.Vector3(atpos) },
new DetectParams[0])); new DetectParams[0]));
} }
@ -399,8 +391,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
myScriptEngine.PostObjectEvent(localID, new EventParams( myScriptEngine.PostObjectEvent(localID, new EventParams(
"at_rot_target", new object[] { "at_rot_target", new object[] {
new LSL_Types.LSLInteger(handle), new LSL_Types.LSLInteger(handle),
new LSL_Types.Quaternion(targetrot.X,targetrot.Y,targetrot.Z,targetrot.W), new LSL_Types.Quaternion(targetrot),
new LSL_Types.Quaternion(atrot.X,atrot.Y,atrot.Z,atrot.W) }, new LSL_Types.Quaternion(atrot) },
new DetectParams[0])); new DetectParams[0]));
} }

View File

@ -982,10 +982,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
return false; 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})", UUID assetID = item.AssetID;
// item.Name, itemID.ToString(), part.ParentGroup.RootPart.Name);
ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID);
@ -1164,10 +1166,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
stateSource, m_MaxScriptQueue); stateSource, m_MaxScriptQueue);
// if (DebugLevel >= 1) // if (DebugLevel >= 1)
m_log.DebugFormat( // m_log.DebugFormat(
"[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", // "[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.Name, item.Name, itemID, part.UUID,
part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); // part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
if (presence != null) if (presence != null)
{ {
@ -1465,9 +1467,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
else if (p[i] is string) else if (p[i] is string)
lsl_p[i] = new LSL_Types.LSLString((string)p[i]); lsl_p[i] = new LSL_Types.LSLString((string)p[i]);
else if (p[i] is Vector3) 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) 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) else if (p[i] is float)
lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]);
else else
@ -1491,9 +1493,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
else if (p[i] is string) else if (p[i] is string)
lsl_p[i] = new LSL_Types.LSLString((string)p[i]); lsl_p[i] = new LSL_Types.LSLString((string)p[i]);
else if (p[i] is Vector3) 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) 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) else if (p[i] is float)
lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]);
else else

View File

@ -164,5 +164,19 @@ namespace OpenSim.Services.Connectors
m_database.RemoveRegionEnvironmentSettings(regionUUID); 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<string, string> GetExtra(UUID regionID)
{
return m_database.GetExtra(regionID);
}
} }
} }

View File

@ -127,6 +127,19 @@ namespace OpenSim.Data.Null
{ {
m_store.RemoveRegionEnvironmentSettings(regionUUID); m_store.RemoveRegionEnvironmentSettings(regionUUID);
} }
public void SaveExtra(UUID regionID, string name, string value)
{
}
public void RemoveExtra(UUID regionID, string name)
{
}
public Dictionary<string, string> GetExtra(UUID regionID)
{
return null;
}
} }
/// <summary> /// <summary>
@ -318,5 +331,18 @@ namespace OpenSim.Data.Null
public void Shutdown() public void Shutdown()
{ {
} }
public void SaveExtra(UUID regionID, string name, string value)
{
}
public void RemoveExtra(UUID regionID, string name)
{
}
public Dictionary<string, string> GetExtra(UUID regionID)
{
return null;
}
} }
} }

View File

@ -933,6 +933,11 @@ namespace OpenSim.Tests.Common.Mock
} }
public void Close() public void Close()
{
Close(false);
}
public void Close(bool force)
{ {
// Fire the callback for this connection closing // Fire the callback for this connection closing
// This is necesary to get the presence detector to notice that a client has logged out. // This is necesary to get the presence detector to notice that a client has logged out.

View File

@ -87,10 +87,18 @@
;; from the selected region_info_source. ;; from the selected region_info_source.
; allow_regionless = false ; 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 ;# {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!). ;; Maximum size for non-physical prims. Affects resizing of existing prims. This can be overriden in the region config file (as NonphysicalPrimMax!).
; NonphysicalPrimMax = 256 ; 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 ;# {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. ;; Maximum size where a prim can be physical. Affects resizing of existing prims. This can be overriden in the region config file.
; PhysicalPrimMax = 10 ; PhysicalPrimMax = 10
@ -675,7 +683,9 @@
;; Maximum number of events to queue for a script (excluding timers) ;; Maximum number of events to queue for a script (excluding timers)
; MaxScriptEventQueue = 300 ; 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 ; ThreadStackSize = 262144
;# {DeleteScriptsOnStartup} {} {Delete previously compiled script DLLs on startup?} (true false) true ;# {DeleteScriptsOnStartup} {} {Delete previously compiled script DLLs on startup?} (true false) true

View File

@ -894,7 +894,7 @@
AvatarDensity = 60.0 AvatarDensity = 60.0
AvatarCapsuleRadius = 0.37 AvatarCapsuleRadius = 0.37
AvatarCapsuleHeight = 1.5 AvatarCapsuleHeight = 1.5
AvatarContactProcessingThreshold = 0.1; AvatarContactProcessingThreshold = 0.1
MaxObjectMass = 10000.01 MaxObjectMass = 10000.01
@ -908,19 +908,19 @@
CcdSweptSphereRadius = 0.0 CcdSweptSphereRadius = 0.0
ContactProcessingThreshold = 0.1 ContactProcessingThreshold = 0.1
; If setting a pool size, also disable dynamic allocation (default pool size is 4096 with dynamic alloc) ; If setting a pool size, also disable dynamic allocation (default pool size is 4096 with dynamic alloc)
MaxPersistantManifoldPoolSize = 0; MaxPersistantManifoldPoolSize = 0
ShouldDisableContactPoolDynamicAllocation = False; ShouldDisableContactPoolDynamicAllocation = False
ShouldForceUpdateAllAabbs = False; ShouldForceUpdateAllAabbs = False
ShouldRandomizeSolverOrder = False; ShouldRandomizeSolverOrder = False
ShouldSplitSimulationIslands = False; ShouldSplitSimulationIslands = False
ShouldEnableFrictionCaching = False; ShouldEnableFrictionCaching = False
NumberOfSolverIterations = 0; NumberOfSolverIterations = 0;
; Linkset constraint parameters ; Linkset constraint parameters
LinkConstraintUseFrameOffset = False; LinkConstraintUseFrameOffset = False
LinkConstraintEnableTransMotor = True; LinkConstraintEnableTransMotor = True
LinkConstraintTransMotorMaxVel = 5.0; LinkConstraintTransMotorMaxVel = 5.0
LinkConstraintTransMotorMaxForce = 0.1; LinkConstraintTransMotorMaxForce = 0.1
; Whether to mesh sculpties ; Whether to mesh sculpties
@ -931,16 +931,24 @@
; level of detail for physical meshes. 32,16,8 or 4 with 32 being full detail ; level of detail for physical meshes. 32,16,8 or 4 with 32 being full detail
MeshLevelOfDetail = 8 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 ; number^2 non-physical level of detail of the sculpt texture. 32x32 - 1024 verticies
SculptLevelOfDetail = 32 SculptLevelOfDetail = 32
; Bullet step parameters ; Bullet step parameters
MaxSubSteps = 10; MaxSubSteps = 10
FixedTimeStep = .01667 FixedTimeStep = .01667
MaxCollisionsPerFrame = 2048 MaxCollisionsPerFrame = 2048
MaxUpdatesPerFrame = 8192 MaxUpdatesPerFrame = 8192
; Detailed physics debug logging
PhysicsLoggingEnabled = False
PhysicsLoggingDir = "."
VehicleLoggingEnabled = False
[RemoteAdmin] [RemoteAdmin]
enabled = false enabled = false

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1799,6 +1799,7 @@
<Reference name="System.Core"/> <Reference name="System.Core"/>
<Reference name="System.Xml"/> <Reference name="System.Xml"/>
<Reference name="Mono.Addins" path="../../../bin/"/> <Reference name="Mono.Addins" path="../../../bin/"/>
<Reference name="NDesk.Options" path="../../../bin/"/>
<Reference name="OpenMetaverseTypes" path="../../../bin/"/> <Reference name="OpenMetaverseTypes" path="../../../bin/"/>
<Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/> <Reference name="OpenMetaverse.StructuredData" path="../../../bin/"/>
<Reference name="OpenMetaverse" path="../../../bin/"/> <Reference name="OpenMetaverse" path="../../../bin/"/>