Merge branch 'ubitwork' of ssh://3dhosting.de/var/git/careminster into ubitwork

avinationmerge
ubit 2012-08-16 16:13:38 +02:00
commit d09fa0d76e
66 changed files with 2147 additions and 838 deletions

View File

@ -91,6 +91,7 @@ what it is today.
* Fly-Man * Fly-Man
* Flyte Xevious * Flyte Xevious
* Garmin Kawaguichi * Garmin Kawaguichi
* Gryc Ueusp
* Imaze Rhiano * Imaze Rhiano
* Intimidated * Intimidated
* Jeremy Bongio (IBM) * Jeremy Bongio (IBM)

View File

@ -2207,5 +2207,18 @@ VALUES
{ {
return new UUID[0]; return new UUID[0];
} }
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

@ -2094,5 +2094,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

@ -156,5 +156,18 @@ namespace OpenSim.Data.Null
{ {
return new UUID[0]; return new UUID[0];
} }
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

@ -2894,5 +2894,18 @@ namespace OpenSim.Data.SQLite
{ {
return new UUID[0]; return new UUID[0];
} }
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

@ -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)
@ -509,4 +511,4 @@ namespace OpenSim.Framework.Console
} }
} }
} }
} }

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; } }
@ -76,4 +78,4 @@ namespace OpenSim.Framework.Console
public string[] Resolve(string[] cmd) { return null; } public string[] Resolve(string[] cmd) { return null; }
public XmlElement GetXml(XmlDocument doc) { return null; } public XmlElement GetXml(XmlDocument doc) { return null; }
} }
} }

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

@ -126,7 +126,7 @@ namespace OpenSim.Framework
public delegate void ObjectDrop(uint localID, IClientAPI remoteClient); public delegate void ObjectDrop(uint localID, IClientAPI remoteClient);
public delegate void UpdatePrimFlags( public delegate void UpdatePrimFlags(
uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom,ExtraPhysicsData PhysData, IClientAPI remoteClient); uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient);
public delegate void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient); public delegate void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient);

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>
@ -87,4 +91,4 @@ namespace OpenSim.Framework
string ReadLine(string p, bool isCommand, bool e); string ReadLine(string p, bool isCommand, bool e);
} }
} }

View File

@ -97,6 +97,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 +141,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>

View File

@ -93,6 +93,8 @@ namespace OpenSim.Framework.Serialization.External
"MediaURL", (ld, xtr) => ld.MediaURL = xtr.ReadElementString("MediaURL")); "MediaURL", (ld, xtr) => ld.MediaURL = xtr.ReadElementString("MediaURL"));
m_ldProcessors.Add( m_ldProcessors.Add(
"MusicURL", (ld, xtr) => ld.MusicURL = xtr.ReadElementString("MusicURL")); "MusicURL", (ld, xtr) => ld.MusicURL = xtr.ReadElementString("MusicURL"));
m_ldProcessors.Add(
"OwnerID", (ld, xtr) => ld.OwnerID = UUID.Parse(xtr.ReadElementString("OwnerID")));
m_ldProcessors.Add( m_ldProcessors.Add(
"ParcelAccessList", ProcessParcelAccessList); "ParcelAccessList", ProcessParcelAccessList);
@ -186,7 +188,16 @@ namespace OpenSim.Framework.Serialization.External
return landData; return landData;
} }
public static string Serialize(LandData landData) /// <summary>
/// Serialize land data
/// </summary>
/// <param name='landData'></param>
/// <param name='options'>
/// Serialization options.
/// Can be null if there are no options.
/// "wipe-owners" will write UUID.Zero rather than the ownerID so that a later reload loads all parcels with the estate owner as the owner
/// </param>
public static string Serialize(LandData landData, Dictionary<string, object> options)
{ {
StringWriter sw = new StringWriter(); StringWriter sw = new StringWriter();
XmlTextWriter xtw = new XmlTextWriter(sw); XmlTextWriter xtw = new XmlTextWriter(sw);
@ -215,7 +226,14 @@ namespace OpenSim.Framework.Serialization.External
xtw.WriteElementString("MediaID", landData.MediaID.ToString()); xtw.WriteElementString("MediaID", landData.MediaID.ToString());
xtw.WriteElementString("MediaURL", landData.MediaURL); xtw.WriteElementString("MediaURL", landData.MediaURL);
xtw.WriteElementString("MusicURL", landData.MusicURL); xtw.WriteElementString("MusicURL", landData.MusicURL);
xtw.WriteElementString("OwnerID", landData.OwnerID.ToString());
UUID ownerIdToWrite;
if (options != null && options.ContainsKey("wipe-owners"))
ownerIdToWrite = UUID.Zero;
else
ownerIdToWrite = landData.OwnerID;
xtw.WriteElementString("OwnerID", ownerIdToWrite.ToString());
xtw.WriteStartElement("ParcelAccessList"); xtw.WriteStartElement("ParcelAccessList");
foreach (LandAccessEntry pal in landData.ParcelAccessList) foreach (LandAccessEntry pal in landData.ParcelAccessList)

View File

@ -42,22 +42,23 @@ namespace OpenSim.Framework.Serialization.Tests
private LandData land; private LandData land;
private LandData landWithParcelAccessList; private LandData landWithParcelAccessList;
private static string preSerialized = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\n<LandData>\n <Area>128</Area>\n <AuctionID>0</AuctionID>\n <AuthBuyerID>00000000-0000-0000-0000-000000000000</AuthBuyerID>\n <Category>10</Category>\n <ClaimDate>0</ClaimDate>\n <ClaimPrice>0</ClaimPrice>\n <GlobalID>54ff9641-dd40-4a2c-b1f1-47dd3af24e50</GlobalID>\n <GroupID>d740204e-bbbf-44aa-949d-02c7d739f6a5</GroupID>\n <IsGroupOwned>False</IsGroupOwned>\n <Bitmap>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</Bitmap>\n <Description>land data to test LandDataSerializer</Description>\n <Flags>536870944</Flags>\n <LandingType>2</LandingType>\n <Name>LandDataSerializerTest Land</Name>\n <Status>0</Status>\n <LocalID>0</LocalID>\n <MediaAutoScale>1</MediaAutoScale>\n <MediaID>d4452578-2f25-4b97-a81b-819af559cfd7</MediaID>\n <MediaURL>http://videos.opensimulator.org/bumblebee.mp4</MediaURL>\n <MusicURL />\n <OwnerID>1b8eedf9-6d15-448b-8015-24286f1756bf</OwnerID>\n <ParcelAccessList />\n <PassHours>0</PassHours>\n <PassPrice>0</PassPrice>\n <SalePrice>0</SalePrice>\n <SnapshotID>00000000-0000-0000-0000-000000000000</SnapshotID>\n <UserLocation>&lt;0, 0, 0&gt;</UserLocation>\n <UserLookAt>&lt;0, 0, 0&gt;</UserLookAt>\n <Dwell>0</Dwell>\n <OtherCleanTime>0</OtherCleanTime>\n</LandData>"; // private static string preSerialized = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\n<LandData>\n <Area>128</Area>\n <AuctionID>0</AuctionID>\n <AuthBuyerID>00000000-0000-0000-0000-000000000000</AuthBuyerID>\n <Category>10</Category>\n <ClaimDate>0</ClaimDate>\n <ClaimPrice>0</ClaimPrice>\n <GlobalID>54ff9641-dd40-4a2c-b1f1-47dd3af24e50</GlobalID>\n <GroupID>d740204e-bbbf-44aa-949d-02c7d739f6a5</GroupID>\n <IsGroupOwned>False</IsGroupOwned>\n <Bitmap>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</Bitmap>\n <Description>land data to test LandDataSerializer</Description>\n <Flags>536870944</Flags>\n <LandingType>2</LandingType>\n <Name>LandDataSerializerTest Land</Name>\n <Status>0</Status>\n <LocalID>0</LocalID>\n <MediaAutoScale>1</MediaAutoScale>\n <MediaID>d4452578-2f25-4b97-a81b-819af559cfd7</MediaID>\n <MediaURL>http://videos.opensimulator.org/bumblebee.mp4</MediaURL>\n <MusicURL />\n <OwnerID>1b8eedf9-6d15-448b-8015-24286f1756bf</OwnerID>\n <ParcelAccessList />\n <PassHours>0</PassHours>\n <PassPrice>0</PassPrice>\n <SalePrice>0</SalePrice>\n <SnapshotID>00000000-0000-0000-0000-000000000000</SnapshotID>\n <UserLocation>&lt;0, 0, 0&gt;</UserLocation>\n <UserLookAt>&lt;0, 0, 0&gt;</UserLookAt>\n <Dwell>0</Dwell>\n <OtherCleanTime>0</OtherCleanTime>\n</LandData>";
private static string preSerializedWithParcelAccessList = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\n<LandData>\n <Area>128</Area>\n <AuctionID>0</AuctionID>\n <AuthBuyerID>00000000-0000-0000-0000-000000000000</AuthBuyerID>\n <Category>10</Category>\n <ClaimDate>0</ClaimDate>\n <ClaimPrice>0</ClaimPrice>\n <GlobalID>54ff9641-dd40-4a2c-b1f1-47dd3af24e50</GlobalID>\n <GroupID>d740204e-bbbf-44aa-949d-02c7d739f6a5</GroupID>\n <IsGroupOwned>False</IsGroupOwned>\n <Bitmap>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</Bitmap>\n <Description>land data to test LandDataSerializer</Description>\n <Flags>536870944</Flags>\n <LandingType>2</LandingType>\n <Name>LandDataSerializerTest Land</Name>\n <Status>0</Status>\n <LocalID>0</LocalID>\n <MediaAutoScale>1</MediaAutoScale>\n <MediaID>d4452578-2f25-4b97-a81b-819af559cfd7</MediaID>\n <MediaURL>http://videos.opensimulator.org/bumblebee.mp4</MediaURL>\n <MusicURL />\n <OwnerID>1b8eedf9-6d15-448b-8015-24286f1756bf</OwnerID>\n <ParcelAccessList>\n <ParcelAccessEntry>\n <AgentID>62d65d45-c91a-4f77-862c-46557d978b6c</AgentID>\n <Time>0</Time>\n <AccessList>2</AccessList>\n </ParcelAccessEntry>\n <ParcelAccessEntry>\n <AgentID>ec2a8d18-2378-4fe0-8b68-2a31b57c481e</AgentID>\n <Time>0</Time>\n <AccessList>1</AccessList>\n </ParcelAccessEntry>\n </ParcelAccessList>\n <PassHours>0</PassHours>\n <PassPrice>0</PassPrice>\n <SalePrice>0</SalePrice>\n <SnapshotID>00000000-0000-0000-0000-000000000000</SnapshotID>\n <UserLocation>&lt;0, 0, 0&gt;</UserLocation>\n <UserLookAt>&lt;0, 0, 0&gt;</UserLookAt>\n <Dwell>0</Dwell>\n <OtherCleanTime>0</OtherCleanTime>\n</LandData>"; private static string preSerializedWithParcelAccessList
= "<?xml version=\"1.0\" encoding=\"utf-16\"?>\n<LandData>\n <Area>128</Area>\n <AuctionID>0</AuctionID>\n <AuthBuyerID>00000000-0000-0000-0000-000000000000</AuthBuyerID>\n <Category>10</Category>\n <ClaimDate>0</ClaimDate>\n <ClaimPrice>0</ClaimPrice>\n <GlobalID>54ff9641-dd40-4a2c-b1f1-47dd3af24e50</GlobalID>\n <GroupID>d740204e-bbbf-44aa-949d-02c7d739f6a5</GroupID>\n <IsGroupOwned>False</IsGroupOwned>\n <Bitmap>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</Bitmap>\n <Description>land data to test LandDataSerializer</Description>\n <Flags>536870944</Flags>\n <LandingType>2</LandingType>\n <Name>LandDataSerializerTest Land</Name>\n <Status>0</Status>\n <LocalID>0</LocalID>\n <MediaAutoScale>1</MediaAutoScale>\n <MediaID>d4452578-2f25-4b97-a81b-819af559cfd7</MediaID>\n <MediaURL>http://videos.opensimulator.org/bumblebee.mp4</MediaURL>\n <MusicURL />\n <OwnerID>1b8eedf9-6d15-448b-8015-24286f1756bf</OwnerID>\n <ParcelAccessList>\n <ParcelAccessEntry>\n <AgentID>62d65d45-c91a-4f77-862c-46557d978b6c</AgentID>\n <Time>0</Time>\n <AccessList>2</AccessList>\n </ParcelAccessEntry>\n <ParcelAccessEntry>\n <AgentID>ec2a8d18-2378-4fe0-8b68-2a31b57c481e</AgentID>\n <Time>0</Time>\n <AccessList>1</AccessList>\n </ParcelAccessEntry>\n </ParcelAccessList>\n <PassHours>0</PassHours>\n <PassPrice>0</PassPrice>\n <SalePrice>0</SalePrice>\n <SnapshotID>00000000-0000-0000-0000-000000000000</SnapshotID>\n <UserLocation>&lt;0, 0, 0&gt;</UserLocation>\n <UserLookAt>&lt;0, 0, 0&gt;</UserLookAt>\n <Dwell>0</Dwell>\n <OtherCleanTime>0</OtherCleanTime>\n</LandData>";
[SetUp] [SetUp]
public void setup() public void setup()
{ {
// setup LandData object // setup LandData object
this.land = new LandData(); this.land = new LandData();
this.land.AABBMax = new Vector3(0, 0, 0); this.land.AABBMax = new Vector3(1, 2, 3);
this.land.AABBMin = new Vector3(128, 128, 128); this.land.AABBMin = new Vector3(129, 130, 131);
this.land.Area = 128; this.land.Area = 128;
this.land.AuctionID = 0; this.land.AuctionID = 4;
this.land.AuthBuyerID = new UUID(); this.land.AuthBuyerID = new UUID("7176df0c-6c50-45db-8a37-5e78be56a0cd");
this.land.Category = ParcelCategory.Residential; this.land.Category = ParcelCategory.Residential;
this.land.ClaimDate = 0; this.land.ClaimDate = 1;
this.land.ClaimPrice = 0; this.land.ClaimPrice = 2;
this.land.GlobalID = new UUID("54ff9641-dd40-4a2c-b1f1-47dd3af24e50"); this.land.GlobalID = new UUID("54ff9641-dd40-4a2c-b1f1-47dd3af24e50");
this.land.GroupID = new UUID("d740204e-bbbf-44aa-949d-02c7d739f6a5"); this.land.GroupID = new UUID("d740204e-bbbf-44aa-949d-02c7d739f6a5");
this.land.Description = "land data to test LandDataSerializer"; this.land.Description = "land data to test LandDataSerializer";
@ -65,7 +66,7 @@ namespace OpenSim.Framework.Serialization.Tests
this.land.LandingType = (byte)LandingType.Direct; this.land.LandingType = (byte)LandingType.Direct;
this.land.Name = "LandDataSerializerTest Land"; this.land.Name = "LandDataSerializerTest Land";
this.land.Status = ParcelStatus.Leased; this.land.Status = ParcelStatus.Leased;
this.land.LocalID = 0; this.land.LocalID = 1;
this.land.MediaAutoScale = (byte)0x01; this.land.MediaAutoScale = (byte)0x01;
this.land.MediaID = new UUID("d4452578-2f25-4b97-a81b-819af559cfd7"); this.land.MediaID = new UUID("d4452578-2f25-4b97-a81b-819af559cfd7");
this.land.MediaURL = "http://videos.opensimulator.org/bumblebee.mp4"; this.land.MediaURL = "http://videos.opensimulator.org/bumblebee.mp4";
@ -90,26 +91,26 @@ namespace OpenSim.Framework.Serialization.Tests
/// <summary> /// <summary>
/// Test the LandDataSerializer.Serialize() method /// Test the LandDataSerializer.Serialize() method
/// </summary> /// </summary>
[Test] // [Test]
public void LandDataSerializerSerializeTest() // public void LandDataSerializerSerializeTest()
{ // {
TestHelpers.InMethod(); // TestHelpers.InMethod();
//
string serialized = LandDataSerializer.Serialize(this.land).Replace("\r\n", "\n"); // string serialized = LandDataSerializer.Serialize(this.land).Replace("\r\n", "\n");
Assert.That(serialized.Length > 0, "Serialize(LandData) returned empty string"); // Assert.That(serialized.Length > 0, "Serialize(LandData) returned empty string");
//
// adding a simple boolean variable because resharper nUnit integration doesn't like this // // adding a simple boolean variable because resharper nUnit integration doesn't like this
// XML data in the Assert.That statement. Not sure why. // // XML data in the Assert.That statement. Not sure why.
bool result = (serialized == preSerialized); // bool result = (serialized == preSerialized);
Assert.That(result, "result of Serialize LandData does not match expected result"); // Assert.That(result, "result of Serialize LandData does not match expected result");
//
string serializedWithParcelAccessList = LandDataSerializer.Serialize(this.landWithParcelAccessList).Replace("\r\n", "\n"); // string serializedWithParcelAccessList = LandDataSerializer.Serialize(this.landWithParcelAccessList).Replace("\r\n", "\n");
Assert.That(serializedWithParcelAccessList.Length > 0, // Assert.That(serializedWithParcelAccessList.Length > 0,
"Serialize(LandData) returned empty string for LandData object with ParcelAccessList"); // "Serialize(LandData) returned empty string for LandData object with ParcelAccessList");
result = (serializedWithParcelAccessList == preSerializedWithParcelAccessList); // result = (serializedWithParcelAccessList == preSerializedWithParcelAccessList);
Assert.That(result, // Assert.That(result,
"result of Serialize(LandData) does not match expected result (pre-serialized with parcel access list"); // "result of Serialize(LandData) does not match expected result (pre-serialized with parcel access list");
} // }
/// <summary> /// <summary>
/// Test the LandDataSerializer.Deserialize() method /// Test the LandDataSerializer.Deserialize() method
@ -120,10 +121,28 @@ namespace OpenSim.Framework.Serialization.Tests
TestHelpers.InMethod(); TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure(); // log4net.Config.XmlConfigurator.Configure();
LandData ld = LandDataSerializer.Deserialize(LandDataSerializerTest.preSerialized); LandData ld = LandDataSerializer.Deserialize(LandDataSerializer.Serialize(this.land, null));
Assert.That(ld != null, "Deserialize(string) returned null"); Assert.That(ld, Is.Not.Null, "Deserialize(string) returned null");
Assert.That(ld.GlobalID == this.land.GlobalID, "Reified LandData.GlobalID != original LandData.GlobalID"); // Assert.That(ld.AABBMax, Is.EqualTo(land.AABBMax));
Assert.That(ld.Name == this.land.Name, "Reified LandData.Name != original LandData.Name"); // Assert.That(ld.AABBMin, Is.EqualTo(land.AABBMin));
Assert.That(ld.Area, Is.EqualTo(land.Area));
Assert.That(ld.AuctionID, Is.EqualTo(land.AuctionID));
Assert.That(ld.AuthBuyerID, Is.EqualTo(land.AuthBuyerID));
Assert.That(ld.Category, Is.EqualTo(land.Category));
Assert.That(ld.ClaimDate, Is.EqualTo(land.ClaimDate));
Assert.That(ld.ClaimPrice, Is.EqualTo(land.ClaimPrice));
Assert.That(ld.GlobalID, Is.EqualTo(land.GlobalID), "Reified LandData.GlobalID != original LandData.GlobalID");
Assert.That(ld.GroupID, Is.EqualTo(land.GroupID));
Assert.That(ld.Description, Is.EqualTo(land.Description));
Assert.That(ld.Flags, Is.EqualTo(land.Flags));
Assert.That(ld.LandingType, Is.EqualTo(land.LandingType));
Assert.That(ld.Name, Is.EqualTo(land.Name), "Reified LandData.Name != original LandData.Name");
Assert.That(ld.Status, Is.EqualTo(land.Status));
Assert.That(ld.LocalID, Is.EqualTo(land.LocalID));
Assert.That(ld.MediaAutoScale, Is.EqualTo(land.MediaAutoScale));
Assert.That(ld.MediaID, Is.EqualTo(land.MediaID));
Assert.That(ld.MediaURL, Is.EqualTo(land.MediaURL));
Assert.That(ld.OwnerID, Is.EqualTo(land.OwnerID));
} }
[Test] [Test]

View File

@ -294,14 +294,13 @@ namespace OpenSim
"save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [<OAR path>]", "save oar [-h|--home=<url>] [--noassets] [--publish] [--perm=<permissions>] [<OAR path>]",
"Save a region's data to an OAR archive.", "Save a region's data to an OAR archive.",
// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine // "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine
"-h|--home=<url> adds the url of the profile service to the saved user information." + Environment.NewLine "-h|--home=<url> adds the url of the profile service to the saved user information.\n"
+ "--noassets stops assets being saved to the OAR." + Environment.NewLine + "--noassets stops assets being saved to the OAR.\n"
+ "--publish saves an OAR stripped of owner and last owner information." + Environment.NewLine + "--publish saves an OAR stripped of owner and last owner information.\n"
+ " on reload, the estate owner will be the owner of all objects" + Environment.NewLine + " on reload, the estate owner will be the owner of all objects\n"
+ " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published" + Environment.NewLine + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n"
+ " this option is EXPERIMENTAL" + Environment.NewLine + "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR.\n"
+ "--perm=<permissions> stops objects with insufficient permissions from being saved to the OAR." + Environment.NewLine + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n"
+ " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer" + Environment.NewLine
+ "The OAR path must be a filesystem path." + "The OAR path must be a filesystem path."
+ " If this is not given then the oar is saved to region.oar in the current directory.", + " If this is not given then the oar is saved to region.oar in the current directory.",
SaveOar); SaveOar);

