Compare commits
183 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5eb2526e88 | ||
|
|
641b08aa78 | ||
|
|
15d5f3d09d | ||
|
|
07dbe46ba3 | ||
|
|
ff867b59cf | ||
|
|
d4b8a13a1d | ||
|
|
a858c5daee | ||
|
|
8d431c6359 | ||
|
|
663bfbb372 | ||
|
|
d297eb39e5 | ||
|
|
29218cdb31 | ||
|
|
359f9efc76 | ||
|
|
fb211c64fd | ||
|
|
a3d140b57c | ||
|
|
f7b88d1c40 | ||
|
|
32b534f324 | ||
|
|
ffdc798720 | ||
|
|
ae852bb873 | ||
|
|
d3adf9b2b3 | ||
|
|
7c140570db | ||
|
|
7b6987ce83 | ||
|
|
0376b8ddbc | ||
|
|
2d2495cc45 | ||
|
|
a0eda6eb16 | ||
|
|
dac31303b7 | ||
|
|
edd3577b66 | ||
|
|
054db94d5d | ||
|
|
794c5f5a6d | ||
|
|
b625579780 | ||
|
|
7e41559917 | ||
|
|
8cd415c2b0 | ||
|
|
4c58c1b116 | ||
|
|
e6f43023b6 | ||
|
|
bcf944db48 | ||
|
|
7a9eee8538 | ||
|
|
05648c2c4a | ||
|
|
dff746df7b | ||
|
|
973f2e8be5 | ||
|
|
3c019bea8c | ||
|
|
68814f904e | ||
|
|
3bd3f448a2 | ||
|
|
7c6e8fab15 | ||
|
|
3ed0d79b00 | ||
|
|
d89b974680 | ||
|
|
c76c63725b | ||
|
|
6b277394c0 | ||
|
|
adce58b33a | ||
|
|
1f88179a65 | ||
|
|
ec726413dd | ||
|
|
3d736d575f | ||
|
|
0c3061f973 | ||
|
|
3bf7bd6359 | ||
|
|
7ea832d47c | ||
|
|
c1cece4b82 | ||
|
|
aa44df9c04 | ||
|
|
1e18f0f26a | ||
|
|
8a7fbfb06a | ||
|
|
e916b1399f | ||
|
|
72c2d13ac6 | ||
|
|
a6d689c529 | ||
|
|
ab9bfe5156 | ||
|
|
4e26d039d6 | ||
|
|
3082fdd0f6 | ||
|
|
e90168c738 | ||
|
|
a5c6cb2fc9 | ||
|
|
6ea95a3294 | ||
|
|
6e86b23012 | ||
|
|
58714b0aca | ||
|
|
5203665bb2 | ||
|
|
2a2e120470 | ||
|
|
a8044999fb | ||
|
|
3d504261b0 | ||
|
|
a0d178b284 | ||
|
|
f8a89a79eb | ||
|
|
e04047152f | ||
|
|
f3a5e3a02b | ||
|
|
ba58331b29 | ||
|
|
476996bee8 | ||
|
|
01771aca40 | ||
|
|
cd325fdf02 | ||
|
|
67477290ad | ||
|
|
582a256646 | ||
|
|
d188272462 | ||
|
|
632908db9e | ||
|
|
82b23f7cc1 | ||
|
|
a08687aef3 | ||
|
|
2ad9d656b3 | ||
|
|
1747030d19 | ||
|
|
c557684666 | ||
|
|
a3cbda0d74 | ||
|
|
4f3fabae5b | ||
|
|
aede42b875 | ||
|
|
a533db7e27 | ||
|
|
4820dfd733 | ||
|
|
1369058280 | ||
|
|
568de9313a | ||
|
|
219326dd8e | ||
|
|
9925317239 | ||
|
|
150748392e | ||
|
|
555edc4ef7 | ||
|
|
481c00f50a | ||
|
|
ede3b9ab07 | ||
|
|
b863a15a82 | ||
|
|
aee4353e9c | ||
|
|
e6fb458597 | ||
|
|
812c498ef4 | ||
|
|
970727e57e | ||
|
|
bcbd450fe4 | ||
|
|
9aec62f0ac | ||
|
|
dd0556abc9 | ||
|
|
8769e4ee73 | ||
|
|
d72d599056 | ||
|
|
ca33619e11 | ||
|
|
ffdde05bb7 | ||
|
|
fb84ff96a9 | ||
|
|
52d7af05bc | ||
|
|
2b0c8bc480 | ||
|
|
2a70afeca2 | ||
|
|
5d7751da89 | ||
|
|
9d6fe1224a | ||
|
|
e4e5237086 | ||
|
|
28d0aff2e3 | ||
|
|
7068fddd2f | ||
|
|
466d684fbe | ||
|
|
74f5253a36 | ||
|
|
3ad827174e | ||
|
|
56da788243 | ||
|
|
7243d4f842 | ||
|
|
f57c1ac386 | ||
|
|
0860a0d856 | ||
|
|
03d76e9403 | ||
|
|
5c192b9bab | ||
|
|
ccc69d66a1 | ||
|
|
8eda290262 | ||
|
|
e31e23d68d | ||
|
|
99e339dd40 | ||
|
|
e9ea911563 | ||
|
|
9995421df1 | ||
|
|
57a9879669 | ||
|
|
376441e550 | ||
|
|
ae5db637f2 | ||
|
|
ef4122213c | ||
|
|
e286a95d76 | ||
|
|
0aa1f1cc3f | ||
|
|
5a1b6fdf06 | ||
|
|
7679384829 | ||
|
|
9f83f4bfa3 | ||
|
|
2b982ab212 | ||
|
|
dd10cf01e7 | ||
|
|
9efe7bf7ba | ||
|
|
68f112888b | ||
|
|
b05a2fc4ed | ||
|
|
257446889b | ||
|
|
77a7758cf5 | ||
|
|
c1c1d48af1 | ||
|
|
6f1f299619 | ||
|
|
11a4b9ec1d | ||
|
|
ebbf349c6a | ||
|
|
c27ff70d5c | ||
|
|
c7f2debd38 | ||
|
|
dc82ad0f7a | ||
|
|
f6562e2269 | ||
|
|
faa710aee1 | ||
|
|
d8125fb1f7 | ||
|
|
c42fe6c159 | ||
|
|
a5b6492223 | ||
|
|
1be072f19e | ||
|
|
4bbdcfb5ee | ||
|
|
9bd2c1b88a | ||
|
|
62acfabec4 | ||
|
|
50db8649aa | ||
|
|
fe4c3a37c0 | ||
|
|
58c630c18e | ||
|
|
3ecd39068c | ||
|
|
3a55d5b123 | ||
|
|
0c7ce4fc98 | ||
|
|
3ca770cd2c | ||
|
|
320982cae3 | ||
|
|
38e79b80a8 | ||
|
|
5ab151c2d6 | ||
|
|
19417fca41 | ||
|
|
926c0b90a1 | ||
|
|
4adb3471ac |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -66,7 +66,6 @@ Examples/*.dll
|
||||
OpenSim.build
|
||||
OpenSim.sln
|
||||
OpenSim.suo
|
||||
OpenSim.userprefs
|
||||
Prebuild/Prebuild.build
|
||||
Prebuild/Prebuild.sln
|
||||
TestResult.xml
|
||||
|
||||
@@ -92,6 +92,7 @@ what it is today.
|
||||
* Flyte Xevious
|
||||
* Garmin Kawaguichi
|
||||
* Gryc Ueusp
|
||||
* Hiro Lecker
|
||||
* Imaze Rhiano
|
||||
* Intimidated
|
||||
* Jeremy Bongio (IBM)
|
||||
|
||||
@@ -163,7 +163,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||
|
||||
if (texture == null)
|
||||
{
|
||||
// m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
|
||||
//m_log.DebugFormat("[GETTEXTURE]: texture was not in the cache");
|
||||
|
||||
// Fetch locally or remotely. Misses return a 404
|
||||
texture = m_assetService.Get(textureID.ToString());
|
||||
@@ -197,7 +197,7 @@ namespace OpenSim.Capabilities.Handlers
|
||||
}
|
||||
else // it was on the cache
|
||||
{
|
||||
// m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
|
||||
//m_log.DebugFormat("[GETTEXTURE]: texture was in the cache");
|
||||
WriteTextureData(httpRequest, httpResponse, texture, format);
|
||||
return true;
|
||||
}
|
||||
@@ -219,30 +219,12 @@ namespace OpenSim.Capabilities.Handlers
|
||||
int start, end;
|
||||
if (TryParseRange(range, out start, out end))
|
||||
{
|
||||
|
||||
// Before clamping start make sure we can satisfy it in order to avoid
|
||||
// sending back the last byte instead of an error status
|
||||
if (start >= texture.Data.Length)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}",
|
||||
texture.ID, start, texture.Data.Length);
|
||||
|
||||
// Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back
|
||||
// Requested Range Not Satisfiable (416) here. However, it appears that at least recent implementations
|
||||
// of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously
|
||||
// received a very small texture may attempt to fetch bytes from the server past the
|
||||
// range of data that it received originally. Whether this happens appears to depend on whether
|
||||
// the viewer's estimation of how large a request it needs to make for certain discard levels
|
||||
// (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard
|
||||
// level 2. If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable
|
||||
// here will cause the viewer to treat the texture as bad and never display the full resolution
|
||||
// However, if we return PartialContent (or OK) instead, the viewer will display that resolution.
|
||||
|
||||
// response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
|
||||
// response.AddHeader("Content-Range", String.Format("bytes */{0}", texture.Data.Length));
|
||||
// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
|
||||
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
|
||||
response.ContentType = texture.Metadata.ContentType;
|
||||
response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -250,18 +232,12 @@ namespace OpenSim.Capabilities.Handlers
|
||||
start = Utils.Clamp(start, 0, end);
|
||||
int len = end - start + 1;
|
||||
|
||||
// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
|
||||
//m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID);
|
||||
|
||||
// Always return PartialContent, even if the range covered the entire data length
|
||||
// We were accidentally sending back 404 before in this situation
|
||||
// https://issues.apache.org/bugzilla/show_bug.cgi?id=51878 supports sending 206 even if the
|
||||
// entire range is requested, and viewer 3.2.2 (and very probably earlier) seems fine with this.
|
||||
//
|
||||
// We also do not want to send back OK even if the whole range was satisfiable since this causes
|
||||
// HTTP textures on at least Imprudence 1.4.0-beta2 to never display the final texture quality.
|
||||
// if (end > maxEnd)
|
||||
// response.StatusCode = (int)System.Net.HttpStatusCode.OK;
|
||||
// else
|
||||
response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent;
|
||||
|
||||
response.ContentLength = len;
|
||||
|
||||
@@ -2202,5 +2202,18 @@ VALUES
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveExtra(UUID regionID, string name, string value)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveExtra(UUID regionID, string name)
|
||||
{
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetExtra(UUID regionID)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1985,5 +1985,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -895,3 +895,10 @@ CREATE TABLE `regionenvironment` (
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 45
|
||||
|
||||
BEGIN;
|
||||
|
||||
CREATE TABLE `regionextra` (`RegionID` char(36) not null, `Name` varchar(32) not null, `value` text, primary key(`RegionID`, `Name`));
|
||||
|
||||
COMMIT;
|
||||
|
||||
@@ -151,5 +151,18 @@ namespace OpenSim.Data.Null
|
||||
public void Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
public void SaveExtra(UUID regionID, string name, string value)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveExtra(UUID regionID, string name)
|
||||
{
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetExtra(UUID regionID)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2890,5 +2890,17 @@ namespace OpenSim.Data.SQLite
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveExtra(UUID regionID, string name, string value)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveExtra(UUID regionID, string name)
|
||||
{
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetExtra(UUID regionID)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -678,6 +678,8 @@ namespace OpenSim.Framework.Console
|
||||
{
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public event OnOutputDelegate OnOutput;
|
||||
|
||||
public ICommands Commands { get; private set; }
|
||||
|
||||
public CommandConsole(string defaultPrompt) : base(defaultPrompt)
|
||||
@@ -697,6 +699,13 @@ namespace OpenSim.Framework.Console
|
||||
Output(s);
|
||||
}
|
||||
|
||||
protected void FireOnOutput(string text)
|
||||
{
|
||||
OnOutputDelegate onOutput = OnOutput;
|
||||
if (onOutput != null)
|
||||
onOutput(text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display a command prompt on the console and wait for user input
|
||||
/// </summary>
|
||||
|
||||
@@ -319,6 +319,8 @@ namespace OpenSim.Framework.Console
|
||||
|
||||
public override void Output(string text, string level)
|
||||
{
|
||||
FireOnOutput(text);
|
||||
|
||||
lock (m_commandLine)
|
||||
{
|
||||
if (m_cursorYPosition == -1)
|
||||
@@ -509,4 +511,4 @@ namespace OpenSim.Framework.Console
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ namespace OpenSim.Framework.Console
|
||||
/// </summary>
|
||||
public class MockConsole : ICommandConsole
|
||||
{
|
||||
public event OnOutputDelegate OnOutput;
|
||||
|
||||
private MockCommands m_commands = new MockCommands();
|
||||
|
||||
public ICommands Commands { get { return m_commands; } }
|
||||
@@ -76,4 +78,4 @@ namespace OpenSim.Framework.Console
|
||||
public string[] Resolve(string[] cmd) { return null; }
|
||||
public XmlElement GetXml(XmlDocument doc) { return null; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,7 @@ namespace OpenSim.Framework.Console
|
||||
m_LineNumber++;
|
||||
m_Scrollback.Add(String.Format("{0}", m_LineNumber)+":"+level+":"+text);
|
||||
}
|
||||
FireOnOutput(text.Trim());
|
||||
System.Console.WriteLine(text.Trim());
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace OpenSim.Framework
|
||||
public class Constants
|
||||
{
|
||||
public const uint RegionSize = 256;
|
||||
public const uint RegionHeight = 4096;
|
||||
public const byte TerrainPatchSize = 16;
|
||||
public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f";
|
||||
|
||||
|
||||
@@ -74,8 +74,12 @@ namespace OpenSim.Framework
|
||||
XmlElement GetXml(XmlDocument doc);
|
||||
}
|
||||
|
||||
public delegate void OnOutputDelegate(string message);
|
||||
|
||||
public interface ICommandConsole : IConsole
|
||||
{
|
||||
event OnOutputDelegate OnOutput;
|
||||
|
||||
ICommands Commands { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -87,4 +91,4 @@ namespace OpenSim.Framework
|
||||
|
||||
string ReadLine(string p, bool isCommand, bool e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,9 @@ namespace OpenSim.Framework
|
||||
public UUID lastMapUUID = UUID.Zero;
|
||||
public string lastMapRefresh = "0";
|
||||
|
||||
private float m_nonphysPrimMin = 0;
|
||||
private int m_nonphysPrimMax = 0;
|
||||
private float m_physPrimMin = 0;
|
||||
private int m_physPrimMax = 0;
|
||||
private bool m_clampPrimSize = false;
|
||||
private int m_objectCapacity = 0;
|
||||
@@ -285,11 +287,21 @@ namespace OpenSim.Framework
|
||||
set { m_windlight = value; }
|
||||
}
|
||||
|
||||
public float NonphysPrimMin
|
||||
{
|
||||
get { return m_nonphysPrimMin; }
|
||||
}
|
||||
|
||||
public int NonphysPrimMax
|
||||
{
|
||||
get { return m_nonphysPrimMax; }
|
||||
}
|
||||
|
||||
public float PhysPrimMin
|
||||
{
|
||||
get { return m_physPrimMin; }
|
||||
}
|
||||
|
||||
public int PhysPrimMax
|
||||
{
|
||||
get { return m_physPrimMax; }
|
||||
@@ -623,16 +635,28 @@ namespace OpenSim.Framework
|
||||
m_regionType = config.GetString("RegionType", String.Empty);
|
||||
allKeys.Remove("RegionType");
|
||||
|
||||
// Prim stuff
|
||||
//
|
||||
#region Prim stuff
|
||||
|
||||
m_nonphysPrimMin = config.GetFloat("NonphysicalPrimMin", 0);
|
||||
allKeys.Remove("NonphysicalPrimMin");
|
||||
|
||||
m_nonphysPrimMax = config.GetInt("NonphysicalPrimMax", 0);
|
||||
allKeys.Remove("NonphysicalPrimMax");
|
||||
|
||||
m_physPrimMin = config.GetFloat("PhysicalPrimMin", 0);
|
||||
allKeys.Remove("PhysicalPrimMin");
|
||||
|
||||
m_physPrimMax = config.GetInt("PhysicalPrimMax", 0);
|
||||
allKeys.Remove("PhysicalPrimMax");
|
||||
|
||||
m_clampPrimSize = config.GetBoolean("ClampPrimSize", false);
|
||||
allKeys.Remove("ClampPrimSize");
|
||||
|
||||
m_objectCapacity = config.GetInt("MaxPrims", 15000);
|
||||
allKeys.Remove("MaxPrims");
|
||||
|
||||
#endregion
|
||||
|
||||
m_agentCapacity = config.GetInt("MaxAgents", 100);
|
||||
allKeys.Remove("MaxAgents");
|
||||
|
||||
@@ -668,10 +692,18 @@ namespace OpenSim.Framework
|
||||
|
||||
config.Set("ExternalHostName", m_externalHostName);
|
||||
|
||||
if (m_nonphysPrimMin != 0)
|
||||
config.Set("NonphysicalPrimMax", m_nonphysPrimMin);
|
||||
|
||||
if (m_nonphysPrimMax != 0)
|
||||
config.Set("NonphysicalPrimMax", m_nonphysPrimMax);
|
||||
|
||||
if (m_physPrimMin != 0)
|
||||
config.Set("PhysicalPrimMax", m_physPrimMin);
|
||||
|
||||
if (m_physPrimMax != 0)
|
||||
config.Set("PhysicalPrimMax", m_physPrimMax);
|
||||
|
||||
config.Set("ClampPrimSize", m_clampPrimSize.ToString());
|
||||
|
||||
if (m_objectCapacity != 0)
|
||||
@@ -754,9 +786,15 @@ namespace OpenSim.Framework
|
||||
configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY,
|
||||
"Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("nonphysical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT,
|
||||
"Minimum size for nonphysical prims", m_nonphysPrimMin.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Maximum size for nonphysical prims", m_nonphysPrimMax.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("physical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT,
|
||||
"Minimum size for nonphysical prims", m_physPrimMin.ToString(), true);
|
||||
|
||||
configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32,
|
||||
"Maximum size for physical prims", m_physPrimMax.ToString(), true);
|
||||
|
||||
|
||||
@@ -449,7 +449,9 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
if (TryGetStreamHandler(handlerKey, out requestHandler))
|
||||
{
|
||||
if (DebugLevel >= 3)
|
||||
LogIncomingToStreamHandler(request, requestHandler);
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found stream handler for {0} {1} {2} {3}",
|
||||
request.HttpMethod, request.Url.PathAndQuery, requestHandler.Name, requestHandler.Description);
|
||||
|
||||
response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type.
|
||||
|
||||
@@ -561,7 +563,9 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
if (DoWeHaveALLSDHandler(request.RawUrl))
|
||||
{
|
||||
if (DebugLevel >= 3)
|
||||
LogIncomingToContentTypeHandler(request);
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
buffer = HandleLLSDRequests(request, response);
|
||||
}
|
||||
@@ -569,14 +573,18 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
else if (DoWeHaveAHTTPHandler(request.RawUrl))
|
||||
{
|
||||
if (DebugLevel >= 3)
|
||||
LogIncomingToContentTypeHandler(request);
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
buffer = HandleHTTPRequest(request, response);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DebugLevel >= 3)
|
||||
LogIncomingToXmlRpcHandler(request);
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
|
||||
request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
// generic login request.
|
||||
buffer = HandleXmlRpcRequests(request, response);
|
||||
@@ -646,58 +654,6 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
}
|
||||
}
|
||||
|
||||
private void LogIncomingToStreamHandler(OSHttpRequest request, IRequestHandler requestHandler)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found stream handler for {0} {1} {2} {3}",
|
||||
request.HttpMethod, request.Url.PathAndQuery, requestHandler.Name, requestHandler.Description);
|
||||
|
||||
if (DebugLevel >= 4)
|
||||
LogIncomingInDetail(request);
|
||||
}
|
||||
|
||||
private void LogIncomingToContentTypeHandler(OSHttpRequest request)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}",
|
||||
request.ContentType, request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
if (DebugLevel >= 4)
|
||||
LogIncomingInDetail(request);
|
||||
}
|
||||
|
||||
private void LogIncomingToXmlRpcHandler(OSHttpRequest request)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
"[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}",
|
||||
request.HttpMethod, request.Url.PathAndQuery);
|
||||
|
||||
if (DebugLevel >= 4)
|
||||
LogIncomingInDetail(request);
|
||||
}
|
||||
|
||||
private void LogIncomingInDetail(OSHttpRequest request)
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(Util.Copy(request.InputStream), Encoding.UTF8))
|
||||
{
|
||||
string output;
|
||||
|
||||
if (DebugLevel == 4)
|
||||
{
|
||||
const int sampleLength = 80;
|
||||
char[] sampleChars = new char[sampleLength];
|
||||
reader.Read(sampleChars, 0, sampleLength);
|
||||
output = string.Format("[BASE HTTP SERVER]: {0}...", new string(sampleChars).Replace("\n", @"\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
output = string.Format("[BASE HTTP SERVER]: {0}", reader.ReadToEnd());
|
||||
}
|
||||
|
||||
m_log.Debug(output);
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetStreamHandler(string handlerKey, out IRequestHandler streamHandler)
|
||||
{
|
||||
string bestMatch = null;
|
||||
|
||||
@@ -29,7 +29,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using log4net;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Framework.Console;
|
||||
@@ -105,11 +104,6 @@ namespace OpenSim.Framework.Servers
|
||||
|
||||
public static void RegisterHttpConsoleCommands(ICommandConsole console)
|
||||
{
|
||||
console.Commands.AddCommand(
|
||||
"Comms", false, "show http-handlers",
|
||||
"show http-handlers",
|
||||
"Show all registered http handlers", HandleShowHttpHandlersCommand);
|
||||
|
||||
console.Commands.AddCommand(
|
||||
"Debug", false, "debug http", "debug http [<level>]",
|
||||
"Turn on inbound non-poll http request debugging.",
|
||||
@@ -117,8 +111,6 @@ namespace OpenSim.Framework.Servers
|
||||
+ "If level >= 1, then short warnings are logged when receiving bad input data.\n"
|
||||
+ "If level >= 2, then long warnings are logged when receiving bad input data.\n"
|
||||
+ "If level >= 3, then short notices about all incoming non-poll HTTP requests are logged.\n"
|
||||
+ "If level >= 4, then a sample from the beginning of the incoming data is logged.\n"
|
||||
+ "If level >= 5, then the entire incoming data is logged.\n"
|
||||
+ "If no level is specified then the current level is returned.",
|
||||
HandleDebugHttpCommand);
|
||||
}
|
||||
@@ -144,55 +136,10 @@ namespace OpenSim.Framework.Servers
|
||||
}
|
||||
else
|
||||
{
|
||||
MainConsole.Instance.Output("Usage: debug http 0..5");
|
||||
MainConsole.Instance.Output("Usage: debug http 0..3");
|
||||
}
|
||||
}
|
||||
|
||||
private static void HandleShowHttpHandlersCommand(string module, string[] args)
|
||||
{
|
||||
if (args.Length != 2)
|
||||
{
|
||||
MainConsole.Instance.Output("Usage: show http-handlers");
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder handlers = new StringBuilder();
|
||||
|
||||
lock (m_Servers)
|
||||
{
|
||||
foreach (BaseHttpServer httpServer in m_Servers.Values)
|
||||
{
|
||||
handlers.AppendFormat(
|
||||
"Registered HTTP Handlers for server at {0}:{1}\n", httpServer.ListenIPAddress, httpServer.Port);
|
||||
|
||||
handlers.AppendFormat("* XMLRPC:\n");
|
||||
foreach (String s in httpServer.GetXmlRpcHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
handlers.AppendFormat("* HTTP:\n");
|
||||
List<String> poll = httpServer.GetPollServiceHandlerKeys();
|
||||
foreach (String s in httpServer.GetHTTPHandlerKeys())
|
||||
handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty));
|
||||
|
||||
handlers.AppendFormat("* Agent:\n");
|
||||
foreach (String s in httpServer.GetAgentHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
handlers.AppendFormat("* LLSD:\n");
|
||||
foreach (String s in httpServer.GetLLSDHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
handlers.AppendFormat("* StreamHandlers ({0}):\n", httpServer.GetStreamHandlerKeys().Count);
|
||||
foreach (String s in httpServer.GetStreamHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
handlers.Append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
MainConsole.Instance.Output(handlers.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register an already started HTTP server to the collection of known servers.
|
||||
/// </summary>
|
||||
|
||||
@@ -29,8 +29,8 @@ namespace OpenSim
|
||||
{
|
||||
public class VersionInfo
|
||||
{
|
||||
private const string VERSION_NUMBER = "0.7.4";
|
||||
private const Flavour VERSION_FLAVOUR = Flavour.Extended;
|
||||
private const string VERSION_NUMBER = "0.7.5";
|
||||
private const Flavour VERSION_FLAVOUR = Flavour.Dev;
|
||||
|
||||
public enum Flavour
|
||||
{
|
||||
|
||||
@@ -1007,38 +1007,6 @@ namespace OpenSim.Framework
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy data from one stream to another, leaving the read position of both streams at the beginning.
|
||||
/// </summary>
|
||||
/// <param name='inputStream'>
|
||||
/// Input stream. Must be seekable.
|
||||
/// </param>
|
||||
/// <exception cref='ArgumentException'>
|
||||
/// Thrown if the input stream is not seekable.
|
||||
/// </exception>
|
||||
public static Stream Copy(Stream inputStream)
|
||||
{
|
||||
if (!inputStream.CanSeek)
|
||||
throw new ArgumentException("Util.Copy(Stream inputStream) must receive an inputStream that can seek");
|
||||
|
||||
const int readSize = 256;
|
||||
byte[] buffer = new byte[readSize];
|
||||
MemoryStream ms = new MemoryStream();
|
||||
|
||||
int count = inputStream.Read(buffer, 0, readSize);
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
ms.Write(buffer, 0, count);
|
||||
count = inputStream.Read(buffer, 0, readSize);
|
||||
}
|
||||
|
||||
ms.Position = 0;
|
||||
inputStream.Position = 0;
|
||||
|
||||
return ms;
|
||||
}
|
||||
|
||||
public static XmlRpcResponse XmlRpcCommand(string url, string methodName, params object[] args)
|
||||
{
|
||||
return SendXmlRpcCommand(url, methodName, args);
|
||||
|
||||
@@ -332,6 +332,10 @@ namespace OpenSim
|
||||
"show circuits",
|
||||
"Show agent circuit data", HandleShow);
|
||||
|
||||
m_console.Commands.AddCommand("Comms", false, "show http-handlers",
|
||||
"show http-handlers",
|
||||
"Show all registered http handlers", HandleShow);
|
||||
|
||||
m_console.Commands.AddCommand("Comms", false, "show pending-objects",
|
||||
"show pending-objects",
|
||||
"Show # of objects on the pending queues of all scene viewers", HandleShow);
|
||||
@@ -416,6 +420,7 @@ namespace OpenSim
|
||||
{
|
||||
RunCommandScript(m_shutdownCommandsFile);
|
||||
}
|
||||
|
||||
base.ShutdownSpecific();
|
||||
}
|
||||
|
||||
@@ -1008,6 +1013,33 @@ namespace OpenSim
|
||||
HandleShowCircuits();
|
||||
break;
|
||||
|
||||
case "http-handlers":
|
||||
System.Text.StringBuilder handlers = new System.Text.StringBuilder("Registered HTTP Handlers:\n");
|
||||
|
||||
handlers.AppendFormat("* XMLRPC:\n");
|
||||
foreach (String s in HttpServer.GetXmlRpcHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
handlers.AppendFormat("* HTTP:\n");
|
||||
List<String> poll = HttpServer.GetPollServiceHandlerKeys();
|
||||
foreach (String s in HttpServer.GetHTTPHandlerKeys())
|
||||
handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty));
|
||||
|
||||
handlers.AppendFormat("* Agent:\n");
|
||||
foreach (String s in HttpServer.GetAgentHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
handlers.AppendFormat("* LLSD:\n");
|
||||
foreach (String s in HttpServer.GetLLSDHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
handlers.AppendFormat("* StreamHandlers ({0}):\n", HttpServer.GetStreamHandlerKeys().Count);
|
||||
foreach (String s in HttpServer.GetStreamHandlerKeys())
|
||||
handlers.AppendFormat("\t{0}\n", s);
|
||||
|
||||
MainConsole.Instance.Output(handlers.ToString());
|
||||
break;
|
||||
|
||||
case "modules":
|
||||
MainConsole.Instance.Output("The currently loaded shared modules are:");
|
||||
foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules)
|
||||
|
||||
234
OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
Normal file
234
OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,6 +107,8 @@ namespace Flotsam.RegionModules.AssetCache
|
||||
private IAssetService m_AssetService;
|
||||
private List<Scene> m_Scenes = new List<Scene>();
|
||||
|
||||
private bool m_DeepScanBeforePurge;
|
||||
|
||||
public FlotsamAssetCache()
|
||||
{
|
||||
m_InvalidChars.AddRange(Path.GetInvalidPathChars());
|
||||
@@ -168,6 +170,8 @@ namespace Flotsam.RegionModules.AssetCache
|
||||
m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen);
|
||||
|
||||
m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt);
|
||||
|
||||
m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge);
|
||||
}
|
||||
|
||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory);
|
||||
@@ -502,10 +506,13 @@ namespace Flotsam.RegionModules.AssetCache
|
||||
// Purge all files last accessed prior to this point
|
||||
DateTime purgeLine = DateTime.Now - m_FileExpiration;
|
||||
|
||||
// An asset cache may contain local non-temporary assets that are not in the asset service. Therefore,
|
||||
// before cleaning up expired files we must scan the objects in the scene to make sure that we retain
|
||||
// such local assets if they have not been recently accessed.
|
||||
TouchAllSceneAssets(false);
|
||||
// An optional deep scan at this point will ensure assets present in scenes,
|
||||
// or referenced by objects in the scene, but not recently accessed
|
||||
// are not purged.
|
||||
if (m_DeepScanBeforePurge)
|
||||
{
|
||||
CacheScenes();
|
||||
}
|
||||
|
||||
foreach (string dir in Directory.GetDirectories(m_CacheDirectory))
|
||||
{
|
||||
@@ -698,14 +705,11 @@ namespace Flotsam.RegionModules.AssetCache
|
||||
|
||||
/// <summary>
|
||||
/// Iterates through all Scenes, doing a deep scan through assets
|
||||
/// to update the access time of all assets present in the scene or referenced by assets
|
||||
/// in the scene.
|
||||
/// to cache all assets present in the scene or referenced by assets
|
||||
/// in the scene
|
||||
/// </summary>
|
||||
/// <param name="storeUncached">
|
||||
/// If true, then assets scanned which are not found in cache are added to the cache.
|
||||
/// </param>
|
||||
/// <returns>Number of distinct asset references found in the scene.</returns>
|
||||
private int TouchAllSceneAssets(bool storeUncached)
|
||||
/// <returns></returns>
|
||||
private int CacheScenes()
|
||||
{
|
||||
UuidGatherer gatherer = new UuidGatherer(m_AssetService);
|
||||
|
||||
@@ -728,7 +732,7 @@ namespace Flotsam.RegionModules.AssetCache
|
||||
{
|
||||
File.SetLastAccessTime(filename, DateTime.Now);
|
||||
}
|
||||
else if (storeUncached)
|
||||
else
|
||||
{
|
||||
m_AssetService.Get(assetID.ToString());
|
||||
}
|
||||
@@ -856,14 +860,13 @@ namespace Flotsam.RegionModules.AssetCache
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case "assets":
|
||||
m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes.");
|
||||
m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes.");
|
||||
|
||||
Util.FireAndForget(delegate {
|
||||
int assetReferenceTotal = TouchAllSceneAssets(true);
|
||||
m_log.InfoFormat(
|
||||
"[FLOTSAM ASSET CACHE]: Completed check with {0} assets.",
|
||||
assetReferenceTotal);
|
||||
int assetsCached = CacheScenes();
|
||||
m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached);
|
||||
});
|
||||
|
||||
break;
|
||||
|
||||
@@ -239,7 +239,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
sp.ClearAttachments();
|
||||
}
|
||||
|
||||
public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent)
|
||||
public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool temp)
|
||||
{
|
||||
lock (sp.AttachmentsSyncLock)
|
||||
{
|
||||
@@ -298,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
group.AbsolutePosition = attachPos;
|
||||
|
||||
if (sp.PresenceType != PresenceType.Npc)
|
||||
UpdateUserInventoryWithAttachment(sp, group, attachmentPt);
|
||||
UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp);
|
||||
|
||||
AttachToAgent(sp, group, attachmentPt, attachPos, silent);
|
||||
}
|
||||
@@ -306,7 +306,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
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
|
||||
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
|
||||
@@ -316,18 +316,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
{
|
||||
if (attachments[0].FromItemID != UUID.Zero)
|
||||
DetachSingleAttachmentToInvInternal(sp, attachments[0]);
|
||||
else
|
||||
m_log.WarnFormat(
|
||||
"[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);
|
||||
// Error logging commented because UUID.Zero now means temp attachment
|
||||
// else
|
||||
// m_log.WarnFormat(
|
||||
// "[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.
|
||||
UUID newAttachmentItemID = group.FromItemID;
|
||||
if (newAttachmentItemID == UUID.Zero)
|
||||
newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
|
||||
if (!temp)
|
||||
{
|
||||
UUID newAttachmentItemID = group.FromItemID;
|
||||
if (newAttachmentItemID == UUID.Zero)
|
||||
newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
|
||||
|
||||
ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
|
||||
ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
|
||||
}
|
||||
}
|
||||
|
||||
public SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt)
|
||||
@@ -406,6 +410,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
|
||||
UUID inventoryID = so.FromItemID;
|
||||
|
||||
// As per Linden spec, drop is disabled for temp attachs
|
||||
if (inventoryID == UUID.Zero)
|
||||
return;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[ATTACHMENTS MODULE]: In DetachSingleAttachmentToGround(), object is {0} {1}, associated item is {2}",
|
||||
// so.Name, so.LocalId, inventoryID);
|
||||
@@ -416,7 +424,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
so.PrimCount, sp.UUID, sp.AbsolutePosition))
|
||||
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)
|
||||
m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
|
||||
|
||||
@@ -521,6 +531,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
/// <param name="saveAllScripted"></param>
|
||||
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!
|
||||
INPCModule module = m_scene.RequestModuleInterface<INPCModule>();
|
||||
if (module != null)
|
||||
@@ -777,7 +794,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
// This will throw if the attachment fails
|
||||
try
|
||||
{
|
||||
AttachObject(sp, objatt, attachmentPt, false);
|
||||
AttachObject(sp, objatt, attachmentPt, false, false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -931,7 +948,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
AttachmentPt &= 0x7f;
|
||||
|
||||
// Calls attach with a Zero position
|
||||
if (AttachObject(sp, part.ParentGroup, AttachmentPt, false))
|
||||
if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, false))
|
||||
{
|
||||
// m_log.Debug(
|
||||
// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
|
||||
@@ -955,7 +972,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
|
||||
SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
|
||||
|
||||
if (sp != null && group != null)
|
||||
if (sp != null && group != null && group.FromItemID != UUID.Zero)
|
||||
DetachSingleAttachmentToInv(sp, group);
|
||||
}
|
||||
|
||||
@@ -973,7 +990,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||
|
||||
foreach (SceneObjectGroup group in attachments)
|
||||
{
|
||||
if (group.FromItemID == itemID)
|
||||
if (group.FromItemID == itemID && group.FromItemID != UUID.Zero)
|
||||
{
|
||||
DetachSingleAttachmentToInv(sp, group);
|
||||
return;
|
||||
|
||||
@@ -189,7 +189,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
|
||||
|
||||
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false);
|
||||
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false);
|
||||
|
||||
// Check status on scene presence
|
||||
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.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
|
||||
|
||||
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false);
|
||||
scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false);
|
||||
|
||||
Assert.That(sp.HasAttachments(), Is.False);
|
||||
Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
|
||||
|
||||
@@ -482,9 +482,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends
|
||||
Util.FireAndForget(
|
||||
delegate
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}",
|
||||
// friendList.Count, agentID, online);
|
||||
m_log.DebugFormat(
|
||||
"[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}",
|
||||
friendList.Count, agentID, online);
|
||||
|
||||
// Notify about this user status
|
||||
StatusNotify(friendList, agentID, online);
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
{
|
||||
public class DynamicTextureModule : IRegionModule, IDynamicTextureManager
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
//private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private const int ALL_SIDES = -1;
|
||||
|
||||
@@ -54,17 +54,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
/// </summary>
|
||||
public bool ReuseTextures { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If false, then textures which have a low data size are not reused when ReuseTextures = true.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those
|
||||
/// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen
|
||||
/// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is
|
||||
/// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused
|
||||
/// to work around this problem.</remarks>
|
||||
public bool ReuseLowDataTextures { get; set; }
|
||||
|
||||
private Dictionary<UUID, Scene> RegisteredScenes = new Dictionary<UUID, Scene>();
|
||||
|
||||
private Dictionary<string, IDynamicTextureRender> RenderPlugins =
|
||||
@@ -94,17 +83,18 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
/// <summary>
|
||||
/// Called by code which actually renders the dynamic texture to supply texture data.
|
||||
/// </summary>
|
||||
/// <param name="updaterId"></param>
|
||||
/// <param name="texture"></param>
|
||||
public void ReturnData(UUID updaterId, IDynamicTexture texture)
|
||||
/// <param name="id"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="isReuseable">True if the data generated can be reused for subsequent identical requests</param>
|
||||
public void ReturnData(UUID id, byte[] data, bool isReuseable)
|
||||
{
|
||||
DynamicTextureUpdater updater = null;
|
||||
|
||||
lock (Updaters)
|
||||
{
|
||||
if (Updaters.ContainsKey(updaterId))
|
||||
if (Updaters.ContainsKey(id))
|
||||
{
|
||||
updater = Updaters[updaterId];
|
||||
updater = Updaters[id];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,16 +103,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
if (RegisteredScenes.ContainsKey(updater.SimUUID))
|
||||
{
|
||||
Scene scene = RegisteredScenes[updater.SimUUID];
|
||||
UUID newTextureID = updater.DataReceived(texture.Data, scene);
|
||||
UUID newTextureID = updater.DataReceived(data, scene);
|
||||
|
||||
if (ReuseTextures
|
||||
&& !updater.BlendWithOldTexture
|
||||
&& texture.IsReuseable
|
||||
&& (ReuseLowDataTextures || IsDataSizeReuseable(texture)))
|
||||
{
|
||||
if (ReuseTextures && isReuseable && !updater.BlendWithOldTexture)
|
||||
m_reuseableDynamicTextures.Store(
|
||||
GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID);
|
||||
}
|
||||
GenerateReusableTextureKey(updater.BodyData, updater.Params), newTextureID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,27 +123,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the texture is reuseable based on its data size.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a workaround for a viewer bug where very small data size textures relative to their pixel size
|
||||
/// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard
|
||||
/// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5).
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
private bool IsDataSizeReuseable(IDynamicTexture texture)
|
||||
{
|
||||
// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height);
|
||||
int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5);
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}",
|
||||
// discardLevel2DataThreshold, texture.Data.Length);
|
||||
|
||||
return discardLevel2DataThreshold < texture.Data.Length;
|
||||
}
|
||||
|
||||
public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url,
|
||||
string extraParams, int updateTimer)
|
||||
{
|
||||
@@ -285,18 +249,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
}
|
||||
}
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}",
|
||||
// part.Name, part.ParentGroup.Scene.Name);
|
||||
|
||||
RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
// m_log.DebugFormat(
|
||||
// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}",
|
||||
// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name);
|
||||
|
||||
// No need to add to updaters as the texture is always the same. Not that this functionality
|
||||
// apppears to be implemented anyway.
|
||||
updater.UpdatePart(part, (UUID)objReusableTextureUUID);
|
||||
@@ -329,10 +285,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
{
|
||||
IConfig texturesConfig = config.Configs["Textures"];
|
||||
if (texturesConfig != null)
|
||||
{
|
||||
ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false);
|
||||
ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false);
|
||||
}
|
||||
|
||||
if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID))
|
||||
{
|
||||
@@ -495,10 +448,8 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface<IJ2KDecoder>();
|
||||
if (cacheLayerDecode != null)
|
||||
{
|
||||
if (!cacheLayerDecode.Decode(asset.FullID, asset.Data))
|
||||
m_log.WarnFormat(
|
||||
"[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed",
|
||||
asset.ID, part.Name, part.ParentGroup.Scene.Name);
|
||||
cacheLayerDecode.Decode(asset.FullID, asset.Data);
|
||||
cacheLayerDecode = null;
|
||||
}
|
||||
|
||||
UUID oldID = UpdatePart(part, asset.FullID);
|
||||
|
||||
@@ -84,6 +84,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
public string body;
|
||||
public int responseCode;
|
||||
public string responseBody;
|
||||
public string responseType = "text/plain";
|
||||
//public ManualResetEvent ev;
|
||||
public bool requestDone;
|
||||
public int startTime;
|
||||
@@ -302,6 +303,22 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
}
|
||||
}
|
||||
|
||||
public void HttpContentType(UUID request, string type)
|
||||
{
|
||||
lock (m_UrlMap)
|
||||
{
|
||||
if (m_RequestMap.ContainsKey(request))
|
||||
{
|
||||
UrlData urlData = m_RequestMap[request];
|
||||
urlData.requests[request].responseType = type;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void HttpResponse(UUID request, int status, string body)
|
||||
{
|
||||
lock (m_UrlMap)
|
||||
@@ -504,7 +521,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
|
||||
//put response
|
||||
response["int_response_code"] = requestData.responseCode;
|
||||
response["str_response_string"] = requestData.responseBody;
|
||||
response["content_type"] = "text/plain";
|
||||
response["content_type"] = requestData.responseType;
|
||||
// response["content_type"] = "text/plain";
|
||||
response["keepalive"] = false;
|
||||
response["reusecontext"] = false;
|
||||
|
||||
|
||||
@@ -32,7 +32,6 @@ using System.Net;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Imaging;
|
||||
using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using log4net;
|
||||
@@ -74,12 +73,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||
// return false;
|
||||
// }
|
||||
|
||||
public IDynamicTexture ConvertUrl(string url, string extraParams)
|
||||
public byte[] ConvertUrl(string url, string extraParams)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IDynamicTexture ConvertData(string bodyData, string extraParams)
|
||||
public byte[] ConvertData(string bodyData, string extraParams)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -172,11 +171,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||
|
||||
private void HttpRequestReturn(IAsyncResult result)
|
||||
{
|
||||
|
||||
RequestState state = (RequestState) result.AsyncState;
|
||||
WebRequest request = (WebRequest) state.Request;
|
||||
Stream stream = null;
|
||||
byte[] imageJ2000 = new byte[0];
|
||||
Size newSize = new Size(0, 0);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -189,43 +188,37 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||
try
|
||||
{
|
||||
Bitmap image = new Bitmap(stream);
|
||||
Size newsize;
|
||||
|
||||
// TODO: make this a bit less hard coded
|
||||
if ((image.Height < 64) && (image.Width < 64))
|
||||
{
|
||||
newSize.Width = 32;
|
||||
newSize.Height = 32;
|
||||
newsize = new Size(32, 32);
|
||||
}
|
||||
else if ((image.Height < 128) && (image.Width < 128))
|
||||
{
|
||||
newSize.Width = 64;
|
||||
newSize.Height = 64;
|
||||
newsize = new Size(64, 64);
|
||||
}
|
||||
else if ((image.Height < 256) && (image.Width < 256))
|
||||
{
|
||||
newSize.Width = 128;
|
||||
newSize.Height = 128;
|
||||
newsize = new Size(128, 128);
|
||||
}
|
||||
else if ((image.Height < 512 && image.Width < 512))
|
||||
{
|
||||
newSize.Width = 256;
|
||||
newSize.Height = 256;
|
||||
newsize = new Size(256, 256);
|
||||
}
|
||||
else if ((image.Height < 1024 && image.Width < 1024))
|
||||
{
|
||||
newSize.Width = 512;
|
||||
newSize.Height = 512;
|
||||
newsize = new Size(512, 512);
|
||||
}
|
||||
else
|
||||
{
|
||||
newSize.Width = 1024;
|
||||
newSize.Height = 1024;
|
||||
newsize = new Size(1024, 1024);
|
||||
}
|
||||
|
||||
using (Bitmap resize = new Bitmap(image, newSize))
|
||||
{
|
||||
imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
|
||||
}
|
||||
Bitmap resize = new Bitmap(image, newsize);
|
||||
|
||||
imageJ2000 = OpenJPEG.EncodeFromImage(resize, true);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
@@ -240,6 +233,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||
}
|
||||
catch (WebException)
|
||||
{
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -249,13 +243,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL
|
||||
}
|
||||
}
|
||||
|
||||
m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}",
|
||||
m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}",
|
||||
imageJ2000.Length, state.RequestID);
|
||||
|
||||
m_textureManager.ReturnData(
|
||||
state.RequestID,
|
||||
new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
|
||||
request.RequestUri, null, imageJ2000, newSize, false));
|
||||
m_textureManager.ReturnData(state.RequestID, imageJ2000, false);
|
||||
}
|
||||
|
||||
#region Nested type: RequestState
|
||||
|
||||
@@ -57,7 +57,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
|
||||
|
||||
m_dtm = new DynamicTextureModule();
|
||||
m_dtm.ReuseTextures = reuseTextures;
|
||||
// m_dtm.ReuseLowDataTextures = reuseTextures;
|
||||
|
||||
m_vrm = new VectorRenderModule();
|
||||
|
||||
@@ -202,7 +201,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
|
||||
public void TestRepeatSameDrawReusingTexture()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
|
||||
|
||||
@@ -230,46 +228,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests
|
||||
Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test a low data dynamically generated texture such that it is treated as a low data texture that causes
|
||||
/// problems for current viewers.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the
|
||||
/// texture
|
||||
/// </remarks>
|
||||
[Test]
|
||||
public void TestRepeatSameDrawLowDataTexture()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;";
|
||||
|
||||
SetupScene(true);
|
||||
SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene);
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"1024",
|
||||
0);
|
||||
|
||||
UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID;
|
||||
|
||||
m_dtm.AddDynamicTextureData(
|
||||
m_scene.RegionInfo.RegionID,
|
||||
so.UUID,
|
||||
m_vrm.GetContentType(),
|
||||
dtText,
|
||||
"1024",
|
||||
0);
|
||||
|
||||
Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRepeatSameDrawDifferentExtraParamsReusingTexture()
|
||||
{
|
||||
|
||||
@@ -35,7 +35,6 @@ using System.Net;
|
||||
using Nini.Config;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Imaging;
|
||||
using OpenSim.Region.CoreModules.Scripting.DynamicTexture;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using log4net;
|
||||
@@ -47,11 +46,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
{
|
||||
public class VectorRenderModule : IRegionModule, IDynamicTextureRender
|
||||
{
|
||||
// These fields exist for testing purposes, please do not remove.
|
||||
// private static bool s_flipper;
|
||||
// private static byte[] s_asset1Data;
|
||||
// private static byte[] s_asset2Data;
|
||||
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private Scene m_scene;
|
||||
@@ -86,14 +80,20 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
// return lines.Any((str, r) => str.StartsWith("Image"));
|
||||
// }
|
||||
|
||||
public IDynamicTexture ConvertUrl(string url, string extraParams)
|
||||
public byte[] ConvertUrl(string url, string extraParams)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public IDynamicTexture ConvertData(string bodyData, string extraParams)
|
||||
public byte[] ConvertData(string bodyData, string extraParams)
|
||||
{
|
||||
return Draw(bodyData, extraParams);
|
||||
bool reuseable;
|
||||
return Draw(bodyData, extraParams, out reuseable);
|
||||
}
|
||||
|
||||
private byte[] ConvertData(string bodyData, string extraParams, out bool reuseable)
|
||||
{
|
||||
return Draw(bodyData, extraParams, out reuseable);
|
||||
}
|
||||
|
||||
public bool AsyncConvertUrl(UUID id, string url, string extraParams)
|
||||
@@ -104,7 +104,10 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
public bool AsyncConvertData(UUID id, string bodyData, string extraParams)
|
||||
{
|
||||
// XXX: This isn't actually being done asynchronously!
|
||||
m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams));
|
||||
bool reuseable;
|
||||
byte[] data = ConvertData(bodyData, extraParams, out reuseable);
|
||||
|
||||
m_textureManager.ReturnData(id, data, reuseable);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -158,13 +161,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
{
|
||||
m_textureManager.RegisterRender(GetContentType(), this);
|
||||
}
|
||||
|
||||
// This code exists for testing purposes, please do not remove.
|
||||
// s_asset1Data = m_scene.AssetService.Get("00000000-0000-1111-9999-000000000001").Data;
|
||||
// s_asset1Data = m_scene.AssetService.Get("9f4acf0d-1841-4e15-bdb8-3a12efc9dd8f").Data;
|
||||
|
||||
// Terrain dirt - smallest bin/assets file (6004 bytes)
|
||||
// s_asset2Data = m_scene.AssetService.Get("b8d3965a-ad78-bf43-699b-bff8eca6c975").Data;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
@@ -183,7 +179,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
|
||||
#endregion
|
||||
|
||||
private IDynamicTexture Draw(string data, string extraParams)
|
||||
private byte[] Draw(string data, string extraParams, out bool reuseable)
|
||||
{
|
||||
// We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha
|
||||
// we will now support multiple comma seperated params in the form width:256,height:512,alpha:255
|
||||
@@ -326,7 +322,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
|
||||
Bitmap bitmap = null;
|
||||
Graphics graph = null;
|
||||
bool reuseable = false;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -369,14 +364,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
}
|
||||
|
||||
byte[] imageJ2000 = new byte[0];
|
||||
|
||||
// This code exists for testing purposes, please do not remove.
|
||||
// if (s_flipper)
|
||||
// imageJ2000 = s_asset1Data;
|
||||
// else
|
||||
// imageJ2000 = s_asset2Data;
|
||||
//
|
||||
// s_flipper = !s_flipper;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -389,8 +376,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender
|
||||
e.Message, e.StackTrace);
|
||||
}
|
||||
|
||||
return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture(
|
||||
data, extraParams, imageJ2000, new Size(width, height), reuseable);
|
||||
return imageJ2000;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -204,11 +204,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset
|
||||
public byte[] GetData(string id)
|
||||
{
|
||||
// m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id);
|
||||
|
||||
AssetBase asset = null;
|
||||
|
||||
if (m_Cache != null)
|
||||
asset = m_Cache.Get(id);
|
||||
|
||||
AssetBase asset = m_Cache.Get(id);
|
||||
|
||||
if (asset != null)
|
||||
return asset.Data;
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
* 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.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using log4net.Config;
|
||||
using Nini.Config;
|
||||
using NUnit.Framework;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset;
|
||||
using OpenSim.Tests.Common;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class AssetConnectorsTests : OpenSimTestCase
|
||||
{
|
||||
[Test]
|
||||
public void TestAddAsset()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
IConfigSource config = new IniConfigSource();
|
||||
config.AddConfig("Modules");
|
||||
config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
|
||||
config.AddConfig("AssetService");
|
||||
config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
|
||||
config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
|
||||
|
||||
LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
|
||||
lasc.Initialise(config);
|
||||
|
||||
AssetBase a1 = AssetHelpers.CreateNotecardAsset();
|
||||
lasc.Store(a1);
|
||||
|
||||
AssetBase retreivedA1 = lasc.Get(a1.ID);
|
||||
Assert.That(retreivedA1.ID, Is.EqualTo(a1.ID));
|
||||
Assert.That(retreivedA1.Metadata.ID, Is.EqualTo(a1.Metadata.ID));
|
||||
Assert.That(retreivedA1.Data.Length, Is.EqualTo(a1.Data.Length));
|
||||
|
||||
AssetMetadata retrievedA1Metadata = lasc.GetMetadata(a1.ID);
|
||||
Assert.That(retrievedA1Metadata.ID, Is.EqualTo(a1.ID));
|
||||
|
||||
byte[] retrievedA1Data = lasc.GetData(a1.ID);
|
||||
Assert.That(retrievedA1Data.Length, Is.EqualTo(a1.Data.Length));
|
||||
|
||||
// TODO: Add cache and check that this does receive a copy of the asset
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddTemporaryAsset()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
IConfigSource config = new IniConfigSource();
|
||||
config.AddConfig("Modules");
|
||||
config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
|
||||
config.AddConfig("AssetService");
|
||||
config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
|
||||
config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
|
||||
|
||||
LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
|
||||
lasc.Initialise(config);
|
||||
|
||||
AssetBase a1 = AssetHelpers.CreateNotecardAsset();
|
||||
a1.Temporary = true;
|
||||
|
||||
lasc.Store(a1);
|
||||
|
||||
Assert.That(lasc.Get(a1.ID), Is.Null);
|
||||
Assert.That(lasc.GetData(a1.ID), Is.Null);
|
||||
Assert.That(lasc.GetMetadata(a1.ID), Is.Null);
|
||||
|
||||
// TODO: Add cache and check that this does receive a copy of the asset
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestAddLocalAsset()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
IConfigSource config = new IniConfigSource();
|
||||
config.AddConfig("Modules");
|
||||
config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector");
|
||||
config.AddConfig("AssetService");
|
||||
config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService");
|
||||
config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
|
||||
|
||||
LocalAssetServicesConnector lasc = new LocalAssetServicesConnector();
|
||||
lasc.Initialise(config);
|
||||
|
||||
AssetBase a1 = AssetHelpers.CreateNotecardAsset();
|
||||
a1.Local = true;
|
||||
|
||||
lasc.Store(a1);
|
||||
|
||||
Assert.That(lasc.Get(a1.ID), Is.Null);
|
||||
Assert.That(lasc.GetData(a1.ID), Is.Null);
|
||||
Assert.That(lasc.GetMetadata(a1.ID), Is.Null);
|
||||
|
||||
// TODO: Add cache and check that this does receive a copy of the asset
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ using OpenSim.Tests.Common;
|
||||
namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class GridConnectorsTests : OpenSimTestCase
|
||||
public class GridConnectorsTests
|
||||
{
|
||||
LocalGridServicesConnector m_LocalConnector;
|
||||
private void SetUp()
|
||||
|
||||
@@ -97,6 +97,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to cache lookups for valid groups.
|
||||
/// </summary>
|
||||
private IDictionary<UUID, bool> m_validGroupUuids = new Dictionary<UUID, bool>();
|
||||
|
||||
private IGroupsModule m_groupsModule;
|
||||
|
||||
public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId)
|
||||
{
|
||||
m_scene = scene;
|
||||
@@ -120,6 +127,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
|
||||
// Zero can never be a valid user id
|
||||
m_validUserUuids[UUID.Zero] = false;
|
||||
|
||||
m_groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
|
||||
}
|
||||
|
||||
public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId)
|
||||
@@ -132,6 +141,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
|
||||
// Zero can never be a valid user id
|
||||
m_validUserUuids[UUID.Zero] = false;
|
||||
|
||||
m_groupsModule = m_scene.RequestModuleInterface<IGroupsModule>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -302,6 +313,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
if (!ResolveUserUuid(part.LastOwnerID))
|
||||
part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
|
||||
if (!ResolveGroupUuid(part.GroupID))
|
||||
part.GroupID = UUID.Zero;
|
||||
|
||||
// And zap any troublesome sit target information
|
||||
// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
|
||||
// part.SitTargetPosition = new Vector3(0, 0, 0);
|
||||
@@ -318,13 +332,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
{
|
||||
kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
}
|
||||
|
||||
if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty)
|
||||
{
|
||||
if (!ResolveUserUuid(kvp.Value.CreatorID))
|
||||
kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
}
|
||||
|
||||
if (UserManager != null)
|
||||
UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData);
|
||||
|
||||
if (!ResolveGroupUuid(kvp.Value.GroupID))
|
||||
kvp.Value.GroupID = UUID.Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -364,9 +383,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
foreach (string serialisedParcel in serialisedParcels)
|
||||
{
|
||||
LandData parcel = LandDataSerializer.Deserialize(serialisedParcel);
|
||||
|
||||
// Validate User and Group UUID's
|
||||
|
||||
if (!ResolveUserUuid(parcel.OwnerID))
|
||||
parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
|
||||
|
||||
|
||||
if (!ResolveGroupUuid(parcel.GroupID))
|
||||
{
|
||||
parcel.GroupID = UUID.Zero;
|
||||
parcel.IsGroupOwned = false;
|
||||
}
|
||||
|
||||
List<LandAccessEntry> accessList = new List<LandAccessEntry>();
|
||||
foreach (LandAccessEntry entry in parcel.ParcelAccessList)
|
||||
{
|
||||
if (ResolveUserUuid(entry.AgentID))
|
||||
accessList.Add(entry);
|
||||
// else, drop this access rule
|
||||
}
|
||||
parcel.ParcelAccessList = accessList;
|
||||
|
||||
// m_log.DebugFormat(
|
||||
// "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}",
|
||||
// parcel.Name, parcel.LocalID, parcel.Area);
|
||||
@@ -401,6 +438,30 @@ namespace OpenSim.Region.CoreModules.World.Archiver
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Look up the given group id to check whether it's one that is valid for this grid.
|
||||
/// </summary>
|
||||
/// <param name="uuid"></param>
|
||||
/// <returns></returns>
|
||||
private bool ResolveGroupUuid(UUID uuid)
|
||||
{
|
||||
if (uuid == UUID.Zero)
|
||||
return true; // this means the object has no group
|
||||
|
||||
if (!m_validGroupUuids.ContainsKey(uuid))
|
||||
{
|
||||
bool exists;
|
||||
|
||||
if (m_groupsModule == null)
|
||||
exists = false;
|
||||
else
|
||||
exists = (m_groupsModule.GetGroupRecord(uuid) != null);
|
||||
|
||||
m_validGroupUuids.Add(uuid, exists);
|
||||
}
|
||||
|
||||
return m_validGroupUuids[uuid];
|
||||
}
|
||||
|
||||
/// Load an asset
|
||||
/// </summary>
|
||||
/// <param name="assetFilename"></param>
|
||||
|
||||
@@ -51,7 +51,7 @@ using RegionSettings = OpenSim.Framework.RegionSettings;
|
||||
namespace OpenSim.Region.CoreModules.World.Archiver.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class ArchiverTests : OpenSimTestCase
|
||||
public class ArchiverTests
|
||||
{
|
||||
private Guid m_lastRequestId;
|
||||
private string m_lastErrorMessage;
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.World.Land
|
||||
/// without recounting the whole sim.
|
||||
///
|
||||
/// We start out tainted so that the first get call resets the various prim counts.
|
||||
/// </value>
|
||||
/// <value>
|
||||
private bool m_Tainted = true;
|
||||
|
||||
private Object m_TaintLock = new Object();
|
||||
|
||||
@@ -414,6 +414,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
private void LoadPlugins()
|
||||
{
|
||||
m_plugineffects = new Dictionary<string, ITerrainEffect>();
|
||||
LoadPlugins(Assembly.GetCallingAssembly());
|
||||
string plugineffectsPath = "Terrain";
|
||||
|
||||
// Load the files in the Terrain/ dir
|
||||
@@ -427,32 +428,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
try
|
||||
{
|
||||
Assembly library = Assembly.LoadFrom(file);
|
||||
foreach (Type pluginType in library.GetTypes())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (pluginType.IsAbstract || pluginType.IsNotPublic)
|
||||
continue;
|
||||
|
||||
string typeName = pluginType.Name;
|
||||
|
||||
if (pluginType.GetInterface("ITerrainEffect", false) != null)
|
||||
{
|
||||
ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString()));
|
||||
|
||||
InstallPlugin(typeName, terEffect);
|
||||
}
|
||||
else if (pluginType.GetInterface("ITerrainLoader", false) != null)
|
||||
{
|
||||
ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString()));
|
||||
m_loaders[terLoader.FileExtension] = terLoader;
|
||||
m_log.Info("L ... " + typeName);
|
||||
}
|
||||
}
|
||||
catch (AmbiguousMatchException)
|
||||
{
|
||||
}
|
||||
}
|
||||
LoadPlugins(library);
|
||||
}
|
||||
catch (BadImageFormatException)
|
||||
{
|
||||
@@ -460,6 +436,36 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadPlugins(Assembly library)
|
||||
{
|
||||
foreach (Type pluginType in library.GetTypes())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (pluginType.IsAbstract || pluginType.IsNotPublic)
|
||||
continue;
|
||||
|
||||
string typeName = pluginType.Name;
|
||||
|
||||
if (pluginType.GetInterface("ITerrainEffect", false) != null)
|
||||
{
|
||||
ITerrainEffect terEffect = (ITerrainEffect)Activator.CreateInstance(library.GetType(pluginType.ToString()));
|
||||
|
||||
InstallPlugin(typeName, terEffect);
|
||||
}
|
||||
else if (pluginType.GetInterface("ITerrainLoader", false) != null)
|
||||
{
|
||||
ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString()));
|
||||
m_loaders[terLoader.FileExtension] = terLoader;
|
||||
m_log.Info("L ... " + typeName);
|
||||
}
|
||||
}
|
||||
catch (AmbiguousMatchException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void InstallPlugin(string pluginName, ITerrainEffect effect)
|
||||
{
|
||||
lock (m_plugineffects)
|
||||
@@ -1176,7 +1182,8 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
|
||||
private void InterfaceRunPluginEffect(Object[] args)
|
||||
{
|
||||
if ((string) args[0] == "list")
|
||||
string firstArg = (string)args[0];
|
||||
if (firstArg == "list")
|
||||
{
|
||||
m_log.Info("List of loaded plugins");
|
||||
foreach (KeyValuePair<string, ITerrainEffect> kvp in m_plugineffects)
|
||||
@@ -1185,14 +1192,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((string) args[0] == "reload")
|
||||
if (firstArg == "reload")
|
||||
{
|
||||
LoadPlugins();
|
||||
return;
|
||||
}
|
||||
if (m_plugineffects.ContainsKey((string) args[0]))
|
||||
if (m_plugineffects.ContainsKey(firstArg))
|
||||
{
|
||||
m_plugineffects[(string) args[0]].RunEffect(m_channel);
|
||||
m_plugineffects[firstArg].RunEffect(m_channel);
|
||||
CheckForTerrainUpdates();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -208,6 +208,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height);
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()");
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@@ -673,4 +676,4 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// <param name="AttachmentPt"></param>
|
||||
/// <param name="silent"></param>
|
||||
/// <returns>true if the object was successfully attached, false otherwise</returns>
|
||||
bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent);
|
||||
bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool temp);
|
||||
|
||||
/// <summary>
|
||||
/// Rez an attachment from user inventory and change inventory status to match.
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using OpenMetaverse;
|
||||
|
||||
@@ -35,14 +33,7 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
public interface IDynamicTextureManager
|
||||
{
|
||||
void RegisterRender(string handleType, IDynamicTextureRender render);
|
||||
|
||||
/// <summary>
|
||||
/// Used by IDynamicTextureRender implementations to return renders
|
||||
/// </summary>
|
||||
/// <param name='id'></param>
|
||||
/// <param name='data'></param>
|
||||
/// <param name='isReuseable'></param>
|
||||
void ReturnData(UUID id, IDynamicTexture texture);
|
||||
void ReturnData(UUID id, byte[] data, bool isReuseable);
|
||||
|
||||
UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams,
|
||||
int updateTimer);
|
||||
@@ -134,53 +125,11 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
// /// <param name='extraParams'></param>
|
||||
// bool AlwaysIdenticalConversion(string bodyData, string extraParams);
|
||||
|
||||
IDynamicTexture ConvertUrl(string url, string extraParams);
|
||||
IDynamicTexture ConvertData(string bodyData, string extraParams);
|
||||
|
||||
byte[] ConvertUrl(string url, string extraParams);
|
||||
byte[] ConvertData(string bodyData, string extraParams);
|
||||
bool AsyncConvertUrl(UUID id, string url, string extraParams);
|
||||
bool AsyncConvertData(UUID id, string bodyData, string extraParams);
|
||||
|
||||
void GetDrawStringSize(string text, string fontName, int fontSize,
|
||||
out double xSize, out double ySize);
|
||||
}
|
||||
|
||||
public interface IDynamicTexture
|
||||
{
|
||||
/// <summary>
|
||||
/// Input commands used to generate this data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Null if input commands were not used.
|
||||
/// </remarks>
|
||||
string InputCommands { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Uri used to generate this data.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Null if a uri was not used.
|
||||
/// </remarks>
|
||||
Uri InputUri { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Extra input params used to generate this data.
|
||||
/// </summary>
|
||||
string InputParams { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Texture data.
|
||||
/// </summary>
|
||||
byte[] Data { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Size of texture.
|
||||
/// </summary>
|
||||
Size Size { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Signal whether the texture is reuseable (i.e. whether the same input data will always generate the same
|
||||
/// texture).
|
||||
/// </summary>
|
||||
bool IsReuseable { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
|
||||
public interface IJsonStoreModule
|
||||
{
|
||||
bool CreateStore(string value, ref UUID result);
|
||||
bool CreateStore(string value, out UUID result);
|
||||
bool DestroyStore(UUID storeID);
|
||||
bool TestPath(UUID storeID, string path, bool useJson);
|
||||
bool SetValue(UUID storeID, string path, string value, bool useJson);
|
||||
|
||||
39
OpenSim/Region/Framework/Interfaces/IRegionConsole.cs
Normal file
39
OpenSim/Region/Framework/Interfaces/IRegionConsole.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -54,9 +54,9 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
void RegisterScriptInvocation(object target, string method);
|
||||
|
||||
/// <summary>
|
||||
/// Register an instance method as a script call by method info
|
||||
/// Register a static or instance method as a script call by method info
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="target">If target is a Type object, will assume method is static.</param>
|
||||
/// <param name="method"></param>
|
||||
void RegisterScriptInvocation(object target, MethodInfo method);
|
||||
|
||||
@@ -67,6 +67,13 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// <param name="methods"></param>
|
||||
void RegisterScriptInvocation(object target, string[] methods);
|
||||
|
||||
/// <summary>
|
||||
/// Register one or more static methods as script calls by method name
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="methods"></param>
|
||||
void RegisterScriptInvocation(Type target, string[] methods);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of all registered script calls
|
||||
/// </summary>
|
||||
|
||||
@@ -116,5 +116,10 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// <param name="regionUUID">the region UUID</param>
|
||||
void RemoveRegionEnvironmentSettings(UUID regionUUID);
|
||||
|
||||
void SaveExtra(UUID regionID, string name, string value);
|
||||
|
||||
void RemoveExtra(UUID regionID, string name);
|
||||
|
||||
Dictionary<string, string> GetExtra(UUID regionID);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,6 +127,12 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
/// <param name="regionUUID">the region UUID</param>
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID);
|
||||
void ReleaseURL(string url);
|
||||
void HttpResponse(UUID request, int status, string body);
|
||||
void HttpContentType(UUID request, string type);
|
||||
|
||||
string GetHttpHeader(UUID request, string header);
|
||||
int GetFreeUrls();
|
||||
|
||||
|
||||
@@ -47,71 +47,26 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
public delegate void OnFrameDelegate();
|
||||
|
||||
/// <summary>
|
||||
/// Triggered on each sim frame.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.Update"/>
|
||||
/// Core uses it for things like Sun, Wind & Clouds
|
||||
/// The MRM module also uses it.
|
||||
/// </remarks>
|
||||
public event OnFrameDelegate OnFrame;
|
||||
|
||||
public delegate void ClientMovement(ScenePresence client);
|
||||
|
||||
/// <summary>
|
||||
/// Trigerred when an agent moves.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.ScenePresence.HandleAgentUpdate"/>
|
||||
/// prior to <see cref="OpenSim.Region.Framework.Scenes.ScenePresence.TriggerScenePresenceUpdated"/>
|
||||
/// </remarks>
|
||||
public event ClientMovement OnClientMovement;
|
||||
|
||||
public delegate void OnTerrainTaintedDelegate();
|
||||
|
||||
/// <summary>
|
||||
/// Triggered if the terrain has been edited
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This gets triggered in <see cref="OpenSim.Region.CoreModules.World.Terrain.CheckForTerrainUpdates"/>
|
||||
/// after it determines that an update has been made.
|
||||
/// </remarks>
|
||||
public event OnTerrainTaintedDelegate OnTerrainTainted;
|
||||
|
||||
public delegate void OnTerrainTickDelegate();
|
||||
|
||||
/// <summary>
|
||||
/// Triggered if the terrain has been edited
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.UpdateTerrain"/>
|
||||
/// but is used by core solely to update the physics engine.
|
||||
/// </remarks>
|
||||
public event OnTerrainTickDelegate OnTerrainTick;
|
||||
|
||||
public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a region is backed up/persisted to storage
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This gets triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.Backup"/>
|
||||
/// and is fired before the persistence occurs.
|
||||
/// </remarks>
|
||||
public event OnBackupDelegate OnBackup;
|
||||
|
||||
public delegate void OnClientConnectCoreDelegate(IClientCore client);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a new client connects to the scene.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This gets triggered in <see cref="TriggerOnNewClient"/>,
|
||||
/// which checks if an instance of <see cref="OpenSim.Framework.IClientAPI"/>
|
||||
/// also implements <see cref="OpenSim.Framework.Client.IClientCore"/> and as such,
|
||||
/// is not triggered by <see cref="OpenSim.Region.OptionalModules.World.NPC">NPCs</see>.
|
||||
/// </remarks>
|
||||
public event OnClientConnectCoreDelegate OnClientConnect;
|
||||
|
||||
public delegate void OnNewClientDelegate(IClientAPI client);
|
||||
@@ -132,74 +87,22 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
public delegate void OnNewPresenceDelegate(ScenePresence presence);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a new presence is added to the scene
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both
|
||||
/// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
|
||||
/// </remarks>
|
||||
public event OnNewPresenceDelegate OnNewPresence;
|
||||
|
||||
public delegate void OnRemovePresenceDelegate(UUID agentId);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when a presence is removed from the scene
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/> which is used by both
|
||||
/// <see cref="OpenSim.Framework.PresenceType.User">users</see> and <see cref="OpenSim.Framework.PresenceType.Npc">NPCs</see>
|
||||
/// </remarks>
|
||||
public event OnRemovePresenceDelegate OnRemovePresence;
|
||||
|
||||
public delegate void OnParcelPrimCountUpdateDelegate();
|
||||
|
||||
/// <summary>
|
||||
/// Triggered whenever the prim count may have been altered, or prior
|
||||
/// to an action that requires the current prim count to be accurate.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerParcelPrimCountUpdate"/> in
|
||||
/// <see cref="OpenSim.OpenSimBase.CreateRegion"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.EventManagerOnRequestParcelPrimCountUpdate"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ClientOnParcelObjectOwnerRequest"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.GetPrimsFree"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.UpdateLandSold"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.DeedToGroup"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandObject.SendLandUpdateToClient"/>
|
||||
/// </remarks>
|
||||
public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate;
|
||||
|
||||
public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered in response to <see cref="OnParcelPrimCountUpdate"/> for
|
||||
/// objects that actually contribute to parcel prim count.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerParcelPrimCountAdd"/> in
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.EventManagerOnParcelPrimCountUpdate"/>
|
||||
/// </remarks>
|
||||
public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd;
|
||||
|
||||
public delegate void OnPluginConsoleDelegate(string[] args);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered after <see cref="OpenSim.IApplicationPlugin.PostInitialise"/>
|
||||
/// has been called for all <see cref="OpenSim.IApplicationPlugin"/>
|
||||
/// loaded via <see cref="OpenSim.OpenSimBase.LoadPlugins"/>.
|
||||
/// Handlers for this event are typically used to parse the arguments
|
||||
/// from <see cref="OnPluginConsoleDelegate"/> in order to process or
|
||||
/// filter the arguments and pass them onto <see cref="OpenSim.Region.CoreModules.Framework.InterfaceCommander.Commander.ProcessConsoleCommand"/>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerOnPluginConsole"/> in
|
||||
/// <see cref="Scene.SendCommandToPlugins"/> via
|
||||
/// <see cref="SceneManager.SendCommandToPluginModules"/> via
|
||||
/// <see cref="OpenSim.OpenSimBase.HandleCommanderCommand"/> via
|
||||
/// <see cref="OpenSim.OpenSimBase.AddPluginCommands"/> via
|
||||
/// <see cref="OpenSim.OpenSimBase.StartupSpecific"/>
|
||||
/// </remarks>
|
||||
public event OnPluginConsoleDelegate OnPluginConsole;
|
||||
|
||||
/// <summary>
|
||||
@@ -216,14 +119,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
public event OnSetRootAgentSceneDelegate OnSetRootAgentScene;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered after parcel properties have been updated.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerOnParcelPropertiesUpdateRequest"/> in
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ClientOnParcelPropertiesUpdateRequest"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.World.Land.LandManagementModule.ProcessPropertiesUpdate"/>
|
||||
/// </remarks>
|
||||
public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest;
|
||||
|
||||
/// <summary>
|
||||
@@ -238,34 +133,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <summary>
|
||||
/// Fired when an object is touched/grabbed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The originalID is the local ID of the part that was actually touched. The localID itself is always that of
|
||||
/// the root part.
|
||||
/// Triggerd in response to <see cref="OpenSim.Framework.IClientAPI.OnGrabObject"/>
|
||||
/// via <see cref="TriggerObjectGrab"/>
|
||||
/// in <see cref="Scene.ProcessObjectGrab"/>
|
||||
/// </remarks>
|
||||
public event ObjectGrabDelegate OnObjectGrab;
|
||||
public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object is being touched/grabbed continuously.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered in response to <see cref="OpenSim.Framework.IClientAPI.OnGrabUpdate"/>
|
||||
/// via <see cref="TriggerObjectGrabbing"/>
|
||||
/// in <see cref="Scene.ProcessObjectGrabUpdate"/>
|
||||
/// </remarks>
|
||||
public event ObjectGrabDelegate OnObjectGrabbing;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object stops being touched/grabbed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered in response to <see cref="OpenSim.Framework.IClientAPI.OnDeGrabObject"/>
|
||||
/// via <see cref="TriggerObjectDeGrab"/>
|
||||
/// in <see cref="Scene.ProcessObjectDeGrab"/>
|
||||
/// </remarks>
|
||||
public event ObjectDeGrabDelegate OnObjectDeGrab;
|
||||
public event ScriptResetDelegate OnScriptReset;
|
||||
|
||||
@@ -340,6 +213,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// </remarks>
|
||||
public event NewScript OnNewScript;
|
||||
|
||||
public delegate void ExtraSettingChangedDelegate(Scene scene, string name, string value);
|
||||
public event ExtraSettingChangedDelegate OnExtraSettingChanged;
|
||||
|
||||
public virtual void TriggerNewScript(UUID clientID, SceneObjectPart part, UUID itemID)
|
||||
{
|
||||
NewScript handlerNewScript = OnNewScript;
|
||||
@@ -472,27 +348,12 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <summary>
|
||||
/// Triggered when an object is added to the scene.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerObjectAddedToScene"/>
|
||||
/// in <see cref="Scene.AddNewSceneObject"/>,
|
||||
/// <see cref="Scene.DuplicateObject"/>,
|
||||
/// <see cref="Scene.doObjectDuplicateOnRay"/>
|
||||
/// </remarks>
|
||||
public event Action<SceneObjectGroup> OnObjectAddedToScene;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for <see cref="OnObjectBeingRemovedFromScene"/>
|
||||
/// </summary>
|
||||
/// <param name="obj">The object being removed from the scene</param>
|
||||
public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object is removed from the scene.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerObjectBeingRemovedFromScene"/>
|
||||
/// in <see cref="Scene.DeleteSceneObject"/>
|
||||
/// </remarks>
|
||||
public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
|
||||
public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene;
|
||||
|
||||
public delegate void NoticeNoLandDataFromStorage();
|
||||
@@ -508,20 +369,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate;
|
||||
|
||||
public delegate void ParcelPrimCountTainted();
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when the parcel prim count has been altered.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered by <see cref="TriggerParcelPrimCountTainted"/> in
|
||||
/// <see cref="OpenSim.Region.CoreModules.Avatar.Attachments.AttachmentsModule.DetachSingleAttachmentToGround"/>,
|
||||
/// <see cref="OpenSim.Region.CoreModules.Avatar.Attachments.AttachmentsModule.AttachToAgent"/>,
|
||||
/// <see cref="Scene.DeleteSceneObject"/>,
|
||||
/// <see cref="Scene.SelectPrim"/>,
|
||||
/// <see cref="Scene.DeselectPrim"/>,
|
||||
/// <see cref="SceneObjectGroup.UpdatePrimFlags"/>,
|
||||
/// <see cref="SceneObjectGroup.AbsolutePosition"/>
|
||||
/// </remarks>
|
||||
public event ParcelPrimCountTainted OnParcelPrimCountTainted;
|
||||
public event GetScriptRunning OnGetScriptRunning;
|
||||
|
||||
@@ -634,9 +481,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <param name="copy"></param>
|
||||
/// <param name="original"></param>
|
||||
/// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
|
||||
/// <remarks>
|
||||
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.SceneObjectPart.Copy"/>
|
||||
/// </remarks>
|
||||
public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy;
|
||||
public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed);
|
||||
|
||||
@@ -745,29 +589,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
public delegate void LandBuy(Object sender, LandBuyArgs e);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an attempt to transfer grid currency occurs
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessMoneyTransferRequest"/>
|
||||
/// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientGridEvents"/>
|
||||
/// via <see cref="OpenSim.Region.Framework.Scenes.Scene.SubscribeToClientEvents"/>
|
||||
/// via <see cref="OpenSim.Region.Framework.Scenes.Scene.AddNewClient"/>
|
||||
/// </remarks>
|
||||
public event MoneyTransferEvent OnMoneyTransfer;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered after after <see cref="OnValidateLandBuy"/>
|
||||
/// </summary>
|
||||
public event LandBuy OnLandBuy;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered to allow or prevent a real estate transaction
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggered in <see cref="OpenSim.Region.Framework.Scenes.Scene.ProcessParcelBuy"/>
|
||||
/// <seealso cref="OpenSim.Region.OptionalModules.World.MoneyModule.SampleMoneyModule.ValidateLandBuy"/>
|
||||
/// </remarks>
|
||||
public event LandBuy OnValidateLandBuy;
|
||||
|
||||
public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID)
|
||||
@@ -2771,5 +2594,25 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
}
|
||||
|
||||
public void TriggerExtraSettingChanged(Scene scene, string name, string val)
|
||||
{
|
||||
ExtraSettingChangedDelegate handler = OnExtraSettingChanged;
|
||||
|
||||
if (handler != null)
|
||||
{
|
||||
foreach (ExtraSettingChangedDelegate d in handler.GetInvocationList())
|
||||
{
|
||||
try
|
||||
{
|
||||
d(scene, name, val);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("[EVENT MANAGER]: Delegate for ExtraSettingChanged failed - continuing {0} - {1}",
|
||||
e.Message, e.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1943,6 +1943,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
deleteIDs.Add(localID);
|
||||
deleteGroups.Add(grp);
|
||||
|
||||
// If child prims have invalid perms, fix them
|
||||
grp.AdjustChildPrimPermissions();
|
||||
|
||||
if (remoteClient == null)
|
||||
{
|
||||
// Autoreturn has a null client. Nothing else does. So
|
||||
|
||||
@@ -103,8 +103,26 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// </summary>
|
||||
public bool CollidablePrims { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Minimum value of the size of a non-physical prim in each axis
|
||||
/// </summary>
|
||||
public float m_minNonphys = 0.01f;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum value of the size of a non-physical prim in each axis
|
||||
/// </summary>
|
||||
public float m_maxNonphys = 256;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum value of the size of a physical prim in each axis
|
||||
/// </summary>
|
||||
public float m_minPhys = 0.01f;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum value of the size of a physical prim in each axis
|
||||
/// </summary>
|
||||
public float m_maxPhys = 10;
|
||||
|
||||
public bool m_clampPrimSize;
|
||||
public bool m_trustBinaries;
|
||||
public bool m_allowScriptCrossings;
|
||||
@@ -174,6 +192,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
protected ICapabilitiesModule m_capsModule;
|
||||
protected IGroupsModule m_groupsModule;
|
||||
|
||||
private Dictionary<string, string> m_extraSettings;
|
||||
|
||||
/// <summary>
|
||||
/// Current scene frame number
|
||||
/// </summary>
|
||||
@@ -635,6 +655,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
// FIXME: It shouldn't be up to the database plugins to create this data - we should do it when a new
|
||||
// region is set up and avoid these gyrations.
|
||||
RegionSettings rs = simDataService.LoadRegionSettings(RegionInfo.RegionID);
|
||||
m_extraSettings = simDataService.GetExtra(RegionInfo.RegionID);
|
||||
|
||||
bool updatedTerrainTextures = false;
|
||||
if (rs.TerrainTexture1 == UUID.Zero)
|
||||
{
|
||||
@@ -717,14 +739,25 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims);
|
||||
CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims);
|
||||
|
||||
m_minNonphys = startupConfig.GetFloat("NonphysicalPrimMin", m_minNonphys);
|
||||
if (RegionInfo.NonphysPrimMin > 0)
|
||||
{
|
||||
m_minNonphys = RegionInfo.NonphysPrimMin;
|
||||
}
|
||||
|
||||
m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
|
||||
if (RegionInfo.NonphysPrimMax > 0)
|
||||
{
|
||||
m_maxNonphys = RegionInfo.NonphysPrimMax;
|
||||
}
|
||||
|
||||
m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
|
||||
m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys);
|
||||
if (RegionInfo.PhysPrimMin > 0)
|
||||
{
|
||||
m_minPhys = RegionInfo.PhysPrimMin;
|
||||
}
|
||||
|
||||
m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
|
||||
if (RegionInfo.PhysPrimMax > 0)
|
||||
{
|
||||
m_maxPhys = RegionInfo.PhysPrimMax;
|
||||
@@ -817,8 +850,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
|
||||
// FIXME: Ultimately this should be in a module.
|
||||
SendPeriodicAppearanceUpdates = true;
|
||||
|
||||
IConfig appearanceConfig = m_config.Configs["Appearance"];
|
||||
if (appearanceConfig != null)
|
||||
{
|
||||
@@ -2630,7 +2661,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
|
||||
|
||||
if (AttachmentsModule != null)
|
||||
AttachmentsModule.AttachObject(sp, grp, 0, false);
|
||||
AttachmentsModule.AttachObject(sp, grp, 0, false, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4303,16 +4334,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
return LandChannel.GetLandObject(x, y).LandData;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get LandData by position.
|
||||
/// </summary>
|
||||
/// <param name="pos"></param>
|
||||
/// <returns></returns>
|
||||
public LandData GetLandData(Vector3 pos)
|
||||
{
|
||||
return GetLandData(pos.X, pos.Y);
|
||||
}
|
||||
|
||||
public LandData GetLandData(uint x, uint y)
|
||||
{
|
||||
m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
|
||||
@@ -4560,18 +4581,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
return m_sceneGraph.GetSceneObjectGroup(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to get the SOG via its UUID
|
||||
/// </summary>
|
||||
/// <param name="fullID"></param>
|
||||
/// <param name="sog"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog)
|
||||
{
|
||||
sog = GetSceneObjectGroup(fullID);
|
||||
return sog != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a prim by name from the scene (will return the first
|
||||
/// found, if there are more than one prim with the same name)
|
||||
@@ -4603,18 +4612,6 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
return m_sceneGraph.GetSceneObjectPart(fullID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to get a prim via its UUID
|
||||
/// </summary>
|
||||
/// <param name="fullID"></param>
|
||||
/// <param name="sop"></param>
|
||||
/// <returns></returns>
|
||||
public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop)
|
||||
{
|
||||
sop = GetSceneObjectPart(fullID);
|
||||
return sop != null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a scene object group that contains the prim with the given local id
|
||||
/// </summary>
|
||||
@@ -5482,5 +5479,44 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
callback(asset);
|
||||
}
|
||||
|
||||
public string GetExtraSetting(string name)
|
||||
{
|
||||
string val;
|
||||
|
||||
if (!m_extraSettings.TryGetValue(name, out val))
|
||||
return String.Empty;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
public void StoreExtraSetting(string name, string val)
|
||||
{
|
||||
string oldVal;
|
||||
|
||||
if (m_extraSettings.TryGetValue(name, out oldVal))
|
||||
{
|
||||
if (oldVal == val)
|
||||
return;
|
||||
}
|
||||
|
||||
m_extraSettings[name] = val;
|
||||
|
||||
m_SimulationDataService.SaveExtra(RegionInfo.RegionID, name, val);
|
||||
|
||||
m_eventManager.TriggerExtraSettingChanged(this, name, val);
|
||||
}
|
||||
|
||||
public void RemoveExtraSetting(string name)
|
||||
{
|
||||
if (!m_extraSettings.ContainsKey(name))
|
||||
return;
|
||||
|
||||
m_extraSettings.Remove(name);
|
||||
|
||||
m_SimulationDataService.RemoveExtra(RegionInfo.RegionID, name);
|
||||
|
||||
m_eventManager.TriggerExtraSettingChanged(this, name, String.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,12 +375,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
{
|
||||
Vector3 scale = part.Shape.Scale;
|
||||
|
||||
if (scale.X > m_parentScene.m_maxNonphys)
|
||||
scale.X = m_parentScene.m_maxNonphys;
|
||||
if (scale.Y > m_parentScene.m_maxNonphys)
|
||||
scale.Y = m_parentScene.m_maxNonphys;
|
||||
if (scale.Z > m_parentScene.m_maxNonphys)
|
||||
scale.Z = m_parentScene.m_maxNonphys;
|
||||
scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X));
|
||||
scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y));
|
||||
scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z));
|
||||
|
||||
part.Shape.Scale = scale;
|
||||
}
|
||||
|
||||
@@ -2131,6 +2131,9 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
// Can't do this yet since backup still makes use of the root part without any synchronization
|
||||
// objectGroup.m_rootPart = null;
|
||||
|
||||
// If linking prims with different permissions, fix them
|
||||
AdjustChildPrimPermissions();
|
||||
|
||||
AttachToBackup();
|
||||
|
||||
// Here's the deal, this is ABSOLUTELY CRITICAL so the physics scene gets the update about the
|
||||
@@ -2622,12 +2625,21 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
}
|
||||
|
||||
public void AdjustChildPrimPermissions()
|
||||
{
|
||||
ForEachPart(part =>
|
||||
{
|
||||
if (part != RootPart)
|
||||
part.ClonePermissions(RootPart);
|
||||
});
|
||||
}
|
||||
|
||||
public void UpdatePermissions(UUID AgentID, byte field, uint localID,
|
||||
uint mask, byte addRemTF)
|
||||
{
|
||||
SceneObjectPart[] parts = m_parts.GetArray();
|
||||
for (int i = 0; i < parts.Length; i++)
|
||||
parts[i].UpdatePermissions(AgentID, field, localID, mask, addRemTF);
|
||||
RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
|
||||
|
||||
AdjustChildPrimPermissions();
|
||||
|
||||
HasGroupChanged = true;
|
||||
|
||||
@@ -2674,17 +2686,17 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
RootPart.StoreUndoState(true);
|
||||
|
||||
scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
|
||||
scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
|
||||
scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
|
||||
scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X));
|
||||
scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y));
|
||||
scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z));
|
||||
|
||||
PhysicsActor pa = m_rootPart.PhysActor;
|
||||
|
||||
if (pa != null && pa.IsPhysical)
|
||||
{
|
||||
scale.X = Math.Min(scale.X, Scene.m_maxPhys);
|
||||
scale.Y = Math.Min(scale.Y, Scene.m_maxPhys);
|
||||
scale.Z = Math.Min(scale.Z, Scene.m_maxPhys);
|
||||
scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X));
|
||||
scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y));
|
||||
scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z));
|
||||
}
|
||||
|
||||
float x = (scale.X / RootPart.Scale.X);
|
||||
@@ -2716,6 +2728,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
y *= a;
|
||||
z *= a;
|
||||
}
|
||||
else if (oldSize.X * x < m_scene.m_minPhys)
|
||||
{
|
||||
f = m_scene.m_minPhys / oldSize.X;
|
||||
a = f / x;
|
||||
x *= a;
|
||||
y *= a;
|
||||
z *= a;
|
||||
}
|
||||
|
||||
if (oldSize.Y * y > m_scene.m_maxPhys)
|
||||
{
|
||||
@@ -2725,6 +2745,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
y *= a;
|
||||
z *= a;
|
||||
}
|
||||
else if (oldSize.Y * y < m_scene.m_minPhys)
|
||||
{
|
||||
f = m_scene.m_minPhys / oldSize.Y;
|
||||
a = f / y;
|
||||
x *= a;
|
||||
y *= a;
|
||||
z *= a;
|
||||
}
|
||||
|
||||
if (oldSize.Z * z > m_scene.m_maxPhys)
|
||||
{
|
||||
@@ -2734,6 +2762,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
y *= a;
|
||||
z *= a;
|
||||
}
|
||||
else if (oldSize.Z * z < m_scene.m_minPhys)
|
||||
{
|
||||
f = m_scene.m_minPhys / oldSize.Z;
|
||||
a = f / z;
|
||||
x *= a;
|
||||
y *= a;
|
||||
z *= a;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2745,6 +2781,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
y *= a;
|
||||
z *= a;
|
||||
}
|
||||
else if (oldSize.X * x < m_scene.m_minNonphys)
|
||||
{
|
||||
f = m_scene.m_minNonphys / oldSize.X;
|
||||
a = f / x;
|
||||
x *= a;
|
||||
y *= a;
|
||||
z *= a;
|
||||
}
|
||||
|
||||
if (oldSize.Y * y > m_scene.m_maxNonphys)
|
||||
{
|
||||
@@ -2754,6 +2798,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
y *= a;
|
||||
z *= a;
|
||||
}
|
||||
else if (oldSize.Y * y < m_scene.m_minNonphys)
|
||||
{
|
||||
f = m_scene.m_minNonphys / oldSize.Y;
|
||||
a = f / y;
|
||||
x *= a;
|
||||
y *= a;
|
||||
z *= a;
|
||||
}
|
||||
|
||||
if (oldSize.Z * z > m_scene.m_maxNonphys)
|
||||
{
|
||||
@@ -2763,6 +2815,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
y *= a;
|
||||
z *= a;
|
||||
}
|
||||
else if (oldSize.Z * z < m_scene.m_minNonphys)
|
||||
{
|
||||
f = m_scene.m_minNonphys / oldSize.Z;
|
||||
a = f / z;
|
||||
x *= a;
|
||||
y *= a;
|
||||
z *= a;
|
||||
}
|
||||
}
|
||||
|
||||
// obPart.IgnoreUndoUpdate = false;
|
||||
|
||||
@@ -2368,17 +2368,16 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <param name="scale"></param>
|
||||
public void Resize(Vector3 scale)
|
||||
{
|
||||
scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys);
|
||||
scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys);
|
||||
scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys);
|
||||
scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X));
|
||||
scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y));
|
||||
scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z));
|
||||
|
||||
PhysicsActor pa = PhysActor;
|
||||
|
||||
if (pa != null && pa.IsPhysical)
|
||||
{
|
||||
scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys);
|
||||
scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys);
|
||||
scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys);
|
||||
scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X));
|
||||
scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y));
|
||||
scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z));
|
||||
}
|
||||
|
||||
// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
|
||||
@@ -2852,23 +2851,32 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the color of prim faces
|
||||
/// Set the color & alpha of prim faces
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <param name="face"></param>
|
||||
public void SetFaceColor(Vector3 color, int face)
|
||||
/// <param name="color"></param>
|
||||
/// <param name="alpha"></param>
|
||||
public void SetFaceColorAlpha(int face, Vector3 color, double ?alpha)
|
||||
{
|
||||
Vector3 clippedColor = Util.Clip(color, 0.0f, 1.0f);
|
||||
float clippedAlpha = alpha.HasValue ?
|
||||
Util.Clip((float)alpha.Value, 0.0f, 1.0f) : 0;
|
||||
|
||||
// The only way to get a deep copy/ If we don't do this, we can
|
||||
// mever detect color changes further down.
|
||||
// never detect color changes further down.
|
||||
Byte[] buf = Shape.Textures.GetBytes();
|
||||
Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length);
|
||||
Color4 texcolor;
|
||||
if (face >= 0 && face < GetNumberOfSides())
|
||||
{
|
||||
texcolor = tex.CreateFace((uint)face).RGBA;
|
||||
texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f);
|
||||
texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f);
|
||||
texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f);
|
||||
texcolor.R = clippedColor.X;
|
||||
texcolor.G = clippedColor.Y;
|
||||
texcolor.B = clippedColor.Z;
|
||||
if (alpha.HasValue)
|
||||
{
|
||||
texcolor.A = clippedAlpha;
|
||||
}
|
||||
tex.FaceTextures[face].RGBA = texcolor;
|
||||
UpdateTextureEntry(tex.GetBytes());
|
||||
return;
|
||||
@@ -2880,15 +2888,23 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
if (tex.FaceTextures[i] != null)
|
||||
{
|
||||
texcolor = tex.FaceTextures[i].RGBA;
|
||||
texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f);
|
||||
texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f);
|
||||
texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f);
|
||||
texcolor.R = clippedColor.X;
|
||||
texcolor.G = clippedColor.Y;
|
||||
texcolor.B = clippedColor.Z;
|
||||
if (alpha.HasValue)
|
||||
{
|
||||
texcolor.A = clippedAlpha;
|
||||
}
|
||||
tex.FaceTextures[i].RGBA = texcolor;
|
||||
}
|
||||
texcolor = tex.DefaultTexture.RGBA;
|
||||
texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f);
|
||||
texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f);
|
||||
texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f);
|
||||
texcolor.R = clippedColor.X;
|
||||
texcolor.G = clippedColor.Y;
|
||||
texcolor.B = clippedColor.Z;
|
||||
if (alpha.HasValue)
|
||||
{
|
||||
texcolor.A = clippedAlpha;
|
||||
}
|
||||
tex.DefaultTexture.RGBA = texcolor;
|
||||
}
|
||||
UpdateTextureEntry(tex.GetBytes());
|
||||
@@ -3874,6 +3890,27 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
}
|
||||
|
||||
public void ClonePermissions(SceneObjectPart source)
|
||||
{
|
||||
bool update = false;
|
||||
|
||||
if (BaseMask != source.BaseMask ||
|
||||
OwnerMask != source.OwnerMask ||
|
||||
GroupMask != source.GroupMask ||
|
||||
EveryoneMask != source.EveryoneMask ||
|
||||
NextOwnerMask != source.NextOwnerMask)
|
||||
update = true;
|
||||
|
||||
BaseMask = source.BaseMask;
|
||||
OwnerMask = source.OwnerMask;
|
||||
GroupMask = source.GroupMask;
|
||||
EveryoneMask = source.EveryoneMask;
|
||||
NextOwnerMask = source.NextOwnerMask;
|
||||
|
||||
if (update)
|
||||
SendFullUpdateToAllClients();
|
||||
}
|
||||
|
||||
public bool IsHingeJoint()
|
||||
{
|
||||
// For now, we use the NINJA naming scheme for identifying joints.
|
||||
@@ -4237,6 +4274,57 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
ScheduleFullUpdate();
|
||||
}
|
||||
|
||||
public void UpdateSlice(float begin, float end)
|
||||
{
|
||||
if (end < begin)
|
||||
{
|
||||
float temp = begin;
|
||||
begin = end;
|
||||
end = temp;
|
||||
}
|
||||
end = Math.Min(1f, Math.Max(0f, end));
|
||||
begin = Math.Min(Math.Min(1f, Math.Max(0f, begin)), end - 0.02f);
|
||||
if (begin < 0.02f && end < 0.02f)
|
||||
{
|
||||
begin = 0f;
|
||||
end = 0.02f;
|
||||
}
|
||||
|
||||
ushort uBegin = (ushort)(50000.0 * begin);
|
||||
ushort uEnd = (ushort)(50000.0 * (1f - end));
|
||||
bool updatePossiblyNeeded = false;
|
||||
PrimType primType = GetPrimType();
|
||||
if (primType == PrimType.SPHERE || primType == PrimType.TORUS || primType == PrimType.TUBE || primType == PrimType.RING)
|
||||
{
|
||||
if (m_shape.ProfileBegin != uBegin || m_shape.ProfileEnd != uEnd)
|
||||
{
|
||||
m_shape.ProfileBegin = uBegin;
|
||||
m_shape.ProfileEnd = uEnd;
|
||||
updatePossiblyNeeded = true;
|
||||
}
|
||||
}
|
||||
else if (m_shape.PathBegin != uBegin || m_shape.PathEnd != uEnd)
|
||||
{
|
||||
m_shape.PathBegin = uBegin;
|
||||
m_shape.PathEnd = uEnd;
|
||||
updatePossiblyNeeded = true;
|
||||
}
|
||||
|
||||
if (updatePossiblyNeeded && ParentGroup != null)
|
||||
{
|
||||
ParentGroup.HasGroupChanged = true;
|
||||
}
|
||||
if (updatePossiblyNeeded && PhysActor != null)
|
||||
{
|
||||
PhysActor.Shape = m_shape;
|
||||
ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
|
||||
}
|
||||
if (updatePossiblyNeeded)
|
||||
{
|
||||
ScheduleFullUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics
|
||||
/// engine can use it.
|
||||
|
||||
@@ -1387,17 +1387,22 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
bool DCFlagKeyPressed = false;
|
||||
Vector3 agent_control_v3 = Vector3.Zero;
|
||||
|
||||
bool oldflying = Flying;
|
||||
bool newFlying = actor.Flying;
|
||||
|
||||
if (ForceFly)
|
||||
actor.Flying = true;
|
||||
newFlying = true;
|
||||
else if (FlyDisabled)
|
||||
actor.Flying = false;
|
||||
newFlying = false;
|
||||
else
|
||||
actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
|
||||
newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
|
||||
|
||||
if (actor.Flying != oldflying)
|
||||
if (actor.Flying != newFlying)
|
||||
{
|
||||
// Note: ScenePresence.Flying is actually fetched from the physical actor
|
||||
// so setting PhysActor.Flying here also sets the ScenePresence's value.
|
||||
actor.Flying = newFlying;
|
||||
update_movementflag = true;
|
||||
}
|
||||
|
||||
if (ParentID == 0)
|
||||
{
|
||||
@@ -3413,13 +3418,16 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
public List<SceneObjectGroup> GetAttachments(uint attachmentPoint)
|
||||
{
|
||||
List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
|
||||
|
||||
lock (m_attachments)
|
||||
|
||||
if (attachmentPoint >= 0)
|
||||
{
|
||||
foreach (SceneObjectGroup so in m_attachments)
|
||||
lock (m_attachments)
|
||||
{
|
||||
if (attachmentPoint == so.AttachmentPoint)
|
||||
attachments.Add(so);
|
||||
foreach (SceneObjectGroup so in m_attachments)
|
||||
{
|
||||
if (attachmentPoint == so.AttachmentPoint)
|
||||
attachments.Add(so);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -447,7 +447,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice
|
||||
// settings allow voice, then whether parcel allows
|
||||
// voice, if all do retrieve or obtain the parcel
|
||||
// voice channel
|
||||
LandData land = scene.GetLandData(avatar.AbsolutePosition);
|
||||
LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y);
|
||||
|
||||
//m_log.DebugFormat("[FreeSwitchVoice][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);
|
||||
|
||||
@@ -623,7 +623,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice
|
||||
// settings allow voice, then whether parcel allows
|
||||
// voice, if all do retrieve or obtain the parcel
|
||||
// voice channel
|
||||
LandData land = scene.GetLandData(avatar.AbsolutePosition);
|
||||
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}",
|
||||
scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param);
|
||||
|
||||
@@ -175,15 +175,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
///
|
||||
/// </summary>
|
||||
// -----------------------------------------------------------------
|
||||
public bool CreateStore(string value, ref UUID result)
|
||||
public bool CreateStore(string value, out UUID result)
|
||||
{
|
||||
if (result == UUID.Zero)
|
||||
result = UUID.Random();
|
||||
|
||||
JsonStore map = null;
|
||||
result = UUID.Zero;
|
||||
|
||||
if (! m_enabled) return false;
|
||||
|
||||
UUID uuid = UUID.Random();
|
||||
JsonStore map = null;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -196,8 +195,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
}
|
||||
|
||||
lock (m_JsonValueStore)
|
||||
m_JsonValueStore.Add(result,map);
|
||||
m_JsonValueStore.Add(uuid,map);
|
||||
|
||||
result = uuid;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
if (! m_JsonValueStore.TryGetValue(storeID,out map))
|
||||
{
|
||||
m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value)
|
||||
{
|
||||
UUID uuid = UUID.Zero;
|
||||
if (! m_store.CreateStore(value, ref uuid))
|
||||
if (! m_store.CreateStore(value, out uuid))
|
||||
GenerateRuntimeError("Failed to create Json store");
|
||||
|
||||
return uuid;
|
||||
|
||||
@@ -130,13 +130,25 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
|
||||
m_scriptModule.PostScriptEvent(script, "link_message", args);
|
||||
}
|
||||
|
||||
private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods)
|
||||
{
|
||||
BindingFlags getMethodFlags =
|
||||
BindingFlags.NonPublic | BindingFlags.Public;
|
||||
|
||||
if (searchInstanceMethods)
|
||||
getMethodFlags |= BindingFlags.Instance;
|
||||
else
|
||||
getMethodFlags |= BindingFlags.Static;
|
||||
|
||||
return target.GetMethod(meth, getMethodFlags);
|
||||
}
|
||||
|
||||
public void RegisterScriptInvocation(object target, string meth)
|
||||
{
|
||||
MethodInfo mi = target.GetType().GetMethod(meth,
|
||||
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true);
|
||||
if (mi == null)
|
||||
{
|
||||
m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth);
|
||||
m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -151,38 +163,54 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms
|
||||
|
||||
public void RegisterScriptInvocation(object target, MethodInfo mi)
|
||||
{
|
||||
m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, target.GetType().Name);
|
||||
m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name);
|
||||
|
||||
Type delegateType;
|
||||
var typeArgs = mi.GetParameters()
|
||||
List<Type> typeArgs = mi.GetParameters()
|
||||
.Select(p => p.ParameterType)
|
||||
.ToList();
|
||||
|
||||
if (mi.ReturnType == typeof(void))
|
||||
{
|
||||
delegateType = Expression.GetActionType(typeArgs.ToArray());
|
||||
delegateType = Expression.GetActionType(typeArgs.ToArray());
|
||||
}
|
||||
else
|
||||
{
|
||||
typeArgs.Add(mi.ReturnType);
|
||||
delegateType = Expression.GetFuncType(typeArgs.ToArray());
|
||||
typeArgs.Add(mi.ReturnType);
|
||||
delegateType = Expression.GetFuncType(typeArgs.ToArray());
|
||||
}
|
||||
|
||||
Delegate fcall = Delegate.CreateDelegate(delegateType, target, mi);
|
||||
Delegate fcall;
|
||||
if (!(target is Type))
|
||||
fcall = Delegate.CreateDelegate(delegateType, target, mi);
|
||||
else
|
||||
fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name);
|
||||
|
||||
lock (m_scriptInvocation)
|
||||
{
|
||||
ParameterInfo[] parameters = fcall.Method.GetParameters ();
|
||||
ParameterInfo[] parameters = fcall.Method.GetParameters();
|
||||
if (parameters.Length < 2) // Must have two UUID params
|
||||
return;
|
||||
|
||||
// Hide the first two parameters
|
||||
Type[] parmTypes = new Type[parameters.Length - 2];
|
||||
for (int i = 2 ; i < parameters.Length ; i++)
|
||||
for (int i = 2; i < parameters.Length; i++)
|
||||
parmTypes[i - 2] = parameters[i].ParameterType;
|
||||
m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType);
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterScriptInvocation(Type target, string[] methods)
|
||||
{
|
||||
foreach (string method in methods)
|
||||
{
|
||||
MethodInfo mi = GetMethodInfoFromType(target, method, false);
|
||||
if (mi == null)
|
||||
m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method);
|
||||
else
|
||||
RegisterScriptInvocation(target, mi);
|
||||
}
|
||||
}
|
||||
|
||||
public Delegate[] GetScriptInvocationList()
|
||||
{
|
||||
|
||||
118
OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
Executable file
118
OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs
Executable 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,13 +34,12 @@ using OpenSim.Region.Physics.Manager;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
public class BSCharacter : PhysicsActor
|
||||
public class BSCharacter : BSPhysObject
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly string LogHeader = "[BULLETS CHAR]";
|
||||
|
||||
private BSScene _scene;
|
||||
public BSScene Scene { get { return _scene; } }
|
||||
public BSScene Scene { get; private set; }
|
||||
private String _avName;
|
||||
// private bool _stopped;
|
||||
private Vector3 _size;
|
||||
@@ -74,11 +73,8 @@ public class BSCharacter : PhysicsActor
|
||||
private bool _kinematic;
|
||||
private float _buoyancy;
|
||||
|
||||
private BulletBody m_body;
|
||||
public BulletBody Body {
|
||||
get { return m_body; }
|
||||
set { m_body = value; }
|
||||
}
|
||||
public override BulletBody Body { get; set; }
|
||||
public override BSLinkset Linkset { get; set; }
|
||||
|
||||
private int _subscribedEventsMs = 0;
|
||||
private int _nextCollisionOkTime = 0;
|
||||
@@ -95,17 +91,21 @@ public class BSCharacter : PhysicsActor
|
||||
{
|
||||
_localID = localID;
|
||||
_avName = avName;
|
||||
_scene = parent_scene;
|
||||
Scene = parent_scene;
|
||||
_position = pos;
|
||||
_size = size;
|
||||
_flying = isFlying;
|
||||
_orientation = Quaternion.Identity;
|
||||
_velocity = Vector3.Zero;
|
||||
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
|
||||
_scale = new Vector3(1f, 1f, 1f);
|
||||
_density = _scene.Params.avatarDensity;
|
||||
// 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;
|
||||
ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale
|
||||
|
||||
Linkset = new BSLinkset(Scene, this);
|
||||
|
||||
ShapeData shapeData = new ShapeData();
|
||||
shapeData.ID = _localID;
|
||||
shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR;
|
||||
@@ -116,16 +116,20 @@ public class BSCharacter : PhysicsActor
|
||||
shapeData.Mass = _mass;
|
||||
shapeData.Buoyancy = _buoyancy;
|
||||
shapeData.Static = ShapeData.numericFalse;
|
||||
shapeData.Friction = _scene.Params.avatarFriction;
|
||||
shapeData.Restitution = _scene.Params.avatarRestitution;
|
||||
shapeData.Friction = Scene.Params.avatarFriction;
|
||||
shapeData.Restitution = Scene.Params.avatarRestitution;
|
||||
|
||||
// do actual create at taint time
|
||||
_scene.TaintedObject(delegate()
|
||||
Scene.TaintedObject("BSCharacter.create", delegate()
|
||||
{
|
||||
BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData);
|
||||
DetailLog("{0},BSCharacter.create", _localID);
|
||||
BulletSimAPI.CreateObject(Scene.WorldID, shapeData);
|
||||
|
||||
m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
||||
// avatars get all collisions no matter what
|
||||
// Set the buoyancy for flying. This will be refactored when all the settings happen in C#
|
||||
BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
|
||||
|
||||
Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(Scene.World.Ptr, LocalID));
|
||||
// avatars get all collisions no matter what (makes walking on ground and such work)
|
||||
BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
});
|
||||
|
||||
@@ -133,12 +137,12 @@ public class BSCharacter : PhysicsActor
|
||||
}
|
||||
|
||||
// called when this character is being destroyed and the resources should be released
|
||||
public void Destroy()
|
||||
public override void Destroy()
|
||||
{
|
||||
// DetailLog("{0},Destroy", LocalID);
|
||||
_scene.TaintedObject(delegate()
|
||||
DetailLog("{0},BSCharacter.Destroy", LocalID);
|
||||
Scene.TaintedObject("BSCharacter.destroy", delegate()
|
||||
{
|
||||
BulletSimAPI.DestroyObject(_scene.WorldID, _localID);
|
||||
BulletSimAPI.DestroyObject(Scene.WorldID, _localID);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -150,9 +154,28 @@ public class BSCharacter : PhysicsActor
|
||||
public override bool Stopped {
|
||||
get { return false; }
|
||||
}
|
||||
public override Vector3 Size {
|
||||
get { return _size; }
|
||||
set { _size = value;
|
||||
public override Vector3 Size {
|
||||
get
|
||||
{
|
||||
// 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 {
|
||||
@@ -179,31 +202,78 @@ public class BSCharacter : PhysicsActor
|
||||
|
||||
public override Vector3 Position {
|
||||
get {
|
||||
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||
// _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
|
||||
return _position;
|
||||
}
|
||||
set {
|
||||
_position = value;
|
||||
_scene.TaintedObject(delegate()
|
||||
PositionSanityCheck();
|
||||
|
||||
Scene.TaintedObject("BSCharacter.setPosition", delegate()
|
||||
{
|
||||
DetailLog("{0},SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
||||
DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", 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.TerrainManager.GetTerrainHeightAtXYZ(_position);
|
||||
if (Position.Z < terrainHeight)
|
||||
{
|
||||
DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight);
|
||||
_position.Z = terrainHeight + 2.0f;
|
||||
ret = true;
|
||||
}
|
||||
|
||||
// TODO: check for out of bounds
|
||||
return ret;
|
||||
}
|
||||
|
||||
// A version of the sanity check that also makes sure a new position value is
|
||||
// pushed back to the physics engine. This routine would be used by anyone
|
||||
// who is not already pushing the value.
|
||||
private bool PositionSanityCheck2()
|
||||
{
|
||||
bool ret = false;
|
||||
if (PositionSanityCheck())
|
||||
{
|
||||
// The new position value must be pushed into the physics engine but we can't
|
||||
// just assign to "Position" because of potential call loops.
|
||||
Scene.TaintedObject("BSCharacter.PositionSanityCheck", delegate()
|
||||
{
|
||||
DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
|
||||
});
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public override float Mass {
|
||||
get {
|
||||
return _mass;
|
||||
}
|
||||
}
|
||||
|
||||
// used when we only want this prim's mass and not the linkset thing
|
||||
public override float MassRaw { get {return _mass; } }
|
||||
|
||||
public override Vector3 Force {
|
||||
get { return _force; }
|
||||
set {
|
||||
_force = value;
|
||||
// m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force);
|
||||
Scene.TaintedObject(delegate()
|
||||
Scene.TaintedObject("BSCharacter.SetForce", delegate()
|
||||
{
|
||||
DetailLog("{0},setForce,taint,force={1}", LocalID, _force);
|
||||
DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force);
|
||||
BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force);
|
||||
});
|
||||
}
|
||||
@@ -228,10 +298,10 @@ public class BSCharacter : PhysicsActor
|
||||
set {
|
||||
_velocity = value;
|
||||
// m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity);
|
||||
_scene.TaintedObject(delegate()
|
||||
Scene.TaintedObject("BSCharacter.setVelocity", delegate()
|
||||
{
|
||||
DetailLog("{0},setVelocity,taint,vel={1}", LocalID, _velocity);
|
||||
BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity);
|
||||
DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity);
|
||||
BulletSimAPI.SetObjectVelocity(Scene.WorldID, _localID, _velocity);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -254,10 +324,10 @@ public class BSCharacter : PhysicsActor
|
||||
set {
|
||||
_orientation = value;
|
||||
// m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation);
|
||||
_scene.TaintedObject(delegate()
|
||||
Scene.TaintedObject("BSCharacter.setOrientation", delegate()
|
||||
{
|
||||
// _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||
BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation);
|
||||
// _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, _localID);
|
||||
BulletSimAPI.SetObjectTranslation(Scene.WorldID, _localID, _position, _orientation);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -279,6 +349,8 @@ public class BSCharacter : PhysicsActor
|
||||
this.Buoyancy = ComputeBuoyancyFromFlying(_flying);
|
||||
}
|
||||
}
|
||||
// Flying is implimented by changing the avatar's buoyancy.
|
||||
// Would this be done better with a vehicle type?
|
||||
private float ComputeBuoyancyFromFlying(bool ifFlying) {
|
||||
return ifFlying ? 1f : 0f;
|
||||
}
|
||||
@@ -292,11 +364,11 @@ public class BSCharacter : PhysicsActor
|
||||
set { _throttleUpdates = value; }
|
||||
}
|
||||
public override bool IsColliding {
|
||||
get { return (_collidingStep == _scene.SimulationStep); }
|
||||
get { return (_collidingStep == Scene.SimulationStep); }
|
||||
set { _isColliding = value; }
|
||||
}
|
||||
public override bool CollidingGround {
|
||||
get { return (_collidingGroundStep == _scene.SimulationStep); }
|
||||
get { return (_collidingGroundStep == Scene.SimulationStep); }
|
||||
set { _collidingGround = value; }
|
||||
}
|
||||
public override bool CollidingObj {
|
||||
@@ -318,10 +390,10 @@ public class BSCharacter : PhysicsActor
|
||||
public override float Buoyancy {
|
||||
get { return _buoyancy; }
|
||||
set { _buoyancy = value;
|
||||
_scene.TaintedObject(delegate()
|
||||
Scene.TaintedObject("BSCharacter.setBuoyancy", delegate()
|
||||
{
|
||||
DetailLog("{0},setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
||||
BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy);
|
||||
DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy);
|
||||
BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -365,9 +437,9 @@ public class BSCharacter : PhysicsActor
|
||||
_force.Y += force.Y;
|
||||
_force.Z += force.Z;
|
||||
// m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force);
|
||||
_scene.TaintedObject(delegate()
|
||||
Scene.TaintedObject("BSCharacter.AddForce", delegate()
|
||||
{
|
||||
DetailLog("{0},setAddForce,taint,addedForce={1}", LocalID, _force);
|
||||
DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force);
|
||||
BulletSimAPI.AddObjectForce2(Body.Ptr, _force);
|
||||
});
|
||||
}
|
||||
@@ -391,17 +463,23 @@ public class BSCharacter : PhysicsActor
|
||||
// make sure first collision happens
|
||||
_nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
|
||||
|
||||
Scene.TaintedObject(delegate()
|
||||
Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate()
|
||||
{
|
||||
BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override void ZeroMotion()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop collision events
|
||||
public override void UnSubscribeEvents() {
|
||||
_subscribedEventsMs = 0;
|
||||
// Avatars get all their collision events
|
||||
// Scene.TaintedObject(delegate()
|
||||
// Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate()
|
||||
// {
|
||||
// BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
// });
|
||||
@@ -416,73 +494,57 @@ public class BSCharacter : PhysicsActor
|
||||
{
|
||||
_avatarVolume = (float)(
|
||||
Math.PI
|
||||
* _scene.Params.avatarCapsuleRadius * _scale.X
|
||||
* _scene.Params.avatarCapsuleRadius * _scale.Y
|
||||
* _scene.Params.avatarCapsuleHeight * _scale.Z);
|
||||
* _scale.X
|
||||
* _scale.Y // the area of capsule cylinder
|
||||
* _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;
|
||||
}
|
||||
|
||||
// The physics engine says that properties have updated. Update same and inform
|
||||
// the world that things have changed.
|
||||
public void UpdateProperties(EntityProperties entprop)
|
||||
public override 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;
|
||||
_orientation = entprop.Rotation;
|
||||
_velocity = entprop.Velocity;
|
||||
_acceleration = entprop.Acceleration;
|
||||
_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();
|
||||
|
||||
// Do some sanity checking for the avatar. Make sure it's above ground and inbounds.
|
||||
PositionSanityCheck2();
|
||||
|
||||
float heightHere = Scene.TerrainManager.GetTerrainHeightAtXYZ(_position); // only for debug
|
||||
DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5},terrain={6}",
|
||||
LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity, heightHere);
|
||||
}
|
||||
|
||||
// Called by the scene when a collision with this object is reported
|
||||
// The collision, if it should be reported to the character, is placed in a collection
|
||||
// that will later be sent to the simulator when SendCollisions() is called.
|
||||
CollisionEventUpdate collisionCollection = null;
|
||||
public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
|
||||
public override void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth)
|
||||
{
|
||||
// m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith);
|
||||
|
||||
// The following makes IsColliding() and IsCollidingGround() work
|
||||
_collidingStep = _scene.SimulationStep;
|
||||
_collidingStep = Scene.SimulationStep;
|
||||
if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID)
|
||||
{
|
||||
_collidingGroundStep = _scene.SimulationStep;
|
||||
_collidingGroundStep = Scene.SimulationStep;
|
||||
}
|
||||
// DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith);
|
||||
|
||||
// throttle collisions to the rate specified in the subscription
|
||||
if (_subscribedEventsMs != 0) {
|
||||
int nowTime = _scene.SimulationNowTime;
|
||||
int nowTime = Scene.SimulationNowTime;
|
||||
if (nowTime >= _nextCollisionOkTime) {
|
||||
_nextCollisionOkTime = nowTime + _subscribedEventsMs;
|
||||
|
||||
@@ -493,7 +555,7 @@ public class BSCharacter : PhysicsActor
|
||||
}
|
||||
}
|
||||
|
||||
public void SendCollisions()
|
||||
public override void SendCollisions()
|
||||
{
|
||||
/*
|
||||
if (collisionCollection != null && collisionCollection.Count > 0)
|
||||
@@ -507,7 +569,10 @@ public class BSCharacter : PhysicsActor
|
||||
if (collisionCollection == null)
|
||||
collisionCollection = new CollisionEventUpdate();
|
||||
base.SendCollisionUpdate(collisionCollection);
|
||||
collisionCollection.Clear();
|
||||
// If there were any collisions in the collection, make sure we don't use the
|
||||
// same instance next time.
|
||||
if (collisionCollection.Count > 0)
|
||||
collisionCollection = null;
|
||||
// End kludge
|
||||
}
|
||||
|
||||
|
||||
@@ -32,43 +32,33 @@ using OpenMetaverse;
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
|
||||
public class BSConstraint : IDisposable
|
||||
public abstract class BSConstraint : IDisposable
|
||||
{
|
||||
private BulletSim m_world;
|
||||
private BulletBody m_body1;
|
||||
private BulletBody m_body2;
|
||||
private BulletConstraint m_constraint;
|
||||
private bool m_enabled = false;
|
||||
protected BulletSim m_world;
|
||||
protected BulletBody m_body1;
|
||||
protected BulletBody m_body2;
|
||||
protected BulletConstraint m_constraint;
|
||||
protected bool m_enabled = false;
|
||||
|
||||
public BSConstraint(BulletSim world, BulletBody obj1, BulletBody obj2,
|
||||
Vector3 frame1, Quaternion frame1rot,
|
||||
Vector3 frame2, Quaternion frame2rot
|
||||
)
|
||||
public BSConstraint()
|
||||
{
|
||||
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)
|
||||
{
|
||||
// BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID);
|
||||
BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr);
|
||||
m_enabled = false;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public BulletBody Body1 { get { return m_body1; } }
|
||||
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;
|
||||
if (m_enabled)
|
||||
@@ -76,7 +66,7 @@ public class BSConstraint : IDisposable
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool SetAngularLimits(Vector3 low, Vector3 high)
|
||||
public virtual bool SetAngularLimits(Vector3 low, Vector3 high)
|
||||
{
|
||||
bool ret = false;
|
||||
if (m_enabled)
|
||||
@@ -84,42 +74,38 @@ public class BSConstraint : IDisposable
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool SetCFMAndERP(float cfm, float erp)
|
||||
{
|
||||
bool ret = true;
|
||||
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
|
||||
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL);
|
||||
BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL);
|
||||
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()
|
||||
public virtual bool CalculateTransforms()
|
||||
{
|
||||
bool ret = false;
|
||||
if (m_enabled)
|
||||
{
|
||||
// Recompute the internal transforms
|
||||
BulletSimAPI.CalculateTransforms2(m_constraint.Ptr);
|
||||
ret = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Reset this constraint making sure it has all its internal structures
|
||||
// recomputed and is enabled and ready to go.
|
||||
public virtual bool RecomputeConstraintVariables(float mass)
|
||||
{
|
||||
bool ret = false;
|
||||
if (m_enabled)
|
||||
{
|
||||
ret = CalculateTransforms();
|
||||
if (ret)
|
||||
{
|
||||
// m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}",
|
||||
// BSScene.DetailLogZero, Body1.ID, Body2.ID);
|
||||
BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_world.scene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,29 +56,25 @@ public class BSConstraintCollection : IDisposable
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
foreach (BSConstraint cons in m_constraints)
|
||||
lock (m_constraints)
|
||||
{
|
||||
cons.Dispose();
|
||||
foreach (BSConstraint cons in m_constraints)
|
||||
{
|
||||
cons.Dispose();
|
||||
}
|
||||
m_constraints.Clear();
|
||||
}
|
||||
m_constraints.Clear();
|
||||
}
|
||||
|
||||
public 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)
|
||||
{
|
||||
// There is only one constraint between any bodies. Remove any old just to make sure.
|
||||
RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
|
||||
lock (m_constraints)
|
||||
{
|
||||
// There is only one constraint between any bodies. Remove any old just to make sure.
|
||||
RemoveAndDestroyConstraint(cons.Body1, cons.Body2);
|
||||
|
||||
m_constraints.Add(cons);
|
||||
m_constraints.Add(cons);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -92,16 +88,19 @@ public class BSConstraintCollection : IDisposable
|
||||
|
||||
uint lookingID1 = body1.ID;
|
||||
uint lookingID2 = body2.ID;
|
||||
ForEachConstraint(delegate(BSConstraint constrain)
|
||||
lock (m_constraints)
|
||||
{
|
||||
if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
|
||||
|| (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
|
||||
foreach (BSConstraint constrain in m_constraints)
|
||||
{
|
||||
foundConstraint = constrain;
|
||||
found = true;
|
||||
if ((constrain.Body1.ID == lookingID1 && constrain.Body2.ID == lookingID2)
|
||||
|| (constrain.Body1.ID == lookingID2 && constrain.Body2.ID == lookingID1))
|
||||
{
|
||||
foundConstraint = constrain;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
});
|
||||
}
|
||||
returnConstraint = foundConstraint;
|
||||
return found;
|
||||
}
|
||||
@@ -111,24 +110,35 @@ public class BSConstraintCollection : IDisposable
|
||||
// Return 'true' if a constraint was found and destroyed.
|
||||
public bool RemoveAndDestroyConstraint(BulletBody body1, BulletBody body2)
|
||||
{
|
||||
// return BulletSimAPI.RemoveConstraint(m_world.ID, obj1.ID, obj2.ID);
|
||||
|
||||
bool ret = false;
|
||||
BSConstraint constrain;
|
||||
|
||||
if (this.TryGetConstraint(body1, body2, out constrain))
|
||||
lock (m_constraints)
|
||||
{
|
||||
// remove the constraint from our collection
|
||||
m_constraints.Remove(constrain);
|
||||
// tell the engine that all its structures need to be freed
|
||||
constrain.Dispose();
|
||||
// we destroyed something
|
||||
ret = true;
|
||||
BSConstraint constrain;
|
||||
if (this.TryGetConstraint(body1, body2, out constrain))
|
||||
{
|
||||
// remove the constraint from our collection
|
||||
RemoveAndDestroyConstraint(constrain);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// The constraint MUST exist in the collection
|
||||
public bool RemoveAndDestroyConstraint(BSConstraint constrain)
|
||||
{
|
||||
lock (m_constraints)
|
||||
{
|
||||
// remove the constraint from our collection
|
||||
m_constraints.Remove(constrain);
|
||||
}
|
||||
// tell the engine that all its structures need to be freed
|
||||
constrain.Dispose();
|
||||
// we destroyed something
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove all constraints that reference the passed body.
|
||||
// Return 'true' if any constraints were destroyed.
|
||||
public bool RemoveAndDestroyConstraint(BulletBody body1)
|
||||
@@ -137,16 +147,15 @@ public class BSConstraintCollection : IDisposable
|
||||
|
||||
List<BSConstraint> toRemove = new List<BSConstraint>();
|
||||
uint lookingID = body1.ID;
|
||||
ForEachConstraint(delegate(BSConstraint constrain)
|
||||
{
|
||||
if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
|
||||
{
|
||||
toRemove.Add(constrain);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
lock (m_constraints)
|
||||
{
|
||||
foreach (BSConstraint constrain in m_constraints)
|
||||
{
|
||||
if (constrain.Body1.ID == lookingID || constrain.Body2.ID == lookingID)
|
||||
{
|
||||
toRemove.Add(constrain);
|
||||
}
|
||||
}
|
||||
foreach (BSConstraint constrain in toRemove)
|
||||
{
|
||||
m_constraints.Remove(constrain);
|
||||
@@ -158,27 +167,16 @@ public class BSConstraintCollection : IDisposable
|
||||
|
||||
public bool RecalculateAllConstraints()
|
||||
{
|
||||
foreach (BSConstraint constrain in m_constraints)
|
||||
{
|
||||
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)
|
||||
{
|
||||
bool ret = false;
|
||||
lock (m_constraints)
|
||||
{
|
||||
foreach (BSConstraint constrain in m_constraints)
|
||||
{
|
||||
if (action(constrain))
|
||||
break;
|
||||
constrain.CalculateTransforms();
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
private int frcount = 0; // Used to limit dynamics debug output to
|
||||
// every 100th frame
|
||||
|
||||
private BSScene m_physicsScene;
|
||||
private BSPrim m_prim; // the prim this dynamic controller belongs to
|
||||
|
||||
// Vehicle properties
|
||||
@@ -74,7 +75,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
// HOVER_UP_ONLY
|
||||
// LIMIT_MOTOR_UP
|
||||
// LIMIT_ROLL_ONLY
|
||||
private VehicleFlag m_Hoverflags = (VehicleFlag)0;
|
||||
private Vector3 m_BlockingEndPoint = Vector3.Zero;
|
||||
private Quaternion m_RollreferenceFrame = Quaternion.Identity;
|
||||
// Linear properties
|
||||
@@ -124,15 +124,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
private float m_verticalAttractionEfficiency = 1.0f; // damped
|
||||
private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor.
|
||||
|
||||
public BSDynamics(BSPrim myPrim)
|
||||
public BSDynamics(BSScene myScene, BSPrim myPrim)
|
||||
{
|
||||
m_physicsScene = myScene;
|
||||
m_prim = myPrim;
|
||||
m_type = Vehicle.TYPE_NONE;
|
||||
}
|
||||
|
||||
internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep)
|
||||
{
|
||||
DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
|
||||
VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
|
||||
switch (pParam)
|
||||
{
|
||||
case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
|
||||
@@ -231,7 +232,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
|
||||
internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep)
|
||||
{
|
||||
DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
|
||||
VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
|
||||
switch (pParam)
|
||||
{
|
||||
case Vehicle.ANGULAR_FRICTION_TIMESCALE:
|
||||
@@ -266,7 +267,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
|
||||
internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
|
||||
{
|
||||
DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
|
||||
VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue);
|
||||
switch (pParam)
|
||||
{
|
||||
case Vehicle.REFERENCE_FRAME:
|
||||
@@ -280,164 +281,27 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
|
||||
internal void ProcessVehicleFlags(int pParam, bool remove)
|
||||
{
|
||||
DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove);
|
||||
VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove);
|
||||
VehicleFlag parm = (VehicleFlag)pParam;
|
||||
if (remove)
|
||||
{
|
||||
if (pParam == -1)
|
||||
{
|
||||
m_flags = (VehicleFlag)0;
|
||||
m_Hoverflags = (VehicleFlag)0;
|
||||
return;
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT)
|
||||
else
|
||||
{
|
||||
if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != (VehicleFlag)0)
|
||||
m_Hoverflags &= ~(VehicleFlag.HOVER_GLOBAL_HEIGHT);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY)
|
||||
{
|
||||
if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != (VehicleFlag)0)
|
||||
m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY)
|
||||
{
|
||||
if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != (VehicleFlag)0)
|
||||
m_Hoverflags &= ~(VehicleFlag.HOVER_UP_ONLY);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY)
|
||||
{
|
||||
if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != (VehicleFlag)0)
|
||||
m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP)
|
||||
{
|
||||
if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != (VehicleFlag)0)
|
||||
m_flags &= ~(VehicleFlag.LIMIT_MOTOR_UP);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.LIMIT_ROLL_ONLY) == (int)VehicleFlag.LIMIT_ROLL_ONLY)
|
||||
{
|
||||
if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) != (VehicleFlag)0)
|
||||
m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK)
|
||||
{
|
||||
if ((m_flags & VehicleFlag.MOUSELOOK_BANK) != (VehicleFlag)0)
|
||||
m_flags &= ~(VehicleFlag.MOUSELOOK_BANK);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER)
|
||||
{
|
||||
if ((m_flags & VehicleFlag.MOUSELOOK_STEER) != (VehicleFlag)0)
|
||||
m_flags &= ~(VehicleFlag.MOUSELOOK_STEER);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP)
|
||||
{
|
||||
if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) != (VehicleFlag)0)
|
||||
m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED)
|
||||
{
|
||||
if ((m_flags & VehicleFlag.CAMERA_DECOUPLED) != (VehicleFlag)0)
|
||||
m_flags &= ~(VehicleFlag.CAMERA_DECOUPLED);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X)
|
||||
{
|
||||
if ((m_flags & VehicleFlag.NO_X) != (VehicleFlag)0)
|
||||
m_flags &= ~(VehicleFlag.NO_X);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y)
|
||||
{
|
||||
if ((m_flags & VehicleFlag.NO_Y) != (VehicleFlag)0)
|
||||
m_flags &= ~(VehicleFlag.NO_Y);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z)
|
||||
{
|
||||
if ((m_flags & VehicleFlag.NO_Z) != (VehicleFlag)0)
|
||||
m_flags &= ~(VehicleFlag.NO_Z);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT)
|
||||
{
|
||||
if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != (VehicleFlag)0)
|
||||
m_Hoverflags &= ~(VehicleFlag.LOCK_HOVER_HEIGHT);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION)
|
||||
{
|
||||
if ((m_flags & VehicleFlag.NO_DEFLECTION) != (VehicleFlag)0)
|
||||
m_flags &= ~(VehicleFlag.NO_DEFLECTION);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION)
|
||||
{
|
||||
if ((m_flags & VehicleFlag.LOCK_ROTATION) != (VehicleFlag)0)
|
||||
m_flags &= ~(VehicleFlag.LOCK_ROTATION);
|
||||
m_flags &= ~parm;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT)
|
||||
{
|
||||
m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT | m_flags);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY)
|
||||
{
|
||||
m_Hoverflags |= (VehicleFlag.HOVER_TERRAIN_ONLY | m_flags);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY)
|
||||
{
|
||||
m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY | m_flags);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY)
|
||||
{
|
||||
m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY | m_flags);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP)
|
||||
{
|
||||
m_flags |= (VehicleFlag.LIMIT_MOTOR_UP | m_flags);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK)
|
||||
{
|
||||
m_flags |= (VehicleFlag.MOUSELOOK_BANK | m_flags);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER)
|
||||
{
|
||||
m_flags |= (VehicleFlag.MOUSELOOK_STEER | m_flags);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP)
|
||||
{
|
||||
m_flags |= (VehicleFlag.NO_DEFLECTION_UP | m_flags);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED)
|
||||
{
|
||||
m_flags |= (VehicleFlag.CAMERA_DECOUPLED | m_flags);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X)
|
||||
{
|
||||
m_flags |= (VehicleFlag.NO_X);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y)
|
||||
{
|
||||
m_flags |= (VehicleFlag.NO_Y);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z)
|
||||
{
|
||||
m_flags |= (VehicleFlag.NO_Z);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT)
|
||||
{
|
||||
m_Hoverflags |= (VehicleFlag.LOCK_HOVER_HEIGHT);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION)
|
||||
{
|
||||
m_flags |= (VehicleFlag.NO_DEFLECTION);
|
||||
}
|
||||
if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION)
|
||||
{
|
||||
m_flags |= (VehicleFlag.LOCK_ROTATION);
|
||||
}
|
||||
else {
|
||||
m_flags |= parm;
|
||||
}
|
||||
}//end ProcessVehicleFlags
|
||||
|
||||
internal void ProcessTypeChange(Vehicle pType)
|
||||
internal void ProcessTypeChange(Vehicle pType, float stepSize)
|
||||
{
|
||||
DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType);
|
||||
VDetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType);
|
||||
// Set Defaults For Type
|
||||
m_type = pType;
|
||||
switch (pType)
|
||||
@@ -478,10 +342,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
// m_bankingMix = 1;
|
||||
// m_bankingTimescale = 10;
|
||||
// m_referenceFrame = Quaternion.Identity;
|
||||
m_Hoverflags &=
|
||||
m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
|
||||
m_flags &=
|
||||
~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
|
||||
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
|
||||
m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
|
||||
break;
|
||||
case Vehicle.TYPE_CAR:
|
||||
m_linearFrictionTimescale = new Vector3(100, 2, 1000);
|
||||
@@ -506,10 +370,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
// m_bankingMix = 1;
|
||||
// m_bankingTimescale = 1;
|
||||
// m_referenceFrame = Quaternion.Identity;
|
||||
m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
|
||||
m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
|
||||
VehicleFlag.LIMIT_MOTOR_UP);
|
||||
m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY);
|
||||
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
|
||||
m_flags |= (VehicleFlag.HOVER_UP_ONLY);
|
||||
break;
|
||||
case Vehicle.TYPE_BOAT:
|
||||
m_linearFrictionTimescale = new Vector3(10, 3, 2);
|
||||
@@ -534,12 +398,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
// m_bankingMix = 0.8f;
|
||||
// m_bankingTimescale = 1;
|
||||
// m_referenceFrame = Quaternion.Identity;
|
||||
m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
|
||||
m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
|
||||
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
|
||||
m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY);
|
||||
m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
|
||||
VehicleFlag.LIMIT_MOTOR_UP);
|
||||
m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY);
|
||||
m_flags |= (VehicleFlag.HOVER_WATER_ONLY);
|
||||
break;
|
||||
case Vehicle.TYPE_AIRPLANE:
|
||||
m_linearFrictionTimescale = new Vector3(200, 10, 5);
|
||||
@@ -564,7 +428,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
// m_bankingMix = 0.7f;
|
||||
// m_bankingTimescale = 2;
|
||||
// m_referenceFrame = Quaternion.Identity;
|
||||
m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
|
||||
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
|
||||
VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
|
||||
m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
|
||||
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
|
||||
@@ -592,15 +456,16 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
// m_bankingMix = 0.7f;
|
||||
// m_bankingTimescale = 5;
|
||||
// m_referenceFrame = Quaternion.Identity;
|
||||
m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
|
||||
m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
|
||||
VehicleFlag.HOVER_UP_ONLY);
|
||||
m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP);
|
||||
m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
|
||||
m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT);
|
||||
m_flags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT);
|
||||
break;
|
||||
}
|
||||
}//end SetDefaultsForType
|
||||
|
||||
// One step of the vehicle properties for the next 'pTimestep' seconds.
|
||||
internal void Step(float pTimestep)
|
||||
{
|
||||
if (m_type == Vehicle.TYPE_NONE) return;
|
||||
@@ -613,7 +478,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
MoveAngular(pTimestep);
|
||||
LimitRotation(pTimestep);
|
||||
|
||||
DetailLog("{0},Dynamics,done,pos={1},force={2},velocity={3},angvel={4}",
|
||||
VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}",
|
||||
m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity);
|
||||
}// end Step
|
||||
|
||||
@@ -657,7 +522,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
|
||||
*/
|
||||
|
||||
DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}",
|
||||
VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}",
|
||||
m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector);
|
||||
}
|
||||
else
|
||||
@@ -669,7 +534,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
m_lastLinearVelocityVector = Vector3.Zero;
|
||||
}
|
||||
|
||||
// convert requested object velocity to world-referenced vector
|
||||
// convert requested object velocity to object relative vector
|
||||
Quaternion rotq = m_prim.Orientation;
|
||||
m_dir = m_lastLinearVelocityVector * rotq;
|
||||
|
||||
@@ -722,42 +587,42 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
if (changed)
|
||||
{
|
||||
m_prim.Position = pos;
|
||||
DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
|
||||
VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}",
|
||||
m_prim.LocalID, m_BlockingEndPoint, posChange, pos);
|
||||
}
|
||||
}
|
||||
|
||||
// If below the terrain, move us above the ground a little.
|
||||
if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos))
|
||||
if (pos.Z < m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos))
|
||||
{
|
||||
pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2;
|
||||
pos.Z = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2;
|
||||
m_prim.Position = pos;
|
||||
DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos);
|
||||
VDetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos);
|
||||
}
|
||||
|
||||
// Check if hovering
|
||||
if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
|
||||
if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0)
|
||||
{
|
||||
// We should hover, get the target height
|
||||
if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0)
|
||||
if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0)
|
||||
{
|
||||
m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight;
|
||||
}
|
||||
if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
|
||||
if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0)
|
||||
{
|
||||
m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
|
||||
m_VhoverTargetHeight = m_prim.Scene.TerrainManager.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight;
|
||||
}
|
||||
if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
|
||||
if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0)
|
||||
{
|
||||
m_VhoverTargetHeight = m_VhoverHeight;
|
||||
}
|
||||
|
||||
if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0)
|
||||
if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0)
|
||||
{
|
||||
// If body is aready heigher, use its height as target height
|
||||
if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z;
|
||||
}
|
||||
if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
|
||||
if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0)
|
||||
{
|
||||
if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2)
|
||||
{
|
||||
@@ -779,7 +644,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
}
|
||||
}
|
||||
|
||||
DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight);
|
||||
VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight);
|
||||
|
||||
// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped
|
||||
// m_VhoverTimescale = 0f; // time to acheive height
|
||||
@@ -809,13 +674,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
grav.Z = (float)(grav.Z * 1.125);
|
||||
}
|
||||
float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos);
|
||||
float terraintemp = m_prim.Scene.TerrainManager.GetTerrainHeightAtXYZ(pos);
|
||||
float postemp = (pos.Z - terraintemp);
|
||||
if (postemp > 2.5f)
|
||||
{
|
||||
grav.Z = (float)(grav.Z * 1.037125);
|
||||
}
|
||||
DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
|
||||
VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav);
|
||||
//End Experimental Values
|
||||
}
|
||||
if ((m_flags & (VehicleFlag.NO_X)) != 0)
|
||||
@@ -844,7 +709,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep);
|
||||
m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount;
|
||||
|
||||
DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}",
|
||||
VDetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}",
|
||||
m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount);
|
||||
|
||||
} // end MoveLinear()
|
||||
@@ -870,13 +735,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
// There are m_angularMotorApply steps.
|
||||
Vector3 origAngularVelocity = m_angularMotorVelocity;
|
||||
// ramp up to new value
|
||||
// current velocity += error / (time to get there / step interval)
|
||||
// current velocity += error / (time to get there / step interval)
|
||||
// requested speed - last motor speed
|
||||
m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep);
|
||||
m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep);
|
||||
m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep);
|
||||
|
||||
DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}",
|
||||
VDetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}",
|
||||
m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity);
|
||||
|
||||
m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected
|
||||
@@ -887,6 +752,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
// No motor recently applied, keep the body velocity
|
||||
// and decay the velocity
|
||||
m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep);
|
||||
if (m_angularMotorVelocity.LengthSquared() < 0.00001)
|
||||
m_angularMotorVelocity = Vector3.Zero;
|
||||
} // end motor section
|
||||
|
||||
// Vertical attractor section
|
||||
@@ -924,7 +791,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
vertattr.X += bounce * angularVelocity.X;
|
||||
vertattr.Y += bounce * angularVelocity.Y;
|
||||
|
||||
DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}",
|
||||
VDetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}",
|
||||
m_prim.LocalID, verterr, bounce, vertattr);
|
||||
|
||||
} // else vertical attractor is off
|
||||
@@ -942,13 +809,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
m_lastAngularVelocity.X = 0;
|
||||
m_lastAngularVelocity.Y = 0;
|
||||
DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
|
||||
VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
|
||||
}
|
||||
|
||||
if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f))
|
||||
{
|
||||
m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero.
|
||||
DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
|
||||
VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity);
|
||||
}
|
||||
|
||||
// apply friction
|
||||
@@ -958,7 +825,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
// Apply to the body
|
||||
m_prim.RotationalVelocity = m_lastAngularVelocity;
|
||||
|
||||
DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity);
|
||||
VDetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity);
|
||||
} //end MoveAngular
|
||||
|
||||
internal void LimitRotation(float timestep)
|
||||
@@ -1005,11 +872,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
if (changed)
|
||||
m_prim.Orientation = m_rot;
|
||||
|
||||
DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot);
|
||||
VDetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot);
|
||||
}
|
||||
|
||||
// Invoke the detailed logger and output something if it's enabled.
|
||||
private void DetailLog(string msg, params Object[] args)
|
||||
private void VDetailLog(string msg, params Object[] args)
|
||||
{
|
||||
if (m_prim.Scene.VehicleLoggingEnabled)
|
||||
m_prim.Scene.PhysicsLogging.Write(msg, args);
|
||||
|
||||
55
OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs
Executable file
55
OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs
Executable 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -36,12 +36,17 @@ public class BSLinkset
|
||||
{
|
||||
private static string LogHeader = "[BULLETSIM LINKSET]";
|
||||
|
||||
private BSPrim m_linksetRoot;
|
||||
public BSPrim Root { get { return m_linksetRoot; } }
|
||||
private BSPhysObject m_linksetRoot;
|
||||
public BSPhysObject LinksetRoot { get { return m_linksetRoot; } }
|
||||
|
||||
private BSScene m_scene;
|
||||
private BSScene m_physicsScene;
|
||||
public BSScene PhysicsScene { get { return m_physicsScene; } }
|
||||
|
||||
private List<BSPrim> m_children;
|
||||
static int m_nextLinksetID = 1;
|
||||
public int LinksetID { get; private set; }
|
||||
|
||||
// The children under the root in this linkset
|
||||
private List<BSPhysObject> m_children;
|
||||
|
||||
// We lock the diddling of linkset classes to prevent any badness.
|
||||
// This locks the modification of the instances of this class. Changes
|
||||
@@ -69,28 +74,35 @@ public class BSLinkset
|
||||
get { return ComputeLinksetGeometricCenter(); }
|
||||
}
|
||||
|
||||
public BSLinkset(BSScene scene, BSPrim parent)
|
||||
public BSLinkset(BSScene scene, BSPhysObject parent)
|
||||
{
|
||||
// A simple linkset of one (no children)
|
||||
m_scene = scene;
|
||||
LinksetID = m_nextLinksetID++;
|
||||
// We create LOTS of linksets.
|
||||
if (m_nextLinksetID < 0)
|
||||
m_nextLinksetID = 1;
|
||||
m_physicsScene = scene;
|
||||
m_linksetRoot = parent;
|
||||
m_children = new List<BSPrim>();
|
||||
m_children = new List<BSPhysObject>();
|
||||
m_mass = parent.MassRaw;
|
||||
}
|
||||
|
||||
// Link to a linkset where the child knows the parent.
|
||||
// Parent changing should not happen so do some sanity checking.
|
||||
// We return the parent's linkset so the child can track it's membership.
|
||||
public BSLinkset AddMeToLinkset(BSPrim child, BSPrim parent)
|
||||
// We return the parent's linkset so the child can track its membership.
|
||||
public BSLinkset AddMeToLinkset(BSPhysObject child)
|
||||
{
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
parent.Linkset.AddChildToLinkset(child);
|
||||
AddChildToLinkset(child);
|
||||
}
|
||||
return parent.Linkset;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BSLinkset RemoveMeFromLinkset(BSPrim child)
|
||||
// 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(BSPhysObject child)
|
||||
{
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
@@ -101,7 +113,7 @@ public class BSLinkset
|
||||
{
|
||||
// Note that we don't do a foreach because the remove routine
|
||||
// takes it out of the list.
|
||||
RemoveChildFromLinkset(m_children[0]);
|
||||
RemoveChildFromOtherLinkset(m_children[0]);
|
||||
}
|
||||
m_children.Clear(); // just to make sure
|
||||
}
|
||||
@@ -113,76 +125,33 @@ public class BSLinkset
|
||||
}
|
||||
|
||||
// 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
|
||||
public bool IsRoot(BSPrim requestor)
|
||||
public bool IsRoot(BSPhysObject requestor)
|
||||
{
|
||||
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)
|
||||
public bool HasAnyChildren { get { return (m_children.Count > 0); } }
|
||||
|
||||
// Return 'true' if this child is in this linkset
|
||||
public bool HasChild(BSPrim child)
|
||||
public bool HasChild(BSPhysObject child)
|
||||
{
|
||||
bool ret = false;
|
||||
foreach (BSPrim bp in m_children)
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
if (child.LocalID == bp.LocalID)
|
||||
foreach (BSPhysObject bp in m_children)
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
if (child.LocalID == bp.LocalID)
|
||||
{
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
@@ -191,7 +160,7 @@ public class BSLinkset
|
||||
private float ComputeLinksetMass()
|
||||
{
|
||||
float mass = m_linksetRoot.MassRaw;
|
||||
foreach (BSPrim bp in m_children)
|
||||
foreach (BSPhysObject bp in m_children)
|
||||
{
|
||||
mass += bp.MassRaw;
|
||||
}
|
||||
@@ -203,12 +172,16 @@ public class BSLinkset
|
||||
OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw;
|
||||
float totalMass = m_linksetRoot.MassRaw;
|
||||
|
||||
foreach (BSPrim bp in m_children)
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
com += bp.Position * bp.MassRaw;
|
||||
totalMass += bp.MassRaw;
|
||||
foreach (BSPhysObject bp in m_children)
|
||||
{
|
||||
com += bp.Position * bp.MassRaw;
|
||||
totalMass += bp.MassRaw;
|
||||
}
|
||||
if (totalMass != 0f)
|
||||
com /= totalMass;
|
||||
}
|
||||
com /= totalMass;
|
||||
|
||||
return com;
|
||||
}
|
||||
@@ -217,135 +190,223 @@ public class BSLinkset
|
||||
{
|
||||
OMV.Vector3 com = m_linksetRoot.Position;
|
||||
|
||||
foreach (BSPrim bp in m_children)
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
com += bp.Position * bp.MassRaw;
|
||||
foreach (BSPhysObject bp in m_children)
|
||||
{
|
||||
com += bp.Position * bp.MassRaw;
|
||||
}
|
||||
com /= (m_children.Count + 1);
|
||||
}
|
||||
com /= m_children.Count + 1;
|
||||
|
||||
return com;
|
||||
}
|
||||
|
||||
// I am the root of a linkset and a new child is being added
|
||||
public void AddChildToLinkset(BSPrim pchild)
|
||||
// When physical properties are changed the linkset needs to recalculate
|
||||
// its internal properties.
|
||||
public void Refresh(BSPhysObject 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 (BSPhysObject 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(BSPhysObject child)
|
||||
{
|
||||
BSPrim child = pchild;
|
||||
if (!HasChild(child))
|
||||
{
|
||||
m_children.Add(child);
|
||||
|
||||
m_scene.TaintedObject(delegate()
|
||||
BSPhysObject rootx = LinksetRoot; // capture the root as of now
|
||||
BSPhysObject childx = child;
|
||||
m_physicsScene.TaintedObject("AddChildToLinkset", delegate()
|
||||
{
|
||||
DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID);
|
||||
DetailLog("{0},AddChildToLinkset,child={1}", m_linksetRoot.LocalID, pchild.LocalID);
|
||||
PhysicallyLinkAChildToRoot(pchild); // build the physical binding between me and the child
|
||||
DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID);
|
||||
PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child
|
||||
});
|
||||
}
|
||||
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(BSPhysObject pchild)
|
||||
{
|
||||
pchild.Linkset = new BSLinkset(m_physicsScene, pchild);
|
||||
RemoveChildFromLinkset(pchild);
|
||||
}
|
||||
|
||||
// I am the root of a linkset and one of my children is being removed.
|
||||
// Safe to call even if the child is not really in my linkset.
|
||||
public void RemoveChildFromLinkset(BSPrim pchild)
|
||||
private void RemoveChildFromLinkset(BSPhysObject child)
|
||||
{
|
||||
BSPrim child = pchild;
|
||||
|
||||
if (m_children.Remove(child))
|
||||
{
|
||||
m_scene.TaintedObject(delegate()
|
||||
BSPhysObject rootx = LinksetRoot; // capture the root as of now
|
||||
BSPhysObject childx = child;
|
||||
m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate()
|
||||
{
|
||||
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)
|
||||
{
|
||||
// if the linkset is empty, make sure all linkages have been removed
|
||||
PhysicallyUnlinkAllChildrenFromRoot();
|
||||
}
|
||||
else
|
||||
{
|
||||
PhysicallyUnlinkAChildFromRoot(pchild);
|
||||
}
|
||||
PhysicallyUnlinkAChildFromRoot(rootx, childx);
|
||||
});
|
||||
|
||||
RecomputeLinksetConstraintVariables();
|
||||
}
|
||||
else
|
||||
{
|
||||
// This will happen if we remove the root of the linkset first. Non-fatal occurance.
|
||||
// m_scene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
|
||||
// PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a constraint between me (root of linkset) and the passed prim (the child).
|
||||
// Called at taint time!
|
||||
private void PhysicallyLinkAChildToRoot(BSPrim childPrim)
|
||||
private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
|
||||
{
|
||||
// Zero motion for children so they don't interpolate
|
||||
childPrim.ZeroMotion();
|
||||
|
||||
// relative position normalized to the root prim
|
||||
OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(m_linksetRoot.Orientation);
|
||||
OMV.Vector3 childRelativePosition = (childPrim.Position - m_linksetRoot.Position) * invThisOrientation;
|
||||
// Relative position normalized to the root prim
|
||||
// Essentually a vector pointing from center of rootPrim to center of childPrim
|
||||
OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;
|
||||
|
||||
// relative rotation of the child to the parent
|
||||
OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
|
||||
// real world coordinate of midpoint between the two objects
|
||||
OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);
|
||||
|
||||
// create a constraint that allows no freedom of movement between the two objects
|
||||
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
||||
// 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);
|
||||
BSConstraint constrain = m_scene.Constraints.CreateConstraint(
|
||||
m_scene.World, m_linksetRoot.Body, childPrim.Body,
|
||||
// childRelativePosition,
|
||||
// childRelativeRotation,
|
||||
OMV.Vector3.Zero,
|
||||
OMV.Quaternion.Identity,
|
||||
OMV.Vector3.Zero,
|
||||
OMV.Quaternion.Identity
|
||||
DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}",
|
||||
rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint);
|
||||
BS6DofConstraint constrain = new BS6DofConstraint(
|
||||
m_physicsScene.World, rootPrim.Body, childPrim.Body,
|
||||
midPoint,
|
||||
true,
|
||||
true
|
||||
);
|
||||
/* NOTE: below is an attempt to build constraint with full frame computation, etc.
|
||||
* Using the midpoint is easier since it lets the Bullet code use the transforms
|
||||
* of the objects.
|
||||
* Code left as a warning to future programmers.
|
||||
// ==================================================================================
|
||||
// relative position normalized to the root prim
|
||||
OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
|
||||
OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;
|
||||
|
||||
// relative rotation of the child to the parent
|
||||
OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
|
||||
OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
|
||||
|
||||
// create a constraint that allows no freedom of movement between the two objects
|
||||
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
|
||||
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.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
|
||||
|
||||
// tweek the constraint to increase stability
|
||||
constrain.UseFrameOffset(m_scene.BoolNumeric(m_scene.Params.linkConstraintUseFrameOffset));
|
||||
constrain.TranslationalLimitMotor(m_scene.BoolNumeric(m_scene.Params.linkConstraintEnableTransMotor),
|
||||
m_scene.Params.linkConstraintTransMotorMaxVel,
|
||||
m_scene.Params.linkConstraintTransMotorMaxForce);
|
||||
constrain.SetCFMAndERP(m_scene.Params.linkConstraintCFM, m_scene.Params.linkConstraintERP);
|
||||
constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset));
|
||||
constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor),
|
||||
PhysicsScene.Params.linkConstraintTransMotorMaxVel,
|
||||
PhysicsScene.Params.linkConstraintTransMotorMaxForce);
|
||||
constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
|
||||
|
||||
RecomputeLinksetConstraintVariables();
|
||||
}
|
||||
|
||||
// Remove linkage between myself and a particular child
|
||||
// Called at taint time!
|
||||
private void PhysicallyUnlinkAChildFromRoot(BSPrim childPrim)
|
||||
private void PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
|
||||
{
|
||||
DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}",
|
||||
LogHeader, m_linksetRoot.LocalID, childPrim.LocalID);
|
||||
DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", m_linksetRoot.LocalID, m_linksetRoot.LocalID, childPrim.LocalID);
|
||||
// BulletSimAPI.RemoveConstraint(_scene.WorldID, LocalID, childPrim.LocalID);
|
||||
m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body, childPrim.Body);
|
||||
DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
|
||||
|
||||
// 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
|
||||
// Called at taint time!
|
||||
private void PhysicallyUnlinkAllChildrenFromRoot()
|
||||
private void PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
|
||||
{
|
||||
// DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader);
|
||||
DetailLog("{0},PhysicallyUnlinkAllChildren,taint", m_linksetRoot.LocalID);
|
||||
m_scene.Constraints.RemoveAndDestroyConstraint(m_linksetRoot.Body);
|
||||
// BulletSimAPI.RemoveConstraintByID(_scene.WorldID, LocalID);
|
||||
}
|
||||
DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
|
||||
|
||||
// Invoke the detailed logger and output something if it's enabled.
|
||||
private void DebugLog(string msg, params Object[] args)
|
||||
{
|
||||
m_scene.Logger.DebugFormat(msg, args);
|
||||
m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body);
|
||||
}
|
||||
|
||||
// Invoke the detailed logger and output something if it's enabled.
|
||||
private void DetailLog(string msg, params Object[] args)
|
||||
{
|
||||
m_scene.PhysicsLogging.Write(msg, args);
|
||||
m_physicsScene.PhysicsLogging.Write(msg, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
63
OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs → OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
Normal file → Executable file
63
OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs → OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
Normal file → Executable file
@@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
* Copyright (c) Contributors, http://opensimulator.org/
|
||||
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||
*
|
||||
@@ -6,7 +6,7 @@
|
||||
* 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
|
||||
* * 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
|
||||
@@ -24,38 +24,37 @@
|
||||
* (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.Drawing;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture
|
||||
using OMV = OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
public class DynamicTexture : IDynamicTexture
|
||||
{
|
||||
public string InputCommands { get; private set; }
|
||||
public Uri InputUri { get; private set; }
|
||||
public string InputParams { get; private set; }
|
||||
public byte[] Data { get; private set; }
|
||||
public Size Size { get; private set; }
|
||||
public bool IsReuseable { get; private set; }
|
||||
// Class to wrap all objects.
|
||||
// The rest of BulletSim doesn't need to keep checking for avatars or prims
|
||||
// unless the difference is significant.
|
||||
public abstract class BSPhysObject : PhysicsActor
|
||||
{
|
||||
public abstract BSLinkset Linkset { get; set; }
|
||||
|
||||
public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable)
|
||||
{
|
||||
InputCommands = inputCommands;
|
||||
InputParams = inputParams;
|
||||
Data = data;
|
||||
Size = size;
|
||||
IsReuseable = isReuseable;
|
||||
}
|
||||
public abstract void Collide(uint collidingWith, BSPhysObject collidee, ActorTypes type,
|
||||
OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth);
|
||||
public abstract void SendCollisions();
|
||||
|
||||
public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable)
|
||||
{
|
||||
InputUri = inputUri;
|
||||
InputParams = inputParams;
|
||||
Data = data;
|
||||
Size = size;
|
||||
IsReuseable = isReuseable;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return the object mass without calculating it or side effects
|
||||
public abstract float MassRaw { get; }
|
||||
|
||||
public abstract BulletBody Body { get; set; }
|
||||
public abstract void ZeroMotion();
|
||||
|
||||
public virtual void StepVehicle(float timeStep) { }
|
||||
|
||||
public abstract void UpdateProperties(EntityProperties entprop);
|
||||
|
||||
public abstract void Destroy();
|
||||
}
|
||||
}
|
||||
@@ -37,13 +37,11 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet;
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
[Serializable]
|
||||
public sealed class BSPrim : PhysicsActor
|
||||
public sealed class BSPrim : BSPhysObject
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly string LogHeader = "[BULLETS PRIM]";
|
||||
|
||||
private void DebugLog(string mm, params Object[] xx) { if (_scene.shouldDebugLog) m_log.DebugFormat(mm, xx); }
|
||||
|
||||
private IMesh _mesh;
|
||||
private PrimitiveBaseShape _pbs;
|
||||
private ShapeData.PhysicsShapeType _shapeType;
|
||||
@@ -90,23 +88,14 @@ public sealed class BSPrim : PhysicsActor
|
||||
private float _buoyancy;
|
||||
|
||||
// Membership in a linkset is controlled by this class.
|
||||
private BSLinkset _linkset;
|
||||
public BSLinkset Linkset
|
||||
{
|
||||
get { return _linkset; }
|
||||
set { _linkset = value; }
|
||||
}
|
||||
public override BSLinkset Linkset { get; set; }
|
||||
|
||||
private int _subscribedEventsMs = 0;
|
||||
private int _nextCollisionOkTime = 0;
|
||||
long _collidingStep;
|
||||
long _collidingGroundStep;
|
||||
|
||||
private BulletBody m_body;
|
||||
public BulletBody Body {
|
||||
get { return m_body; }
|
||||
set { m_body = value; }
|
||||
}
|
||||
public override BulletBody Body { get; set; }
|
||||
|
||||
private BSDynamics _vehicle;
|
||||
|
||||
@@ -138,39 +127,45 @@ public sealed class BSPrim : PhysicsActor
|
||||
_isPhysical = pisPhysical;
|
||||
_isVolumeDetect = false;
|
||||
_subscribedEventsMs = 0;
|
||||
_friction = _scene.Params.defaultFriction; // TODO: compute based on object material
|
||||
_density = _scene.Params.defaultDensity; // 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
|
||||
_restitution = _scene.Params.defaultRestitution;
|
||||
_linkset = new BSLinkset(_scene, this); // a linkset of one
|
||||
_vehicle = new BSDynamics(this); // add vehicleness
|
||||
Linkset = new BSLinkset(Scene, this); // a linkset of one
|
||||
_vehicle = new BSDynamics(Scene, this); // add vehicleness
|
||||
_mass = CalculateMass();
|
||||
// do the actual object creation at taint time
|
||||
_scene.TaintedObject(delegate()
|
||||
DetailLog("{0},BSPrim.constructor,call", LocalID);
|
||||
_scene.TaintedObject("BSPrim.create", delegate()
|
||||
{
|
||||
RecreateGeomAndObject();
|
||||
|
||||
// Get the pointer to the physical body for this object.
|
||||
// At the moment, we're still letting BulletSim manage the creation and destruction
|
||||
// of the object. Someday we'll move that into the C# code.
|
||||
m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
||||
Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID));
|
||||
});
|
||||
}
|
||||
|
||||
// called when this prim is being destroyed and we should free all the resources
|
||||
public void Destroy()
|
||||
public override void Destroy()
|
||||
{
|
||||
// m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
|
||||
// DetailLog("{0},Destroy", LocalID);
|
||||
|
||||
// Undo any links between me and any other object
|
||||
BSPhysObject 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
|
||||
_vehicle.ProcessTypeChange(Vehicle.TYPE_NONE);
|
||||
_scene.RemoveVehiclePrim(this); // just to make sure
|
||||
this.VehicleType = (int)Vehicle.TYPE_NONE;
|
||||
|
||||
_scene.TaintedObject(delegate()
|
||||
_scene.TaintedObject("BSPrim.destroy", delegate()
|
||||
{
|
||||
// Undo any links between me and any other object
|
||||
_linkset = _linkset.RemoveMeFromLinkset(this);
|
||||
|
||||
DetailLog("{0},BSPrim.Destroy,taint,", LocalID);
|
||||
// everything in the C# world will get garbage collected. Tell the C++ world to free stuff.
|
||||
BulletSimAPI.DestroyObject(_scene.WorldID, LocalID);
|
||||
});
|
||||
@@ -183,11 +178,11 @@ public sealed class BSPrim : PhysicsActor
|
||||
get { return _size; }
|
||||
set {
|
||||
_size = value;
|
||||
_scene.TaintedObject(delegate()
|
||||
_scene.TaintedObject("BSPrim.setSize", delegate()
|
||||
{
|
||||
_mass = CalculateMass(); // changing size changes the mass
|
||||
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();
|
||||
});
|
||||
}
|
||||
@@ -195,7 +190,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
public override PrimitiveBaseShape Shape {
|
||||
set {
|
||||
_pbs = value;
|
||||
_scene.TaintedObject(delegate()
|
||||
_scene.TaintedObject("BSPrim.setShape", delegate()
|
||||
{
|
||||
_mass = CalculateMass(); // changing the shape changes the mass
|
||||
RecreateGeomAndObject();
|
||||
@@ -213,7 +208,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
public override bool Selected {
|
||||
set {
|
||||
_isSelected = value;
|
||||
_scene.TaintedObject(delegate()
|
||||
_scene.TaintedObject("BSPrim.setSelected", delegate()
|
||||
{
|
||||
SetObjectDynamic();
|
||||
});
|
||||
@@ -224,10 +219,16 @@ public sealed class BSPrim : PhysicsActor
|
||||
// link me to the specified parent
|
||||
public override void link(PhysicsActor obj) {
|
||||
BSPrim parent = obj as BSPrim;
|
||||
DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, obj.LocalID);
|
||||
DetailLog("{0},link,parent={1}", LocalID, obj.LocalID);
|
||||
if (parent != null)
|
||||
{
|
||||
BSPhysObject 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;
|
||||
}
|
||||
|
||||
@@ -235,11 +236,14 @@ public sealed class BSPrim : PhysicsActor
|
||||
public override void delink() {
|
||||
// TODO: decide if this parent checking needs to happen at taint time
|
||||
// Race condition here: if link() and delink() in same simulation tick, the delink will not happen
|
||||
DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID,
|
||||
_linkset.Root._avName+"/"+_linkset.Root.LocalID.ToString());
|
||||
DetailLog("{0},delink,parent={1}", LocalID, _linkset.Root.LocalID.ToString());
|
||||
|
||||
_linkset.RemoveMeFromLinkset(this);
|
||||
BSPhysObject 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;
|
||||
}
|
||||
|
||||
@@ -247,7 +251,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
// Do it to the properties so the values get set in the physics engine.
|
||||
// Push the setting of the values to the viewer.
|
||||
// Called at taint time!
|
||||
public void ZeroMotion()
|
||||
public override void ZeroMotion()
|
||||
{
|
||||
_velocity = OMV.Vector3.Zero;
|
||||
_acceleration = OMV.Vector3.Zero;
|
||||
@@ -262,13 +266,13 @@ public sealed class BSPrim : PhysicsActor
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public override OMV.Vector3 Position {
|
||||
get {
|
||||
if (!_linkset.IsRoot(this))
|
||||
if (!Linkset.IsRoot(this))
|
||||
// child prims move around based on their parent. Need to get the latest location
|
||||
_position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID);
|
||||
|
||||
@@ -279,9 +283,9 @@ public sealed class BSPrim : PhysicsActor
|
||||
set {
|
||||
_position = value;
|
||||
// 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);
|
||||
});
|
||||
}
|
||||
@@ -293,32 +297,32 @@ public sealed class BSPrim : PhysicsActor
|
||||
{
|
||||
get
|
||||
{
|
||||
return _linkset.LinksetMass;
|
||||
return Linkset.LinksetMass;
|
||||
}
|
||||
}
|
||||
|
||||
// used when we only want this prim's mass and not the linkset thing
|
||||
public float MassRaw { get { return _mass; } }
|
||||
public override float MassRaw { get { return _mass; } }
|
||||
|
||||
// Is this used?
|
||||
public override OMV.Vector3 CenterOfMass
|
||||
{
|
||||
get { return _linkset.CenterOfMass; }
|
||||
get { return Linkset.CenterOfMass; }
|
||||
}
|
||||
|
||||
// Is this used?
|
||||
public override OMV.Vector3 GeometricCenter
|
||||
{
|
||||
get { return _linkset.GeometricCenter; }
|
||||
get { return Linkset.GeometricCenter; }
|
||||
}
|
||||
|
||||
public override OMV.Vector3 Force {
|
||||
get { return _force; }
|
||||
set {
|
||||
_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.SetObjectForce2(Body.Ptr, _force);
|
||||
});
|
||||
@@ -331,53 +335,41 @@ public sealed class BSPrim : PhysicsActor
|
||||
}
|
||||
set {
|
||||
Vehicle type = (Vehicle)value;
|
||||
_scene.TaintedObject(delegate()
|
||||
BSPrim vehiclePrim = this;
|
||||
_scene.TaintedObject("setVehicleType", delegate()
|
||||
{
|
||||
DetailLog("{0},SetVehicleType,taint,type={1}", LocalID, type);
|
||||
_vehicle.ProcessTypeChange(type);
|
||||
if (type == Vehicle.TYPE_NONE)
|
||||
{
|
||||
_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;
|
||||
// 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, Scene.LastSimulatedTimestep);
|
||||
// Tell the scene about the vehicle so it will get processing each frame.
|
||||
_scene.VehicleInSceneTypeChanged(this, type);
|
||||
});
|
||||
}
|
||||
}
|
||||
public override void VehicleFloatParam(int param, float value)
|
||||
{
|
||||
_scene.TaintedObject(delegate()
|
||||
_scene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
|
||||
{
|
||||
_vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
|
||||
});
|
||||
}
|
||||
public override void VehicleVectorParam(int param, OMV.Vector3 value)
|
||||
{
|
||||
_scene.TaintedObject(delegate()
|
||||
_scene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
|
||||
{
|
||||
_vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep);
|
||||
});
|
||||
}
|
||||
public override void VehicleRotationParam(int param, OMV.Quaternion rotation)
|
||||
{
|
||||
_scene.TaintedObject(delegate()
|
||||
_scene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
|
||||
{
|
||||
_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
|
||||
});
|
||||
}
|
||||
public override void VehicleFlags(int param, bool remove)
|
||||
{
|
||||
_scene.TaintedObject(delegate()
|
||||
_scene.TaintedObject("BSPrim.VehicleFlags", delegate()
|
||||
{
|
||||
_vehicle.ProcessVehicleFlags(param, remove);
|
||||
});
|
||||
@@ -385,7 +377,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
|
||||
// Called each simulation step to advance vehicle characteristics.
|
||||
// Called from Scene when doing simulation step so we're in taint processing time.
|
||||
public void StepVehicle(float timeStep)
|
||||
public override void StepVehicle(float timeStep)
|
||||
{
|
||||
if (IsPhysical)
|
||||
_vehicle.Step(timeStep);
|
||||
@@ -395,7 +387,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
public override void SetVolumeDetect(int param) {
|
||||
bool newValue = (param != 0);
|
||||
_isVolumeDetect = newValue;
|
||||
_scene.TaintedObject(delegate()
|
||||
_scene.TaintedObject("BSPrim.SetVolumeDetect", delegate()
|
||||
{
|
||||
SetObjectDynamic();
|
||||
});
|
||||
@@ -406,9 +398,9 @@ public sealed class BSPrim : PhysicsActor
|
||||
get { return _velocity; }
|
||||
set {
|
||||
_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);
|
||||
});
|
||||
}
|
||||
@@ -416,7 +408,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
public override OMV.Vector3 Torque {
|
||||
get { return _torque; }
|
||||
set { _torque = value;
|
||||
DetailLog("{0},SetTorque,call,torque={1}", LocalID, _torque);
|
||||
DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque);
|
||||
}
|
||||
}
|
||||
public override float CollisionScore {
|
||||
@@ -430,7 +422,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
}
|
||||
public override OMV.Quaternion Orientation {
|
||||
get {
|
||||
if (!_linkset.IsRoot(this))
|
||||
if (!Linkset.IsRoot(this))
|
||||
{
|
||||
// Children move around because tied to parent. Get a fresh value.
|
||||
_orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID);
|
||||
@@ -440,10 +432,10 @@ public sealed class BSPrim : PhysicsActor
|
||||
set {
|
||||
_orientation = value;
|
||||
// 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);
|
||||
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);
|
||||
});
|
||||
}
|
||||
@@ -457,7 +449,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
get { return _isPhysical; }
|
||||
set {
|
||||
_isPhysical = value;
|
||||
_scene.TaintedObject(delegate()
|
||||
_scene.TaintedObject("BSPrim.setIsPhysical", delegate()
|
||||
{
|
||||
SetObjectDynamic();
|
||||
});
|
||||
@@ -478,26 +470,29 @@ public sealed class BSPrim : PhysicsActor
|
||||
|
||||
// Make gravity work if the object is physical and not selected
|
||||
// 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()
|
||||
{
|
||||
// RA: remove this for the moment.
|
||||
// The problem is that dynamic objects are hulls so if we are becoming physical
|
||||
// the shape has to be checked and possibly built.
|
||||
// Maybe a VerifyCorrectPhysicalShape() routine?
|
||||
// RecreateGeomAndObject();
|
||||
// If it's becoming dynamic, it will need hullness
|
||||
VerifyCorrectPhysicalShape();
|
||||
|
||||
// Bullet wants static objects to have a mass of zero
|
||||
float mass = IsStatic ? 0f : _mass;
|
||||
|
||||
DetailLog("{0},SetObjectDynamic,taint,static={1},solid={2},mass={3}", LocalID, IsStatic, IsSolid, 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
|
||||
public override bool Flying {
|
||||
get { return _flying; }
|
||||
set { _flying = value; }
|
||||
set {
|
||||
_flying = value;
|
||||
}
|
||||
}
|
||||
public override bool SetAlwaysRun {
|
||||
get { return _setAlwaysRun; }
|
||||
@@ -546,9 +541,9 @@ public sealed class BSPrim : PhysicsActor
|
||||
set {
|
||||
_rotationalVelocity = value;
|
||||
// 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);
|
||||
});
|
||||
}
|
||||
@@ -563,9 +558,9 @@ public sealed class BSPrim : PhysicsActor
|
||||
get { return _buoyancy; }
|
||||
set {
|
||||
_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);
|
||||
});
|
||||
}
|
||||
@@ -617,7 +612,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader);
|
||||
return;
|
||||
}
|
||||
_scene.TaintedObject(delegate()
|
||||
_scene.TaintedObject("BSPrim.AddForce", delegate()
|
||||
{
|
||||
OMV.Vector3 fSum = OMV.Vector3.Zero;
|
||||
lock (m_accumulatedForces)
|
||||
@@ -628,17 +623,17 @@ public sealed class BSPrim : PhysicsActor
|
||||
}
|
||||
m_accumulatedForces.Clear();
|
||||
}
|
||||
DetailLog("{0},AddObjectForce,taint,force={1}", LocalID, _force);
|
||||
DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force);
|
||||
BulletSimAPI.AddObjectForce2(Body.Ptr, fSum);
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
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) {
|
||||
_subscribedEventsMs = ms;
|
||||
@@ -647,7 +642,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
// make sure first collision happens
|
||||
_nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs;
|
||||
|
||||
Scene.TaintedObject(delegate()
|
||||
Scene.TaintedObject("BSPrim.SubscribeEvents", delegate()
|
||||
{
|
||||
BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
});
|
||||
@@ -655,7 +650,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
}
|
||||
public override void UnSubscribeEvents() {
|
||||
_subscribedEventsMs = 0;
|
||||
Scene.TaintedObject(delegate()
|
||||
Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate()
|
||||
{
|
||||
BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS);
|
||||
});
|
||||
@@ -977,26 +972,26 @@ public sealed class BSPrim : PhysicsActor
|
||||
{
|
||||
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);
|
||||
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;
|
||||
// Bullet native objects are scaled by the Bullet engine so pass the size in
|
||||
_scale = _size;
|
||||
// TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
// }
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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))
|
||||
{
|
||||
DetailLog("{0},CreateGeom,box", LocalID);
|
||||
DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild);
|
||||
_shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX;
|
||||
_scale = _size;
|
||||
// TODO: do we need to check for and destroy a mesh or hull that might have been left from before?
|
||||
@@ -1032,19 +1027,26 @@ public sealed class BSPrim : PhysicsActor
|
||||
// No locking here because this is done when we know physics is not simulating
|
||||
private void CreateGeomMesh()
|
||||
{
|
||||
float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD;
|
||||
// level of detail based on size and type of the object
|
||||
float lod = _scene.MeshLOD;
|
||||
if (_pbs.SculptEntry)
|
||||
lod = _scene.SculptLOD;
|
||||
float maxAxis = Math.Max(_size.X, Math.Max(_size.Y, _size.Z));
|
||||
if (maxAxis > _scene.MeshMegaPrimThreshold)
|
||||
lod = _scene.MeshMegaPrimLOD;
|
||||
|
||||
ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod);
|
||||
// m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey);
|
||||
|
||||
// if this new shape is the same as last time, don't recreate the mesh
|
||||
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
|
||||
if (_meshKey != 0)
|
||||
{
|
||||
// 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);
|
||||
_mesh = null;
|
||||
_meshKey = 0;
|
||||
@@ -1074,7 +1076,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
_shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH;
|
||||
// meshes are already scaled by the meshmerizer
|
||||
_scale = new OMV.Vector3(1f, 1f, 1f);
|
||||
DetailLog("{0},CreateGeomMesh,done", LocalID);
|
||||
DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1088,28 +1090,21 @@ public sealed class BSPrim : PhysicsActor
|
||||
// if the hull hasn't changed, don't rebuild it
|
||||
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
|
||||
if (_hullKey != 0)
|
||||
{
|
||||
// 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);
|
||||
_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;
|
||||
if (_meshKey != _hullKey)
|
||||
{
|
||||
// if the underlying mesh has changed, rebuild it
|
||||
CreateGeomMesh();
|
||||
}
|
||||
|
||||
// Make sure the underlying mesh exists and is correct
|
||||
CreateGeomMesh();
|
||||
|
||||
int[] indices = _mesh.getIndexListAsInt();
|
||||
List<OMV.Vector3> vertices = _mesh.getVertexList();
|
||||
@@ -1135,7 +1130,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
// create the hull into the _hulls variable
|
||||
convexBuilder.process(dcomp);
|
||||
|
||||
// Convert the vertices and indices for passing to unmanaged
|
||||
// Convert the vertices and indices for passing to unmanaged.
|
||||
// The hull information is passed as a large floating point array.
|
||||
// The format is:
|
||||
// convHulls[0] = number of hulls
|
||||
@@ -1195,7 +1190,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
_shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL;
|
||||
// meshes are already scaled by the meshmerizer
|
||||
_scale = new OMV.Vector3(1f, 1f, 1f);
|
||||
DetailLog("{0},CreateGeomHull,done", LocalID);
|
||||
DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1207,6 +1202,27 @@ public sealed class BSPrim : PhysicsActor
|
||||
return;
|
||||
}
|
||||
|
||||
private void VerifyCorrectPhysicalShape()
|
||||
{
|
||||
if (IsStatic)
|
||||
{
|
||||
// if static, we don't need a hull so, if there is one, rebuild without it
|
||||
if (_hullKey != 0)
|
||||
{
|
||||
RecreateGeomAndObject();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if not static, it will need a hull to efficiently collide with things
|
||||
if (_hullKey == 0)
|
||||
{
|
||||
RecreateGeomAndObject();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Create an object in Bullet if it has not already been created
|
||||
// No locking here because this is done when the physics engine is not simulating
|
||||
// Returns 'true' if an object was actually created.
|
||||
@@ -1221,7 +1237,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape);
|
||||
|
||||
// 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;
|
||||
}
|
||||
@@ -1274,7 +1290,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
const float ACCELERATION_TOLERANCE = 0.01f;
|
||||
const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f;
|
||||
|
||||
public void UpdateProperties(EntityProperties entprop)
|
||||
public override void UpdateProperties(EntityProperties entprop)
|
||||
{
|
||||
/*
|
||||
UpdatedProperties changed = 0;
|
||||
@@ -1322,7 +1338,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
// Don't check for damping here -- it's done in BulletSim and SceneObjectPart.
|
||||
|
||||
// Updates only for individual prims and for the root object of a linkset.
|
||||
if (_linkset.IsRoot(this))
|
||||
if (Linkset.IsRoot(this))
|
||||
{
|
||||
// Assign to the local variables so the normal set action does not happen
|
||||
_position = entprop.Position;
|
||||
@@ -1331,9 +1347,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
_acceleration = entprop.Acceleration;
|
||||
_rotationalVelocity = entprop.RotationalVelocity;
|
||||
|
||||
// m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}",
|
||||
// LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity);
|
||||
DetailLog("{0},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);
|
||||
|
||||
base.RequestPhysicsterseUpdate();
|
||||
@@ -1342,7 +1356,7 @@ public sealed class BSPrim : PhysicsActor
|
||||
else
|
||||
{
|
||||
// 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,
|
||||
entprop.Acceleration, entprop.RotationalVelocity);
|
||||
}
|
||||
@@ -1350,8 +1364,9 @@ public sealed class BSPrim : PhysicsActor
|
||||
}
|
||||
|
||||
// I've collided with something
|
||||
CollisionEventUpdate collisionCollection = null;
|
||||
public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
|
||||
// Called at taint time from within the Step() function
|
||||
CollisionEventUpdate collisionCollection;
|
||||
public override void Collide(uint collidingWith, BSPhysObject collidee, 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);
|
||||
|
||||
@@ -1362,8 +1377,16 @@ public sealed class BSPrim : PhysicsActor
|
||||
_collidingGroundStep = _scene.SimulationStep;
|
||||
}
|
||||
|
||||
// if someone is subscribed to collision events....
|
||||
if (_subscribedEventsMs != 0) {
|
||||
// DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith);
|
||||
|
||||
// prims in the same linkset cannot collide with each other
|
||||
if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// if someone has subscribed for collision events....
|
||||
if (SubscribedEvents()) {
|
||||
// throttle the collisions to the number of milliseconds specified in the subscription
|
||||
int nowTime = _scene.SimulationNowTime;
|
||||
if (nowTime >= _nextCollisionOkTime) {
|
||||
@@ -1377,12 +1400,14 @@ public sealed class BSPrim : PhysicsActor
|
||||
}
|
||||
|
||||
// The scene is telling us it's time to pass our collected collisions into the simulator
|
||||
public void SendCollisions()
|
||||
public override void SendCollisions()
|
||||
{
|
||||
if (collisionCollection != null && collisionCollection.Count > 0)
|
||||
{
|
||||
base.SendCollisionUpdate(collisionCollection);
|
||||
collisionCollection.Clear();
|
||||
// The collisionCollection structure is passed around in the simulator.
|
||||
// Make sure we don't have a handle to that one and that a new one is used next time.
|
||||
collisionCollection = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,8 +39,6 @@ using log4net;
|
||||
using OpenMetaverse;
|
||||
|
||||
// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
|
||||
// Debug linkset
|
||||
// Test with multiple regions in one simulator
|
||||
// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight)
|
||||
// Test sculpties
|
||||
// Compute physics FPS reasonably
|
||||
@@ -54,10 +52,8 @@ using OpenMetaverse;
|
||||
// Use collision masks for collision with terrain and phantom objects
|
||||
// Check out llVolumeDetect. Must do something for that.
|
||||
// Should prim.link() and prim.delink() membership checking happen at taint time?
|
||||
// changing the position and orientation of a linked prim must rebuild the constraint with the root.
|
||||
// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once
|
||||
// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
|
||||
// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions)
|
||||
// Implement LockAngularMotion
|
||||
// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
|
||||
// Does NeedsMeshing() really need to exclude all the different shapes?
|
||||
@@ -73,62 +69,61 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly string LogHeader = "[BULLETS SCENE]";
|
||||
|
||||
public void DebugLog(string mm, params Object[] xx) { if (shouldDebugLog) m_log.DebugFormat(mm, xx); }
|
||||
// The name of the region we're working for.
|
||||
public string RegionName { get; private set; }
|
||||
|
||||
public string BulletSimVersion = "?";
|
||||
|
||||
private Dictionary<uint, BSCharacter> m_avatars = new Dictionary<uint, BSCharacter>();
|
||||
private Dictionary<uint, BSPrim> m_prims = new Dictionary<uint, BSPrim>();
|
||||
public Dictionary<uint, BSPhysObject> PhysObjects = new Dictionary<uint, BSPhysObject>();
|
||||
|
||||
private HashSet<BSPhysObject> m_objectsWithCollisions = new HashSet<BSPhysObject>();
|
||||
// Following is a kludge and can be removed when avatar animation updating is
|
||||
// moved to a better place.
|
||||
private HashSet<BSCharacter> m_avatarsWithCollisions = new HashSet<BSCharacter>();
|
||||
private HashSet<BSPrim> m_primsWithCollisions = new HashSet<BSPrim>();
|
||||
private List<BSPrim> m_vehicles = new List<BSPrim>();
|
||||
private float[] m_heightMap;
|
||||
private float m_waterLevel;
|
||||
private uint m_worldID;
|
||||
public uint WorldID { get { return m_worldID; } }
|
||||
|
||||
// List of all the objects that have vehicle properties and should be called
|
||||
// to update each physics step.
|
||||
private List<BSPhysObject> m_vehicles = new List<BSPhysObject>();
|
||||
|
||||
// let my minuions use my logger
|
||||
public ILog Logger { get { return m_log; } }
|
||||
|
||||
private bool m_initialized = false;
|
||||
|
||||
// If non-zero, the number of simulation steps between calls to the physics
|
||||
// engine to output detailed physics stats. Debug logging level must be on also.
|
||||
private int m_detailedStatsStep = 0;
|
||||
|
||||
public IMesher mesher;
|
||||
private float m_meshLOD;
|
||||
public float MeshLOD
|
||||
{
|
||||
get { return m_meshLOD; }
|
||||
}
|
||||
private float m_sculptLOD;
|
||||
public float SculptLOD
|
||||
{
|
||||
get { return m_sculptLOD; }
|
||||
}
|
||||
// Level of Detail values kept as float because that's what the Meshmerizer wants
|
||||
public float MeshLOD { get; private set; }
|
||||
public float MeshMegaPrimLOD { get; private set; }
|
||||
public float MeshMegaPrimThreshold { get; private set; }
|
||||
public float SculptLOD { get; private set; }
|
||||
|
||||
private BulletSim m_worldSim;
|
||||
public BulletSim World
|
||||
{
|
||||
get { return m_worldSim; }
|
||||
}
|
||||
private BSConstraintCollection m_constraintCollection;
|
||||
public BSConstraintCollection Constraints
|
||||
{
|
||||
get { return m_constraintCollection; }
|
||||
}
|
||||
public uint WorldID { get; private set; }
|
||||
public BulletSim World { get; private set; }
|
||||
|
||||
// All the constraints that have been allocated in this instance.
|
||||
public BSConstraintCollection Constraints { get; private set; }
|
||||
|
||||
// Simulation parameters
|
||||
private int m_maxSubSteps;
|
||||
private float m_fixedTimeStep;
|
||||
private long m_simulationStep = 0;
|
||||
public long SimulationStep { get { return m_simulationStep; } }
|
||||
|
||||
// The length of the last timestep we were asked to simulate.
|
||||
// This is used by the vehicle code. Since the vehicle code is called
|
||||
// once per simulation step, its constants need to be scaled by this.
|
||||
public float LastSimulatedTimestep { get; private set; }
|
||||
|
||||
// A value of the time now so all the collision and update routines do not have to get their own
|
||||
// Set to 'now' just before all the prims and actors are called for collisions and updates
|
||||
private int m_simulationNowTime;
|
||||
public int SimulationNowTime { get { return m_simulationNowTime; } }
|
||||
public int SimulationNowTime { get; private set; }
|
||||
|
||||
// True if initialized and ready to do simulation steps
|
||||
private bool m_initialized = false;
|
||||
|
||||
// Pinned memory used to pass step information between managed and unmanaged
|
||||
private int m_maxCollisionsPerFrame;
|
||||
private CollisionDesc[] m_collisionArray;
|
||||
private GCHandle m_collisionArrayPinnedHandle;
|
||||
@@ -145,6 +140,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
|
||||
public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero
|
||||
public const uint GROUNDPLANE_ID = 1;
|
||||
public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here
|
||||
|
||||
private float m_waterLevel;
|
||||
public BSTerrainManager TerrainManager { get; private set; }
|
||||
|
||||
public ConfigurationParameters Params
|
||||
{
|
||||
@@ -155,22 +154,34 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
get { return new Vector3(0f, 0f, Params.gravity); }
|
||||
}
|
||||
|
||||
private float m_maximumObjectMass;
|
||||
public float MaximumObjectMass
|
||||
{
|
||||
get { return m_maximumObjectMass; }
|
||||
}
|
||||
public float MaximumObjectMass { get; private set; }
|
||||
|
||||
// When functions in the unmanaged code must be called, it is only
|
||||
// done at a known time just before the simulation step. The taint
|
||||
// system saves all these function calls and executes them in
|
||||
// order before the simulation.
|
||||
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();
|
||||
|
||||
// A pointer to an instance if this structure is passed to the C++ code
|
||||
// Used to pass basic configuration values to the unmanaged code.
|
||||
ConfigurationParameters[] m_params;
|
||||
GCHandle m_paramsHandle;
|
||||
|
||||
public bool shouldDebugLog { get; private set; }
|
||||
|
||||
// Handle to the callback used by the unmanaged code to call into the managed code.
|
||||
// Used for debug logging.
|
||||
// Need to store the handle in a persistant variable so it won't be freed.
|
||||
private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle;
|
||||
|
||||
// Sometimes you just have to log everything.
|
||||
@@ -179,13 +190,15 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
private string m_physicsLoggingDir;
|
||||
private string m_physicsLoggingPrefix;
|
||||
private int m_physicsLoggingFileMinutes;
|
||||
// 'true' of the vehicle code is to log lots of details
|
||||
public bool VehicleLoggingEnabled { get; private set; }
|
||||
|
||||
private bool m_vehicleLoggingEnabled;
|
||||
public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } }
|
||||
|
||||
#region Construction and Initialization
|
||||
public BSScene(string identifier)
|
||||
{
|
||||
m_initialized = false;
|
||||
// we are passed the name of the region we're working for.
|
||||
RegionName = identifier;
|
||||
}
|
||||
|
||||
public override void Initialise(IMesher meshmerizer, IConfigSource config)
|
||||
@@ -203,6 +216,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
m_updateArray = new EntityProperties[m_maxUpdatesPerFrame];
|
||||
m_updateArrayPinnedHandle = GCHandle.Alloc(m_updateArray, GCHandleType.Pinned);
|
||||
|
||||
mesher = meshmerizer;
|
||||
_taintedObjects = new List<TaintCallbackEntry>();
|
||||
|
||||
// Enable very detailed logging.
|
||||
// By creating an empty logger when not logging, the log message invocation code
|
||||
// can be left in and every call doesn't have to check for null.
|
||||
@@ -215,38 +231,43 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
PhysicsLogging = new Logging.LogWriter();
|
||||
}
|
||||
|
||||
// If Debug logging level, enable logging from the unmanaged code
|
||||
m_DebugLogCallbackHandle = null;
|
||||
if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
|
||||
{
|
||||
m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
|
||||
if (PhysicsLogging.Enabled)
|
||||
// The handle is saved in a variable to make sure it doesn't get freed after this call
|
||||
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
|
||||
else
|
||||
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
|
||||
}
|
||||
|
||||
// Get the version of the DLL
|
||||
// TODO: this doesn't work yet. Something wrong with marshaling the returned string.
|
||||
// BulletSimVersion = BulletSimAPI.GetVersion();
|
||||
// m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion);
|
||||
|
||||
// if Debug, enable logging from the unmanaged code
|
||||
if (m_log.IsDebugEnabled || PhysicsLogging.Enabled)
|
||||
{
|
||||
m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader);
|
||||
if (PhysicsLogging.Enabled)
|
||||
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog);
|
||||
else
|
||||
m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger);
|
||||
// the handle is saved in a variable to make sure it doesn't get freed after this call
|
||||
BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle);
|
||||
}
|
||||
|
||||
_taintedObjects = new List<TaintCallback>();
|
||||
|
||||
mesher = meshmerizer;
|
||||
// The bounding box for the simulated world
|
||||
// The bounding box for the simulated world. The origin is 0,0,0 unless we're
|
||||
// a child in a mega-region.
|
||||
// Turns out that Bullet really doesn't care about the extents of the simulated
|
||||
// area. It tracks active objects no matter where they are.
|
||||
Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f);
|
||||
|
||||
// m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader);
|
||||
m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
|
||||
WorldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(),
|
||||
m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(),
|
||||
m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject());
|
||||
m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(),
|
||||
m_DebugLogCallbackHandle);
|
||||
|
||||
// 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.
|
||||
m_worldSim = new BulletSim(m_worldID, BulletSimAPI.GetSimHandle2(m_worldID));
|
||||
m_constraintCollection = new BSConstraintCollection(World);
|
||||
World = new BulletSim(WorldID, this, BulletSimAPI.GetSimHandle2(WorldID));
|
||||
|
||||
Constraints = new BSConstraintCollection(World);
|
||||
|
||||
TerrainManager = new BSTerrainManager(this);
|
||||
TerrainManager.CreateInitialGroundPlaneAndTerrain();
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
@@ -271,10 +292,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// Very detailed logging for physics debugging
|
||||
m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false);
|
||||
m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", ".");
|
||||
m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-");
|
||||
m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-");
|
||||
m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5);
|
||||
// Very detailed logging for vehicle debugging
|
||||
m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
|
||||
VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false);
|
||||
|
||||
// Do any replacements in the parameters
|
||||
m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -306,6 +330,38 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
// m_log.DebugFormat("{0}: Dispose()", LogHeader);
|
||||
|
||||
// make sure no stepping happens while we're deleting stuff
|
||||
m_initialized = false;
|
||||
|
||||
TerrainManager.ReleaseGroundPlaneAndTerrain();
|
||||
|
||||
foreach (KeyValuePair<uint, BSPhysObject> kvp in PhysObjects)
|
||||
{
|
||||
kvp.Value.Destroy();
|
||||
}
|
||||
PhysObjects.Clear();
|
||||
|
||||
// Now that the prims are all cleaned up, there should be no constraints left
|
||||
if (Constraints != null)
|
||||
{
|
||||
Constraints.Dispose();
|
||||
Constraints = null;
|
||||
}
|
||||
|
||||
// Anything left in the unmanaged code should be cleaned out
|
||||
BulletSimAPI.Shutdown(WorldID);
|
||||
|
||||
// Not logging any more
|
||||
PhysicsLogging.Close();
|
||||
}
|
||||
#endregion // Construction and Initialization
|
||||
|
||||
#region Prim and Avatar addition and removal
|
||||
|
||||
public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying)
|
||||
{
|
||||
m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader);
|
||||
@@ -319,7 +375,13 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
if (!m_initialized) return null;
|
||||
|
||||
BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying);
|
||||
lock (m_avatars) m_avatars.Add(localID, actor);
|
||||
lock (PhysObjects) PhysObjects.Add(localID, actor);
|
||||
|
||||
// TODO: Remove kludge someday.
|
||||
// We must generate a collision for avatars whether they collide or not.
|
||||
// This is required by OpenSim to update avatar animations, etc.
|
||||
lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Add(actor);
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
||||
@@ -334,7 +396,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (m_avatars) m_avatars.Remove(actor.LocalID);
|
||||
lock (PhysObjects) PhysObjects.Remove(actor.LocalID);
|
||||
// Remove kludge someday
|
||||
lock (m_avatarsWithCollisions) m_avatarsWithCollisions.Remove(bsactor);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -352,10 +416,11 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
BSPrim bsprim = prim as BSPrim;
|
||||
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
|
||||
{
|
||||
lock (m_prims) m_prims.Remove(bsprim.LocalID);
|
||||
lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -377,8 +442,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
|
||||
if (!m_initialized) return null;
|
||||
|
||||
DetailLog("{0},AddPrimShape,call", localID);
|
||||
|
||||
BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
|
||||
lock (m_prims) m_prims.Add(localID, prim);
|
||||
lock (PhysObjects) PhysObjects.Add(localID, prim);
|
||||
return prim;
|
||||
}
|
||||
|
||||
@@ -387,6 +454,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// information call is not needed.
|
||||
public override void AddPhysicsActorTaint(PhysicsActor prim) { }
|
||||
|
||||
#endregion // Prim and Avatar addition and removal
|
||||
|
||||
#region Simulation
|
||||
// Simulate one timestep
|
||||
public override float Simulate(float timeStep)
|
||||
{
|
||||
@@ -400,9 +470,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// prevent simulation until we've been initialized
|
||||
if (!m_initialized) return 10.0f;
|
||||
|
||||
long simulateStartTime = Util.EnvironmentTickCount();
|
||||
int simulateStartTime = Util.EnvironmentTickCount();
|
||||
|
||||
// update the prim states while we know the physics engine is not busy
|
||||
int numTaints = _taintedObjects.Count;
|
||||
ProcessTaints();
|
||||
|
||||
// Some of the prims operate with special vehicle properties
|
||||
@@ -414,15 +485,18 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
int numSubSteps = 0;
|
||||
try
|
||||
{
|
||||
numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
|
||||
numSubSteps = BulletSimAPI.PhysicsStep(WorldID, timeStep, m_maxSubSteps, m_fixedTimeStep,
|
||||
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, nTaints= {1}, substeps={2}, updates={3}, colliders={4}",
|
||||
DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e);
|
||||
DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", "0000000000", numSubSteps, updatedEntityCount, collidersCount);
|
||||
// updatedEntityCount = 0;
|
||||
m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}",
|
||||
LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e);
|
||||
DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}",
|
||||
DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount);
|
||||
updatedEntityCount = 0;
|
||||
collidersCount = 0;
|
||||
}
|
||||
|
||||
@@ -430,7 +504,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// Don't have to use the pointers passed back since we know it is the same pinned memory we passed in
|
||||
|
||||
// Get a value for 'now' so all the collision and update routines don't have to get their own
|
||||
m_simulationNowTime = Util.EnvironmentTickCount();
|
||||
SimulationNowTime = Util.EnvironmentTickCount();
|
||||
|
||||
// If there were collisions, process them by sending the event to the prim.
|
||||
// Collisions must be processed before updates.
|
||||
@@ -449,19 +523,16 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
|
||||
// The above SendCollision's batch up the collisions on the objects.
|
||||
// Now push the collisions into the simulator.
|
||||
foreach (BSPrim bsp in m_primsWithCollisions)
|
||||
foreach (BSPhysObject bsp in m_objectsWithCollisions)
|
||||
bsp.SendCollisions();
|
||||
m_primsWithCollisions.Clear();
|
||||
m_objectsWithCollisions.Clear();
|
||||
|
||||
// This is a kludge to get avatar movement updated.
|
||||
// Don't send collisions only if there were collisions -- send everytime.
|
||||
// ODE sends collisions even if there are none and this is used to update
|
||||
// avatar animations and stuff.
|
||||
// foreach (BSCharacter bsc in m_avatarsWithCollisions)
|
||||
// bsc.SendCollisions();
|
||||
foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
|
||||
kvp.Value.SendCollisions();
|
||||
m_avatarsWithCollisions.Clear();
|
||||
foreach (BSPhysObject bpo in m_avatarsWithCollisions)
|
||||
bpo.SendCollisions();
|
||||
// m_avatarsWithCollisions.Clear();
|
||||
|
||||
// If any of the objects had updated properties, tell the object it has been changed by the physics engine
|
||||
if (updatedEntityCount > 0)
|
||||
@@ -469,16 +540,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
for (int ii = 0; ii < updatedEntityCount; ii++)
|
||||
{
|
||||
EntityProperties entprop = m_updateArray[ii];
|
||||
BSPrim prim;
|
||||
if (m_prims.TryGetValue(entprop.ID, out prim))
|
||||
BSPhysObject pobj;
|
||||
if (PhysObjects.TryGetValue(entprop.ID, out pobj))
|
||||
{
|
||||
prim.UpdateProperties(entprop);
|
||||
continue;
|
||||
}
|
||||
BSCharacter actor;
|
||||
if (m_avatars.TryGetValue(entprop.ID, out actor))
|
||||
{
|
||||
actor.UpdateProperties(entprop);
|
||||
pobj.UpdateProperties(entprop);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -498,61 +563,57 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
|
||||
// return (timeStep * (float)simulateTotalTime);
|
||||
|
||||
// TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation.
|
||||
return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f;
|
||||
// TODO: FIX THIS: fps calculation possibly wrong.
|
||||
// This calculation says 1/timeStep is the ideal frame rate. Any time added to
|
||||
// that by the physics simulation gives a slower frame rate.
|
||||
long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime);
|
||||
if (totalSimulationTime >= timeStep)
|
||||
return 0;
|
||||
return 1f / (timeStep + totalSimulationTime);
|
||||
}
|
||||
|
||||
// Something has collided
|
||||
private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penitration)
|
||||
private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration)
|
||||
{
|
||||
if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID)
|
||||
if (localID <= TerrainManager.HighestTerrainID)
|
||||
{
|
||||
return; // don't send collisions to the terrain
|
||||
}
|
||||
|
||||
ActorTypes type = ActorTypes.Prim;
|
||||
if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID)
|
||||
type = ActorTypes.Ground;
|
||||
else if (m_avatars.ContainsKey(collidingWith))
|
||||
type = ActorTypes.Agent;
|
||||
BSPhysObject collider = PhysObjects[localID];
|
||||
// TODO: as of this code, terrain was not in the physical object list.
|
||||
// When BSTerrain is created and it will be in the list, we can remove
|
||||
// the possibility that it's not there and just fetch the collidee.
|
||||
BSPhysObject collidee = null;
|
||||
|
||||
BSPrim prim;
|
||||
if (m_prims.TryGetValue(localID, out prim)) {
|
||||
prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
|
||||
m_primsWithCollisions.Add(prim);
|
||||
return;
|
||||
ActorTypes type = ActorTypes.Prim;
|
||||
if (collidingWith <= TerrainManager.HighestTerrainID)
|
||||
{
|
||||
type = ActorTypes.Ground;
|
||||
}
|
||||
BSCharacter actor;
|
||||
if (m_avatars.TryGetValue(localID, out actor)) {
|
||||
actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration);
|
||||
m_avatarsWithCollisions.Add(actor);
|
||||
return;
|
||||
else
|
||||
{
|
||||
collidee = PhysObjects[collidingWith];
|
||||
if (collidee is BSCharacter)
|
||||
type = ActorTypes.Agent;
|
||||
}
|
||||
|
||||
// DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith);
|
||||
|
||||
collider.Collide(collidingWith, collidee, type, collidePoint, collideNormal, penetration);
|
||||
m_objectsWithCollisions.Add(collider);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
#endregion // Simulation
|
||||
|
||||
public override void GetResults() { }
|
||||
|
||||
#region Terrain
|
||||
|
||||
public override void SetTerrain(float[] heightMap) {
|
||||
m_heightMap = heightMap;
|
||||
this.TaintedObject(delegate()
|
||||
{
|
||||
BulletSimAPI.SetHeightmap(m_worldID, m_heightMap);
|
||||
});
|
||||
}
|
||||
|
||||
// Someday we will have complex terrain with caves and tunnels
|
||||
// For the moment, it's flat and convex
|
||||
public float GetTerrainHeightAtXYZ(Vector3 loc)
|
||||
{
|
||||
return GetTerrainHeightAtXY(loc.X, loc.Y);
|
||||
}
|
||||
|
||||
public float GetTerrainHeightAtXY(float tX, float tY)
|
||||
{
|
||||
if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize)
|
||||
return 30;
|
||||
return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)];
|
||||
TerrainManager.SetTerrain(heightMap);
|
||||
}
|
||||
|
||||
public override void SetWaterLevel(float baseheight)
|
||||
@@ -570,37 +631,26 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
// Although no one seems to check this, I do support combining.
|
||||
public override bool SupportsCombining()
|
||||
{
|
||||
// m_log.DebugFormat("{0}: Dispose()", LogHeader);
|
||||
|
||||
// make sure no stepping happens while we're deleting stuff
|
||||
m_initialized = false;
|
||||
|
||||
if (m_constraintCollection != null)
|
||||
{
|
||||
m_constraintCollection.Dispose();
|
||||
m_constraintCollection = null;
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<uint, BSCharacter> kvp in m_avatars)
|
||||
{
|
||||
kvp.Value.Destroy();
|
||||
}
|
||||
m_avatars.Clear();
|
||||
|
||||
foreach (KeyValuePair<uint, BSPrim> kvp in m_prims)
|
||||
{
|
||||
kvp.Value.Destroy();
|
||||
}
|
||||
m_prims.Clear();
|
||||
|
||||
// Anything left in the unmanaged code should be cleaned out
|
||||
BulletSimAPI.Shutdown(WorldID);
|
||||
|
||||
// Not logging any more
|
||||
PhysicsLogging.Close();
|
||||
return TerrainManager.SupportsCombining();
|
||||
}
|
||||
// This call says I am a child to region zero in a mega-region. 'pScene' is that
|
||||
// of region zero, 'offset' is my offset from regions zero's origin, and
|
||||
// 'extents' is the largest XY that is handled in my region.
|
||||
public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
|
||||
{
|
||||
TerrainManager.Combine(pScene, offset, extents);
|
||||
}
|
||||
|
||||
// Unhook all the combining that I know about.
|
||||
public override void UnCombine(PhysicsScene pScene)
|
||||
{
|
||||
TerrainManager.UnCombine(pScene);
|
||||
}
|
||||
|
||||
#endregion // Terrain
|
||||
|
||||
public override Dictionary<uint, float> GetTopColliders()
|
||||
{
|
||||
@@ -727,12 +777,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// Calls to the PhysicsActors can't directly call into the physics engine
|
||||
// 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.
|
||||
public void TaintedObject(TaintCallback callback)
|
||||
public void TaintedObject(String ident, TaintCallback callback)
|
||||
{
|
||||
if (!m_initialized) return;
|
||||
|
||||
lock (_taintLock)
|
||||
_taintedObjects.Add(callback);
|
||||
_taintedObjects.Add(new TaintCallbackEntry(ident, callback));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -744,22 +794,22 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
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
|
||||
List<TaintCallback> oldList;
|
||||
List<TaintCallbackEntry> oldList;
|
||||
lock (_taintLock)
|
||||
{
|
||||
oldList = _taintedObjects;
|
||||
_taintedObjects = new List<TaintCallback>();
|
||||
_taintedObjects = new List<TaintCallbackEntry>();
|
||||
}
|
||||
|
||||
foreach (TaintCallback callback in oldList)
|
||||
foreach (TaintCallbackEntry tcbe in oldList)
|
||||
{
|
||||
try
|
||||
{
|
||||
callback();
|
||||
tcbe.callback();
|
||||
}
|
||||
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();
|
||||
@@ -767,6 +817,20 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
}
|
||||
|
||||
#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.
|
||||
// Safe to call if prim is already in the vehicle list.
|
||||
public void AddVehiclePrim(BSPrim vehicle)
|
||||
@@ -797,14 +861,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// no locking because only called when physics engine is not busy
|
||||
private void ProcessVehicles(float timeStep)
|
||||
{
|
||||
foreach (BSPrim prim in m_vehicles)
|
||||
foreach (BSPhysObject pobj in m_vehicles)
|
||||
{
|
||||
prim.StepVehicle(timeStep);
|
||||
pobj.StepVehicle(timeStep);
|
||||
}
|
||||
}
|
||||
#endregion Vehicles
|
||||
|
||||
#region Parameters
|
||||
#region INI and command line parameter processing
|
||||
|
||||
delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val);
|
||||
delegate float ParamGet(BSScene scene);
|
||||
@@ -812,12 +876,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
|
||||
private struct ParameterDefn
|
||||
{
|
||||
public string name;
|
||||
public string desc;
|
||||
public float defaultValue;
|
||||
public ParamUser userParam;
|
||||
public ParamGet getter;
|
||||
public ParamSet setter;
|
||||
public string name; // string name of the parameter
|
||||
public string desc; // a short description of what the parameter means
|
||||
public float defaultValue; // default value if not specified anywhere else
|
||||
public ParamUser userParam; // get the value from the configuration file
|
||||
public ParamGet getter; // return the current value stored for this parameter
|
||||
public ParamSet setter; // set the current value for this parameter
|
||||
public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s)
|
||||
{
|
||||
name = n;
|
||||
@@ -834,7 +898,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
// 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
|
||||
// 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.
|
||||
//
|
||||
// A ParameterDefn() takes the following parameters:
|
||||
@@ -864,16 +928,26 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
(s) => { return s.NumericBool(s._forceSimplePrimMeshing); },
|
||||
(s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ),
|
||||
|
||||
new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
|
||||
new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)",
|
||||
8f,
|
||||
(s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); },
|
||||
(s) => { return (float)s.m_meshLOD; },
|
||||
(s,p,l,v) => { s.m_meshLOD = (int)v; } ),
|
||||
new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
|
||||
32,
|
||||
(s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); },
|
||||
(s) => { return (float)s.m_sculptLOD; },
|
||||
(s,p,l,v) => { s.m_sculptLOD = (int)v; } ),
|
||||
(s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); },
|
||||
(s) => { return s.MeshLOD; },
|
||||
(s,p,l,v) => { s.MeshLOD = v; } ),
|
||||
new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters",
|
||||
16f,
|
||||
(s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); },
|
||||
(s) => { return s.MeshMegaPrimLOD; },
|
||||
(s,p,l,v) => { s.MeshMegaPrimLOD = v; } ),
|
||||
new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD",
|
||||
10f,
|
||||
(s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); },
|
||||
(s) => { return s.MeshMegaPrimThreshold; },
|
||||
(s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ),
|
||||
new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)",
|
||||
32f,
|
||||
(s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); },
|
||||
(s) => { return s.SculptLOD; },
|
||||
(s,p,l,v) => { s.SculptLOD = v; } ),
|
||||
|
||||
new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps",
|
||||
10f,
|
||||
@@ -897,9 +971,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
(s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ),
|
||||
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
|
||||
10000.01f,
|
||||
(s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); },
|
||||
(s) => { return (float)s.m_maximumObjectMass; },
|
||||
(s,p,l,v) => { s.m_maximumObjectMass = v; } ),
|
||||
(s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); },
|
||||
(s) => { return (float)s.MaximumObjectMass; },
|
||||
(s,p,l,v) => { s.MaximumObjectMass = v; } ),
|
||||
|
||||
new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
|
||||
2200f,
|
||||
@@ -943,42 +1017,42 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
0f,
|
||||
(s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].linearDamping; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); } ),
|
||||
new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)",
|
||||
0f,
|
||||
(s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].angularDamping; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); } ),
|
||||
new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static",
|
||||
0.2f,
|
||||
(s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].deactivationTime; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); } ),
|
||||
new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static",
|
||||
0.8f,
|
||||
(s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].linearSleepingThreshold; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ),
|
||||
new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static",
|
||||
1.0f,
|
||||
(s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].angularSleepingThreshold; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ),
|
||||
new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" ,
|
||||
0f, // set to zero to disable
|
||||
(s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].ccdMotionThreshold; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ),
|
||||
new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" ,
|
||||
0f,
|
||||
(s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].ccdSweptSphereRadius; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ),
|
||||
new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" ,
|
||||
0.1f,
|
||||
(s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].contactProcessingThreshold; },
|
||||
(s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ),
|
||||
|
||||
new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" ,
|
||||
0.5f,
|
||||
@@ -996,45 +1070,50 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
(s) => { return s.m_params[0].terrainRestitution; },
|
||||
(s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ),
|
||||
new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.",
|
||||
0.5f,
|
||||
0.2f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarFriction; },
|
||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ),
|
||||
new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.",
|
||||
60f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarDensity; },
|
||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ),
|
||||
new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.",
|
||||
0f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarRestitution; },
|
||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ),
|
||||
new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar",
|
||||
0.37f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarCapsuleRadius; },
|
||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ),
|
||||
new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar",
|
||||
1.5f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarCapsuleHeight; },
|
||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ),
|
||||
new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions",
|
||||
0.1f,
|
||||
(s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].avatarContactProcessingThreshold; },
|
||||
(s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ),
|
||||
(s,p,l,v) => { s.UpdateParameterObject(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
|
||||
(s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); },
|
||||
(s) => { return s.m_params[0].maxPersistantManifoldPoolSize; },
|
||||
(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",
|
||||
ConfigurationParameters.numericTrue,
|
||||
(s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
|
||||
ConfigurationParameters.numericFalse,
|
||||
(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,p,l,v) => { s.m_params[0].shouldDisableContactPoolDynamicAllocation = v; } ),
|
||||
new ParameterDefn("ShouldForceUpdateAllAabbs", "Enable to recomputer AABBs every simulator step",
|
||||
@@ -1099,12 +1178,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
(s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); },
|
||||
(s) => { return (float)s.m_detailedStatsStep; },
|
||||
(s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ),
|
||||
new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements",
|
||||
ConfigurationParameters.numericFalse,
|
||||
(s,cf,p,v) => { s.shouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); },
|
||||
(s) => { return s.NumericBool(s.shouldDebugLog); },
|
||||
(s,p,l,v) => { s.shouldDebugLog = s.BoolNumeric(v); } ),
|
||||
|
||||
};
|
||||
|
||||
// Convert a boolean to our numeric true and false values
|
||||
@@ -1162,6 +1235,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
|
||||
private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1];
|
||||
|
||||
// This creates an array in the correct format for returning the list of
|
||||
// parameters. This is used by the 'list' option of the 'physics' command.
|
||||
private void BuildParameterTable()
|
||||
{
|
||||
if (SettableParameters.Length < ParameterDefinitions.Length)
|
||||
@@ -1212,18 +1287,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
}
|
||||
|
||||
// check to see if we are updating a parameter for a particular or all of the prims
|
||||
protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val)
|
||||
protected void UpdateParameterObject(ref float loc, string parm, uint localID, float val)
|
||||
{
|
||||
List<uint> operateOn;
|
||||
lock (m_prims) operateOn = new List<uint>(m_prims.Keys);
|
||||
UpdateParameterSet(operateOn, ref loc, parm, localID, val);
|
||||
}
|
||||
|
||||
// check to see if we are updating a parameter for a particular or all of the avatars
|
||||
protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val)
|
||||
{
|
||||
List<uint> operateOn;
|
||||
lock (m_avatars) operateOn = new List<uint>(m_avatars.Keys);
|
||||
lock (PhysObjects) operateOn = new List<uint>(PhysObjects.Keys);
|
||||
UpdateParameterSet(operateOn, ref loc, parm, localID, val);
|
||||
}
|
||||
|
||||
@@ -1243,10 +1310,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
List<uint> objectIDs = lIDs;
|
||||
string xparm = parm.ToLower();
|
||||
float xval = val;
|
||||
TaintedObject(delegate() {
|
||||
TaintedObject("BSScene.UpdateParameterSet", delegate() {
|
||||
foreach (uint lID in objectIDs)
|
||||
{
|
||||
BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval);
|
||||
BulletSimAPI.UpdateParameter(WorldID, lID, xparm, xval);
|
||||
}
|
||||
});
|
||||
break;
|
||||
@@ -1263,8 +1330,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
uint xlocalID = localID;
|
||||
string xparm = parm.ToLower();
|
||||
float xval = val;
|
||||
TaintedObject(delegate() {
|
||||
BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval);
|
||||
TaintedObject("BSScene.TaintedUpdateParameter", delegate() {
|
||||
BulletSimAPI.UpdateParameter(WorldID, xlocalID, xparm, xval);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1289,10 +1356,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
|
||||
#endregion Runtime settable parameters
|
||||
|
||||
// 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);
|
||||
}
|
||||
// used to fill in the LocalID when there isn't one
|
||||
public const string DetailLogZero = "0000000000";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
464
OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
Executable file
464
OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
Executable file
@@ -0,0 +1,464 @@
|
||||
/*
|
||||
* 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 OpenSim.Framework;
|
||||
using OpenSim.Region.Framework;
|
||||
using OpenSim.Region.CoreModules;
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
||||
using Nini.Config;
|
||||
using log4net;
|
||||
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
public class BSTerrainManager
|
||||
{
|
||||
static string LogHeader = "[BULLETSIM TERRAIN MANAGER]";
|
||||
|
||||
// These height values are fractional so the odd values will be
|
||||
// noticable when debugging.
|
||||
public const float HEIGHT_INITIALIZATION = 24.987f;
|
||||
public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f;
|
||||
public const float HEIGHT_GETHEIGHT_RET = 24.765f;
|
||||
|
||||
// If the min and max height are equal, we reduce the min by this
|
||||
// amount to make sure that a bounding box is built for the terrain.
|
||||
public const float HEIGHT_EQUAL_FUDGE = 0.2f;
|
||||
|
||||
public const float TERRAIN_COLLISION_MARGIN = 0.0f;
|
||||
|
||||
// Until the whole simulator is changed to pass us the region size, we rely on constants.
|
||||
public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, 0f);
|
||||
|
||||
// The scene that I am part of
|
||||
private BSScene m_physicsScene;
|
||||
|
||||
// The ground plane created to keep thing from falling to infinity.
|
||||
private BulletBody m_groundPlane;
|
||||
|
||||
// If doing mega-regions, if we're region zero we will be managing multiple
|
||||
// region terrains since region zero does the physics for the whole mega-region.
|
||||
private Dictionary<Vector2, BulletHeightMapInfo> m_heightMaps;
|
||||
|
||||
// True of the terrain has been modified.
|
||||
// Used to force recalculation of terrain height after terrain has been modified
|
||||
private bool m_terrainModified;
|
||||
|
||||
// If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount.
|
||||
// This is incremented before assigning to new region so it is the last ID allocated.
|
||||
private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1;
|
||||
public uint HighestTerrainID { get {return m_terrainCount; } }
|
||||
|
||||
// If doing mega-regions, this holds our offset from region zero of
|
||||
// the mega-regions. "parentScene" points to the PhysicsScene of region zero.
|
||||
private Vector3 m_worldOffset;
|
||||
// If the parent region (region 0), this is the extent of the combined regions
|
||||
// relative to the origin of region zero
|
||||
private Vector3 m_worldMax;
|
||||
private PhysicsScene m_parentScene;
|
||||
|
||||
public BSTerrainManager(BSScene physicsScene)
|
||||
{
|
||||
m_physicsScene = physicsScene;
|
||||
m_heightMaps = new Dictionary<Vector2,BulletHeightMapInfo>();
|
||||
m_terrainModified = false;
|
||||
|
||||
// Assume one region of default size
|
||||
m_worldOffset = Vector3.Zero;
|
||||
m_worldMax = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, 4096f);
|
||||
m_parentScene = null;
|
||||
}
|
||||
|
||||
// Create the initial instance of terrain and the underlying ground plane.
|
||||
// The objects are allocated in the unmanaged space and the pointers are tracked
|
||||
// by the managed code.
|
||||
// The terrains and the groundPlane are not added to the list of PhysObjects.
|
||||
// This is called from the initialization routine so we presume it is
|
||||
// safe to call Bullet in real time. We hope no one is moving prims around yet.
|
||||
public void CreateInitialGroundPlaneAndTerrain()
|
||||
{
|
||||
// The ground plane is here to catch things that are trying to drop to negative infinity
|
||||
BulletShape groundPlaneShape = new BulletShape(BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN));
|
||||
m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
|
||||
BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.Ptr, Vector3.Zero, Quaternion.Identity));
|
||||
BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
|
||||
|
||||
Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE);
|
||||
Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION);
|
||||
int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y;
|
||||
float[] initialMap = new float[totalHeights];
|
||||
for (int ii = 0; ii < totalHeights; ii++)
|
||||
{
|
||||
initialMap[ii] = HEIGHT_INITIALIZATION;
|
||||
}
|
||||
UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true);
|
||||
}
|
||||
|
||||
// Release all the terrain structures we might have allocated
|
||||
public void ReleaseGroundPlaneAndTerrain()
|
||||
{
|
||||
if (m_groundPlane.Ptr != IntPtr.Zero)
|
||||
{
|
||||
if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, m_groundPlane.Ptr))
|
||||
{
|
||||
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, m_groundPlane.Ptr);
|
||||
}
|
||||
m_groundPlane.Ptr = IntPtr.Zero;
|
||||
}
|
||||
|
||||
ReleaseTerrain();
|
||||
}
|
||||
|
||||
// Release all the terrain we have allocated
|
||||
public void ReleaseTerrain()
|
||||
{
|
||||
foreach (KeyValuePair<Vector2, BulletHeightMapInfo> kvp in m_heightMaps)
|
||||
{
|
||||
if (BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr))
|
||||
{
|
||||
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, kvp.Value.terrainBody.Ptr);
|
||||
BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr);
|
||||
}
|
||||
}
|
||||
m_heightMaps.Clear();
|
||||
}
|
||||
|
||||
// The simulator wants to set a new heightmap for the terrain.
|
||||
public void SetTerrain(float[] heightMap) {
|
||||
if (m_worldOffset != Vector3.Zero && m_parentScene != null)
|
||||
{
|
||||
// If a child of a mega-region, we shouldn't have any terrain allocated for us
|
||||
ReleaseGroundPlaneAndTerrain();
|
||||
// If doing the mega-prim stuff and we are the child of the zero region,
|
||||
// the terrain is added to our parent
|
||||
if (m_parentScene is BSScene)
|
||||
{
|
||||
DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}",
|
||||
BSScene.DetailLogZero, m_worldOffset, m_worldMax);
|
||||
((BSScene)m_parentScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID,
|
||||
heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If not doing the mega-prim thing, just change the terrain
|
||||
DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero);
|
||||
|
||||
UpdateOrCreateTerrain(BSScene.TERRAIN_ID, heightMap, m_worldOffset, m_worldOffset+DefaultRegionSize, false);
|
||||
}
|
||||
}
|
||||
|
||||
// If called with no mapInfo for the terrain, this will create a new mapInfo and terrain
|
||||
// based on the passed information. The 'id' should be either the terrain id or
|
||||
// BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used.
|
||||
// The latter feature is for creating child terrains for mega-regions.
|
||||
// If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0)
|
||||
// then a new body and shape is created and the mapInfo is filled.
|
||||
// This call is used for doing the initial terrain creation.
|
||||
// If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new
|
||||
// terrain shape is created and added to the body.
|
||||
// This call is most often used to update the heightMap and parameters of the terrain.
|
||||
// The 'doNow' boolean says whether to do all the unmanaged activities right now (like when
|
||||
// calling this routine from initialization or taint-time routines) or whether to delay
|
||||
// all the unmanaged activities to taint-time.
|
||||
private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool doNow)
|
||||
{
|
||||
DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},doNow={3}",
|
||||
BSScene.DetailLogZero, minCoords, maxCoords, doNow);
|
||||
|
||||
float minZ = float.MaxValue;
|
||||
float maxZ = float.MinValue;
|
||||
Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y);
|
||||
|
||||
int heightMapSize = heightMap.Length;
|
||||
for (int ii = 0; ii < heightMapSize; ii++)
|
||||
{
|
||||
float height = heightMap[ii];
|
||||
if (height < minZ) minZ = height;
|
||||
if (height > maxZ) maxZ = height;
|
||||
}
|
||||
|
||||
// The shape of the terrain is from its base to its extents.
|
||||
minCoords.Z = minZ;
|
||||
maxCoords.Z = maxZ;
|
||||
|
||||
BulletHeightMapInfo mapInfo;
|
||||
if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo))
|
||||
{
|
||||
// If this is terrain we know about, it's easy to update
|
||||
|
||||
mapInfo.heightMap = heightMap;
|
||||
mapInfo.minCoords = minCoords;
|
||||
mapInfo.maxCoords = maxCoords;
|
||||
mapInfo.minZ = minZ;
|
||||
mapInfo.maxZ = maxZ;
|
||||
mapInfo.sizeX = maxCoords.X - minCoords.X;
|
||||
mapInfo.sizeY = maxCoords.Y - minCoords.Y;
|
||||
DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
|
||||
BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
|
||||
|
||||
BSScene.TaintCallback rebuildOperation = delegate()
|
||||
{
|
||||
if (m_parentScene != null)
|
||||
{
|
||||
// It's possible that Combine() was called after this code was queued.
|
||||
// If we are a child of combined regions, we don't create any terrain for us.
|
||||
DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero);
|
||||
|
||||
// Get rid of any terrain that may have been allocated for us.
|
||||
ReleaseGroundPlaneAndTerrain();
|
||||
|
||||
// I hate doing this, but just bail
|
||||
return;
|
||||
}
|
||||
|
||||
if (mapInfo.terrainBody.Ptr != IntPtr.Zero)
|
||||
{
|
||||
// Updating an existing terrain.
|
||||
DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}",
|
||||
BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY);
|
||||
|
||||
// Remove from the dynamics world because we're going to mangle this object
|
||||
BulletSimAPI.RemoveObjectFromWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||
|
||||
// Get rid of the old terrain
|
||||
BulletSimAPI.DestroyObject2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||
BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr);
|
||||
mapInfo.Ptr = IntPtr.Zero;
|
||||
|
||||
/*
|
||||
// NOTE: This routine is half here because I can't get the terrain shape replacement
|
||||
// to work. In the short term, the above three lines completely delete the old
|
||||
// terrain and the code below recreates one from scratch.
|
||||
// Hopefully the Bullet community will help me out on this one.
|
||||
|
||||
// First, release the old collision shape (there is only one terrain)
|
||||
BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr);
|
||||
|
||||
// Fill the existing height map info with the new location and size information
|
||||
BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID,
|
||||
mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
|
||||
|
||||
// Create a terrain shape based on the new info
|
||||
mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
|
||||
|
||||
// Stuff the shape into the existing terrain body
|
||||
BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr);
|
||||
*/
|
||||
}
|
||||
// else
|
||||
{
|
||||
// Creating a new terrain.
|
||||
DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}",
|
||||
BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ);
|
||||
|
||||
mapInfo.ID = id;
|
||||
mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.ID,
|
||||
mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN);
|
||||
|
||||
// The terrain object initial position is at the center of the object
|
||||
Vector3 centerPos;
|
||||
centerPos.X = minCoords.X + (mapInfo.sizeX / 2f);
|
||||
centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f);
|
||||
centerPos.Z = minZ + ((maxZ - minZ) / 2f);
|
||||
|
||||
// Create the terrain shape from the mapInfo
|
||||
mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr));
|
||||
|
||||
mapInfo.terrainBody = new BulletBody(mapInfo.ID,
|
||||
BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.Ptr,
|
||||
centerPos, Quaternion.Identity));
|
||||
}
|
||||
|
||||
// Make sure the entry is in the heightmap table
|
||||
m_heightMaps[terrainRegionBase] = mapInfo;
|
||||
|
||||
// Set current terrain attributes
|
||||
BulletSimAPI.SetFriction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainFriction);
|
||||
BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainHitFraction);
|
||||
BulletSimAPI.SetRestitution2(mapInfo.terrainBody.Ptr, m_physicsScene.Params.terrainRestitution);
|
||||
BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.Ptr, CollisionFlags.CF_STATIC_OBJECT);
|
||||
|
||||
BulletSimAPI.SetMassProps2(mapInfo.terrainBody.Ptr, 0f, Vector3.Zero);
|
||||
BulletSimAPI.UpdateInertiaTensor2(mapInfo.terrainBody.Ptr);
|
||||
|
||||
// Return the new terrain to the world of physical objects
|
||||
BulletSimAPI.AddObjectToWorld2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||
|
||||
// redo its bounding box now that it is in the world
|
||||
BulletSimAPI.UpdateSingleAabb2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr);
|
||||
|
||||
// Make sure the new shape is processed.
|
||||
BulletSimAPI.Activate2(mapInfo.terrainBody.Ptr, true);
|
||||
};
|
||||
|
||||
// There is the option to do the changes now (we're already in 'taint time'), or
|
||||
// to do the Bullet operations later.
|
||||
if (doNow)
|
||||
rebuildOperation();
|
||||
else
|
||||
m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't know about this terrain so either we are creating a new terrain or
|
||||
// our mega-prim child is giving us a new terrain to add to the phys world
|
||||
|
||||
// if this is a child terrain, calculate a unique terrain id
|
||||
uint newTerrainID = id;
|
||||
if (newTerrainID >= BSScene.CHILDTERRAIN_ID)
|
||||
newTerrainID = ++m_terrainCount;
|
||||
|
||||
float[] heightMapX = heightMap;
|
||||
Vector3 minCoordsX = minCoords;
|
||||
Vector3 maxCoordsX = maxCoords;
|
||||
|
||||
DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}",
|
||||
BSScene.DetailLogZero, newTerrainID, minCoords, minCoords);
|
||||
|
||||
// Code that must happen at taint-time
|
||||
BSScene.TaintCallback createOperation = delegate()
|
||||
{
|
||||
DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y);
|
||||
// Create a new mapInfo that will be filled with the new info
|
||||
mapInfo = new BulletHeightMapInfo(id, heightMapX,
|
||||
BulletSimAPI.CreateHeightMapInfo2(m_physicsScene.World.Ptr, newTerrainID,
|
||||
minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN));
|
||||
// Put the unfilled heightmap info into the collection of same
|
||||
m_heightMaps.Add(terrainRegionBase, mapInfo);
|
||||
// Build the terrain
|
||||
UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true);
|
||||
};
|
||||
|
||||
// If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time.
|
||||
if (doNow)
|
||||
createOperation();
|
||||
else
|
||||
m_physicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation);
|
||||
}
|
||||
}
|
||||
|
||||
// Someday we will have complex terrain with caves and tunnels
|
||||
public float GetTerrainHeightAtXYZ(Vector3 loc)
|
||||
{
|
||||
// For the moment, it's flat and convex
|
||||
return GetTerrainHeightAtXY(loc.X, loc.Y);
|
||||
}
|
||||
|
||||
// Given an X and Y, find the height of the terrain.
|
||||
// Since we could be handling multiple terrains for a mega-region,
|
||||
// the base of the region is calcuated assuming all regions are
|
||||
// the same size and that is the default.
|
||||
// Once the heightMapInfo is found, we have all the information to
|
||||
// compute the offset into the array.
|
||||
private float lastHeightTX = 999999f;
|
||||
private float lastHeightTY = 999999f;
|
||||
private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT;
|
||||
public float GetTerrainHeightAtXY(float tX, float tY)
|
||||
{
|
||||
// You'd be surprized at the number of times this routine is called
|
||||
// with the same parameters as last time.
|
||||
if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY)
|
||||
return lastHeight;
|
||||
|
||||
lastHeightTX = tX;
|
||||
lastHeightTY = tY;
|
||||
float ret = HEIGHT_GETHEIGHT_RET;
|
||||
|
||||
int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X;
|
||||
int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y;
|
||||
Vector2 terrainBaseXY = new Vector2(offsetX, offsetY);
|
||||
|
||||
BulletHeightMapInfo mapInfo;
|
||||
if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo))
|
||||
{
|
||||
float regionX = tX - offsetX;
|
||||
float regionY = tY - offsetY;
|
||||
if (regionX > mapInfo.sizeX) regionX = 0;
|
||||
if (regionY > mapInfo.sizeY) regionY = 0;
|
||||
int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX;
|
||||
ret = mapInfo.heightMap[mapIndex];
|
||||
m_terrainModified = false;
|
||||
DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}",
|
||||
BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_physicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}",
|
||||
LogHeader, m_physicsScene.RegionName, tX, tY);
|
||||
}
|
||||
lastHeight = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Although no one seems to check this, I do support combining.
|
||||
public bool SupportsCombining()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// This routine is called two ways:
|
||||
// One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum
|
||||
// extent of the combined regions. This is to inform the parent of the size
|
||||
// of the combined regions.
|
||||
// and one with 'offset' as the offset of the child region to the base region,
|
||||
// 'pScene' pointing to the parent and 'extents' of zero. This informs the
|
||||
// child of its relative base and new parent.
|
||||
public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents)
|
||||
{
|
||||
m_worldOffset = offset;
|
||||
m_worldMax = extents;
|
||||
m_parentScene = pScene;
|
||||
if (pScene != null)
|
||||
{
|
||||
// We are a child.
|
||||
// We want m_worldMax to be the highest coordinate of our piece of terrain.
|
||||
m_worldMax = offset + DefaultRegionSize;
|
||||
}
|
||||
DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}",
|
||||
BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax);
|
||||
}
|
||||
|
||||
// Unhook all the combining that I know about.
|
||||
public void UnCombine(PhysicsScene pScene)
|
||||
{
|
||||
// Just like ODE, for the moment a NOP
|
||||
DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero);
|
||||
}
|
||||
|
||||
|
||||
private void DetailLog(string msg, params Object[] args)
|
||||
{
|
||||
m_physicsScene.PhysicsLogging.Write(msg, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,13 +33,25 @@ using OpenMetaverse;
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin {
|
||||
|
||||
// Classes to allow some type checking for the API
|
||||
// These hold pointers to allocated objects in the unmanaged space.
|
||||
|
||||
// The physics engine controller class created at initialization
|
||||
public struct BulletSim
|
||||
{
|
||||
public BulletSim(uint id, IntPtr xx) { ID = id; Ptr = xx; }
|
||||
public BulletSim(uint worldId, BSScene bss, IntPtr xx) { worldID = worldId; scene = bss; Ptr = xx; }
|
||||
public uint worldID;
|
||||
// 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 uint ID;
|
||||
}
|
||||
|
||||
public struct BulletShape
|
||||
{
|
||||
public BulletShape(IntPtr xx) { Ptr = xx; }
|
||||
public IntPtr Ptr;
|
||||
}
|
||||
|
||||
// An allocated Bullet btRigidBody
|
||||
public struct BulletBody
|
||||
{
|
||||
public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; }
|
||||
@@ -47,12 +59,41 @@ public struct BulletBody
|
||||
public uint ID;
|
||||
}
|
||||
|
||||
// An allocated Bullet btConstraint
|
||||
public struct BulletConstraint
|
||||
{
|
||||
public BulletConstraint(IntPtr xx) { Ptr = xx; }
|
||||
public IntPtr Ptr;
|
||||
}
|
||||
|
||||
// An allocated HeightMapThing which hold various heightmap info
|
||||
// Made a class rather than a struct so there would be only one
|
||||
// instance of this and C# will pass around pointers rather
|
||||
// than making copies.
|
||||
public class BulletHeightMapInfo
|
||||
{
|
||||
public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) {
|
||||
ID = id;
|
||||
Ptr = xx;
|
||||
heightMap = hm;
|
||||
terrainRegionBase = new Vector2(0f, 0f);
|
||||
minCoords = new Vector3(100f, 100f, 25f);
|
||||
maxCoords = new Vector3(101f, 101f, 26f);
|
||||
minZ = maxZ = 0f;
|
||||
sizeX = sizeY = 256f;
|
||||
}
|
||||
public uint ID;
|
||||
public IntPtr Ptr;
|
||||
public float[] heightMap;
|
||||
public Vector2 terrainRegionBase;
|
||||
public Vector3 minCoords;
|
||||
public Vector3 maxCoords;
|
||||
public float sizeX, sizeY;
|
||||
public float minZ, maxZ;
|
||||
public BulletShape terrainShape;
|
||||
public BulletBody terrainBody;
|
||||
}
|
||||
|
||||
// ===============================================================================
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct ConvexHull
|
||||
@@ -158,6 +199,7 @@ public struct ConfigurationParameters
|
||||
public float avatarContactProcessingThreshold;
|
||||
|
||||
public float maxPersistantManifoldPoolSize;
|
||||
public float maxCollisionAlgorithmPoolSize;
|
||||
public float shouldDisableContactPoolDynamicAllocation;
|
||||
public float shouldForceUpdateAllAabbs;
|
||||
public float shouldRandomizeSolverOrder;
|
||||
@@ -218,6 +260,10 @@ public enum ConstraintParamAxis : int
|
||||
// ===============================================================================
|
||||
static class BulletSimAPI {
|
||||
|
||||
// Link back to the managed code for outputting log messages
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
public static extern string GetVersion();
|
||||
@@ -225,7 +271,11 @@ public static extern string GetVersion();
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern uint Initialize(Vector3 maxPosition, IntPtr parms,
|
||||
int maxCollisions, IntPtr collisionArray,
|
||||
int maxUpdates, IntPtr updateArray);
|
||||
int maxUpdates, IntPtr updateArray,
|
||||
DebugLogCallback logRoutine);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap);
|
||||
@@ -339,8 +389,6 @@ public static extern Vector3 RecoverFromPenetration(uint worldID, uint id);
|
||||
public static extern void DumpBulletStatistics();
|
||||
|
||||
// Log a debug message
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg);
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetDebugLogCallback(DebugLogCallback callback);
|
||||
|
||||
@@ -362,7 +410,7 @@ public static extern IntPtr GetSimHandle2(uint worldID);
|
||||
public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id);
|
||||
|
||||
[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]
|
||||
@@ -371,44 +419,98 @@ public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms,
|
||||
int maxUpdates, IntPtr updateArray);
|
||||
|
||||
[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]
|
||||
public static extern void SetHeightmap2(IntPtr sim, float[] heightmap);
|
||||
public static extern void SetHeightMap2(IntPtr world, float[] heightmap);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void Shutdown2(IntPtr sim);
|
||||
|
||||
[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 IntPtr updatedEntitiesPtr,
|
||||
out int collidersCount,
|
||||
out IntPtr collidersPtr);
|
||||
|
||||
/*
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateMesh2(IntPtr sim, int indicesCount, int* indices, int verticesCount, float* vertices );
|
||||
public static extern bool PushUpdate2(IntPtr obj);
|
||||
|
||||
// =====================================================================================
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateMeshShape2(IntPtr world,
|
||||
int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices,
|
||||
int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices );
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool BuildHull2(IntPtr sim, IntPtr mesh);
|
||||
public static extern IntPtr CreateHullShape2(IntPtr world,
|
||||
int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool ReleaseHull2(IntPtr sim, IntPtr mesh);
|
||||
public static extern IntPtr BuildHullShape2(IntPtr world, IntPtr meshShape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool DestroyMesh2(IntPtr sim, IntPtr mesh);
|
||||
public static extern IntPtr BuildNativeShape2(IntPtr world,
|
||||
float shapeType, float collisionMargin, Vector3 scale);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateObject2(IntPtr sim, ShapeData shapeData);
|
||||
*/
|
||||
public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateConstraint2(IntPtr sim, IntPtr obj1, IntPtr obj2,
|
||||
public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetBodyShape2(IntPtr sim, IntPtr obj, IntPtr shape);
|
||||
// =====================================================================================
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords,
|
||||
[MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords,
|
||||
[MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool ReleaseHeightMapInfo2(IntPtr heightMapInfo);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo);
|
||||
|
||||
// =====================================================================================
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
||||
Vector3 frame1loc, Quaternion frame1rot,
|
||||
Vector3 frame2loc, Quaternion frame2rot,
|
||||
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr Create6DofConstraintToPoint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
||||
Vector3 joinPoint,
|
||||
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr CreateHingeConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2,
|
||||
Vector3 pivotinA, Vector3 pivotinB,
|
||||
Vector3 axisInA, Vector3 axisInB,
|
||||
bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetConstraintEnable2(IntPtr constrain, float numericTrueFalse);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetFrames2(IntPtr constrain,
|
||||
Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetLinearLimits2(IntPtr constrain, Vector3 low, Vector3 hi);
|
||||
|
||||
@@ -421,6 +523,9 @@ public static extern bool UseFrameOffset2(IntPtr constrain, float enable);
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool TranslationalLimitMotor2(IntPtr constrain, float enable, float targetVel, float maxMotorForce);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetBreakingImpulseThreshold2(IntPtr constrain, float threshold);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool CalculateTransforms2(IntPtr constrain);
|
||||
|
||||
@@ -428,7 +533,18 @@ public static extern bool CalculateTransforms2(IntPtr constrain);
|
||||
public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams paramIndex, float value, ConstraintParamAxis axis);
|
||||
|
||||
[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 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]
|
||||
public static extern void Activate2(IntPtr obj, bool forceActivation);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern Vector3 GetPosition2(IntPtr obj);
|
||||
@@ -472,6 +588,9 @@ public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val);
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetFriction2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetHitFraction2(IntPtr obj, float val);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetRestitution2(IntPtr obj, float val);
|
||||
|
||||
@@ -481,6 +600,9 @@ public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val);
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern CollisionFlags GetCollisionFlags2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags);
|
||||
|
||||
@@ -502,6 +624,9 @@ public static extern bool SetGravity2(IntPtr obj, Vector3 val);
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr ClearForces2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr ClearAllForces2(IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool SetMargin2(IntPtr obj, float val);
|
||||
|
||||
@@ -509,13 +634,7 @@ public static extern bool SetMargin2(IntPtr obj, float val);
|
||||
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]
|
||||
public static extern bool DestroyObject2(IntPtr world, uint id);
|
||||
public static extern bool DestroyObject2(IntPtr world, IntPtr obj);
|
||||
|
||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||
public static extern void DumpPhysicsStatistics2(IntPtr sim);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -304,7 +304,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY:
|
||||
idx++;
|
||||
iV = rules.GetVector3Item(idx);
|
||||
wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z);
|
||||
wl.cloudDetailXYDensity = iV;
|
||||
break;
|
||||
case (int)ScriptBaseClass.WL_CLOUD_SCALE:
|
||||
idx++;
|
||||
@@ -329,7 +329,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY:
|
||||
idx++;
|
||||
iV = rules.GetVector3Item(idx);
|
||||
wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z);
|
||||
wl.cloudXYDensity = iV;
|
||||
break;
|
||||
case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER:
|
||||
idx++;
|
||||
@@ -384,7 +384,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE:
|
||||
idx++;
|
||||
iV = rules.GetVector3Item(idx);
|
||||
wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z);
|
||||
wl.reflectionWaveletScale = iV;
|
||||
break;
|
||||
case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE:
|
||||
idx++;
|
||||
@@ -422,7 +422,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
case (int)ScriptBaseClass.WL_WATER_COLOR:
|
||||
idx++;
|
||||
iV = rules.GetVector3Item(idx);
|
||||
wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z);
|
||||
wl.waterColor = iV;
|
||||
break;
|
||||
case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT:
|
||||
idx++;
|
||||
|
||||
@@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
// ---------- Integer ----------
|
||||
else if (lslparm is LSL_Integer)
|
||||
{
|
||||
if (type == typeof(int))
|
||||
if (type == typeof(int) || type == typeof(float))
|
||||
return (int)(LSL_Integer)lslparm;
|
||||
}
|
||||
|
||||
@@ -333,8 +333,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
{
|
||||
if (type == typeof(OpenMetaverse.Quaternion))
|
||||
{
|
||||
LSL_Rotation rot = (LSL_Rotation)lslparm;
|
||||
return new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s);
|
||||
return (OpenMetaverse.Quaternion)((LSL_Rotation)lslparm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,8 +342,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
{
|
||||
if (type == typeof(OpenMetaverse.Vector3))
|
||||
{
|
||||
LSL_Vector vect = (LSL_Vector)lslparm;
|
||||
return new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z);
|
||||
return (OpenMetaverse.Vector3)((LSL_Vector)lslparm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,13 +365,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
result[i] = new UUID((LSL_Key)plist[i]);
|
||||
else if (plist[i] is LSL_Rotation)
|
||||
{
|
||||
LSL_Rotation rot = (LSL_Rotation)plist[i];
|
||||
result[i] = new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s);
|
||||
result[i] = (OpenMetaverse.Quaternion)(
|
||||
(LSL_Rotation)plist[i]);
|
||||
}
|
||||
else if (plist[i] is LSL_Vector)
|
||||
{
|
||||
LSL_Vector vect = (LSL_Vector)plist[i];
|
||||
result[i] = new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z);
|
||||
result[i] = (OpenMetaverse.Vector3)(
|
||||
(LSL_Vector)plist[i]);
|
||||
}
|
||||
else
|
||||
MODError("unknown LSL list element type");
|
||||
|
||||
@@ -140,12 +140,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
internal float m_ScriptDistanceFactor = 1.0f;
|
||||
internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >();
|
||||
|
||||
protected IUrlModule m_UrlModule = null;
|
||||
|
||||
public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item)
|
||||
{
|
||||
m_ScriptEngine = ScriptEngine;
|
||||
m_host = host;
|
||||
m_item = item;
|
||||
|
||||
m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
|
||||
|
||||
if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
|
||||
m_OSFunctionsEnabled = true;
|
||||
|
||||
@@ -773,10 +777,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
// We will launch the teleport on a new thread so that when the script threads are terminated
|
||||
// before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
|
||||
Util.FireAndForget(
|
||||
o => World.RequestTeleportLocation(presence.ControllingClient, regionName,
|
||||
new Vector3((float)position.x, (float)position.y, (float)position.z),
|
||||
new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
|
||||
Util.FireAndForget(o => World.RequestTeleportLocation(
|
||||
presence.ControllingClient, regionName, position,
|
||||
lookat, (uint)TPFlags.ViaLocation));
|
||||
|
||||
ScriptSleep(5000);
|
||||
|
||||
@@ -819,10 +822,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
// We will launch the teleport on a new thread so that when the script threads are terminated
|
||||
// before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
|
||||
Util.FireAndForget(
|
||||
o => World.RequestTeleportLocation(presence.ControllingClient, regionHandle,
|
||||
new Vector3((float)position.x, (float)position.y, (float)position.z),
|
||||
new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
|
||||
Util.FireAndForget(o => World.RequestTeleportLocation(
|
||||
presence.ControllingClient, regionHandle,
|
||||
position, lookat, (uint)TPFlags.ViaLocation));
|
||||
|
||||
ScriptSleep(5000);
|
||||
|
||||
@@ -1671,6 +1673,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
return;
|
||||
}
|
||||
|
||||
MessageObject(objUUID, message);
|
||||
}
|
||||
|
||||
private void MessageObject(UUID objUUID, string message)
|
||||
{
|
||||
object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) };
|
||||
|
||||
SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID);
|
||||
@@ -2248,11 +2255,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams");
|
||||
m_host.AddScriptLPS(1);
|
||||
InitLSL();
|
||||
// One needs to cast m_LSL_Api because we're using functions not
|
||||
// on the ILSL_Api interface.
|
||||
LSL_Api LSL_Api = (LSL_Api)m_LSL_Api;
|
||||
LSL_List retVal = new LSL_List();
|
||||
List<SceneObjectPart> parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber);
|
||||
LSL_List remaining = null;
|
||||
List<SceneObjectPart> parts = LSL_Api.GetLinkParts(linknumber);
|
||||
foreach (SceneObjectPart part in parts)
|
||||
{
|
||||
retVal += ((LSL_Api)m_LSL_Api).GetLinkPrimitiveParams(part, rules);
|
||||
remaining = LSL_Api.GetPrimParams(part, rules, ref retVal);
|
||||
}
|
||||
|
||||
while (remaining != null && remaining.Length > 2)
|
||||
{
|
||||
linknumber = remaining.GetLSLIntegerItem(0);
|
||||
rules = remaining.GetSublist(1, -1);
|
||||
parts = LSL_Api.GetLinkParts(linknumber);
|
||||
|
||||
foreach (SceneObjectPart part in parts)
|
||||
remaining = LSL_Api.GetPrimParams(part, rules, ref retVal);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
@@ -2329,7 +2350,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
ownerID = m_host.OwnerID;
|
||||
UUID x = module.CreateNPC(firstname,
|
||||
lastname,
|
||||
new Vector3((float) position.x, (float) position.y, (float) position.z),
|
||||
position,
|
||||
ownerID,
|
||||
senseAsAgent,
|
||||
World,
|
||||
@@ -2446,7 +2467,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
return new LSL_Vector(0, 0, 0);
|
||||
}
|
||||
|
||||
public void osNpcMoveTo(LSL_Key npc, LSL_Vector position)
|
||||
public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo");
|
||||
m_host.AddScriptLPS(1);
|
||||
@@ -2461,7 +2482,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
if (!module.CheckPermissions(npcId, m_host.OwnerID))
|
||||
return;
|
||||
|
||||
Vector3 pos = new Vector3((float) position.x, (float) position.y, (float) position.z);
|
||||
module.MoveToTarget(npcId, World, pos, false, true, false);
|
||||
}
|
||||
}
|
||||
@@ -2481,11 +2501,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
if (!module.CheckPermissions(npcId, m_host.OwnerID))
|
||||
return;
|
||||
|
||||
Vector3 pos = new Vector3((float)target.x, (float)target.y, (float)target.z);
|
||||
module.MoveToTarget(
|
||||
new UUID(npc.m_string),
|
||||
World,
|
||||
pos,
|
||||
target,
|
||||
(options & ScriptBaseClass.OS_NPC_NO_FLY) != 0,
|
||||
(options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0,
|
||||
(options & ScriptBaseClass.OS_NPC_RUNNING) != 0);
|
||||
@@ -2537,7 +2556,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
ScenePresence sp = World.GetScenePresence(npcId);
|
||||
|
||||
if (sp != null)
|
||||
sp.Rotation = LSL_Api.Rot2Quaternion(rotation);
|
||||
sp.Rotation = rotation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2899,6 +2918,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public LSL_Float osGetHealth(string avatar)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.None, "osGetHealth");
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
LSL_Float health = new LSL_Float(-1);
|
||||
ScenePresence presence = World.GetScenePresence(new UUID(avatar));
|
||||
if (presence != null) health = presence.Health;
|
||||
return health;
|
||||
}
|
||||
|
||||
public void osCauseDamage(string avatar, double damage)
|
||||
{
|
||||
@@ -2911,7 +2941,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
ScenePresence presence = World.GetScenePresence(avatarId);
|
||||
if (presence != null)
|
||||
{
|
||||
LandData land = World.GetLandData(pos);
|
||||
LandData land = World.GetLandData((float)pos.X, (float)pos.Y);
|
||||
if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage)
|
||||
{
|
||||
float health = presence.Health;
|
||||
@@ -2958,7 +2988,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
m_host.AddScriptLPS(1);
|
||||
InitLSL();
|
||||
|
||||
return m_LSL_Api.GetLinkPrimitiveParamsEx(prim, rules);
|
||||
return m_LSL_Api.GetPrimitiveParamsEx(prim, rules);
|
||||
}
|
||||
|
||||
public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules)
|
||||
@@ -2967,7 +2997,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
m_host.AddScriptLPS(1);
|
||||
InitLSL();
|
||||
|
||||
m_LSL_Api.SetPrimitiveParamsEx(prim, rules);
|
||||
m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -3199,6 +3229,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
}
|
||||
}
|
||||
|
||||
#region Attachment commands
|
||||
|
||||
public void osForceAttachToAvatar(int attachmentPoint)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar");
|
||||
@@ -3288,6 +3320,175 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
((LSL_Api)m_LSL_Api).DetachFromAvatar();
|
||||
}
|
||||
|
||||
public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments");
|
||||
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
UUID targetUUID;
|
||||
ScenePresence target;
|
||||
LSL_List resp = new LSL_List();
|
||||
|
||||
if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
|
||||
{
|
||||
foreach (object point in attachmentPoints.Data)
|
||||
{
|
||||
LSL_Integer ipoint = new LSL_Integer(
|
||||
(point is LSL_Integer || point is int || point is uint) ?
|
||||
(int)point :
|
||||
0
|
||||
);
|
||||
resp.Add(ipoint);
|
||||
if (ipoint == 0)
|
||||
{
|
||||
// indicates zero attachments
|
||||
resp.Add(new LSL_Integer(0));
|
||||
}
|
||||
else
|
||||
{
|
||||
// gets the number of attachments on the attachment point
|
||||
resp.Add(new LSL_Integer(target.GetAttachments((uint)ipoint).Count));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments");
|
||||
m_host.AddScriptLPS(1);
|
||||
|
||||
UUID targetUUID;
|
||||
ScenePresence target;
|
||||
|
||||
if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target))
|
||||
{
|
||||
List<int> aps = new List<int>();
|
||||
foreach (object point in attachmentPoints.Data)
|
||||
{
|
||||
int ipoint;
|
||||
if (int.TryParse(point.ToString(), out ipoint))
|
||||
{
|
||||
aps.Add(ipoint);
|
||||
}
|
||||
}
|
||||
|
||||
List<SceneObjectGroup> attachments = new List<SceneObjectGroup>();
|
||||
|
||||
bool msgAll = aps.Contains(ScriptBaseClass.OS_ATTACH_MSG_ALL);
|
||||
bool invertPoints = (options & ScriptBaseClass.OS_ATTACH_MSG_INVERT_POINTS) != 0;
|
||||
|
||||
if (msgAll && invertPoints)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (msgAll || invertPoints)
|
||||
{
|
||||
attachments = target.GetAttachments();
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (int point in aps)
|
||||
{
|
||||
if (point > 0)
|
||||
{
|
||||
attachments.AddRange(target.GetAttachments((uint)point));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we have no attachments at this point, exit now
|
||||
if (attachments.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
List<SceneObjectGroup> ignoreThese = new List<SceneObjectGroup>();
|
||||
|
||||
if (invertPoints)
|
||||
{
|
||||
foreach (SceneObjectGroup attachment in attachments)
|
||||
{
|
||||
if (aps.Contains((int)attachment.AttachmentPoint))
|
||||
{
|
||||
ignoreThese.Add(attachment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (SceneObjectGroup attachment in ignoreThese)
|
||||
{
|
||||
attachments.Remove(attachment);
|
||||
}
|
||||
ignoreThese.Clear();
|
||||
|
||||
// if inverting removed all attachments to check, exit now
|
||||
if (attachments.Count < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((options & ScriptBaseClass.OS_ATTACH_MSG_OBJECT_CREATOR) != 0)
|
||||
{
|
||||
foreach (SceneObjectGroup attachment in attachments)
|
||||
{
|
||||
if (attachment.RootPart.CreatorID != m_host.CreatorID)
|
||||
{
|
||||
ignoreThese.Add(attachment);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (SceneObjectGroup attachment in ignoreThese)
|
||||
{
|
||||
attachments.Remove(attachment);
|
||||
}
|
||||
ignoreThese.Clear();
|
||||
|
||||
// if filtering by same object creator removed all
|
||||
// attachments to check, exit now
|
||||
if (attachments.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((options & ScriptBaseClass.OS_ATTACH_MSG_SCRIPT_CREATOR) != 0)
|
||||
{
|
||||
foreach (SceneObjectGroup attachment in attachments)
|
||||
{
|
||||
if (attachment.RootPart.CreatorID != m_item.CreatorID)
|
||||
{
|
||||
ignoreThese.Add(attachment);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (SceneObjectGroup attachment in ignoreThese)
|
||||
{
|
||||
attachments.Remove(attachment);
|
||||
}
|
||||
ignoreThese.Clear();
|
||||
|
||||
// if filtering by object creator must match originating
|
||||
// script creator removed all attachments to check,
|
||||
// exit now
|
||||
if (attachments.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (SceneObjectGroup attachment in attachments)
|
||||
{
|
||||
MessageObject(attachment.RootPart.UUID, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Checks if thing is a UUID.
|
||||
/// </summary>
|
||||
@@ -3337,5 +3538,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
|
||||
return new LSL_Key(m_host.ParentGroup.FromPartID.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the response type for an HTTP request/response
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public void osSetContentType(LSL_Key id, string type)
|
||||
{
|
||||
CheckThreatLevel(ThreatLevel.High,"osSetResponseType");
|
||||
if (m_UrlModule != null)
|
||||
m_UrlModule.HttpContentType(new UUID(id),type);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -351,7 +351,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
||||
q = avatar.Rotation * q;
|
||||
}
|
||||
|
||||
LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
|
||||
LSL_Types.Quaternion r = new LSL_Types.Quaternion(q);
|
||||
LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
|
||||
double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
|
||||
|
||||
@@ -428,9 +428,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
||||
try
|
||||
{
|
||||
Vector3 diff = toRegionPos - fromRegionPos;
|
||||
LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z);
|
||||
double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir);
|
||||
double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
|
||||
double dot = LSL_Types.Vector3.Dot(forward_dir, diff);
|
||||
double mag_obj = LSL_Types.Vector3.Mag(diff);
|
||||
ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
|
||||
}
|
||||
catch
|
||||
@@ -479,7 +478,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
||||
q = avatar.Rotation * q;
|
||||
}
|
||||
|
||||
LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
|
||||
LSL_Types.Quaternion r = new LSL_Types.Quaternion(q);
|
||||
LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
|
||||
double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
|
||||
bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0);
|
||||
@@ -560,8 +559,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
|
||||
double ang_obj = 0;
|
||||
try
|
||||
{
|
||||
Vector3 diff = toRegionPos - fromRegionPos;
|
||||
LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z);
|
||||
LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(
|
||||
toRegionPos - fromRegionPos);
|
||||
double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir);
|
||||
double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
|
||||
ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
|
||||
|
||||
@@ -424,7 +424,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||
LSL_String llXorBase64StringsCorrect(string str1, string str2);
|
||||
void print(string str);
|
||||
|
||||
void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
|
||||
LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
|
||||
void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc);
|
||||
LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||
void osAvatarPlayAnimation(string avatar, string animation);
|
||||
void osAvatarStopAnimation(string avatar, string animation);
|
||||
|
||||
// Attachment commands
|
||||
#region Attachment commands
|
||||
|
||||
/// <summary>
|
||||
/// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH
|
||||
@@ -192,6 +192,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||
/// <remarks>Nothing happens if the object is not attached.</remarks>
|
||||
void osForceDetachFromAvatar();
|
||||
|
||||
/// <summary>
|
||||
/// Returns a strided list of the specified attachment points and the number of attachments on those points.
|
||||
/// </summary>
|
||||
/// <param name="avatar">avatar UUID</param>
|
||||
/// <param name="attachmentPoints">list of ATTACH_* constants</param>
|
||||
/// <returns></returns>
|
||||
LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints);
|
||||
|
||||
/// <summary>
|
||||
/// Sends a specified message to the specified avatar's attachments on
|
||||
/// the specified attachment points.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Behaves as osMessageObject(), without the sending script needing to know the attachment keys in advance.
|
||||
/// </remarks>
|
||||
/// <param name="avatar">avatar UUID</param>
|
||||
/// <param name="message">message string</param>
|
||||
/// <param name="attachmentPoints">list of ATTACH_* constants, or -1 for all attachments. If -1 is specified and OS_ATTACH_MSG_INVERT_POINTS is present in flags, no action is taken.</param>
|
||||
/// <param name="flags">flags further constraining the attachments to deliver the message to.</param>
|
||||
void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags);
|
||||
|
||||
#endregion
|
||||
|
||||
//texture draw functions
|
||||
string osMovePen(string drawList, int x, int y);
|
||||
string osDrawLine(string drawList, int startX, int startY, int endX, int endY);
|
||||
@@ -317,6 +340,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||
int osGetSimulatorMemory();
|
||||
void osKickAvatar(string FirstName,string SurName,string alert);
|
||||
void osSetSpeed(string UUID, LSL_Float SpeedModifier);
|
||||
LSL_Float osGetHealth(string avatar);
|
||||
void osCauseHealing(string avatar, double healing);
|
||||
void osCauseDamage(string avatar, double damage);
|
||||
LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules);
|
||||
@@ -364,5 +388,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
|
||||
/// </summary>
|
||||
/// <returns>Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown.</returns>
|
||||
LSL_Key osGetRezzingObject();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the response type for an HTTP request/response
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
void osSetContentType(LSL_Key id, string type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,6 +237,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
public const int ATTACH_HUD_BOTTOM = 37;
|
||||
public const int ATTACH_HUD_BOTTOM_RIGHT = 38;
|
||||
|
||||
#region osMessageAttachments constants
|
||||
|
||||
/// <summary>
|
||||
/// Instructs osMessageAttachements to send the message to attachments
|
||||
/// on every point.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// One might expect this to be named OS_ATTACH_ALL, but then one might
|
||||
/// also expect functions designed to attach or detach or get
|
||||
/// attachments to work with it too. Attaching a no-copy item to
|
||||
/// many attachments could be dangerous.
|
||||
/// when combined with OS_ATTACH_MSG_INVERT_POINTS, will prevent the
|
||||
/// message from being sent.
|
||||
/// if combined with OS_ATTACH_MSG_OBJECT_CREATOR or
|
||||
/// OS_ATTACH_MSG_SCRIPT_CREATOR, could result in no message being
|
||||
/// sent- this is expected behaviour.
|
||||
/// </remarks>
|
||||
public const int OS_ATTACH_MSG_ALL = -65535;
|
||||
|
||||
/// <summary>
|
||||
/// Instructs osMessageAttachements to invert how the attachment points
|
||||
/// list should be treated (e.g. go from inclusive operation to
|
||||
/// exclusive operation).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This might be used if you want to deliver a message to one set of
|
||||
/// attachments and a different message to everything else. With
|
||||
/// this flag, you only need to build one explicit list for both calls.
|
||||
/// </remarks>
|
||||
public const int OS_ATTACH_MSG_INVERT_POINTS = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Instructs osMessageAttachments to only send the message to
|
||||
/// attachments with a CreatorID that matches the host object CreatorID
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This would be used if distributed in an object vendor/updater server.
|
||||
/// </remarks>
|
||||
public const int OS_ATTACH_MSG_OBJECT_CREATOR = 2;
|
||||
|
||||
/// <summary>
|
||||
/// Instructs osMessageAttachments to only send the message to
|
||||
/// attachments with a CreatorID that matches the sending script CreatorID
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This might be used if the script is distributed independently of a
|
||||
/// containing object.
|
||||
/// </remarks>
|
||||
public const int OS_ATTACH_MSG_SCRIPT_CREATOR = 4;
|
||||
|
||||
#endregion
|
||||
|
||||
public const int LAND_LEVEL = 0;
|
||||
public const int LAND_RAISE = 1;
|
||||
public const int LAND_LOWER = 2;
|
||||
@@ -328,6 +380,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
public const int PRIM_OMEGA = 32;
|
||||
public const int PRIM_POS_LOCAL = 33;
|
||||
public const int PRIM_LINK_TARGET = 34;
|
||||
public const int PRIM_SLICE = 35;
|
||||
public const int PRIM_TEXGEN_DEFAULT = 0;
|
||||
public const int PRIM_TEXGEN_PLANAR = 1;
|
||||
|
||||
|
||||
@@ -289,7 +289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
m_OSSL_Functions.osAvatarStopAnimation(avatar, animation);
|
||||
}
|
||||
|
||||
// Avatar functions
|
||||
#region Attachment commands
|
||||
|
||||
public void osForceAttachToAvatar(int attachmentPoint)
|
||||
{
|
||||
@@ -311,6 +311,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
m_OSSL_Functions.osForceDetachFromAvatar();
|
||||
}
|
||||
|
||||
public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints)
|
||||
{
|
||||
return m_OSSL_Functions.osGetNumberOfAttachments(avatar, attachmentPoints);
|
||||
}
|
||||
|
||||
public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags)
|
||||
{
|
||||
m_OSSL_Functions.osMessageAttachments(avatar, message, attachmentPoints, flags);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// Texture Draw functions
|
||||
|
||||
public string osMovePen(string drawList, int x, int y)
|
||||
@@ -865,7 +877,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
{
|
||||
m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier);
|
||||
}
|
||||
|
||||
|
||||
public LSL_Float osGetHealth(string avatar)
|
||||
{
|
||||
return m_OSSL_Functions.osGetHealth(avatar);
|
||||
}
|
||||
|
||||
public void osCauseDamage(string avatar, double damage)
|
||||
{
|
||||
m_OSSL_Functions.osCauseDamage(avatar, damage);
|
||||
@@ -950,5 +967,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
|
||||
{
|
||||
return m_OSSL_Functions.osGetRezzingObject();
|
||||
}
|
||||
|
||||
public void osSetContentType(LSL_Key id, string type)
|
||||
{
|
||||
m_OSSL_Functions.osSetContentType(id,type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,6 +546,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
|
||||
"OpenSim.Region.ScriptEngine.Shared.dll"));
|
||||
parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
|
||||
"OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll"));
|
||||
parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
|
||||
"OpenMetaverseTypes.dll"));
|
||||
|
||||
if (lang == enumCompileType.yp)
|
||||
{
|
||||
|
||||
@@ -160,11 +160,11 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
else
|
||||
{
|
||||
// Set the values from the touch data provided by the client
|
||||
touchST = new LSL_Types.Vector3(value.STCoord.X, value.STCoord.Y, value.STCoord.Z);
|
||||
touchUV = new LSL_Types.Vector3(value.UVCoord.X, value.UVCoord.Y, value.UVCoord.Z);
|
||||
touchNormal = new LSL_Types.Vector3(value.Normal.X, value.Normal.Y, value.Normal.Z);
|
||||
touchBinormal = new LSL_Types.Vector3(value.Binormal.X, value.Binormal.Y, value.Binormal.Z);
|
||||
touchPos = new LSL_Types.Vector3(value.Position.X, value.Position.Y, value.Position.Z);
|
||||
touchST = new LSL_Types.Vector3(value.STCoord);
|
||||
touchUV = new LSL_Types.Vector3(value.UVCoord);
|
||||
touchNormal = new LSL_Types.Vector3(value.Normal);
|
||||
touchBinormal = new LSL_Types.Vector3(value.Binormal);
|
||||
touchPos = new LSL_Types.Vector3(value.Position);
|
||||
touchFace = value.FaceIndex;
|
||||
}
|
||||
}
|
||||
@@ -181,19 +181,13 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
|
||||
Name = presence.Firstname + " " + presence.Lastname;
|
||||
Owner = Key;
|
||||
Position = new LSL_Types.Vector3(
|
||||
presence.AbsolutePosition.X,
|
||||
presence.AbsolutePosition.Y,
|
||||
presence.AbsolutePosition.Z);
|
||||
Position = new LSL_Types.Vector3(presence.AbsolutePosition);
|
||||
Rotation = new LSL_Types.Quaternion(
|
||||
presence.Rotation.X,
|
||||
presence.Rotation.Y,
|
||||
presence.Rotation.Z,
|
||||
presence.Rotation.W);
|
||||
Velocity = new LSL_Types.Vector3(
|
||||
presence.Velocity.X,
|
||||
presence.Velocity.Y,
|
||||
presence.Velocity.Z);
|
||||
Velocity = new LSL_Types.Vector3(presence.Velocity);
|
||||
|
||||
if (presence.PresenceType != PresenceType.Npc)
|
||||
{
|
||||
@@ -241,16 +235,12 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
}
|
||||
}
|
||||
|
||||
Position = new LSL_Types.Vector3(part.AbsolutePosition.X,
|
||||
part.AbsolutePosition.Y,
|
||||
part.AbsolutePosition.Z);
|
||||
Position = new LSL_Types.Vector3(part.AbsolutePosition);
|
||||
|
||||
Quaternion wr = part.ParentGroup.GroupRotation;
|
||||
Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W);
|
||||
|
||||
Velocity = new LSL_Types.Vector3(part.Velocity.X,
|
||||
part.Velocity.Y,
|
||||
part.Velocity.Z);
|
||||
Velocity = new LSL_Types.Vector3(part.Velocity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,11 @@ using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using OpenSim.Framework;
|
||||
|
||||
using OpenMetaverse;
|
||||
using OMV_Vector3 = OpenMetaverse.Vector3;
|
||||
using OMV_Vector3d = OpenMetaverse.Vector3d;
|
||||
using OMV_Quaternion = OpenMetaverse.Quaternion;
|
||||
|
||||
namespace OpenSim.Region.ScriptEngine.Shared
|
||||
{
|
||||
[Serializable]
|
||||
@@ -54,6 +59,20 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
z = (float)vector.z;
|
||||
}
|
||||
|
||||
public Vector3(OMV_Vector3 vector)
|
||||
{
|
||||
x = vector.X;
|
||||
y = vector.Y;
|
||||
z = vector.Z;
|
||||
}
|
||||
|
||||
public Vector3(OMV_Vector3d vector)
|
||||
{
|
||||
x = vector.X;
|
||||
y = vector.Y;
|
||||
z = vector.Z;
|
||||
}
|
||||
|
||||
public Vector3(double X, double Y, double Z)
|
||||
{
|
||||
x = X;
|
||||
@@ -109,6 +128,26 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
return new list(new object[] { vec });
|
||||
}
|
||||
|
||||
public static implicit operator OMV_Vector3(Vector3 vec)
|
||||
{
|
||||
return new OMV_Vector3((float)vec.x, (float)vec.y, (float)vec.z);
|
||||
}
|
||||
|
||||
public static implicit operator Vector3(OMV_Vector3 vec)
|
||||
{
|
||||
return new Vector3(vec);
|
||||
}
|
||||
|
||||
public static implicit operator OMV_Vector3d(Vector3 vec)
|
||||
{
|
||||
return new OMV_Vector3d(vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
public static implicit operator Vector3(OMV_Vector3d vec)
|
||||
{
|
||||
return new Vector3(vec);
|
||||
}
|
||||
|
||||
public static bool operator ==(Vector3 lhs, Vector3 rhs)
|
||||
{
|
||||
return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z);
|
||||
@@ -322,6 +361,14 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
s = 1;
|
||||
}
|
||||
|
||||
public Quaternion(OMV_Quaternion rot)
|
||||
{
|
||||
x = rot.X;
|
||||
y = rot.Y;
|
||||
z = rot.Z;
|
||||
s = rot.W;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Overriders
|
||||
@@ -368,6 +415,21 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
return new list(new object[] { r });
|
||||
}
|
||||
|
||||
public static implicit operator OMV_Quaternion(Quaternion rot)
|
||||
{
|
||||
// LSL quaternions can normalize to 0, normal Quaternions can't.
|
||||
if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
|
||||
rot.z = 1; // ZERO_ROTATION = 0,0,0,1
|
||||
OMV_Quaternion omvrot = new OMV_Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
|
||||
omvrot.Normalize();
|
||||
return omvrot;
|
||||
}
|
||||
|
||||
public static implicit operator Quaternion(OMV_Quaternion rot)
|
||||
{
|
||||
return new Quaternion(rot);
|
||||
}
|
||||
|
||||
public static bool operator ==(Quaternion lhs, Quaternion rhs)
|
||||
{
|
||||
// Return true if the fields match:
|
||||
@@ -560,12 +622,23 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||
else if (m_data[itemIndex] is LSL_Types.LSLString)
|
||||
return new LSLInteger(m_data[itemIndex].ToString());
|
||||
else
|
||||
throw new InvalidCastException();
|
||||
throw new InvalidCastException(string.Format(
|
||||
"{0} expected but {1} given",
|
||||
typeof(LSL_Types.LSLInteger).Name,
|
||||
m_data[itemIndex] != null ?
|
||||
m_data[itemIndex].GetType().Name : "null"));
|
||||
}
|
||||
|
||||
public LSL_Types.Vector3 GetVector3Item(int itemIndex)
|
||||
{
|
||||
return (LSL_Types.Vector3)m_data[itemIndex];
|
||||
if(m_data[itemIndex] is LSL_Types.Vector3)
|
||||
return (LSL_Types.Vector3)m_data[itemIndex];
|
||||
else
|
||||
throw new InvalidCastException(string.Format(
|
||||
"{0} expected but {1} given",
|
||||
typeof(LSL_Types.Vector3).Name,
|
||||
m_data[itemIndex] != null ?
|
||||
m_data[itemIndex].GetType().Name : "null"));
|
||||
}
|
||||
|
||||
public LSL_Types.Quaternion GetQuaternionItem(int itemIndex)
|
||||
|
||||
@@ -152,9 +152,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
det[0] = new DetectParams();
|
||||
det[0].Key = remoteClient.AgentId;
|
||||
det[0].Populate(myScriptEngine.World);
|
||||
det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X,
|
||||
offsetPos.Y,
|
||||
offsetPos.Z);
|
||||
det[0].OffsetPos = offsetPos;
|
||||
|
||||
if (originalID == 0)
|
||||
{
|
||||
@@ -298,9 +296,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
foreach (DetectedObject detobj in col.Colliders)
|
||||
{
|
||||
DetectParams d = new DetectParams();
|
||||
d.Position = new LSL_Types.Vector3(detobj.posVector.X,
|
||||
detobj.posVector.Y,
|
||||
detobj.posVector.Z);
|
||||
d.Position = detobj.posVector;
|
||||
d.Populate(myScriptEngine.World);
|
||||
det.Add(d);
|
||||
myScriptEngine.PostObjectEvent(localID, new EventParams(
|
||||
@@ -318,9 +314,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
foreach (DetectedObject detobj in col.Colliders)
|
||||
{
|
||||
DetectParams d = new DetectParams();
|
||||
d.Position = new LSL_Types.Vector3(detobj.posVector.X,
|
||||
detobj.posVector.Y,
|
||||
detobj.posVector.Z);
|
||||
d.Position = detobj.posVector;
|
||||
d.Populate(myScriptEngine.World);
|
||||
det.Add(d);
|
||||
myScriptEngine.PostObjectEvent(localID, new EventParams(
|
||||
@@ -337,9 +331,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
foreach (DetectedObject detobj in col.Colliders)
|
||||
{
|
||||
DetectParams d = new DetectParams();
|
||||
d.Position = new LSL_Types.Vector3(detobj.posVector.X,
|
||||
detobj.posVector.Y,
|
||||
detobj.posVector.Z);
|
||||
d.Position = detobj.posVector;
|
||||
d.Populate(myScriptEngine.World);
|
||||
det.Add(d);
|
||||
myScriptEngine.PostObjectEvent(localID, new EventParams(
|
||||
@@ -381,8 +373,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
myScriptEngine.PostObjectEvent(localID, new EventParams(
|
||||
"at_target", new object[] {
|
||||
new LSL_Types.LSLInteger(handle),
|
||||
new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z),
|
||||
new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) },
|
||||
new LSL_Types.Vector3(targetpos),
|
||||
new LSL_Types.Vector3(atpos) },
|
||||
new DetectParams[0]));
|
||||
}
|
||||
|
||||
@@ -399,8 +391,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
myScriptEngine.PostObjectEvent(localID, new EventParams(
|
||||
"at_rot_target", new object[] {
|
||||
new LSL_Types.LSLInteger(handle),
|
||||
new LSL_Types.Quaternion(targetrot.X,targetrot.Y,targetrot.Z,targetrot.W),
|
||||
new LSL_Types.Quaternion(atrot.X,atrot.Y,atrot.Z,atrot.W) },
|
||||
new LSL_Types.Quaternion(targetrot),
|
||||
new LSL_Types.Quaternion(atrot) },
|
||||
new DetectParams[0]));
|
||||
}
|
||||
|
||||
|
||||
@@ -1492,9 +1492,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
else if (p[i] is string)
|
||||
lsl_p[i] = new LSL_Types.LSLString((string)p[i]);
|
||||
else if (p[i] is Vector3)
|
||||
lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z);
|
||||
lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]);
|
||||
else if (p[i] is Quaternion)
|
||||
lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W);
|
||||
lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]);
|
||||
else if (p[i] is float)
|
||||
lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]);
|
||||
else
|
||||
@@ -1518,9 +1518,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
else if (p[i] is string)
|
||||
lsl_p[i] = new LSL_Types.LSLString((string)p[i]);
|
||||
else if (p[i] is Vector3)
|
||||
lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z);
|
||||
lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]);
|
||||
else if (p[i] is Quaternion)
|
||||
lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W);
|
||||
lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]);
|
||||
else if (p[i] is float)
|
||||
lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]);
|
||||
else
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
@@ -72,17 +71,10 @@ namespace OpenSim.Server.Base
|
||||
//
|
||||
private string m_pidFile = String.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Time at which this server was started
|
||||
/// </summary>
|
||||
protected DateTime m_startuptime;
|
||||
|
||||
// Handle all the automagical stuff
|
||||
//
|
||||
public ServicesServerBase(string prompt, string[] args)
|
||||
{
|
||||
m_startuptime = DateTime.Now;
|
||||
|
||||
// Save raw arguments
|
||||
//
|
||||
m_Arguments = args;
|
||||
@@ -258,10 +250,6 @@ namespace OpenSim.Server.Base
|
||||
"command-script <script>",
|
||||
"Run a command script from file", HandleScript);
|
||||
|
||||
MainConsole.Instance.Commands.AddCommand("General", false, "show uptime",
|
||||
"show uptime",
|
||||
"Show server uptime", HandleShow);
|
||||
|
||||
|
||||
// Allow derived classes to perform initialization that
|
||||
// needs to be done after the console has opened
|
||||
@@ -357,34 +345,5 @@ namespace OpenSim.Server.Base
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void HandleShow(string module, string[] cmd)
|
||||
{
|
||||
List<string> args = new List<string>(cmd);
|
||||
|
||||
args.RemoveAt(0);
|
||||
|
||||
string[] showParams = args.ToArray();
|
||||
|
||||
switch (showParams[0])
|
||||
{
|
||||
case "uptime":
|
||||
MainConsole.Instance.Output(GetUptimeReport());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return a report about the uptime of this server
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected string GetUptimeReport()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(String.Format("Time now is {0}\n", DateTime.Now));
|
||||
sb.Append(String.Format("Server has been running since {0}, {1}\n", m_startuptime.DayOfWeek, m_startuptime));
|
||||
sb.Append(String.Format("That is an elapsed time of {0}\n", DateTime.Now - m_startuptime));
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,8 +137,6 @@ namespace OpenSim.Server.Handlers.Avatar
|
||||
if (!UUID.TryParse(request["UserID"].ToString(), out user))
|
||||
return FailureResult();
|
||||
|
||||
RemoveRequestParamsNotForStorage(request);
|
||||
|
||||
AvatarData avatar = new AvatarData(request);
|
||||
if (m_AvatarService.SetAvatar(user, avatar))
|
||||
return SuccessResult();
|
||||
@@ -155,25 +153,11 @@ namespace OpenSim.Server.Handlers.Avatar
|
||||
if (!UUID.TryParse(request["UserID"].ToString(), out user))
|
||||
return FailureResult();
|
||||
|
||||
RemoveRequestParamsNotForStorage(request);
|
||||
|
||||
if (m_AvatarService.ResetAvatar(user))
|
||||
return SuccessResult();
|
||||
|
||||
return FailureResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove parameters that were used to invoke the method and should not in themselves be persisted.
|
||||
/// </summary>
|
||||
/// <param name='request'></param>
|
||||
private void RemoveRequestParamsNotForStorage(Dictionary<string, object> request)
|
||||
{
|
||||
request.Remove("VERSIONMAX");
|
||||
request.Remove("VERSIONMIN");
|
||||
request.Remove("METHOD");
|
||||
request.Remove("UserID");
|
||||
}
|
||||
|
||||
byte[] SetItems(Dictionary<string, object> request)
|
||||
{
|
||||
@@ -189,8 +173,6 @@ namespace OpenSim.Server.Handlers.Avatar
|
||||
if (!(request["Names"] is List<string> || request["Values"] is List<string>))
|
||||
return FailureResult();
|
||||
|
||||
RemoveRequestParamsNotForStorage(request);
|
||||
|
||||
List<string> _names = (List<string>)request["Names"];
|
||||
names = _names.ToArray();
|
||||
List<string> _values = (List<string>)request["Values"];
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace OpenSim.Services.AssetService
|
||||
|
||||
m_Database = LoadPlugin<IAssetDataPlugin>(dllName);
|
||||
if (m_Database == null)
|
||||
throw new Exception(string.Format("Could not find a storage interface in the module {0}", dllName));
|
||||
throw new Exception("Could not find a storage interface in the given module");
|
||||
|
||||
m_Database.Initialise(connString);
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace OpenSim.Services.AssetService
|
||||
m_AssetLoader = LoadPlugin<IAssetLoader>(loaderName);
|
||||
|
||||
if (m_AssetLoader == null)
|
||||
throw new Exception(string.Format("Asset loader could not be loaded from {0}", loaderName));
|
||||
throw new Exception("Asset loader could not be loaded");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||
public string RegisterRegion(UUID scopeID, GridRegion regionInfo)
|
||||
{
|
||||
Vector3d minPosition = new Vector3d(regionInfo.RegionLocX, regionInfo.RegionLocY, 0.0);
|
||||
Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight);
|
||||
Vector3d maxPosition = minPosition + new Vector3d(Constants.RegionSize, Constants.RegionSize, 4096.0);
|
||||
|
||||
OSDMap extraData = new OSDMap
|
||||
{
|
||||
@@ -286,7 +286,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
|
||||
List<GridRegion> foundRegions = new List<GridRegion>();
|
||||
|
||||
Vector3d minPosition = new Vector3d(xmin, ymin, 0.0);
|
||||
Vector3d maxPosition = new Vector3d(xmax, ymax, Constants.RegionHeight);
|
||||
Vector3d maxPosition = new Vector3d(xmax, ymax, 4096.0);
|
||||
|
||||
NameValueCollection requestArgs = new NameValueCollection
|
||||
{
|
||||
|
||||
@@ -164,5 +164,19 @@ namespace OpenSim.Services.Connectors
|
||||
m_database.RemoveRegionEnvironmentSettings(regionUUID);
|
||||
}
|
||||
|
||||
public void SaveExtra(UUID regionID, string name, string val)
|
||||
{
|
||||
m_database.SaveExtra(regionID, name, val);
|
||||
}
|
||||
|
||||
public void RemoveExtra(UUID regionID, string name)
|
||||
{
|
||||
m_database.RemoveExtra(regionID, name);
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetExtra(UUID regionID)
|
||||
{
|
||||
return m_database.GetExtra(regionID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,9 +137,14 @@ namespace OpenSim.Services.GridService
|
||||
if (regionInfos.RegionID == UUID.Zero)
|
||||
return "Invalid RegionID - cannot be zero UUID";
|
||||
|
||||
// This needs better sanity testing. What if regionInfo is registering in
|
||||
// overlapping coords?
|
||||
RegionData region = m_Database.Get(regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
|
||||
if ((region != null) && (region.RegionID != regionInfos.RegionID))
|
||||
{
|
||||
m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.",
|
||||
regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
|
||||
return "Region overlaps another region";
|
||||
}
|
||||
|
||||
if (region != null)
|
||||
{
|
||||
// There is a preexisting record
|
||||
@@ -176,32 +181,7 @@ namespace OpenSim.Services.GridService
|
||||
}
|
||||
}
|
||||
|
||||
if ((region != null) && (region.RegionID != regionInfos.RegionID))
|
||||
{
|
||||
m_log.WarnFormat("[GRID SERVICE]: Region {0} tried to register in coordinates {1}, {2} which are already in use in scope {3}.",
|
||||
regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY, scopeID);
|
||||
return "Region overlaps another region";
|
||||
}
|
||||
|
||||
if ((region != null) && (region.RegionID == regionInfos.RegionID) &&
|
||||
((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY)))
|
||||
{
|
||||
if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.NoMove) != 0)
|
||||
return "Can't move this region";
|
||||
|
||||
// Region reregistering in other coordinates. Delete the old entry
|
||||
m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.",
|
||||
regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY);
|
||||
|
||||
try
|
||||
{
|
||||
m_Database.Delete(regionInfos.RegionID);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e);
|
||||
}
|
||||
}
|
||||
// If we get here, the destination is clear. Now for the real check.
|
||||
|
||||
if (!m_AllowDuplicateNames)
|
||||
{
|
||||
@@ -220,6 +200,31 @@ namespace OpenSim.Services.GridService
|
||||
}
|
||||
}
|
||||
|
||||
// If there is an old record for us, delete it if it is elsewhere.
|
||||
region = m_Database.Get(regionInfos.RegionID, scopeID);
|
||||
if ((region != null) && (region.RegionID == regionInfos.RegionID) &&
|
||||
((region.posX != regionInfos.RegionLocX) || (region.posY != regionInfos.RegionLocY)))
|
||||
{
|
||||
if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.NoMove) != 0)
|
||||
return "Can't move this region";
|
||||
|
||||
if ((Convert.ToInt32(region.Data["flags"]) & (int)OpenSim.Data.RegionFlags.LockedOut) != 0)
|
||||
return "Region locked out";
|
||||
|
||||
// Region reregistering in other coordinates. Delete the old entry
|
||||
m_log.DebugFormat("[GRID SERVICE]: Region {0} ({1}) was previously registered at {2}-{3}. Deleting old entry.",
|
||||
regionInfos.RegionName, regionInfos.RegionID, regionInfos.RegionLocX, regionInfos.RegionLocY);
|
||||
|
||||
try
|
||||
{
|
||||
m_Database.Delete(regionInfos.RegionID);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.DebugFormat("[GRID SERVICE]: Database exception: {0}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Everything is ok, let's register
|
||||
RegionData rdata = RegionInfo2RegionData(regionInfos);
|
||||
rdata.ScopeID = scopeID;
|
||||
@@ -227,8 +232,6 @@ namespace OpenSim.Services.GridService
|
||||
if (region != null)
|
||||
{
|
||||
int oldFlags = Convert.ToInt32(region.Data["flags"]);
|
||||
if ((oldFlags & (int)OpenSim.Data.RegionFlags.LockedOut) != 0)
|
||||
return "Region locked out";
|
||||
|
||||
oldFlags &= ~(int)OpenSim.Data.RegionFlags.Reservation;
|
||||
|
||||
|
||||
@@ -176,7 +176,8 @@ namespace OpenSim.Services.Interfaces
|
||||
List<AvatarAttachment> attachments = appearance.GetAttachments();
|
||||
foreach (AvatarAttachment attach in attachments)
|
||||
{
|
||||
Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString();
|
||||
if (attach.ItemID != UUID.Zero)
|
||||
Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -127,6 +127,19 @@ namespace OpenSim.Data.Null
|
||||
{
|
||||
m_store.RemoveRegionEnvironmentSettings(regionUUID);
|
||||
}
|
||||
|
||||
public void SaveExtra(UUID regionID, string name, string value)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveExtra(UUID regionID, string name)
|
||||
{
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetExtra(UUID regionID)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -318,5 +331,18 @@ namespace OpenSim.Data.Null
|
||||
public void Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
public void SaveExtra(UUID regionID, string name, string value)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveExtra(UUID regionID, string name)
|
||||
{
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetExtra(UUID regionID)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
Json.NET
|
||||
License: The MIT License
|
||||
Copyright (c) 2007 James Newton-King
|
||||
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user