View File

@ -320,8 +320,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

@ -126,9 +126,14 @@ namespace OpenSim.Region.ClientStack.Linden
IConfig sconfig = config.Configs["Startup"]; IConfig sconfig = config.Configs["Startup"];
if (sconfig != null) if (sconfig != null)
{ {
m_persistBakedTextures = sconfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
m_levelUpload = sconfig.GetInt("LevelUpload", 0); m_levelUpload = sconfig.GetInt("LevelUpload", 0);
} }
IConfig appearanceConfig = config.Configs["Appearance"];
if (appearanceConfig != null)
{
m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
}
} }
m_assetService = m_Scene.AssetService; m_assetService = m_Scene.AssetService;

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

@ -66,9 +66,9 @@ namespace OpenSim.Region.ClientStack.Linden
public void Initialise(IConfigSource source) public void Initialise(IConfigSource source)
{ {
IConfig sconfig = source.Configs["Startup"]; IConfig appearanceConfig = source.Configs["Appearance"];
if (sconfig != null) if (appearanceConfig != null)
m_persistBakedTextures = sconfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures);
} }
public void AddRegion(Scene s) public void AddRegion(Scene s)

View File

@ -284,7 +284,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
sp.ClearAttachments(); sp.ClearAttachments();
} }
public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData) public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp)
{ {
lock (sp.AttachmentsSyncLock) lock (sp.AttachmentsSyncLock)
{ {
@ -361,7 +361,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
group.AbsolutePosition = attachPos; group.AbsolutePosition = attachPos;
if (sp.PresenceType != PresenceType.Npc) if (sp.PresenceType != PresenceType.Npc)
UpdateUserInventoryWithAttachment(sp, group, attachmentPt); UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp);
AttachToAgent(sp, group, attachmentPt, attachPos, silent); AttachToAgent(sp, group, attachmentPt, attachPos, silent);
} }
@ -369,7 +369,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return true; return true;
} }
private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt) private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool temp)
{ {
// Remove any previous attachments // Remove any previous attachments
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
@ -379,18 +379,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
{ {
if (attachments[0].FromItemID != UUID.Zero) if (attachments[0].FromItemID != UUID.Zero)
DetachSingleAttachmentToInvInternal(sp, attachments[0]); DetachSingleAttachmentToInvInternal(sp, attachments[0]);
else // Error logging commented because UUID.Zero now means temp attachment
m_log.WarnFormat( // else
"[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!", // m_log.WarnFormat(
attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); // "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!",
// attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
} }
// Add the new attachment to inventory if we don't already have it. // Add the new attachment to inventory if we don't already have it.
UUID newAttachmentItemID = group.FromItemID; if (!temp)
if (newAttachmentItemID == UUID.Zero) {
newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID; UUID newAttachmentItemID = group.FromItemID;
if (newAttachmentItemID == UUID.Zero)
newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
}
} }
public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt) public ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
@ -474,6 +478,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
UUID inventoryID = so.FromItemID; UUID inventoryID = so.FromItemID;
// As per Linden spec, drop is disabled for temp attachs
if (inventoryID == UUID.Zero)
return;
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}", // "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}",
// so.Name, so.LocalId, inventoryID); // so.Name, so.LocalId, inventoryID);
@ -484,7 +492,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
so.PrimCount, sp.UUID, sp.AbsolutePosition)) so.PrimCount, sp.UUID, sp.AbsolutePosition))
return; return;
bool changed = sp.Appearance.DetachAttachment(inventoryID); bool changed = false;
if (inventoryID != UUID.Zero)
changed = sp.Appearance.DetachAttachment(inventoryID);
if (changed && m_scene.AvatarFactory != null) if (changed && m_scene.AvatarFactory != null)
m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID); m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
@ -516,6 +526,10 @@ 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
@ -589,6 +603,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
/// <param name="saveAllScripted"></param> /// <param name="saveAllScripted"></param>
private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, string scriptedState) private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, string scriptedState)
{ {
if (grp.FromItemID == UUID.Zero)
{
// We can't save temp attachments
grp.HasGroupChanged = false;
return;
}
// Saving attachments for NPCs messes them up for the real owner! // Saving attachments for NPCs messes them up for the real owner!
INPCModule module = m_scene.RequestModuleInterface<INPCModule>(); INPCModule module = m_scene.RequestModuleInterface<INPCModule>();
if (module != null) if (module != null)
@ -845,7 +866,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// This will throw if the attachment fails // This will throw if the attachment fails
try try
{ {
AttachObject(sp, objatt, attachmentPt, false, false); AttachObject(sp, objatt, attachmentPt, false, false, false);
} }
catch (Exception e) catch (Exception e)
{ {
@ -1005,7 +1026,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
AttachmentPt &= 0x7f; AttachmentPt &= 0x7f;
// Calls attach with a Zero position // Calls attach with a Zero position
if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true)) if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, false))
{ {
// m_log.Debug( // m_log.Debug(
// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId // "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId

View File

@ -189,7 +189,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false); scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false);
// Check status on scene presence // Check status on scene presence
Assert.That(sp.HasAttachments(), Is.True); Assert.That(sp.HasAttachments(), Is.True);
@ -243,7 +243,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
sp2.AbsolutePosition = new Vector3(0, 0, 0); sp2.AbsolutePosition = new Vector3(0, 0, 0);
sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false); scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false);
Assert.That(sp.HasAttachments(), Is.False); Assert.That(sp.HasAttachments(), Is.False);
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));

View File

@ -66,11 +66,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
scene.RegisterModuleInterface<IAvatarFactoryModule>(this); scene.RegisterModuleInterface<IAvatarFactoryModule>(this);
scene.EventManager.OnNewClient += SubscribeToClientEvents; scene.EventManager.OnNewClient += SubscribeToClientEvents;
IConfig sconfig = config.Configs["Startup"]; IConfig appearanceConfig = config.Configs["Appearance"];
if (sconfig != null) if (appearanceConfig != null)
{ {
m_savetime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime))); m_savetime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSave",Convert.ToString(m_savetime)));
m_sendtime = Convert.ToInt32(sconfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime))); m_sendtime = Convert.ToInt32(appearanceConfig.GetString("DelayBeforeAppearanceSend",Convert.ToString(m_sendtime)));
// m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime); // m_log.InfoFormat("[AVFACTORY] configured for {0} save and {1} send",m_savetime,m_sendtime);
} }

View File

@ -596,9 +596,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
} }
break; break;
case "R": case "R":
Font anewFont = new Font(myFont, FontStyle.Regular); // We need to place this newFont inside its own context so that the .NET compiler
myFont.Dispose(); // doesn't complain about a redefinition of an existing newFont, even though there is none
myFont = anewFont; // The mono compiler doesn't produce this error.
{
Font newFont = new Font(myFont, FontStyle.Regular);
myFont.Dispose();
myFont = newFont;
}
break; break;
} }
} }
@ -768,4 +773,4 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
return null; return null;
} }
} }
} }

View File

@ -137,6 +137,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Authentication
#region IAuthenticationService #region IAuthenticationService
public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
{
// Not implemented at the regions
return string.Empty;
}
public string Authenticate(UUID principalID, string password, int lifetime) public string Authenticate(UUID principalID, string password, int lifetime)
{ {
// Not implemented at the regions // Not implemented at the regions

View File

@ -124,7 +124,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
LandData landData = lo.LandData; LandData landData = lo.LandData;
string landDataPath = String.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH, string landDataPath = String.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH,
landData.GlobalID.ToString()); landData.GlobalID.ToString());
m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData)); m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options));
} }
m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive."); m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive.");

View File

@ -84,7 +84,7 @@ namespace OpenSim.Region.Framework.Interfaces
/// <param name="AttachmentPt"></param> /// <param name="AttachmentPt"></param>
/// <param name="silent"></param> /// <param name="silent"></param>
/// <returns>true if the object was successfully attached, false otherwise</returns> /// <returns>true if the object was successfully attached, false otherwise</returns>
bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo); bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo, bool temp);
/// <summary> /// <summary>
/// Rez an attachment from user inventory and change inventory status to match. /// Rez an attachment from user inventory and change inventory status to match.

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

@ -117,5 +117,11 @@ namespace OpenSim.Region.Framework.Interfaces
void RemoveRegionEnvironmentSettings(UUID regionUUID); void RemoveRegionEnvironmentSettings(UUID regionUUID);
UUID[] GetObjectIDs(UUID regionID); UUID[] GetObjectIDs(UUID regionID);
void SaveExtra(UUID regionID, string name, string value);
void RemoveExtra(UUID regionID, string name);
Dictionary<string, string> GetExtra(UUID regionID);
} }
} }

View File

@ -128,6 +128,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

@ -217,6 +217,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;
@ -2616,5 +2619,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

@ -177,6 +177,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>
@ -658,6 +660,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)
{ {
@ -842,7 +846,6 @@ namespace OpenSim.Region.Framework.Scenes
m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences); m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates);
} }
} }
catch (Exception e) catch (Exception e)
@ -850,6 +853,14 @@ namespace OpenSim.Region.Framework.Scenes
m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString()); m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
} }
// FIXME: Ultimately this should be in a module.
IConfig appearanceConfig = m_config.Configs["Appearance"];
if (appearanceConfig != null)
{
SendPeriodicAppearanceUpdates
= appearanceConfig.GetBoolean("ResendAppearanceUpdates", SendPeriodicAppearanceUpdates);
}
#endregion Region Config #endregion Region Config
#region Interest Management #region Interest Management
@ -2748,7 +2759,7 @@ namespace OpenSim.Region.Framework.Scenes
RootPrim.RemFlag(PrimFlags.TemporaryOnRez); RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
if (AttachmentsModule != null) if (AttachmentsModule != null)
AttachmentsModule.AttachObject(sp, grp, 0, false, false); AttachmentsModule.AttachObject(sp, grp, 0, false, false, false);
} }
else else
{ {
@ -5843,5 +5854,44 @@ Environment.Exit(1);
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

@ -1793,7 +1793,6 @@ namespace OpenSim.Region.Framework.Scenes
try try
{ {
parentGroup.areUpdatesSuspended = true;
List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
@ -1850,7 +1849,6 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup; SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
} }
parentGroup.areUpdatesSuspended = false;
parentGroup.HasGroupChanged = true; parentGroup.HasGroupChanged = true;
parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true); parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
parentGroup.ScheduleGroupForFullUpdate(); parentGroup.ScheduleGroupForFullUpdate();
@ -1896,7 +1894,6 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectGroup group = part.ParentGroup; SceneObjectGroup group = part.ParentGroup;
if (!affectedGroups.Contains(group)) if (!affectedGroups.Contains(group))
{ {
group.areUpdatesSuspended = true;
affectedGroups.Add(group); affectedGroups.Add(group);
} }
} }
@ -1922,7 +1919,6 @@ namespace OpenSim.Region.Framework.Scenes
// However, editing linked parts and unlinking may be different // However, editing linked parts and unlinking may be different
// //
SceneObjectGroup group = root.ParentGroup; SceneObjectGroup group = root.ParentGroup;
group.areUpdatesSuspended = true;
List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
int numChildren = newSet.Count; int numChildren = newSet.Count;
@ -1945,7 +1941,6 @@ namespace OpenSim.Region.Framework.Scenes
group.DelinkFromGroup(p, sendEventsToRemainder); group.DelinkFromGroup(p, sendEventsToRemainder);
if (numChildren > 2) if (numChildren > 2)
{ {
p.ParentGroup.areUpdatesSuspended = true;
} }
else else
{ {
@ -1980,7 +1975,6 @@ namespace OpenSim.Region.Framework.Scenes
foreach (SceneObjectPart newChild in newSet) foreach (SceneObjectPart newChild in newSet)
newChild.ClearUpdateSchedule(); newChild.ClearUpdateSchedule();
newRoot.ParentGroup.areUpdatesSuspended = true;
LinkObjects(newRoot, newSet); LinkObjects(newRoot, newSet);
if (!affectedGroups.Contains(newRoot.ParentGroup)) if (!affectedGroups.Contains(newRoot.ParentGroup))
affectedGroups.Add(newRoot.ParentGroup); affectedGroups.Add(newRoot.ParentGroup);
@ -1998,7 +1992,6 @@ namespace OpenSim.Region.Framework.Scenes
m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
g.TriggerScriptChangedEvent(Changed.LINK); g.TriggerScriptChangedEvent(Changed.LINK);
g.HasGroupChanged = true; // Persist g.HasGroupChanged = true; // Persist
g.areUpdatesSuspended = false;
g.ScheduleGroupForFullUpdate(); g.ScheduleGroupForFullUpdate();
} }
} }

View File

@ -113,25 +113,8 @@ namespace OpenSim.Region.Framework.Scenes
private long m_maxPersistTime = 0; private long m_maxPersistTime = 0;
private long m_minPersistTime = 0; private long m_minPersistTime = 0;
private Random m_rand; private Random m_rand;
private bool m_suspendUpdates;
private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>(); private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
public bool areUpdatesSuspended
{
get
{
return m_suspendUpdates;
}
set
{
m_suspendUpdates = value;
if (!value)
{
QueueForUpdateCheck();
}
}
}
/// <summary> /// <summary>
/// This indicates whether the object has changed such that it needs to be repersisted to permenant storage /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage
/// (the database). /// (the database).
@ -951,7 +934,7 @@ namespace OpenSim.Region.Framework.Scenes
/// its existing localID and UUID. /// its existing localID and UUID.
/// </summary> /// </summary>
/// <param name='part'>Root part for this scene object.</param> /// <param name='part'>Root part for this scene object.</param>
public SceneObjectGroup(SceneObjectPart part) public SceneObjectGroup(SceneObjectPart part) : this()
{ {
SetRootPart(part); SetRootPart(part);
} }

View File

@ -0,0 +1,189 @@
/*
* 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.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using log4net;
using Mono.Addins;
using Nini.Config;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Console;
using OpenSim.Framework.Monitoring;
using OpenSim.Region.ClientStack.LindenUDP;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.OptionalModules.Avatar.Attachments
{
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TempAttachmentsModule")]
public class TempAttachmentsModule : INonSharedRegionModule
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private Scene m_scene;
private IRegionConsole m_console;
public void Initialise(IConfigSource configSource)
{
}
public void AddRegion(Scene scene)
{
}
public void RemoveRegion(Scene scene)
{
}
public void RegionLoaded(Scene scene)
{
m_scene = scene;
IScriptModuleComms comms = scene.RequestModuleInterface<IScriptModuleComms>();
if (comms != null)
{
comms.RegisterScriptInvocation( this, "llAttachToAvatarTemp");
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
{
m_log.ErrorFormat("[TEMP ATTACHS]: Failed to register script functions");
}
}
public void Close()
{
}
public Type ReplaceableInterface
{
get { return null; }
}
public string Name
{
get { return "TempAttachmentsModule"; }
}
private void SendConsoleOutput(UUID agentID, string text)
{
if (m_console == null)
return;
m_console.SendConsoleOutput(agentID, text);
}
private void SetAutoGrantAttachPerms(string module, string[] parms)
{
UUID agentID = new UUID(parms[parms.Length - 1]);
Array.Resize(ref parms, parms.Length - 1);
if (parms.Length != 3)
{
SendConsoleOutput(agentID, "Command parameter error");
return;
}
string val = parms[2];
if (val != "true" && val != "false")
{
SendConsoleOutput(agentID, "Command parameter error");
return;
}
m_scene.StoreExtraSetting("auto_grant_attach_perms", val);
SendConsoleOutput(agentID, String.Format("auto_grant_attach_perms set to {0}", val));
}
private void llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint)
{
SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host);
if (hostPart == null)
return;
if (hostPart.ParentGroup.IsAttachment)
return;
IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface<IAttachmentsModule>();
if (attachmentsModule == null)
return;
TaskInventoryItem item = hostPart.Inventory.GetInventoryItem(script);
if (item == null)
return;
if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH
return;
ScenePresence target;
if (!m_scene.TryGetScenePresence(item.PermsGranter, out target))
return;
if (target.UUID != hostPart.ParentGroup.OwnerID)
{
uint effectivePerms = hostPart.ParentGroup.GetEffectivePermissions();
if ((effectivePerms & (uint)PermissionMask.Transfer) == 0)
return;
hostPart.ParentGroup.SetOwnerId(target.UUID);
hostPart.ParentGroup.SetRootPartOwner(hostPart.ParentGroup.RootPart, target.UUID, target.ControllingClient.ActiveGroupId);
if (m_scene.Permissions.PropagatePermissions())
{
foreach (SceneObjectPart child in hostPart.ParentGroup.Parts)
{
child.Inventory.ChangeInventoryOwner(target.UUID);
child.TriggerScriptChangedEvent(Changed.OWNER);
child.ApplyNextOwnerPermissions();
}
}
hostPart.ParentGroup.RootPart.ObjectSaleType = 0;
hostPart.ParentGroup.RootPart.SalePrice = 10;
hostPart.ParentGroup.HasGroupChanged = true;
hostPart.ParentGroup.RootPart.SendPropertiesToClient(target.ControllingClient);
hostPart.ParentGroup.RootPart.ScheduleFullUpdate();
}
attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true);
}
}
}

View File

@ -469,8 +469,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
avatarName = avatar.Name; avatarName = avatar.Name;
m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: scene = {0}, agentID = {1}", scene, agentID); m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: scene = {0}, agentID = {1}", scene, agentID);
m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}", // m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: request: {0}, path: {1}, param: {2}",
request, path, param); // request, path, param);
XmlElement resp; XmlElement resp;
bool retry = false; bool retry = false;
@ -577,7 +577,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse); string r = LLSDHelpers.SerialiseLLSDReply(voiceAccountResponse);
m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r); // m_log.DebugFormat("[VivoxVoice][PROVISIONVOICE]: avatar \"{0}\": {1}", avatarName, r);
return r; return r;
} }
@ -625,8 +625,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
// voice channel // voice channel
LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", // m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}",
scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param);
// m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: avatar \"{0}\": location: {1} {2} {3}", // m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: avatar \"{0}\": location: {1} {2} {3}",
// avatarName, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z); // avatarName, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, avatar.AbsolutePosition.Z);
@ -656,8 +656,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds); parcelVoiceInfo = new LLSDParcelVoiceInfoResponse(scene.RegionInfo.RegionName, land.LocalID, creds);
string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo); string r = LLSDHelpers.SerialiseLLSDReply(parcelVoiceInfo);
m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}", // m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": {4}",
scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r); // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, r);
return r; return r;
} }
catch (Exception e) catch (Exception e)
@ -684,11 +684,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
public string ChatSessionRequest(Scene scene, string request, string path, string param, public string ChatSessionRequest(Scene scene, string request, string path, string param,
UUID agentID, Caps caps) UUID agentID, Caps caps)
{ {
ScenePresence avatar = scene.GetScenePresence(agentID); // ScenePresence avatar = scene.GetScenePresence(agentID);
string avatarName = avatar.Name; // string avatarName = avatar.Name;
m_log.DebugFormat("[VivoxVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}", // m_log.DebugFormat("[VivoxVoice][CHATSESSION]: avatar \"{0}\": request: {1}, path: {2}, param: {3}",
avatarName, request, path, param); // avatarName, request, path, param);
return "<llsd>true</llsd>"; return "<llsd>true</llsd>";
} }
@ -1119,7 +1119,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
try try
{ {
// Otherwise prepare the request // Otherwise prepare the request
m_log.DebugFormat("[VivoxVoice] Sending request <{0}>", requrl); // m_log.DebugFormat("[VivoxVoice] Sending request <{0}>", requrl);
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requrl); HttpWebRequest req = (HttpWebRequest)WebRequest.Create(requrl);
HttpWebResponse rsp = null; HttpWebResponse rsp = null;

View File

@ -124,9 +124,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC
NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, owner, senseAsAgent, scene); NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, owner, senseAsAgent, scene);
npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, int.MaxValue); npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, int.MaxValue);
m_log.DebugFormat( // m_log.DebugFormat(
"[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}", // "[NPC MODULE]: Creating NPC {0} {1} {2}, owner={3}, senseAsAgent={4} at {5} in {6}",
firstname, lastname, npcAvatar.AgentId, owner, senseAsAgent, position, scene.RegionInfo.RegionName); // firstname, lastname, npcAvatar.AgentId, owner, senseAsAgent, position, scene.RegionInfo.RegionName);
AgentCircuitData acd = new AgentCircuitData(); AgentCircuitData acd = new AgentCircuitData();
acd.AgentID = npcAvatar.AgentId; acd.AgentID = npcAvatar.AgentId;
@ -157,7 +157,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
sp.CompleteMovement(npcAvatar, false); sp.CompleteMovement(npcAvatar, false);
m_avatars.Add(npcAvatar.AgentId, npcAvatar); m_avatars.Add(npcAvatar.AgentId, npcAvatar);
m_log.DebugFormat("[NPC MODULE]: Created NPC {0} {1}", npcAvatar.AgentId, sp.Name); // m_log.DebugFormat("[NPC MODULE]: Created NPC {0} {1}", npcAvatar.AgentId, sp.Name);
} }
} }
ev.Set(); ev.Set();
@ -177,16 +177,17 @@ namespace OpenSim.Region.OptionalModules.World.NPC
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
{ {
ScenePresence sp; ScenePresence sp;
scene.TryGetScenePresence(agentID, out sp); if (scene.TryGetScenePresence(agentID, out sp))
{
// m_log.DebugFormat(
// "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
// sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget);
m_log.DebugFormat( sp.MoveToTarget(pos, noFly, landAtTarget);
"[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}", sp.SetAlwaysRun = running;
sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget);
return true;
sp.MoveToTarget(pos, noFly, landAtTarget); }
sp.SetAlwaysRun = running;
return true;
} }
} }
@ -200,12 +201,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
{ {
ScenePresence sp; ScenePresence sp;
scene.TryGetScenePresence(agentID, out sp); if (scene.TryGetScenePresence(agentID, out sp))
{
sp.Velocity = Vector3.Zero;
sp.ResetMoveToTarget();
sp.Velocity = Vector3.Zero; return true;
sp.ResetMoveToTarget(); }
return true;
} }
} }
@ -223,9 +225,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
{ {
ScenePresence sp;
scene.TryGetScenePresence(agentID, out sp);
m_avatars[agentID].Say(channel, text); m_avatars[agentID].Say(channel, text);
return true; return true;
@ -241,9 +240,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
{ {
ScenePresence sp;
scene.TryGetScenePresence(agentID, out sp);
m_avatars[agentID].Shout(channel, text); m_avatars[agentID].Shout(channel, text);
return true; return true;
@ -260,11 +256,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
{ {
ScenePresence sp; ScenePresence sp;
scene.TryGetScenePresence(agentID, out sp); if (scene.TryGetScenePresence(agentID, out sp))
sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero); {
// sp.HandleAgentSit(m_avatars[agentID], agentID); sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero);
// sp.HandleAgentSit(m_avatars[agentID], agentID);
return true;
return true;
}
} }
} }
@ -277,9 +275,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
{ {
ScenePresence sp;
scene.TryGetScenePresence(agentID, out sp);
m_avatars[agentID].Whisper(channel, text); m_avatars[agentID].Whisper(channel, text);
return true; return true;
@ -296,10 +291,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
{ {
ScenePresence sp; ScenePresence sp;
scene.TryGetScenePresence(agentID, out sp); if (scene.TryGetScenePresence(agentID, out sp))
sp.StandUp(); {
sp.StandUp();
return true; return true;
}
} }
} }
@ -312,6 +309,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
if (m_avatars.ContainsKey(agentID)) if (m_avatars.ContainsKey(agentID))
return m_avatars[agentID].Touch(objectID); return m_avatars[agentID].Touch(objectID);
return false; return false;
} }
} }
@ -322,9 +320,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
{ {
NPCAvatar av; NPCAvatar av;
if (m_avatars.TryGetValue(agentID, out av)) if (m_avatars.TryGetValue(agentID, out av))
{
return av.OwnerID; return av.OwnerID;
}
} }
return UUID.Zero; return UUID.Zero;
@ -352,7 +348,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
scene.RemoveClient(agentID, false); scene.RemoveClient(agentID, false);
m_avatars.Remove(agentID); m_avatars.Remove(agentID);
m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}", agentID, av.Name); // m_log.DebugFormat("[NPC MODULE]: Removed NPC {0} {1}", agentID, av.Name);
return true; return true;
} }
} }

View File

@ -0,0 +1,118 @@
/*
* 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
{
public class BS6DofConstraint : BSConstraint
{
// Create a btGeneric6DofConstraint
public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
Vector3 frame1, Quaternion frame1rot,
Vector3 frame2, Quaternion frame2rot,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
{
m_world = world;
m_body1 = obj1;
m_body2 = obj2;
m_constraint = new BulletConstraint(
BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
frame1, frame1rot,
frame2, frame2rot,
useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
m_enabled = true;
}
public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
Vector3 joinPoint,
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies)
{
m_world = world;
m_body1 = obj1;
m_body2 = obj2;
m_constraint = new BulletConstraint(
BulletSimAPI.Create6DofConstraintToPoint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
joinPoint,
useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies));
m_enabled = true;
}
public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot)
{
bool ret = false;
if (m_enabled)
{
BulletSimAPI.SetFrames2(m_constraint.Ptr, frameA, frameArot, frameB, frameBrot);
ret = true;
}
return ret;
}
public bool SetCFMAndERP(float cfm, float erp)
{
bool ret = false;
if (m_enabled)
{
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
ret = true;
}
return ret;
}
public bool UseFrameOffset(bool useOffset)
{
bool ret = false;
float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
if (m_enabled)
ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
return ret;
}
public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
{
bool ret = false;
float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
if (m_enabled)
ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
return ret;
}
public bool SetBreakingImpulseThreshold(float threshold)
{
bool ret = false;
if (m_enabled)
ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold);
return ret;
}
}
}

View File

@ -40,6 +40,7 @@ public class BSCharacter : PhysicsActor
private static readonly string LogHeader = "[BULLETS CHAR]"; private static readonly string LogHeader = "[BULLETS CHAR]";
private BSScene _scene; private BSScene _scene;
public BSScene Scene { get { return _scene; } }
private String _avName; private String _avName;
// private bool _stopped; // private bool _stopped;
private Vector3 _size; private Vector3 _size;
@ -73,6 +74,12 @@ public class BSCharacter : PhysicsActor
private bool _kinematic; private bool _kinematic;
private float _buoyancy; private float _buoyancy;
private BulletBody m_body;
public BulletBody Body {
get { return m_body; }
set { m_body = value; }
}
private int _subscribedEventsMs = 0; private int _subscribedEventsMs = 0;
private int _nextCollisionOkTime = 0; private int _nextCollisionOkTime = 0;
@ -95,7 +102,9 @@ public class BSCharacter : PhysicsActor
_orientation = Quaternion.Identity; _orientation = Quaternion.Identity;
_velocity = Vector3.Zero; _velocity = Vector3.Zero;
_buoyancy = ComputeBuoyancyFromFlying(isFlying); _buoyancy = ComputeBuoyancyFromFlying(isFlying);
_scale = new Vector3(1f, 1f, 1f); // The dimensions of the avatar capsule are kept in the scale.
// Physics creates a unit capsule which is scaled by the physics engine.
_scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z);
_density = _scene.Params.avatarDensity; _density = _scene.Params.avatarDensity;
ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale
@ -113,9 +122,13 @@ public class BSCharacter : PhysicsActor
shapeData.Restitution = _scene.Params.avatarRestitution; shapeData.Restitution = _scene.Params.avatarRestitution;
// do actual create at taint time // do actual create at taint time
_scene.TaintedObject(delegate() _scene.TaintedObject("BSCharacter.create", delegate()
{ {
BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData);
m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
// avatars get all collisions no matter what
BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
}); });
return; return;
@ -124,7 +137,8 @@ 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()
{ {
_scene.TaintedObject(delegate() // DetailLog("{0},BSCharacter.Destroy", LocalID);
_scene.TaintedObject("BSCharacter.destroy", delegate()
{ {
BulletSimAPI.DestroyObject(_scene.WorldID, _localID); BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
}); });
@ -138,9 +152,28 @@ public class BSCharacter : PhysicsActor
public override bool Stopped { public override bool Stopped {
get { return false; } get { return false; }
} }
public override Vector3 Size { public override Vector3 Size {
get { return _size; } get
set { _size = value; {
// Avatar capsule size is kept in the scale parameter.
return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z);
}
set {
// When an avatar's size is set, only the height is changed
// and that really only depends on the radius.
_size = value;
_scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y);
// TODO: something has to be done with the avatar's vertical position
ComputeAvatarVolumeAndMass();
_scene.TaintedObject("BSCharacter.setSize", delegate()
{
BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true);
});
} }
} }
public override PrimitiveBaseShape Shape { public override PrimitiveBaseShape Shape {
@ -172,12 +205,37 @@ public class BSCharacter : PhysicsActor
} }
set { set {
_position = value; _position = value;
_scene.TaintedObject(delegate() PositionSanityCheck();
_scene.TaintedObject("BSCharacter.setPosition", delegate()
{ {
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);
}); });
} }
} }
// Check that the current position is sane and, if not, modify the position to make it so.
// Check for being below terrain and being out of bounds.
// Returns 'true' of the position was made sane by some action.
private bool PositionSanityCheck()
{
bool ret = false;
// If below the ground, move the avatar up
float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position);
if (_position.Z < terrainHeight)
{
DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation);
_position.Z = terrainHeight + 2.0f;
ret = true;
}
// TODO: check for out of bounds
return ret;
}
public override float Mass { public override float Mass {
get { get {
return _mass; return _mass;
@ -188,9 +246,10 @@ public class BSCharacter : PhysicsActor
set { set {
_force = value; _force = value;
// m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
_scene.TaintedObject(delegate() Scene.TaintedObject("BSCharacter.SetForce", delegate()
{ {
BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force);
}); });
} }
} }
@ -214,8 +273,9 @@ public class BSCharacter : PhysicsActor
set { set {
_velocity = value; _velocity = value;
// m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
_scene.TaintedObject(delegate() _scene.TaintedObject("BSCharacter.setVelocity", delegate()
{ {
DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity);
}); });
} }
@ -239,7 +299,7 @@ public class BSCharacter : PhysicsActor
set { set {
_orientation = value; _orientation = value;
// m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
_scene.TaintedObject(delegate() _scene.TaintedObject("BSCharacter.setOrientation", delegate()
{ {
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
@ -259,9 +319,12 @@ public class BSCharacter : PhysicsActor
public override bool Flying { public override bool Flying {
get { return _flying; } get { return _flying; }
set { set {
_flying = value; if (_flying != value)
// simulate flying by changing the effect of gravity {
this.Buoyancy = ComputeBuoyancyFromFlying(_flying); _flying = value;
// simulate flying by changing the effect of gravity
this.Buoyancy = ComputeBuoyancyFromFlying(_flying);
}
} }
} }
private float ComputeBuoyancyFromFlying(bool ifFlying) { private float ComputeBuoyancyFromFlying(bool ifFlying) {
@ -303,8 +366,9 @@ public class BSCharacter : PhysicsActor
public override float Buoyancy { public override float Buoyancy {
get { return _buoyancy; } get { return _buoyancy; }
set { _buoyancy = value; set { _buoyancy = value;
_scene.TaintedObject(delegate() _scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
{ {
DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
}); });
} }
@ -349,9 +413,10 @@ public class BSCharacter : PhysicsActor
_force.Y += force.Y; _force.Y += force.Y;
_force.Z += force.Z; _force.Z += force.Z;
// 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(delegate() _scene.TaintedObject("BSCharacter.AddForce", delegate()
{ {
BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
BulletSimAPI.AddObjectForce2(Body.Ptr, _force);
}); });
} }
else else
@ -369,11 +434,25 @@ public class BSCharacter : PhysicsActor
// Turn on collision events at a rate no faster than one every the given milliseconds // Turn on collision events at a rate no faster than one every the given milliseconds
public override void SubscribeEvents(int ms) { public override void SubscribeEvents(int ms) {
_subscribedEventsMs = ms; _subscribedEventsMs = ms;
_nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; // make first collision happen if (ms > 0)
{
// make sure first collision happens
_nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate()
{
BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
});
}
} }
// Stop collision events // Stop collision events
public override void UnSubscribeEvents() { public override void UnSubscribeEvents() {
_subscribedEventsMs = 0; _subscribedEventsMs = 0;
// Avatars get all their collision events
// Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate()
// {
// BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
// });
} }
// Return 'true' if someone has subscribed to events // Return 'true' if someone has subscribed to events
public override bool SubscribedEvents() { public override bool SubscribedEvents() {
@ -385,9 +464,15 @@ public class BSCharacter : PhysicsActor
{ {
_avatarVolume = (float)( _avatarVolume = (float)(
Math.PI Math.PI
* _scene.Params.avatarCapsuleRadius * _scale.X * _scale.X
* _scene.Params.avatarCapsuleRadius * _scale.Y * _scale.Y // the area of capsule cylinder
* _scene.Params.avatarCapsuleHeight * _scale.Z); * _scale.Z // times height of capsule cylinder
+ 1.33333333f
* Math.PI
* _scale.X
* Math.Min(_scale.X, _scale.Y)
* _scale.Y // plus the volume of the capsule end caps
);
_mass = _density * _avatarVolume; _mass = _density * _avatarVolume;
} }
@ -395,43 +480,19 @@ public class BSCharacter : PhysicsActor
// the world that things have changed. // the world that things have changed.
public void UpdateProperties(EntityProperties entprop) public void UpdateProperties(EntityProperties entprop)
{ {
/*
bool changed = false;
// we assign to the local variables so the normal set action does not happen
if (_position != entprop.Position) {
_position = entprop.Position;
changed = true;
}
if (_orientation != entprop.Rotation) {
_orientation = entprop.Rotation;
changed = true;
}
if (_velocity != entprop.Velocity) {
_velocity = entprop.Velocity;
changed = true;
}
if (_acceleration != entprop.Acceleration) {
_acceleration = entprop.Acceleration;
changed = true;
}
if (_rotationalVelocity != entprop.RotationalVelocity) {
_rotationalVelocity = entprop.RotationalVelocity;
changed = true;
}
if (changed) {
// m_log.DebugFormat("{0}: UpdateProperties: id={1}, c={2}, pos={3}, rot={4}", LogHeader, LocalID, changed, _position, _orientation);
// Avatar movement is not done by generating this event. There is code in the heartbeat
// loop that updates avatars.
// base.RequestPhysicsterseUpdate();
}
*/
_position = entprop.Position; _position = entprop.Position;
_orientation = entprop.Rotation; _orientation = entprop.Rotation;
_velocity = entprop.Velocity; _velocity = entprop.Velocity;
_acceleration = entprop.Acceleration; _acceleration = entprop.Acceleration;
_rotationalVelocity = entprop.RotationalVelocity; _rotationalVelocity = entprop.RotationalVelocity;
// Avatars don't report theirr changes the usual way. Changes are checked for in the heartbeat loop. // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
// base.RequestPhysicsterseUpdate(); // base.RequestPhysicsterseUpdate();
/*
DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
entprop.Acceleration, entprop.RotationalVelocity);
*/
} }
// Called by the scene when a collision with this object is reported // Called by the scene when a collision with this object is reported
@ -448,6 +509,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) {
@ -476,9 +538,17 @@ 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
} }
// Invoke the detailed logger and output something if it's enabled.
private void DetailLog(string msg, params Object[] args)
{
Scene.PhysicsLogging.Write(msg, args);
}
} }
} }

View File

@ -32,35 +32,26 @@ using OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin namespace OpenSim.Region.Physics.BulletSPlugin
{ {
public class BSConstraint : IDisposable public abstract class BSConstraint : IDisposable
{ {
private BulletSim m_world; protected BulletSim m_world;
private BulletBody m_body1; protected BulletBody m_body1;
private BulletBody m_body2; protected BulletBody m_body2;
private BulletConstraint m_constraint; protected BulletConstraint m_constraint;
private bool m_enabled = false; protected bool m_enabled = false;
public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, public BSConstraint()
Vector3 frame1, Quaternion frame1rot,
Vector3 frame2, Quaternion frame2rot
)
{ {
m_world = world;
m_body1 = obj1;
m_body2 = obj2;
m_constraint = new BulletConstraint(BulletSimAPI.CreateConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr,
frame1, frame1rot,
frame2, frame2rot,
true /*useLinearReferenceFrameA*/, true /*disableCollisionsBetweenLinkedBodies*/));
m_enabled = true;
} }
public void Dispose() public virtual void Dispose()
{ {
if (m_enabled) if (m_enabled)
{ {
// BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID); // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr); bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success);
m_constraint.Ptr = System.IntPtr.Zero;
m_enabled = false; m_enabled = false;
} }
} }
@ -68,7 +59,7 @@ public class BSConstraint : IDisposable
public BulletBody Body1 { get { return m_body1; } } public BulletBody Body1 { get { return m_body1; } }
public BulletBody Body2 { get { return m_body2; } } public BulletBody Body2 { get { return m_body2; } }
public bool SetLinearLimits(Vector3 low, Vector3 high) public virtual bool SetLinearLimits(Vector3 low, Vector3 high)
{ {
bool ret = false; bool ret = false;
if (m_enabled) if (m_enabled)
@ -76,7 +67,7 @@ public class BSConstraint : IDisposable
return ret; return ret;
} }
public bool SetAngularLimits(Vector3 low, Vector3 high) public virtual bool SetAngularLimits(Vector3 low, Vector3 high)
{ {
bool ret = false; bool ret = false;
if (m_enabled) if (m_enabled)
@ -84,42 +75,38 @@ public class BSConstraint : IDisposable
return ret; return ret;
} }
public bool SetCFMAndERP(float cfm, float erp) public virtual bool CalculateTransforms()
{
bool ret = true;
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
return ret;
}
public bool UseFrameOffset(bool useOffset)
{
bool ret = false;
float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
if (m_enabled)
ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff);
return ret;
}
public bool TranslationalLimitMotor(bool enable, float targetVelocity, float maxMotorForce)
{
bool ret = false;
float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse;
if (m_enabled)
ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce);
return ret;
}
public bool CalculateTransforms()
{ {
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

@ -56,29 +56,25 @@ public class BSConstraintCollection : IDisposable
public void Clear() public void Clear()
{ {
foreach (BSConstraint cons in m_constraints) lock (m_constraints)
{ {
cons.Dispose(); foreach (BSConstraint cons in m_constraints)
{
cons.Dispose();
}
m_constraints.Clear();
} }
m_constraints.Clear();
}
public BSConstraint CreateConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
Vector3 frame1, Quaternion frame1rot,
Vector3 frame2, Quaternion frame2rot)
{
BSConstraint constrain = new BSConstraint(world, obj1, obj2, frame1, frame1rot, frame2, frame2rot);
this.AddConstraint(constrain);
return constrain;
} }
public bool AddConstraint(BSConstraint cons) public bool AddConstraint(BSConstraint cons)
{ {
// There is only one constraint between any bodies. Remove any old just to make sure. lock (m_constraints)
RemoveAndDestroyConstraint(cons.Body1, cons.Body2); {
// There is only one constraint between any bodies. Remove any old just to make sure.
RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
m_constraints.Add(cons); m_constraints.Add(cons);
}
return true; return true;
} }
@ -92,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)
{ {
if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2) foreach (BSConstraint constrain in m_constraints)
|| (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
{ {
foundConstraint = constrain; if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
found = true; || (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
{
foundConstraint = constrain;
found = true;
break;
}
} }
return found; }
});
returnConstraint = foundConstraint; returnConstraint = foundConstraint;
return found; return found;
} }
@ -111,24 +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;
BSConstraint constrain; lock (m_constraints)
if (this.TryGetConstraint(body1, body2, out constrain))
{ {
// remove the constraint from our collection BSConstraint constrain;
m_constraints.Remove(constrain); if (this.TryGetConstraint(body1, body2, out constrain))
// tell the engine that all its structures need to be freed {
constrain.Dispose(); // remove the constraint from our collection
// we destroyed something RemoveAndDestroyConstraint(constrain);
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)
@ -137,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)
{
if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
{
toRemove.Add(constrain);
}
return false;
});
lock (m_constraints) lock (m_constraints)
{ {
foreach (BSConstraint constrain in m_constraints)
{
if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
{
toRemove.Add(constrain);
}
}
foreach (BSConstraint constrain in toRemove) foreach (BSConstraint constrain in toRemove)
{ {
m_constraints.Remove(constrain); m_constraints.Remove(constrain);
@ -158,27 +167,16 @@ public class BSConstraintCollection : IDisposable
public bool RecalculateAllConstraints() public bool RecalculateAllConstraints()
{ {
foreach (BSConstraint constrain in m_constraints) bool ret = false;
{
constrain.CalculateTransforms();
}
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

@ -613,7 +613,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}", DetailLog("{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

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,10 +37,12 @@ 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 PhysicsScene { get { return m_physicsScene; } }
// 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.
@ -72,7 +74,7 @@ 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; 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;
@ -80,16 +82,19 @@ public class BSLinkset
// Link to a linkset where the child knows the parent. // Link to a linkset where the child knows the parent.
// Parent changing should not happen so do some sanity checking. // Parent changing should not happen so do some sanity checking.
// We return the parent's linkset so the child can track it's membership. // We return the parent's linkset so the child can track its membership.
public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent) public BSLinkset AddMeToLinkset(BSPrim child)
{ {
lock (m_linksetActivityLock) lock (m_linksetActivityLock)
{ {
parent.Linkset.AddChildToLinkset(child); AddChildToLinkset(child);
} }
return parent.Linkset; 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)
@ -101,7 +106,7 @@ public class BSLinkset
{ {
// Note that we don't do a foreach because the remove routine // Note that we don't do a foreach because the remove routine
// takes it out of the list. // takes it out of the list.
RemoveChildFromLinkset(m_children[0]); RemoveChildFromOtherLinkset(m_children[0]);
} }
m_children.Clear(); // just to make sure m_children.Clear(); // just to make sure
} }
@ -113,63 +118,17 @@ 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(m_scene, child); return new BSLinkset(PhysicsScene, child);
} }
// 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)
{
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)
{
RemoveChildFromLinkset(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)
{ {
return (requestor.LocalID == m_linksetRoot.LocalID); return (requestor.LocalID == m_linksetRoot.LocalID);
} }
public int NumberOfChildren { get { return m_children.Count; } }
// Return 'true' if this linkset has any children (more than the root member) // Return 'true' if this linkset has any children (more than the root member)
public bool HasAnyChildren { get { return (m_children.Count > 0); } } public bool HasAnyChildren { get { return (m_children.Count > 0); } }
@ -177,12 +136,15 @@ public class BSLinkset
public bool HasChild(BSPrim child) public bool HasChild(BSPrim child)
{ {
bool ret = false; bool ret = false;
foreach (BSPrim bp in m_children) lock (m_linksetActivityLock)
{ {
if (child.LocalID == bp.LocalID) foreach (BSPrim bp in m_children)
{ {
ret = true; if (child.LocalID == bp.LocalID)
break; {
ret = true;
break;
}
} }
} }
return ret; return ret;
@ -203,12 +165,16 @@ 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;
foreach (BSPrim bp in m_children) lock (m_linksetActivityLock)
{ {
com += bp.Position * bp.MassRaw; foreach (BSPrim bp in m_children)
totalMass += bp.MassRaw; {
com += bp.Position * bp.MassRaw;
totalMass += bp.MassRaw;
}
if (totalMass != 0f)
com /= totalMass;
} }
com /= totalMass;
return com; return com;
} }
@ -217,135 +183,237 @@ public class BSLinkset
{ {
OMV.Vector3 com = m_linksetRoot.Position; OMV.Vector3 com = m_linksetRoot.Position;
foreach (BSPrim bp in m_children) lock (m_linksetActivityLock)
{ {
com += bp.Position * bp.MassRaw; foreach (BSPrim bp in m_children)
{
com += bp.Position * bp.MassRaw;
}
com /= (m_children.Count + 1);
} }
com /= m_children.Count + 1;
return com; return com;
} }
// I am the root of a linkset and a new child is being added // When physical properties are changed the linkset needs to recalculate
public void AddChildToLinkset(BSPrim pchild) // its internal properties.
public void Refresh(BSPrim requestor)
{
// If there are no children, there aren't any constraints to recompute
if (!HasAnyChildren)
return;
// Only the root does the recomputation
if (IsRoot(requestor))
{
PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate()
{
RecomputeLinksetConstraintVariables();
});
}
}
// Call each of the constraints that make up this linkset and recompute the
// various transforms and variables. Used when objects are added or removed
// from a linkset to make sure the constraints know about the new mass and
// geometry.
// Must only be called at taint time!!
private bool RecomputeLinksetConstraintVariables()
{
float linksetMass = LinksetMass;
lock (m_linksetActivityLock)
{
foreach (BSPrim child in m_children)
{
BSConstraint constrain;
if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain))
{
// DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}",
// LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID);
constrain.RecomputeConstraintVariables(linksetMass);
}
else
{
// Non-fatal error that can happen when children are being added to the linkset but
// their constraints have not been created yet.
// Caused by the fact that m_children is built at run time but building constraints
// happens at taint time.
// m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}",
// m_linksetRoot.Body.ID, child.Body.ID);
}
}
}
return false;
}
// I am the root of a linkset and a new child is being added
// Called while LinkActivity is locked.
private void AddChildToLinkset(BSPrim child)
{ {
BSPrim child = pchild;
if (!HasChild(child)) if (!HasChild(child))
{ {
m_children.Add(child); m_children.Add(child);
m_scene.TaintedObject(delegate() BSPrim rootx = LinksetRoot; // capture the root as of now
BSPrim childx = child;
m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
{ {
DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID);
DetailLog("{0},AddChildToLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child
}); });
} }
return; return;
} }
// Forcefully removing a child from a linkset.
// This is not being called by the child so we have to make sure the child doesn't think
// it's still connected to the linkset.
// Normal OpenSimulator operation will never do this because other SceneObjectPart information
// has to be updated also (like pointer to prim's parent).
private void RemoveChildFromOtherLinkset(BSPrim pchild)
{
pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
RemoveChildFromLinkset(pchild);
}
// I am the root of a linkset and one of my children is being removed. // 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 pchild) private void RemoveChildFromLinkset(BSPrim child)
{ {
BSPrim child = pchild;
if (m_children.Remove(child)) if (m_children.Remove(child))
{ {
m_scene.TaintedObject(delegate() BSPrim rootx = LinksetRoot; // capture the root as of now
BSPrim childx = child;
m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
{ {
DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID);
DetailLog("{0},RemoveChildFromLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID); // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
if (m_children.Count == 0) PhysicallyUnlinkAChildFromRoot(rootx, childx);
{
// if the linkset is empty, make sure all linkages have been removed
PhysicallyUnlinkAllChildrenFromRoot();
}
else
{
PhysicallyUnlinkAChildFromRoot(pchild);
}
}); });
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;
} }
// Create a constraint between me (root of linkset) and the passed prim (the child). // Create a constraint between me (root of linkset) and the passed prim (the child).
// Called at taint time! // Called at taint time!
private void PhysicallyLinkAChildToRoot(BSPrim childPrim) private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim)
{ {
// 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 // Relative position normalized to the root prim
OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation); // Essentually a vector pointing from center of rootPrim to center of childPrim
OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation; OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;
// relative rotation of the child to the parent // real world coordinate of midpoint between the two objects
OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
// 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); // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
DetailLog("{0},LinkAChildToMe,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}",
BSConstraint constrain = m_scene.Constraints.CreateConstraint( rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint);
m_scene.World, m_linksetRoot.Body, childPrim.Body, BS6DofConstraint constrain = new BS6DofConstraint(
// childRelativePosition, m_physicsScene.World, rootPrim.Body, childPrim.Body,
// childRelativeRotation, midPoint,
OMV.Vector3.Zero, true,
OMV.Quaternion.Identity, true
OMV.Vector3.Zero,
OMV.Quaternion.Identity
); );
/* NOTE: 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 here as an example.
// ==================================================================================
// relative position normalized to the root prim
OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
// relative rotation of the child to the parent
OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
// create a constraint that allows no freedom of movement between the two objects
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
// DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID);
DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
BS6DofConstraint constrain = new BS6DofConstraint(
PhysicsScene.World, rootPrim.Body, childPrim.Body,
OMV.Vector3.Zero,
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_physicsScene.Constraints.AddConstraint(constrain);
// zero linear and angular limits makes the objects unable to move in relation to each other
constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); constrain.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 childPrim) private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim)
{ {
DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
LogHeader, m_linksetRoot.LocalID, childPrim.LocalID); // LogHeader, rootPrim.LocalID, childPrim.LocalID);
DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID); DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
// BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID);
m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body, childPrim.Body); // Find the constraint for this link and get rid of it from the overall collection and from my list
m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body);
// Make the child refresh its location
BulletSimAPI.PushUpdate2(childPrim.Body.Ptr);
} }
// Remove linkage between myself and any possible children I might have // Remove linkage between myself and any possible children I might have
// Called at taint time! // Called at taint time!
private void PhysicallyUnlinkAllChildrenFromRoot() private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim)
{ {
// DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID); DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body);
// BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID); m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body);
} }
// Invoke the detailed logger and output something if it's enabled. // Invoke the detailed logger and output something if it's enabled.
private void DebugLog(string msg, params Object[] args) private void DebugLog(string msg, params Object[] args)
{ {
m_scene.Logger.DebugFormat(msg, args); if (m_physicsScene.ShouldDebugLog)
m_physicsScene.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,7 +42,7 @@ 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 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;
@ -138,14 +138,15 @@ public sealed class BSPrim : PhysicsActor
_isPhysical = pisPhysical; _isPhysical = pisPhysical;
_isVolumeDetect = false; _isVolumeDetect = false;
_subscribedEventsMs = 0; _subscribedEventsMs = 0;
_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(this); // add vehicleness
_mass = CalculateMass(); _mass = CalculateMass();
// do the actual object creation at taint time // do the actual object creation at taint time
_scene.TaintedObject(delegate() DetailLog("{0},BSPrim.constructor,call", LocalID);
_scene.TaintedObject("BSPrim.create", delegate()
{ {
RecreateGeomAndObject(); RecreateGeomAndObject();
@ -160,17 +161,22 @@ public sealed class BSPrim : PhysicsActor
public void Destroy() public void Destroy()
{ {
// m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
// DetailLog("{0},Destroy", LocalID);
// Undo any links between me and any other object
BSPrim parentBefore = _linkset.LinksetRoot;
int childrenBefore = _linkset.NumberOfChildren;
_linkset = _linkset.RemoveMeFromLinkset(this);
DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}",
LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
// Undo any vehicle properties // Undo any vehicle properties
_vehicle.ProcessTypeChange(Vehicle.TYPE_NONE); this.VehicleType = (int)Vehicle.TYPE_NONE;
_scene.RemoveVehiclePrim(this); // just to make sure
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.destroy", delegate()
{ {
// Undo any links between me and any other object DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
_linkset = _linkset.RemoveMeFromLinkset(this);
// everything in the C# world will get garbage collected. Tell the C++ world to free stuff. // everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); BulletSimAPI.DestroyObject(_scene.WorldID, LocalID);
}); });
@ -183,11 +189,11 @@ public sealed class BSPrim : PhysicsActor
get { return _size; } get { return _size; }
set { set {
_size = value; _size = value;
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.setSize", delegate()
{ {
_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}: 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();
}); });
} }
@ -195,7 +201,7 @@ public sealed class BSPrim : PhysicsActor
public override PrimitiveBaseShape Shape { public override PrimitiveBaseShape Shape {
set { set {
_pbs = value; _pbs = value;
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.setShape", delegate()
{ {
_mass = CalculateMass(); // changing the shape changes the mass _mass = CalculateMass(); // changing the shape changes the mass
RecreateGeomAndObject(); RecreateGeomAndObject();
@ -213,7 +219,7 @@ public sealed class BSPrim : PhysicsActor
public override bool Selected { public override bool Selected {
set { set {
_isSelected = value; _isSelected = value;
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.setSelected", delegate()
{ {
SetObjectDynamic(); SetObjectDynamic();
}); });
@ -224,10 +230,17 @@ public sealed class BSPrim : PhysicsActor
// link me to the specified parent // link me to the specified parent
public override void link(PhysicsActor obj) { public override void link(PhysicsActor obj) {
BSPrim parent = obj as BSPrim; BSPrim parent = obj as BSPrim;
DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID); if (parent != null)
DetailLog("{0},link,parent={1}", LocalID, obj.LocalID); {
DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID);
BSPrim parentBefore = _linkset.LinksetRoot;
int childrenBefore = _linkset.NumberOfChildren;
_linkset = _linkset.AddMeToLinkset(this, parent); _linkset = parent.Linkset.AddMeToLinkset(this);
DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
}
return; return;
} }
@ -236,10 +249,15 @@ public sealed class BSPrim : PhysicsActor
// 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, DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
_linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString()); _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString());
DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString());
_linkset.RemoveMeFromLinkset(this); BSPrim parentBefore = _linkset.LinksetRoot;
int childrenBefore = _linkset.NumberOfChildren;
_linkset = _linkset.RemoveMeFromLinkset(this);
DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren);
return; return;
} }
@ -262,7 +280,7 @@ public sealed class BSPrim : PhysicsActor
public override void LockAngularMotion(OMV.Vector3 axis) public override void LockAngularMotion(OMV.Vector3 axis)
{ {
DetailLog("{0},LockAngularMotion,call,axis={1}", LocalID, axis); // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
return; return;
} }
@ -279,9 +297,9 @@ public sealed class BSPrim : PhysicsActor
set { set {
_position = value; _position = value;
// TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint?
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.setPosition", delegate()
{ {
DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
}); });
} }
@ -316,9 +334,9 @@ public sealed class BSPrim : PhysicsActor
get { return _force; } get { return _force; }
set { set {
_force = value; _force = value;
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.setForce", delegate()
{ {
DetailLog("{0},SetForce,taint,force={1}", LocalID, _force); // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force);
// BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force);
BulletSimAPI.SetObjectForce2(Body.Ptr, _force); BulletSimAPI.SetObjectForce2(Body.Ptr, _force);
}); });
@ -331,53 +349,41 @@ public sealed class BSPrim : PhysicsActor
} }
set { set {
Vehicle type = (Vehicle)value; Vehicle type = (Vehicle)value;
_scene.TaintedObject(delegate() BSPrim vehiclePrim = this;
_scene.TaintedObject("setVehicleType", delegate()
{ {
DetailLog("{0},SetVehicleType,taint,type={1}", LocalID, type); // Done at taint time so we're sure the physics engine is not using the variables
// Vehicle code changes the parameters for this vehicle type.
_vehicle.ProcessTypeChange(type); _vehicle.ProcessTypeChange(type);
if (type == Vehicle.TYPE_NONE) // Tell the scene about the vehicle so it will get processing each frame.
{ _scene.VehicleInSceneTypeChanged(this, type);
_scene.RemoveVehiclePrim(this);
}
else
{
_scene.TaintedObject(delegate()
{
// Tell the physics engine to clear state
BulletSimAPI.ClearForces2(this.Body.Ptr);
});
// make it so the scene will call us each tick to do vehicle things
_scene.AddVehiclePrim(this);
}
return;
}); });
} }
} }
public override void VehicleFloatParam(int param, float value) public override void VehicleFloatParam(int param, float value)
{ {
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
{ {
_vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
}); });
} }
public override void VehicleVectorParam(int param, OMV.Vector3 value) public override void VehicleVectorParam(int param, OMV.Vector3 value)
{ {
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
{ {
_vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
}); });
} }
public override void VehicleRotationParam(int param, OMV.Quaternion rotation) public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
{ {
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
{ {
_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
}); });
} }
public override void VehicleFlags(int param, bool remove) public override void VehicleFlags(int param, bool remove)
{ {
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.VehicleFlags", delegate()
{ {
_vehicle.ProcessVehicleFlags(param, remove); _vehicle.ProcessVehicleFlags(param, remove);
}); });
@ -395,7 +401,7 @@ public sealed class BSPrim : PhysicsActor
public override void SetVolumeDetect(int param) { public override void SetVolumeDetect(int param) {
bool newValue = (param != 0); bool newValue = (param != 0);
_isVolumeDetect = newValue; _isVolumeDetect = newValue;
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
{ {
SetObjectDynamic(); SetObjectDynamic();
}); });
@ -406,9 +412,9 @@ public sealed class BSPrim : PhysicsActor
get { return _velocity; } get { return _velocity; }
set { set {
_velocity = value; _velocity = value;
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.setVelocity", delegate()
{ {
DetailLog("{0},SetVelocity,taint,vel={1}", LocalID, _velocity); // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity);
BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity);
}); });
} }
@ -416,7 +422,7 @@ public sealed class BSPrim : PhysicsActor
public override OMV.Vector3 Torque { public override OMV.Vector3 Torque {
get { return _torque; } get { return _torque; }
set { _torque = value; set { _torque = value;
DetailLog("{0},SetTorque,call,torque={1}", LocalID, _torque); // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
} }
} }
public override float CollisionScore { public override float CollisionScore {
@ -440,10 +446,10 @@ public sealed class BSPrim : PhysicsActor
set { set {
_orientation = value; _orientation = value;
// TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.setOrientation", delegate()
{ {
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
DetailLog("{0},SetOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
}); });
} }
@ -457,7 +463,7 @@ public sealed class BSPrim : PhysicsActor
get { return _isPhysical; } get { return _isPhysical; }
set { set {
_isPhysical = value; _isPhysical = value;
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.setIsPhysical", delegate()
{ {
SetObjectDynamic(); SetObjectDynamic();
}); });
@ -478,7 +484,6 @@ public sealed class BSPrim : PhysicsActor
// Make gravity work if the object is physical and not selected // Make gravity work if the object is physical and not selected
// No locking here because only called when it is safe // No locking here because only called when it is safe
// Only called at taint time so it is save to call into Bullet.
private void SetObjectDynamic() private void SetObjectDynamic()
{ {
// RA: remove this for the moment. // RA: remove this for the moment.
@ -487,13 +492,16 @@ public sealed class BSPrim : PhysicsActor
// Maybe a VerifyCorrectPhysicalShape() routine? // Maybe a VerifyCorrectPhysicalShape() routine?
// RecreateGeomAndObject(); // RecreateGeomAndObject();
float mass = _mass; // Bullet wants static objects to have a mass of zero
// Bullet wants static objects have a mass of zero float mass = IsStatic ? 0f : _mass;
if (IsStatic)
mass = 0f;
DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, 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);
// DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf);
} }
// prims don't fly // prims don't fly
@ -548,9 +556,9 @@ public sealed class BSPrim : PhysicsActor
set { set {
_rotationalVelocity = value; _rotationalVelocity = value;
// m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity);
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate()
{ {
DetailLog("{0},SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity);
BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity);
}); });
} }
@ -565,9 +573,9 @@ public sealed class BSPrim : PhysicsActor
get { return _buoyancy; } get { return _buoyancy; }
set { set {
_buoyancy = value; _buoyancy = value;
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.setBuoyancy", delegate()
{ {
DetailLog("{0},SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy);
}); });
} }
@ -607,6 +615,7 @@ public sealed class BSPrim : PhysicsActor
private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>(); private List<OMV.Vector3> m_accumulatedForces = new List<OMV.Vector3>();
public override void AddForce(OMV.Vector3 force, bool pushforce) { public override void AddForce(OMV.Vector3 force, bool pushforce) {
// for an object, doesn't matter if force is a pushforce or not
if (force.IsFinite()) if (force.IsFinite())
{ {
// _force += force; // _force += force;
@ -618,40 +627,48 @@ public sealed class BSPrim : PhysicsActor
m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
return; return;
} }
_scene.TaintedObject(delegate() _scene.TaintedObject("BSPrim.AddForce", delegate()
{ {
OMV.Vector3 fSum = OMV.Vector3.Zero;
lock (m_accumulatedForces) lock (m_accumulatedForces)
{ {
if (m_accumulatedForces.Count > 0) foreach (OMV.Vector3 v in m_accumulatedForces)
{ {
OMV.Vector3 fSum = OMV.Vector3.Zero; fSum += v;
foreach (OMV.Vector3 v in m_accumulatedForces)
{
fSum += v;
}
m_accumulatedForces.Clear();
DetailLog("{0},SetObjectForce,taint,force={1}", LocalID, fSum);
BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, fSum);
} }
m_accumulatedForces.Clear();
} }
// DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force);
BulletSimAPI.AddObjectForce2(Body.Ptr, fSum);
}); });
} }
public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { public override void AddAngularForce(OMV.Vector3 force, bool pushforce) {
DetailLog("{0},AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce);
// m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce);
} }
public override void SetMomentum(OMV.Vector3 momentum) { public override void SetMomentum(OMV.Vector3 momentum) {
DetailLog("{0},SetMomentum,call,mom={1}", LocalID, momentum); // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum);
} }
public override void SubscribeEvents(int ms) { public override void SubscribeEvents(int ms) {
_subscribedEventsMs = ms; _subscribedEventsMs = ms;
// make sure first collision happens if (ms > 0)
_nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; {
// make sure first collision happens
_nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
{
BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
});
}
} }
public override void UnSubscribeEvents() { public override void UnSubscribeEvents() {
_subscribedEventsMs = 0; _subscribedEventsMs = 0;
Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate()
{
BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
});
} }
public override bool SubscribedEvents() { public override bool SubscribedEvents() {
return (_subscribedEventsMs > 0); return (_subscribedEventsMs > 0);
@ -970,26 +987,26 @@ public sealed class BSPrim : PhysicsActor
{ {
if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1)
{ {
if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z)
{ // {
// m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size);
if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
{ {
DetailLog("{0},CreateGeom,sphere", LocalID); // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild);
_shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE;
// Bullet native objects are scaled by the Bullet engine so pass the size in // Bullet native objects are scaled by the Bullet engine so pass the size in
_scale = _size; _scale = _size;
// TODO: do we need to check for and destroy a mesh or hull that might have been left from before? // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
ret = true; ret = true;
} }
} // }
} }
else else
{ {
// m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX))
{ {
DetailLog("{0},CreateGeom,box", LocalID); // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
_shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
_scale = _size; _scale = _size;
// TODO: do we need to check for and destroy a mesh or hull that might have been left from before? // TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
@ -1032,12 +1049,12 @@ public sealed class BSPrim : PhysicsActor
// if this new shape is the same as last time, don't recreate the mesh // if this new shape is the same as last time, don't recreate the mesh
if (_meshKey == newMeshKey) return; if (_meshKey == newMeshKey) return;
DetailLog("{0},CreateGeomMesh,create,key={1}", LocalID, _meshKey); // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey);
// 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 (_meshKey != 0) if (_meshKey != 0)
{ {
// m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey);
DetailLog("{0},CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey);
BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey);
_mesh = null; _mesh = null;
_meshKey = 0; _meshKey = 0;
@ -1067,7 +1084,7 @@ public sealed class BSPrim : PhysicsActor
_shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
// meshes are already scaled by the meshmerizer // meshes are already scaled by the meshmerizer
_scale = new OMV.Vector3(1f, 1f, 1f); _scale = new OMV.Vector3(1f, 1f, 1f);
DetailLog("{0},CreateGeomMesh,done", LocalID); // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID);
return; return;
} }
@ -1081,28 +1098,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},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},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},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();
@ -1128,7 +1138,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
@ -1188,7 +1198,7 @@ public sealed class BSPrim : PhysicsActor
_shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
// meshes are already scaled by the meshmerizer // meshes are already scaled by the meshmerizer
_scale = new OMV.Vector3(1f, 1f, 1f); _scale = new OMV.Vector3(1f, 1f, 1f);
DetailLog("{0},CreateGeomHull,done", LocalID); // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
return; return;
} }
@ -1214,7 +1224,7 @@ public sealed class BSPrim : PhysicsActor
bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
// the CreateObject() may have recreated the rigid body. Make sure we have the latest. // the CreateObject() may have recreated the rigid body. Make sure we have the latest.
m_body.Ptr = BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID); Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
return ret; return ret;
} }
@ -1326,8 +1336,8 @@ public sealed class BSPrim : PhysicsActor
// m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", // 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); // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
DetailLog("{0},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();
} }
@ -1335,7 +1345,7 @@ public sealed class BSPrim : PhysicsActor
else else
{ {
// For debugging, we also report the movement of children // For debugging, we also report the movement of children
DetailLog("{0},UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}",
LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, LocalID, entprop.Position, entprop.Rotation, entprop.Velocity,
entprop.Acceleration, entprop.RotationalVelocity); entprop.Acceleration, entprop.RotationalVelocity);
} }
@ -1343,7 +1353,7 @@ public sealed class BSPrim : PhysicsActor
} }
// I've collided with something // I've collided with something
CollisionEventUpdate collisionCollection = null; 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);
@ -1355,6 +1365,8 @@ public sealed class BSPrim : PhysicsActor
_collidingGroundStep = _scene.SimulationStep; _collidingGroundStep = _scene.SimulationStep;
} }
// DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
// 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
@ -1375,7 +1387,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,7 +73,7 @@ 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); } public void DebugLog(string mm, params Object[] xx) { if (ShouldDebugLog) m_log.DebugFormat(mm, xx); }
public string BulletSimVersion = "?"; public string BulletSimVersion = "?";
@ -162,14 +162,24 @@ public class BSScene : PhysicsScene, IPhysicsParameters
} }
public delegate void TaintCallback(); public delegate void TaintCallback();
private List<TaintCallback> _taintedObjects; private struct TaintCallbackEntry
{
public String ident;
public TaintCallback callback;
public TaintCallbackEntry(string i, TaintCallback c)
{
ident = i;
callback = c;
}
}
private List<TaintCallbackEntry> _taintedObjects;
private Object _taintLock = new Object(); private Object _taintLock = new Object();
// A pointer to an instance if this structure is passed to the C++ code // A pointer to an instance if this structure is passed to the C++ code
ConfigurationParameters[] m_params; ConfigurationParameters[] m_params;
GCHandle m_paramsHandle; GCHandle m_paramsHandle;
public bool shouldDebugLog { get; private set; } public bool ShouldDebugLog { get; private set; }
private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
@ -232,7 +242,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
} }
_taintedObjects = new List<TaintCallback>(); _taintedObjects = new List<TaintCallbackEntry>();
mesher = meshmerizer; mesher = meshmerizer;
// The bounding box for the simulated world // The bounding box for the simulated world
@ -245,7 +255,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
// Initialization to support the transition to a new API which puts most of the logic // Initialization to support the transition to a new API which puts most of the logic
// into the C# code so it is easier to modify and add to. // into the C# code so it is easier to modify and add to.
m_worldSim = new BulletSim(m_worldID, BulletSimAPI.GetSimHandle2(m_worldID)); m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID));
m_constraintCollection = new BSConstraintCollection(World); m_constraintCollection = new BSConstraintCollection(World);
m_initialized = true; m_initialized = true;
@ -352,7 +362,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
BSPrim bsprim = prim as BSPrim; BSPrim bsprim = prim as BSPrim;
if (bsprim != null) if (bsprim != null)
{ {
m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); // DetailLog("{0},RemovePrim,call", bsprim.LocalID);
// m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID);
try try
{ {
lock (m_prims) m_prims.Remove(bsprim.LocalID); lock (m_prims) m_prims.Remove(bsprim.LocalID);
@ -377,6 +388,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
if (!m_initialized) return null; if (!m_initialized) return null;
// DetailLog("{0},AddPrimShape,call", localID);
BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
lock (m_prims) m_prims.Add(localID, prim); lock (m_prims) m_prims.Add(localID, prim);
return prim; return prim;
@ -400,7 +413,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();
@ -416,12 +429,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
{ {
numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr);
DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", "0000000000", numSubSteps, updatedEntityCount, collidersCount); // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount);
} }
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}", "0000000000", 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;
} }
@ -498,8 +511,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
@ -535,7 +553,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
public override void SetTerrain(float[] heightMap) { public override void SetTerrain(float[] heightMap) {
m_heightMap = heightMap; m_heightMap = heightMap;
this.TaintedObject(delegate() this.TaintedObject("BSScene.SetTerrain", delegate()
{ {
BulletSimAPI.SetHeightmap(m_worldID, m_heightMap); BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
}); });
@ -577,12 +595,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();
@ -595,6 +607,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);
@ -727,12 +746,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
// Calls to the PhysicsActors can't directly call into the physics engine // Calls to the PhysicsActors can't directly call into the physics engine
// because it might be busy. We delay changes to a known time. // because it might be busy. We delay changes to a known time.
// We rely on C#'s closure to save and restore the context for the delegate. // We rely on C#'s closure to save and restore the context for the delegate.
public void TaintedObject(TaintCallback callback) public void TaintedObject(String ident, TaintCallback callback)
{ {
if (!m_initialized) return; if (!m_initialized) return;
lock (_taintLock) lock (_taintLock)
_taintedObjects.Add(callback); _taintedObjects.Add(new TaintCallbackEntry(ident, callback));
return; return;
} }
@ -744,22 +763,22 @@ public class BSScene : PhysicsScene, IPhysicsParameters
if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process
{ {
// swizzle a new list into the list location so we can process what's there // swizzle a new list into the list location so we can process what's there
List<TaintCallback> oldList; List<TaintCallbackEntry> oldList;
lock (_taintLock) lock (_taintLock)
{ {
oldList = _taintedObjects; oldList = _taintedObjects;
_taintedObjects = new List<TaintCallback>(); _taintedObjects = new List<TaintCallbackEntry>();
} }
foreach (TaintCallback callback in oldList) foreach (TaintCallbackEntry tcbe in oldList)
{ {
try try
{ {
callback(); tcbe.callback();
} }
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat("{0}: ProcessTaints: Exception: {1}", LogHeader, e); m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e);
} }
} }
oldList.Clear(); oldList.Clear();
@ -767,6 +786,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters
} }
#region Vehicles #region Vehicles
public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType)
{
if (newType == Vehicle.TYPE_NONE)
{
RemoveVehiclePrim(vehic);
}
else
{
// make it so the scene will call us each tick to do vehicle things
AddVehiclePrim(vehic);
}
}
// Make so the scene will call this prim for vehicle actions each tick. // Make so the scene will call this prim for vehicle actions each tick.
// Safe to call if prim is already in the vehicle list. // Safe to call if prim is already in the vehicle list.
public void AddVehiclePrim(BSPrim vehicle) public void AddVehiclePrim(BSPrim vehicle)
@ -812,12 +845,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
private struct ParameterDefn private struct ParameterDefn
{ {
public string name; public string name; // string name of the parameter
public string desc; public string desc; // a short description of what the parameter means
public float defaultValue; public float defaultValue; // default value if not specified anywhere else
public ParamUser userParam; public ParamUser userParam; // get the value from the configuration file
public ParamGet getter; public ParamGet getter; // return the current value stored for this parameter
public ParamSet setter; public ParamSet setter; // set the current value for this parameter
public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
{ {
name = n; name = n;
@ -834,7 +867,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
// To add a new externally referencable/settable parameter, add the paramter storage // To add a new externally referencable/settable parameter, add the paramter storage
// location somewhere in the program and make an entry in this table with the // location somewhere in the program and make an entry in this table with the
// getters and setters. // getters and setters.
// To add a new variable, it is easiest to find an existing definition and copy it. // It is easiest to find an existing definition and copy it.
// Parameter values are floats. Booleans are converted to a floating value. // Parameter values are floats. Booleans are converted to a floating value.
// //
// A ParameterDefn() takes the following parameters: // A ParameterDefn() takes the following parameters:
@ -870,7 +903,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
(s) => { return (float)s.m_meshLOD; }, (s) => { return (float)s.m_meshLOD; },
(s,p,l,v) => { s.m_meshLOD = (int)v; } ), (s,p,l,v) => { s.m_meshLOD = (int)v; } ),
new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
32, 32f,
(s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); },
(s) => { return (float)s.m_sculptLOD; }, (s) => { return (float)s.m_sculptLOD; },
(s,p,l,v) => { s.m_sculptLOD = (int)v; } ), (s,p,l,v) => { s.m_sculptLOD = (int)v; } ),
@ -1027,14 +1060,19 @@ public class BSScene : PhysicsScene, IPhysicsParameters
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default)", new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)",
0f, // zero to disable 0f, // zero to disable
(s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
(s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ),
new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)",
0f, // zero to disable
(s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); },
(s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; },
(s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ),
new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count", new ParameterDefn("ShouldDisableContactPoolDynamicAllocation", "Enable to allow large changes in object count",
ConfigurationParameters.numericTrue, ConfigurationParameters.numericFalse,
(s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, (s,cf,p,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
(s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; }, (s) => { return s.m_params[0].shouldDisableContactPoolDynamicAllocation; },
(s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ), (s,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ),
new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step", new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
@ -1101,9 +1139,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
(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", new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
ConfigurationParameters.numericFalse, ConfigurationParameters.numericFalse,
(s,cf,p,v) => { s.shouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); }, (s,cf,p,v) => { s.ShouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
(s) => { return s.NumericBool(s.shouldDebugLog); }, (s) => { return s.NumericBool(s.ShouldDebugLog); },
(s,p,l,v) => { s.shouldDebugLog = s.BoolNumeric(v); } ), (s,p,l,v) => { s.ShouldDebugLog = s.BoolNumeric(v); } ),
}; };
@ -1243,7 +1281,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
List<uint> objectIDs = lIDs; List<uint> objectIDs = lIDs;
string xparm = parm.ToLower(); string xparm = parm.ToLower();
float xval = val; float xval = val;
TaintedObject(delegate() { TaintedObject("BSScene.UpdateParameterSet", delegate() {
foreach (uint lID in objectIDs) foreach (uint lID in objectIDs)
{ {
BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval); BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval);
@ -1263,7 +1301,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
uint xlocalID = localID; uint xlocalID = localID;
string xparm = parm.ToLower(); string xparm = parm.ToLower();
float xval = val; float xval = val;
TaintedObject(delegate() { TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval);
}); });
} }
@ -1289,10 +1327,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
#endregion Runtime settable parameters #endregion Runtime settable parameters
// 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) public void DetailLog(string msg, params Object[] args)
{ {
PhysicsLogging.Write(msg, args); PhysicsLogging.Write(msg, args);
} }
// used to fill in the LocalID when there isn't one
public const string DetailLogZero = "0000000000";
} }
} }

View File

@ -35,9 +35,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin {
// Classes to allow some type checking for the API // Classes to allow some type checking for the API
public struct BulletSim public struct BulletSim
{ {
public BulletSim(uint id, IntPtr xx) { ID = id; Ptr = xx; } public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; }
public IntPtr Ptr;
public uint ID; public uint ID;
// The scene is only in here so very low level routines have a handle to print debug/error messages
public BSScene scene;
public IntPtr Ptr;
} }
public struct BulletBody public struct BulletBody
@ -158,6 +160,7 @@ public struct ConfigurationParameters
public float avatarContactProcessingThreshold; public float avatarContactProcessingThreshold;
public float maxPersistantManifoldPoolSize; public float maxPersistantManifoldPoolSize;
public float maxCollisionAlgorithmPoolSize;
public float shouldDisableContactPoolDynamicAllocation; public float shouldDisableContactPoolDynamicAllocation;
public float shouldForceUpdateAllAabbs; public float shouldForceUpdateAllAabbs;
public float shouldRandomizeSolverOrder; public float shouldRandomizeSolverOrder;
@ -179,17 +182,18 @@ public struct ConfigurationParameters
// Values used by Bullet and BulletSim to control collisions // Values used by Bullet and BulletSim to control collisions
public enum CollisionFlags : uint public enum CollisionFlags : uint
{ {
STATIC_OBJECT = 1 << 0, CF_STATIC_OBJECT = 1 << 0,
KINEMATIC_OBJECT = 1 << 1, CF_KINEMATIC_OBJECT = 1 << 1,
NO_CONTACT_RESPONSE = 1 << 2, CF_NO_CONTACT_RESPONSE = 1 << 2,
CUSTOM_MATERIAL_CALLBACK = 1 << 3, CF_CUSTOM_MATERIAL_CALLBACK = 1 << 3,
CHARACTER_OBJECT = 1 << 4, CF_CHARACTER_OBJECT = 1 << 4,
DISABLE_VISUALIZE_OBJECT = 1 << 5, CF_DISABLE_VISUALIZE_OBJECT = 1 << 5,
DISABLE_SPU_COLLISION_PROCESS = 1 << 6, CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
// Following used by BulletSim to control collisions // Following used by BulletSim to control collisions
VOLUME_DETECT_OBJECT = 1 << 10, BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
PHANTOM_OBJECT = 1 << 11, BS_VOLUME_DETECT_OBJECT = 1 << 11,
PHYSICAL_OBJECT = 1 << 12, BS_PHANTOM_OBJECT = 1 << 12,
BS_PHYSICAL_OBJECT = 1 << 13,
}; };
// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
@ -361,7 +365,7 @@ public static extern IntPtr GetSimHandle2(uint worldID);
public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id); public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr GetBodyHandle2(IntPtr sim, uint id); public static extern IntPtr GetBodyHandle2(IntPtr world, uint id);
// =============================================================================== // ===============================================================================
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
@ -370,44 +374,68 @@ public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
int maxUpdates, IntPtr updateArray); int maxUpdates, IntPtr updateArray);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool UpdateParameter2(IntPtr sim, uint localID, String parm, float value); public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void SetHeightmap2(IntPtr sim, float[] heightmap); public static extern void SetHeightmap2(IntPtr world, float[] heightmap);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern void Shutdown2(IntPtr sim); public static extern void Shutdown2(IntPtr sim);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern int PhysicsStep2(IntPtr sim, float timeStep, int maxSubSteps, float fixedTimeStep, public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep,
out int updatedEntityCount, out int updatedEntityCount,
out IntPtr updatedEntitiesPtr, out IntPtr updatedEntitiesPtr,
out int collidersCount, out int collidersCount,
out IntPtr collidersPtr); out IntPtr collidersPtr);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool PushUpdate2(IntPtr obj);
/* /*
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr CreateMesh2(IntPtr sim, int indicesCount, int* indices, int verticesCount, float* vertices ); public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices );
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool BuildHull2(IntPtr sim, IntPtr mesh); public static extern bool BuildHull2(IntPtr world, IntPtr mesh);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool ReleaseHull2(IntPtr sim, IntPtr mesh); public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool DestroyMesh2(IntPtr sim, IntPtr mesh); public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr CreateObject2(IntPtr sim, ShapeData shapeData); public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData);
*/ */
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2, public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
Vector3 frame1loc, Quaternion frame1rot, Vector3 frame1loc, Quaternion frame1rot,
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);
@ -420,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);
@ -427,7 +458,13 @@ public static extern bool CalculateTransforms2(IntPtr constrain);
public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis); public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool DestroyConstraint2(IntPtr sim, IntPtr constrain); public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern Vector3 GetPosition2(IntPtr obj); public static extern Vector3 GetPosition2(IntPtr obj);
@ -447,6 +484,9 @@ public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocit
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); public static extern bool SetObjectForce2(IntPtr obj, Vector3 force);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool AddObjectForce2(IntPtr obj, Vector3 force);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val);
@ -478,13 +518,16 @@ public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val);
public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr SetCollisionFlags2(IntPtr obj, uint flags); public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr AddToCollisionFlags2(IntPtr obj, uint flags); public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, uint flags); public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia);
@ -498,18 +541,15 @@ 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);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj); public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj);
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
public static extern bool DestroyObject2(IntPtr world, uint id); public static extern bool DestroyObject2(IntPtr world, uint id);

View File

@ -226,6 +226,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
public void llResetScript() public void llResetScript()
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
// We need to tell the URL module, if we hav one, to release
// the allocated URLs
if (m_UrlModule != null)
m_UrlModule.ScriptRemoved(m_item.ItemID);
m_ScriptEngine.ApiResetScript(m_item.ItemID); m_ScriptEngine.ApiResetScript(m_item.ItemID);
} }
@ -331,35 +337,40 @@ 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>();
if (m_host == null || m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted) if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return ret; return ret;
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:
@ -369,7 +380,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>();
@ -1764,13 +1775,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
try try
{ {
parts[0].ParentGroup.areUpdatesSuspended = true;
foreach (SceneObjectPart part in parts) foreach (SceneObjectPart part in parts)
SetAlpha(part, alpha, face); SetAlpha(part, alpha, face);
} }
finally finally
{ {
parts[0].ParentGroup.areUpdatesSuspended = false;
} }
} }
} }
@ -1951,13 +1960,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
try try
{ {
parts[0].ParentGroup.areUpdatesSuspended = true;
foreach (SceneObjectPart part in parts) foreach (SceneObjectPart part in parts)
SetTexture(part, texture, face); SetTexture(part, texture, face);
} }
finally finally
{ {
parts[0].ParentGroup.areUpdatesSuspended = false;
} }
} }
ScriptSleep(200); ScriptSleep(200);
@ -3340,7 +3347,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
if (attachmentsModule != null) if (attachmentsModule != null)
return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true); return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, false);
else else
return false; return false;
} }
@ -3747,29 +3754,17 @@ 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_TRACK_CAMERA | ScriptBaseClass.PERMISSION_TRACK_CAMERA |
ScriptBaseClass.PERMISSION_ATTACH; ScriptBaseClass.PERMISSION_ATTACH;
if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
{
m_host.TaskInventory.LockItemsForWrite(true);
m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
m_host.TaskInventory.LockItemsForWrite(false);
m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
"run_time_permissions", new Object[] {
new LSL_Integer(perm) },
new DetectParams[0]));
return;
}
} }
else else
{ {
@ -3790,26 +3785,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (sitting) if (sitting)
{ {
// 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;
if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
{
m_host.TaskInventory.LockItemsForWrite(true);
m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
m_host.TaskInventory.LockItemsForWrite(false);
m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
"run_time_permissions", new Object[] {
new LSL_Integer(perm) },
new DetectParams[0]));
return;
}
} }
else
{
if (World.GetExtraSetting("auto_grant_attach_perms") == "true")
implicitPerms = ScriptBaseClass.PERMISSION_ATTACH;
}
}
if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
{
m_host.TaskInventory.LockItemsForWrite(true);
m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
m_host.TaskInventory.LockItemsForWrite(false);
m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
"run_time_permissions", new Object[] {
new LSL_Integer(perm) },
new DetectParams[0]));
return;
} }
ScenePresence presence = World.GetScenePresence(agentID); ScenePresence presence = World.GetScenePresence(agentID);
@ -3927,13 +3927,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
try try
{ {
parts[0].ParentGroup.areUpdatesSuspended = true;
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.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face);
} }
finally finally
{ {
parts[0].ParentGroup.areUpdatesSuspended = false;
} }
} }
} }
@ -4051,7 +4049,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
try try
{ {
parts[0].ParentGroup.areUpdatesSuspended = true;
foreach (SceneObjectPart part in parts) foreach (SceneObjectPart part in parts)
{ {
parentPrim.DelinkFromGroup(part.LocalId, true); parentPrim.DelinkFromGroup(part.LocalId, true);
@ -4059,7 +4056,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
finally finally
{ {
parts[0].ParentGroup.areUpdatesSuspended = false;
} }
} }
@ -4074,7 +4070,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
try try
{ {
parts[0].ParentGroup.areUpdatesSuspended = true;
foreach (SceneObjectPart part in parts) foreach (SceneObjectPart part in parts)
{ {
part.ClearUpdateSchedule(); part.ClearUpdateSchedule();
@ -4083,7 +4078,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
finally finally
{ {
parts[0].ParentGroup.areUpdatesSuspended = false;
} }
@ -5369,12 +5363,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
return 0; return 0;
} }
// Vectors & Rotations always return zero in SL, but
// keys don't always return zero, it seems to be a bit complex.
else if (src.Data[index] is LSL_Vector ||
src.Data[index] is LSL_Rotation)
{
return 0;
}
try try
{ {
if (src.Data[index] is LSL_Integer) if (src.Data[index] is LSL_Integer)
return (LSL_Integer) src.Data[index]; return (LSL_Integer)src.Data[index];
else if (src.Data[index] is LSL_Float) else if (src.Data[index] is LSL_Float)
return Convert.ToInt32(((LSL_Float) src.Data[index]).value); return Convert.ToInt32(((LSL_Float)src.Data[index]).value);
return new LSL_Integer(src.Data[index].ToString()); return new LSL_Integer(src.Data[index].ToString());
} }
catch (FormatException) catch (FormatException)
@ -5394,12 +5397,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
return 0.0; return 0.0;
} }
// Vectors & Rotations always return zero in SL
else if (src.Data[index] is LSL_Vector ||
src.Data[index] is LSL_Rotation)
{
return 0;
}
// valid keys seem to get parsed as integers then converted to floats
else
{
UUID uuidt;
if (src.Data[index] is LSL_Key && UUID.TryParse(src.Data[index].ToString(), out uuidt))
{
return Convert.ToDouble(new LSL_Integer(src.Data[index].ToString()).value);
}
}
try try
{ {
if (src.Data[index] is LSL_Integer) if (src.Data[index] is LSL_Integer)
return Convert.ToDouble(((LSL_Integer) src.Data[index]).value); return Convert.ToDouble(((LSL_Integer)src.Data[index]).value);
else if (src.Data[index] is LSL_Float) else if (src.Data[index] is LSL_Float)
return Convert.ToDouble(((LSL_Float) src.Data[index]).value); return Convert.ToDouble(((LSL_Float)src.Data[index]).value);
else if (src.Data[index] is LSL_String) else if (src.Data[index] is LSL_String)
{ {
string str = ((LSL_String) src.Data[index]).m_string; string str = ((LSL_String) src.Data[index]).m_string;
@ -5437,17 +5456,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return src.Data[index].ToString(); return src.Data[index].ToString();
} }
public LSL_String llList2Key(LSL_List src, int index) public LSL_Key llList2Key(LSL_List src, int index)
{ {
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
if (index < 0) if (index < 0)
{ {
index = src.Length + index; index = src.Length + index;
} }
if (index >= src.Length || index < 0) if (index >= src.Length || index < 0)
{ {
return ""; return "";
} }
// SL spits out an empty string for types other than key & string
// At the time of patching, LSL_Key is currently LSL_String,
// so the OR check may be a little redundant, but it's being done
// for completion and should LSL_Key ever be implemented
// as it's own struct
else if (!(src.Data[index] is LSL_String ||
src.Data[index] is LSL_Key))
{
return "";
}
return src.Data[index].ToString(); return src.Data[index].ToString();
} }
@ -5466,6 +5498,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
return (LSL_Vector)src.Data[index]; return (LSL_Vector)src.Data[index];
} }
// SL spits always out ZERO_VECTOR for anything other than
// strings or vectors. Although keys always return ZERO_VECTOR,
// it is currently difficult to make the distinction between
// a string, a key as string and a string that by coincidence
// is a string, so we're going to leave that up to the
// LSL_Vector constructor.
else if (!(src.Data[index] is LSL_String ||
src.Data[index] is LSL_Vector))
{
return new LSL_Vector(0, 0, 0);
}
else else
{ {
return new LSL_Vector(src.Data[index].ToString()); return new LSL_Vector(src.Data[index].ToString());
@ -5483,7 +5527,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
return new LSL_Rotation(0, 0, 0, 1); return new LSL_Rotation(0, 0, 0, 1);
} }
if (src.Data[index].GetType() == typeof(LSL_Rotation))
// SL spits always out ZERO_ROTATION for anything other than
// strings or vectors. Although keys always return ZERO_ROTATION,
// it is currently difficult to make the distinction between
// a string, a key as string and a string that by coincidence
// is a string, so we're going to leave that up to the
// LSL_Rotation constructor.
else if (!(src.Data[index] is LSL_String ||
src.Data[index] is LSL_Rotation))
{
return new LSL_Rotation(0, 0, 0, 1);
}
else if (src.Data[index].GetType() == typeof(LSL_Rotation))
{ {
return (LSL_Rotation)src.Data[index]; return (LSL_Rotation)src.Data[index];
} }
@ -6236,7 +6292,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
try try
{ {
parts[0].ParentGroup.areUpdatesSuspended = true;
foreach (var part in parts) foreach (var part in parts)
{ {
SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
@ -6244,7 +6299,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
finally finally
{ {
parts[0].ParentGroup.areUpdatesSuspended = false;
} }
} }
} }
@ -7689,7 +7743,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);
} }
@ -7703,26 +7758,47 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
private void setLinkPrimParams(int linknumber, LSL_List rules) private void setLinkPrimParams(int linknumber, LSL_List rules)
{ {
List<SceneObjectPart> parts = GetLinkParts(linknumber); List<object> parts = new List<object>();
List<SceneObjectPart> prims = GetLinkParts(linknumber);
List<ScenePresence> avatars = GetLinkAvatars(linknumber); List<ScenePresence> avatars = GetLinkAvatars(linknumber);
if (parts.Count>0) foreach (SceneObjectPart p in prims)
parts.Add(p);
foreach (ScenePresence p in avatars)
parts.Add(p);
LSL_List remaining = null;
if (parts.Count > 0)
{ {
try foreach (object part in parts)
{ {
parts[0].ParentGroup.areUpdatesSuspended = true; if (part is SceneObjectPart)
foreach (SceneObjectPart part in parts) remaining = SetPrimParams((SceneObjectPart)part, rules);
SetPrimParams(part, rules); else
remaining = SetPrimParams((ScenePresence)part, rules);
} }
finally
while((object)remaining != null && remaining.Length > 2)
{ {
parts[0].ParentGroup.areUpdatesSuspended = false; linknumber = remaining.GetLSLIntegerItem(0);
rules = remaining.GetSublist(1,-1);
parts.Clear();
prims = GetLinkParts(linknumber);
avatars = GetLinkAvatars(linknumber);
foreach (SceneObjectPart p in prims)
parts.Add(p);
foreach (ScenePresence p in avatars)
parts.Add(p);
foreach (object part in parts)
{
if (part is SceneObjectPart)
remaining = SetPrimParams((SceneObjectPart)part, rules);
else
remaining = SetPrimParams((ScenePresence)part, rules);
}
} }
} }
if (avatars.Count > 0)
{
foreach (ScenePresence avatar in avatars)
SetPrimParams(avatar, rules);
}
} }
private void SetPhysicsMaterial(SceneObjectPart part, int material_bits, private void SetPhysicsMaterial(SceneObjectPart part, int material_bits,
@ -7784,7 +7860,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return new Vector3((float)x, (float)y, (float)z); return new Vector3((float)x, (float)y, (float)z);
} }
protected void SetPrimParams(ScenePresence av, LSL_List rules) protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules)
{ {
//This is a special version of SetPrimParams to deal with avatars which are sat on the linkset. //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset.
@ -7807,7 +7883,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_POS_LOCAL: case (int)ScriptBaseClass.PRIM_POS_LOCAL:
{ {
if (remain < 1) if (remain < 1)
return; return null;
LSL_Vector v; LSL_Vector v;
v = rules.GetVector3Item(idx++); v = rules.GetVector3Item(idx++);
@ -7841,7 +7917,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_ROTATION: case (int)ScriptBaseClass.PRIM_ROTATION:
{ {
if (remain < 1) if (remain < 1)
return; return null;
LSL_Rotation r; LSL_Rotation r;
r = rules.GetQuaternionItem(idx++); r = rules.GetQuaternionItem(idx++);
@ -7872,7 +7948,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_NAME: case (int)ScriptBaseClass.PRIM_NAME:
case (int)ScriptBaseClass.PRIM_DESC: case (int)ScriptBaseClass.PRIM_DESC:
if (remain < 1) if (remain < 1)
return; return null;
idx++; idx++;
break; break;
@ -7880,13 +7956,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_FULLBRIGHT: case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
case (int)ScriptBaseClass.PRIM_TEXGEN: case (int)ScriptBaseClass.PRIM_TEXGEN:
if (remain < 2) if (remain < 2)
return; return null;
idx += 2; idx += 2;
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++);
remain = rules.Length - idx; remain = rules.Length - idx;
switch (code) switch (code)
@ -7895,13 +7971,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER:
case (int)ScriptBaseClass.PRIM_TYPE_PRISM: case (int)ScriptBaseClass.PRIM_TYPE_PRISM:
if (remain < 6) if (remain < 6)
return; return null;
idx += 6; idx += 6;
break; break;
case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: case (int)ScriptBaseClass.PRIM_TYPE_SPHERE:
if (remain < 5) if (remain < 5)
return; return null;
idx += 5; idx += 5;
break; break;
@ -7909,13 +7985,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_TYPE_TUBE: case (int)ScriptBaseClass.PRIM_TYPE_TUBE:
case (int)ScriptBaseClass.PRIM_TYPE_RING: case (int)ScriptBaseClass.PRIM_TYPE_RING:
if (remain < 11) if (remain < 11)
return; return null;
idx += 11; idx += 11;
break; break;
case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: case (int)ScriptBaseClass.PRIM_TYPE_SCULPT:
if (remain < 2) if (remain < 2)
return; return null;
idx += 2; idx += 2;
break; break;
} }
@ -7926,7 +8002,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_BUMP_SHINY: case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
case (int)ScriptBaseClass.PRIM_OMEGA: case (int)ScriptBaseClass.PRIM_OMEGA:
if (remain < 3) if (remain < 3)
return; return null;
idx += 3; idx += 3;
break; break;
@ -7934,33 +8010,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_POINT_LIGHT: case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL: case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
if (remain < 5) if (remain < 5)
return; return null;
idx += 5; idx += 5;
break; break;
case (int)ScriptBaseClass.PRIM_FLEXIBLE: case (int)ScriptBaseClass.PRIM_FLEXIBLE:
if (remain < 7) if (remain < 7)
return; return null;
idx += 7; idx += 7;
break; 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;
if (positionChanged) return rules.GetSublist(idx, -1);
{
positionChanged = false;
av.OffsetPosition = finalPos;
// av.SendAvatarDataToAllAgents();
av.SendTerseUpdateToAllClients();
}
LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
LSL_List new_rules = rules.GetSublist(idx, -1);
setLinkPrimParams((int)new_linknumber, new_rules);
return;
} }
} }
} }
@ -7975,12 +8040,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
positionChanged = false; positionChanged = false;
} }
} }
return null;
} }
protected void SetPrimParams(SceneObjectPart part, LSL_List rules) protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules)
{ {
if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return; return null;
int idx = 0; int idx = 0;
@ -8005,7 +8071,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++);
currentPosition = GetSetPosTarget(part, v, currentPosition); currentPosition = GetSetPosTarget(part, v, currentPosition);
@ -8014,7 +8080,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);
@ -8022,7 +8088,7 @@ 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++);
SceneObjectPart rootPart = parentgrp.RootPart; SceneObjectPart rootPart = parentgrp.RootPart;
@ -8043,7 +8109,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
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++);
@ -8062,7 +8128,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
@ -8077,7 +8143,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
@ -8091,7 +8157,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
@ -8105,7 +8171,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
@ -8118,7 +8184,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
@ -8137,7 +8203,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
@ -8156,7 +8222,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
@ -8175,7 +8241,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
@ -8187,7 +8253,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();
@ -8204,7 +8270,7 @@ 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++);
@ -8217,7 +8283,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
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++);
@ -8233,7 +8299,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++);
@ -8246,7 +8312,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++);
@ -8256,7 +8322,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++);
@ -8267,7 +8333,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);
@ -8275,17 +8341,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();
parentgrp.ScriptSetPhantomStatus(ph.Equals("1")); parentgrp.ScriptSetPhantomStatus(ph.Equals("1"));
@ -8294,7 +8360,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;
@ -8308,7 +8374,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
if (remain < 1) if (remain < 1)
return; return null;
int shape_type = rules.GetLSLIntegerItem(idx++); int shape_type = rules.GetLSLIntegerItem(idx++);
@ -8324,7 +8390,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL: case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL:
if (remain < 5) if (remain < 5)
return; return null;
int material_bits = rules.GetLSLIntegerItem(idx++); int material_bits = rules.GetLSLIntegerItem(idx++);
float material_density = (float)rules.GetLSLFloatItem(idx++); float material_density = (float)rules.GetLSLFloatItem(idx++);
@ -8338,7 +8404,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();
parentgrp.ScriptSetTemporaryStatus(temp.Equals("1")); parentgrp.ScriptSetTemporaryStatus(temp.Equals("1"));
@ -8347,7 +8413,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++);
@ -8355,7 +8421,7 @@ 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++);
@ -8367,26 +8433,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
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++); LSL_Rotation lr = rules.GetQuaternionItem(idx++);
SetRot(part, Rot2Quaternion(lr)); 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++);
@ -8395,35 +8460,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
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;
// do a pending position change before jumping to other part/avatar return rules.GetSublist(idx, -1);
if (positionChanged)
{
positionChanged = false;
if (parentgrp == null)
return;
if (parentgrp.RootPart == part)
{
Util.FireAndForget(delegate(object x)
{
parentgrp.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z));
});
}
else
{
part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z);
parentgrp.HasGroupChanged = true;
parentgrp.ScheduleGroupForTerseUpdate();
}
}
LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++);
LSL_List new_rules = rules.GetSublist(idx, -1);
setLinkPrimParams((int)new_linknumber, new_rules);
return;
} }
} }
} }
@ -8447,6 +8486,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
} }
} }
} }
return null;
} }
public LSL_String llStringToBase64(string str) public LSL_String llStringToBase64(string str)
@ -12082,7 +12122,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)

View File

@ -2466,8 +2466,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) if (!npcModule.CheckPermissions(npcId, m_host.OwnerID))
return new LSL_Vector(0, 0, 0); return new LSL_Vector(0, 0, 0);
Vector3 pos = World.GetScenePresence(npcId).AbsolutePosition; ScenePresence sp = World.GetScenePresence(npcId);
return new LSL_Vector(pos.X, pos.Y, pos.Z);
if (sp != null)
{
Vector3 pos = sp.AbsolutePosition;
return new LSL_Vector(pos.X, pos.Y, pos.Z);
}
} }
return new LSL_Vector(0, 0, 0); return new LSL_Vector(0, 0, 0);
@ -2535,9 +2540,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W); return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W);
ScenePresence sp = World.GetScenePresence(npcId); ScenePresence sp = World.GetScenePresence(npcId);
Quaternion rot = sp.Rotation;
return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W); if (sp != null)
{
Quaternion rot = sp.Rotation;
return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W);
}
} }
return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W); return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W);
@ -2559,7 +2567,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return; return;
ScenePresence sp = World.GetScenePresence(npcId); ScenePresence sp = World.GetScenePresence(npcId);
sp.Rotation = LSL_Api.Rot2Quaternion(rotation);
if (sp != null)
sp.Rotation = LSL_Api.Rot2Quaternion(rotation);
} }
} }
@ -2737,6 +2747,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
CheckThreatLevel(ThreatLevel.High, "osNpcTouch"); CheckThreatLevel(ThreatLevel.High, "osNpcTouch");
m_host.AddScriptLPS(1); m_host.AddScriptLPS(1);
INPCModule module = World.RequestModuleInterface<INPCModule>(); INPCModule module = World.RequestModuleInterface<INPCModule>();
int linkNum = link_num.value; int linkNum = link_num.value;
if (module != null || (linkNum < 0 && linkNum != ScriptBaseClass.LINK_THIS)) if (module != null || (linkNum < 0 && linkNum != ScriptBaseClass.LINK_THIS))
@ -2744,12 +2755,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
UUID npcId; UUID npcId;
if (!UUID.TryParse(npcLSL_Key, out npcId) || !module.CheckPermissions(npcId, m_host.OwnerID)) if (!UUID.TryParse(npcLSL_Key, out npcId) || !module.CheckPermissions(npcId, m_host.OwnerID))
return; return;
SceneObjectPart part = null; SceneObjectPart part = null;
UUID objectId; UUID objectId;
if (UUID.TryParse(LSL_String.ToString(object_key), out objectId)) if (UUID.TryParse(LSL_String.ToString(object_key), out objectId))
part = World.GetSceneObjectPart(objectId); part = World.GetSceneObjectPart(objectId);
if (part == null) if (part == null)
return; return;
if (linkNum != ScriptBaseClass.LINK_THIS) if (linkNum != ScriptBaseClass.LINK_THIS)
{ {
if (linkNum == 0 || linkNum == ScriptBaseClass.LINK_ROOT) if (linkNum == 0 || linkNum == ScriptBaseClass.LINK_ROOT)
@ -2764,6 +2778,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
return; return;
} }
} }
module.Touch(npcId, part.UUID); module.Touch(npcId, part.UUID);
} }
} }

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;

View File

@ -64,6 +64,15 @@ namespace OpenSim.Services.AuthenticationService
public string Authenticate(UUID principalID, string password, int lifetime) public string Authenticate(UUID principalID, string password, int lifetime)
{ {
UUID realID;
return Authenticate(principalID, password, lifetime, out realID);
}
public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
{
realID = UUID.Zero;
m_log.DebugFormat("[AUTH SERVICE]: Authenticating for {0}, user account service present: {1}", principalID, m_UserAccountService != null); m_log.DebugFormat("[AUTH SERVICE]: Authenticating for {0}, user account service present: {1}", principalID, m_UserAccountService != null);
AuthenticationData data = m_Database.Get(principalID); AuthenticationData data = m_Database.Get(principalID);
UserAccount user = null; UserAccount user = null;
@ -127,6 +136,7 @@ namespace OpenSim.Services.AuthenticationService
if (data.Data["passwordHash"].ToString() == hashed) if (data.Data["passwordHash"].ToString() == hashed)
{ {
m_log.DebugFormat("[PASS AUTH]: {0} {1} impersonating {2}, proceeding with login", a.FirstName, a.LastName, principalID); m_log.DebugFormat("[PASS AUTH]: {0} {1} impersonating {2}, proceeding with login", a.FirstName, a.LastName, principalID);
realID = a.PrincipalID;
return GetToken(principalID, lifetime); return GetToken(principalID, lifetime);
} }
// else // else

View File

@ -60,6 +60,13 @@ namespace OpenSim.Services.AuthenticationService
{ {
} }
public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
{
realID = UUID.Zero;
return Authenticate(principalID, password, lifetime);
}
public string Authenticate(UUID principalID, string password, int lifetime) public string Authenticate(UUID principalID, string password, int lifetime)
{ {
if (new UUID(password) == UUID.Zero) if (new UUID(password) == UUID.Zero)

View File

@ -54,6 +54,13 @@ namespace OpenSim.Services.AuthenticationService
} }
public string Authenticate(UUID principalID, string password, int lifetime) public string Authenticate(UUID principalID, string password, int lifetime)
{
UUID realID;
return Authenticate(principalID, password, lifetime, out realID);
}
public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
{ {
AuthenticationData data = m_Database.Get(principalID); AuthenticationData data = m_Database.Get(principalID);
string result = String.Empty; string result = String.Empty;
@ -62,7 +69,7 @@ namespace OpenSim.Services.AuthenticationService
if (data.Data.ContainsKey("webLoginKey")) if (data.Data.ContainsKey("webLoginKey"))
{ {
m_log.DebugFormat("[AUTH SERVICE]: Attempting web key authentication for PrincipalID {0}", principalID); m_log.DebugFormat("[AUTH SERVICE]: Attempting web key authentication for PrincipalID {0}", principalID);
result = m_svcChecks["web_login_key"].Authenticate(principalID, password, lifetime); result = m_svcChecks["web_login_key"].Authenticate(principalID, password, lifetime, out realID);
if (result == String.Empty) if (result == String.Empty)
{ {
m_log.DebugFormat("[AUTH SERVICE]: Web Login failed for PrincipalID {0}", principalID); m_log.DebugFormat("[AUTH SERVICE]: Web Login failed for PrincipalID {0}", principalID);
@ -71,12 +78,15 @@ namespace OpenSim.Services.AuthenticationService
if (result == string.Empty && data.Data.ContainsKey("passwordHash") && data.Data.ContainsKey("passwordSalt")) if (result == string.Empty && data.Data.ContainsKey("passwordHash") && data.Data.ContainsKey("passwordSalt"))
{ {
m_log.DebugFormat("[AUTH SERVICE]: Attempting password authentication for PrincipalID {0}", principalID); m_log.DebugFormat("[AUTH SERVICE]: Attempting password authentication for PrincipalID {0}", principalID);
result = m_svcChecks["password"].Authenticate(principalID, password, lifetime); result = m_svcChecks["password"].Authenticate(principalID, password, lifetime, out realID);
if (result == String.Empty) if (result == String.Empty)
{ {
m_log.DebugFormat("[AUTH SERVICE]: Password login failed for PrincipalID {0}", principalID); m_log.DebugFormat("[AUTH SERVICE]: Password login failed for PrincipalID {0}", principalID);
} }
} }
realID = UUID.Zero;
if (result == string.Empty) if (result == string.Empty)
{ {
m_log.DebugFormat("[AUTH SERVICE]: Both password and webLoginKey-based authentication failed for PrincipalID {0}", principalID); m_log.DebugFormat("[AUTH SERVICE]: Both password and webLoginKey-based authentication failed for PrincipalID {0}", principalID);
@ -89,4 +99,4 @@ namespace OpenSim.Services.AuthenticationService
return result; return result;
} }
} }
} }

View File

@ -81,6 +81,13 @@ namespace OpenSim.Services.Connectors
m_ServerURI = serviceURI; m_ServerURI = serviceURI;
} }
public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
{
realID = UUID.Zero;
return Authenticate(principalID, password, lifetime);
}
public string Authenticate(UUID principalID, string password, int lifetime) public string Authenticate(UUID principalID, string password, int lifetime)
{ {
Dictionary<string, object> sendData = new Dictionary<string, object>(); Dictionary<string, object> sendData = new Dictionary<string, object>();

View File

@ -102,6 +102,11 @@ namespace OpenSim.Services.Connectors.SimianGrid
m_log.Info("[SIMIAN AUTH CONNECTOR]: No AuthenticationServerURI specified, disabling connector"); m_log.Info("[SIMIAN AUTH CONNECTOR]: No AuthenticationServerURI specified, disabling connector");
} }
public string Authenticate(UUID principalID, string password, int lifetime, out UUID realID)
{
return Authenticate(principalID, password, lifetime);
}
public string Authenticate(UUID principalID, string password, int lifetime) public string Authenticate(UUID principalID, string password, int lifetime)
{ {
NameValueCollection requestArgs = new NameValueCollection NameValueCollection requestArgs = new NameValueCollection

View File

@ -168,5 +168,20 @@ namespace OpenSim.Services.Connectors
{ {
return m_database.GetObjectIDs(regionID); return m_database.GetObjectIDs(regionID);
} }
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

@ -67,6 +67,7 @@ namespace OpenSim.Services.Interfaces
// various services. // various services.
// //
string Authenticate(UUID principalID, string password, int lifetime); string Authenticate(UUID principalID, string password, int lifetime);
string Authenticate(UUID principalID, string password, int lifetime, out UUID realID);
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
// Verification // Verification

View File

@ -182,7 +182,8 @@ namespace OpenSim.Services.Interfaces
List<AvatarAttachment> attachments = appearance.GetAttachments(); List<AvatarAttachment> attachments = appearance.GetAttachments();
foreach (AvatarAttachment attach in attachments) foreach (AvatarAttachment attach in attachments)
{ {
Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString(); if (attach.ItemID != UUID.Zero)
Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString();
} }
} }

View File

@ -150,6 +150,7 @@ namespace OpenSim.Services.LLLoginService
private UUID agentID; private UUID agentID;
private UUID sessionID; private UUID sessionID;
private UUID secureSessionID; private UUID secureSessionID;
private UUID realID;
// Login Flags // Login Flags
private string dst; private string dst;
@ -232,7 +233,7 @@ namespace OpenSim.Services.LLLoginService
GridRegion destination, List<InventoryFolderBase> invSkel, FriendInfo[] friendsList, ILibraryService libService, GridRegion destination, List<InventoryFolderBase> invSkel, FriendInfo[] friendsList, ILibraryService libService,
string where, string startlocation, Vector3 position, Vector3 lookAt, List<InventoryItemBase> gestures, string message, string where, string startlocation, Vector3 position, Vector3 lookAt, List<InventoryItemBase> gestures, string message,
GridRegion home, IPEndPoint clientIP, string mapTileURL, string profileURL, string openIDURL, string searchURL, string currency, GridRegion home, IPEndPoint clientIP, string mapTileURL, string profileURL, string openIDURL, string searchURL, string currency,
string DSTZone) string DSTZone, UUID realID)
: this() : this()
{ {
FillOutInventoryData(invSkel, libService); FillOutInventoryData(invSkel, libService);
@ -245,6 +246,7 @@ namespace OpenSim.Services.LLLoginService
AgentID = account.PrincipalID; AgentID = account.PrincipalID;
SessionID = aCircuit.SessionID; SessionID = aCircuit.SessionID;
SecureSessionID = aCircuit.SecureSessionID; SecureSessionID = aCircuit.SecureSessionID;
RealID = realID;
Message = message; Message = message;
BuddList = ConvertFriendListItem(friendsList); BuddList = ConvertFriendListItem(friendsList);
StartLocation = where; StartLocation = where;
@ -456,6 +458,7 @@ namespace OpenSim.Services.LLLoginService
SessionID = UUID.Random(); SessionID = UUID.Random();
SecureSessionID = UUID.Random(); SecureSessionID = UUID.Random();
AgentID = UUID.Random(); AgentID = UUID.Random();
RealID = UUID.Zero;
Hashtable InitialOutfitHash = new Hashtable(); Hashtable InitialOutfitHash = new Hashtable();
InitialOutfitHash["folder_name"] = "Nightclub Female"; InitialOutfitHash["folder_name"] = "Nightclub Female";
@ -499,6 +502,7 @@ namespace OpenSim.Services.LLLoginService
responseData["http_port"] = (Int32)SimHttpPort; responseData["http_port"] = (Int32)SimHttpPort;
responseData["agent_id"] = AgentID.ToString(); responseData["agent_id"] = AgentID.ToString();
responseData["real_id"] = RealID.ToString();
responseData["session_id"] = SessionID.ToString(); responseData["session_id"] = SessionID.ToString();
responseData["secure_session_id"] = SecureSessionID.ToString(); responseData["secure_session_id"] = SecureSessionID.ToString();
responseData["circuit_code"] = CircuitCode; responseData["circuit_code"] = CircuitCode;
@ -581,6 +585,7 @@ namespace OpenSim.Services.LLLoginService
map["sim_ip"] = OSD.FromString(SimAddress); map["sim_ip"] = OSD.FromString(SimAddress);
map["agent_id"] = OSD.FromUUID(AgentID); map["agent_id"] = OSD.FromUUID(AgentID);
map["real_id"] = OSD.FromUUID(RealID);
map["session_id"] = OSD.FromUUID(SessionID); map["session_id"] = OSD.FromUUID(SessionID);
map["secure_session_id"] = OSD.FromUUID(SecureSessionID); map["secure_session_id"] = OSD.FromUUID(SecureSessionID);
map["circuit_code"] = OSD.FromInteger(CircuitCode); map["circuit_code"] = OSD.FromInteger(CircuitCode);
@ -888,6 +893,12 @@ namespace OpenSim.Services.LLLoginService
set { secureSessionID = value; } set { secureSessionID = value; }
} }
public UUID RealID
{
get { return realID; }
set { realID = value; }
}
public Int32 CircuitCode public Int32 CircuitCode
{ {
get { return circuitCode; } get { return circuitCode; }

View File

@ -327,7 +327,8 @@ namespace OpenSim.Services.LLLoginService
if (!passwd.StartsWith("$1$")) if (!passwd.StartsWith("$1$"))
passwd = "$1$" + Util.Md5Hash(passwd); passwd = "$1$" + Util.Md5Hash(passwd);
passwd = passwd.Remove(0, 3); //remove $1$ passwd = passwd.Remove(0, 3); //remove $1$
string token = m_AuthenticationService.Authenticate(account.PrincipalID, passwd, 30); UUID realID;
string token = m_AuthenticationService.Authenticate(account.PrincipalID, passwd, 30, out realID);
UUID secureSession = UUID.Zero; UUID secureSession = UUID.Zero;
if ((token == string.Empty) || (token != string.Empty && !UUID.TryParse(token, out secureSession))) if ((token == string.Empty) || (token != string.Empty && !UUID.TryParse(token, out secureSession)))
{ {
@ -459,7 +460,7 @@ namespace OpenSim.Services.LLLoginService
= new LLLoginResponse( = new LLLoginResponse(
account, aCircuit, guinfo, destination, inventorySkel, friendsList, m_LibraryService, account, aCircuit, guinfo, destination, inventorySkel, friendsList, m_LibraryService,
where, startLocation, position, lookAt, gestures, m_WelcomeMessage, home, clientIP, where, startLocation, position, lookAt, gestures, m_WelcomeMessage, home, clientIP,
m_MapTileURL, m_ProfileURL, m_OpenIDURL, m_SearchURL, m_Currency, m_DSTZone); m_MapTileURL, m_ProfileURL, m_OpenIDURL, m_SearchURL, m_Currency, m_DSTZone, realID);
m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to {0} {1}", firstName, lastName); m_log.DebugFormat("[LLOGIN SERVICE]: All clear. Sending login response to {0} {1}", firstName, lastName);

View File

@ -132,6 +132,19 @@ namespace OpenSim.Data.Null
{ {
return new UUID[0]; return new UUID[0];
} }
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>
@ -328,5 +341,18 @@ namespace OpenSim.Data.Null
{ {
return new UUID[0]; return new UUID[0];
} }
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

@ -181,11 +181,6 @@
; Objects will always be considered for persistance in the next sweep if the first change occurred this number of seconds ago ; Objects will always be considered for persistance in the next sweep if the first change occurred this number of seconds ago
MaximumTimeBeforePersistenceConsidered = 600 MaximumTimeBeforePersistenceConsidered = 600
; Experimental setting to resend appearance updates every 60 seconds.
; These packets are small and this can help with grey avatar syndrome.
; Default is false
SendPeriodicAppearanceUpdates = false
; ## ; ##
; ## PHYSICS ; ## PHYSICS
; ## ; ##
@ -341,27 +336,12 @@
; OpenJPEG if false ; OpenJPEG if false
; UseCSJ2K = true ; UseCSJ2K = true
; Use "Trash" folder for items deleted from the scene ; Use "Trash" folder for items deleted from the scene
; When set to True (the default) items deleted from the scene will be ; When set to True (the default) items deleted from the scene will be
; stored in the user's trash or lost and found folder. When set to ; stored in the user's trash or lost and found folder. When set to
; False items will be removed from the scene permanently ; False items will be removed from the scene permanently
UseTrashOnDelete = True UseTrashOnDelete = True
; Persist avatar baked textures
; Persisting baked textures can speed up login and region border
; crossings especially with large numbers of users, though it
; will store potentially large numbers of textures in your asset
; database
PersistBakedTextures = false
; Control the delay before appearance is sent to other avatars and
; saved in the avatar service. Attempts to limit the impact caused
; by the very chatty dialog that sets appearance when an avatar
; logs in or teleports into a region; values are in seconds
DelayBeforeAppearanceSave = 5
DelayBeforeAppearanceSend = 2
[RegionReady] [RegionReady]
; Enable this module to get notified once all items and scripts in the region have been completely loaded and compiled ; Enable this module to get notified once all items and scripts in the region have been completely loaded and compiled
@ -671,6 +651,28 @@
CoalesceMultipleObjectsToInventory = true CoalesceMultipleObjectsToInventory = true
[Appearance]
; Persist avatar baked textures
; Persisting baked textures can speed up login and region border
; crossings especially with large numbers of users, though it
; will store potentially large numbers of textures in your asset
; database
PersistBakedTextures = false
; Control the delay before appearance is sent to other avatars and
; saved in the avatar service. Attempts to limit the impact caused
; by the very chatty dialog that sets appearance when an avatar
; logs in or teleports into a region; values are in seconds
DelayBeforeAppearanceSave = 5
DelayBeforeAppearanceSend = 2
; If true, avatar appearance information is resent to other avatars in the simulator every 60 seconds.
; This may help with some situations where avatars are persistently grey, though it will not help
; in other situations (e.g. appearance baking failures where the avatar only appears as a cloud to others).
; This setting is experimental.
ResendAppearanceUpdates = false
[Attachments] [Attachments]
; Controls whether avatar attachments are enabled. ; Controls whether avatar attachments are enabled.
; Defaults to true - only set to false for debugging purposes ; Defaults to true - only set to false for debugging purposes
@ -892,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
@ -906,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
@ -933,11 +935,16 @@
SculptLevelOfDetail = 32 SculptLevelOfDetail = 32
; Bullet step parameters ; Bullet step parameters
MaxSubSteps = 10; MaxSubSteps = 10
FixedTimeStep = .01667 FixedTimeStep = .01667
MaxCollisionsPerFrame = 2048 MaxCollisionsPerFrame = 2048
MaxUpdatesPerFrame = 2048 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.