Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e09467b30d | ||
|
|
afeb5d4917 | ||
|
|
8d5fe5c222 | ||
|
|
61f18d15e1 | ||
|
|
0b2608d8f4 | ||
|
|
30a60d661f | ||
|
|
cc40517863 | ||
|
|
71862f34b6 | ||
|
|
c22276a169 | ||
|
|
13d4f6f747 | ||
|
|
6fe771f27e | ||
|
|
0ad07eb44d | ||
|
|
edb99dcc19 | ||
|
|
a52dfd43b6 | ||
|
|
5920abbf8d | ||
|
|
ef662fc959 | ||
|
|
69d0e168fb | ||
|
|
bcb172301d | ||
|
|
708c3f8b86 | ||
|
|
d652de1d0e | ||
|
|
c2bfdaa026 | ||
|
|
5557b523fd | ||
|
|
b1a165a39a | ||
|
|
70e641c708 | ||
|
|
3e9f3c0383 | ||
|
|
4b797f2ead | ||
|
|
0194a3d890 | ||
|
|
fb903ff490 | ||
|
|
992ef9e971 | ||
|
|
aaa80d11a8 | ||
|
|
a82bd5678e | ||
|
|
058d477ce7 | ||
|
|
4b8c22ecfa | ||
|
|
d3b2cdc2b4 | ||
|
|
586def0bcc | ||
|
|
d55974bcb7 | ||
|
|
6924bd21f4 | ||
|
|
9d001e40e7 | ||
|
|
8fcfd82241 | ||
|
|
cbb8d82c7d | ||
|
|
c72c189864 | ||
|
|
6f3dcf58b8 | ||
|
|
38b476d9d6 | ||
|
|
7524bd5a7c | ||
|
|
adedd70c35 | ||
|
|
0a297a0e52 | ||
|
|
7bb82c8f2e | ||
|
|
745ef40153 | ||
|
|
ae701eccd2 | ||
|
|
6935bec0ab | ||
|
|
a8bc08ebe6 | ||
|
|
85b81ff7f2 | ||
|
|
4808b8ee38 | ||
|
|
222040f1ec | ||
|
|
1b55a9d81e | ||
|
|
d92eb80373 | ||
|
|
1b203601f4 | ||
|
|
2fd184e350 | ||
|
|
6d825d7ea2 | ||
|
|
4d5c04837e | ||
|
|
a08e1b60ec | ||
|
|
b08977ea7d |
@@ -65,6 +65,7 @@ what it is today.
|
||||
* A_Biondi
|
||||
* alex_carnell
|
||||
* Alan Webb (IBM)
|
||||
* Allen Kerensky
|
||||
* BigFootAg
|
||||
* BlueWall Slade
|
||||
* brianw/Sir_Ahzz
|
||||
|
||||
@@ -351,7 +351,8 @@ IF EXISTS (SELECT UUID FROM prims WHERE UUID = @UUID)
|
||||
ScriptAccessPin = @ScriptAccessPin, AllowedDrop = @AllowedDrop, DieAtEdge = @DieAtEdge, SalePrice = @SalePrice,
|
||||
SaleType = @SaleType, ColorR = @ColorR, ColorG = @ColorG, ColorB = @ColorB, ColorA = @ColorA, ParticleSystem = @ParticleSystem,
|
||||
ClickAction = @ClickAction, Material = @Material, CollisionSound = @CollisionSound, CollisionSoundVolume = @CollisionSoundVolume, PassTouches = @PassTouches,
|
||||
LinkNumber = @LinkNumber, MediaURL = @MediaURL, DynAttrs = @DynAttrs
|
||||
LinkNumber = @LinkNumber, MediaURL = @MediaURL, DynAttrs = @DynAttrs,
|
||||
PhysicsShapeType = @PhysicsShapeType, Density = @Density, GravityModifier = @GravityModifier, Friction = @Friction, Restitution = @Restitution
|
||||
WHERE UUID = @UUID
|
||||
END
|
||||
ELSE
|
||||
@@ -366,7 +367,8 @@ ELSE
|
||||
PayPrice, PayButton1, PayButton2, PayButton3, PayButton4, LoopedSound, LoopedSoundGain, TextureAnimation, OmegaX,
|
||||
OmegaY, OmegaZ, CameraEyeOffsetX, CameraEyeOffsetY, CameraEyeOffsetZ, CameraAtOffsetX, CameraAtOffsetY, CameraAtOffsetZ,
|
||||
ForceMouselook, ScriptAccessPin, AllowedDrop, DieAtEdge, SalePrice, SaleType, ColorR, ColorG, ColorB, ColorA,
|
||||
ParticleSystem, ClickAction, Material, CollisionSound, CollisionSoundVolume, PassTouches, LinkNumber, MediaURL, DynAttrs
|
||||
ParticleSystem, ClickAction, Material, CollisionSound, CollisionSoundVolume, PassTouches, LinkNumber, MediaURL, DynAttrs,
|
||||
PhysicsShapeType, Density, GravityModifier, Friction, Restitution
|
||||
) VALUES (
|
||||
@UUID, @CreationDate, @Name, @Text, @Description, @SitName, @TouchName, @ObjectFlags, @OwnerMask, @NextOwnerMask, @GroupMask,
|
||||
@EveryoneMask, @BaseMask, @PositionX, @PositionY, @PositionZ, @GroupPositionX, @GroupPositionY, @GroupPositionZ, @VelocityX,
|
||||
@@ -376,7 +378,8 @@ ELSE
|
||||
@PayPrice, @PayButton1, @PayButton2, @PayButton3, @PayButton4, @LoopedSound, @LoopedSoundGain, @TextureAnimation, @OmegaX,
|
||||
@OmegaY, @OmegaZ, @CameraEyeOffsetX, @CameraEyeOffsetY, @CameraEyeOffsetZ, @CameraAtOffsetX, @CameraAtOffsetY, @CameraAtOffsetZ,
|
||||
@ForceMouselook, @ScriptAccessPin, @AllowedDrop, @DieAtEdge, @SalePrice, @SaleType, @ColorR, @ColorG, @ColorB, @ColorA,
|
||||
@ParticleSystem, @ClickAction, @Material, @CollisionSound, @CollisionSoundVolume, @PassTouches, @LinkNumber, @MediaURL, @DynAttrs
|
||||
@ParticleSystem, @ClickAction, @Material, @CollisionSound, @CollisionSoundVolume, @PassTouches, @LinkNumber, @MediaURL, @DynAttrs,
|
||||
@PhysicsShapeType, @Density, @GravityModifier, @Friction, @Restitution
|
||||
)
|
||||
END";
|
||||
|
||||
@@ -1697,6 +1700,12 @@ VALUES
|
||||
else
|
||||
prim.DynAttrs = new DAMap();
|
||||
|
||||
prim.PhysicsShapeType = Convert.ToByte(primRow["PhysicsShapeType"]);
|
||||
prim.Density = Convert.ToSingle(primRow["Density"]);
|
||||
prim.GravityModifier = Convert.ToSingle(primRow["GravityModifier"]);
|
||||
prim.Friction = Convert.ToSingle(primRow["Friction"]);
|
||||
prim.Restitution = Convert.ToSingle(primRow["Restitution"]);
|
||||
|
||||
return prim;
|
||||
}
|
||||
|
||||
@@ -2095,6 +2104,12 @@ VALUES
|
||||
parameters.Add(_Database.CreateParameter("DynAttrs", prim.DynAttrs.ToXml()));
|
||||
else
|
||||
parameters.Add(_Database.CreateParameter("DynAttrs", null));
|
||||
|
||||
parameters.Add(_Database.CreateParameter("PhysicsShapeType", prim.PhysicsShapeType));
|
||||
parameters.Add(_Database.CreateParameter("Density", (double)prim.Density));
|
||||
parameters.Add(_Database.CreateParameter("GravityModifier", (double)prim.GravityModifier));
|
||||
parameters.Add(_Database.CreateParameter("Friction", (double)prim.Friction));
|
||||
parameters.Add(_Database.CreateParameter("Restitution", (double)prim.Restitution));
|
||||
|
||||
return parameters.ToArray();
|
||||
}
|
||||
|
||||
@@ -1156,3 +1156,15 @@ BEGIN TRANSACTION
|
||||
ALTER TABLE prims ADD COLUMN DynAttrs TEXT;
|
||||
|
||||
COMMIT
|
||||
|
||||
:VERSION 39 #---------------- Extra physics params
|
||||
|
||||
BEGIN TRANSACTION
|
||||
|
||||
ALTER TABLE prims ADD COLUMN `PhysicsShapeType` tinyint(4) NOT NULL default '0';
|
||||
ALTER TABLE prims ADD COLUMN `Density` double NOT NULL default '1000';
|
||||
ALTER TABLE prims ADD COLUMN `GravityModifier` double NOT NULL default '1';
|
||||
ALTER TABLE prims ADD COLUMN `Friction` double NOT NULL default '0.6';
|
||||
ALTER TABLE prims ADD COLUMN `Restitution` double NOT NULL default '0.5';
|
||||
|
||||
COMMIT
|
||||
|
||||
@@ -173,9 +173,9 @@ namespace OpenSim.Data.MySQL
|
||||
"ParticleSystem, ClickAction, Material, " +
|
||||
"CollisionSound, CollisionSoundVolume, " +
|
||||
"PassTouches, " +
|
||||
"LinkNumber, MediaURL, " +
|
||||
"LinkNumber, MediaURL, DynAttrs, " +
|
||||
"PhysicsShapeType, Density, GravityModifier, " +
|
||||
"Friction, Restitution, DynAttrs " +
|
||||
"Friction, Restitution " +
|
||||
") values (" + "?UUID, " +
|
||||
"?CreationDate, ?Name, ?Text, " +
|
||||
"?Description, ?SitName, ?TouchName, " +
|
||||
@@ -208,9 +208,9 @@ namespace OpenSim.Data.MySQL
|
||||
"?ColorB, ?ColorA, ?ParticleSystem, " +
|
||||
"?ClickAction, ?Material, ?CollisionSound, " +
|
||||
"?CollisionSoundVolume, ?PassTouches, " +
|
||||
"?LinkNumber, ?MediaURL, " +
|
||||
"?LinkNumber, ?MediaURL, ?DynAttrs, " +
|
||||
"?PhysicsShapeType, ?Density, ?GravityModifier, " +
|
||||
"?Friction, ?Restitution, ?DynAttrs)";
|
||||
"?Friction, ?Restitution)";
|
||||
|
||||
FillPrimCommand(cmd, prim, obj.UUID, regionUUID);
|
||||
|
||||
@@ -1659,16 +1659,17 @@ namespace OpenSim.Data.MySQL
|
||||
cmd.Parameters.AddWithValue("LinkNumber", prim.LinkNum);
|
||||
cmd.Parameters.AddWithValue("MediaURL", prim.MediaUrl);
|
||||
|
||||
cmd.Parameters.AddWithValue("PhysicsShapeType", prim.PhysicsShapeType);
|
||||
cmd.Parameters.AddWithValue("Density", (double)prim.Density);
|
||||
cmd.Parameters.AddWithValue("GravityModifier", (double)prim.GravityModifier);
|
||||
cmd.Parameters.AddWithValue("Friction", (double)prim.Friction);
|
||||
cmd.Parameters.AddWithValue("Restitution", (double)prim.Restitution);
|
||||
|
||||
if (prim.DynAttrs.Count > 0)
|
||||
cmd.Parameters.AddWithValue("DynAttrs", prim.DynAttrs.ToXml());
|
||||
else
|
||||
cmd.Parameters.AddWithValue("DynAttrs", null);
|
||||
|
||||
cmd.Parameters.AddWithValue("PhysicsShapeType", prim.PhysicsShapeType);
|
||||
cmd.Parameters.AddWithValue("Density", (double)prim.Density);
|
||||
cmd.Parameters.AddWithValue("GravityModifier", (double)prim.GravityModifier);
|
||||
cmd.Parameters.AddWithValue("Friction", (double)prim.Friction);
|
||||
cmd.Parameters.AddWithValue("Restitution", (double)prim.Restitution);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -911,7 +911,7 @@ ALTER TABLE prims ADD COLUMN DynAttrs TEXT;
|
||||
|
||||
COMMIT;
|
||||
|
||||
:VERSION 47 #---------------- Extra prim params
|
||||
:VERSION 47 #---------------- Extra physics params
|
||||
|
||||
BEGIN;
|
||||
|
||||
|
||||
@@ -580,3 +580,15 @@ COMMIT;
|
||||
BEGIN;
|
||||
ALTER TABLE prims ADD COLUMN DynAttrs TEXT;
|
||||
COMMIT;
|
||||
|
||||
:VERSION 28
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE prims ADD COLUMN `PhysicsShapeType` tinyint(4) NOT NULL default '0';
|
||||
ALTER TABLE prims ADD COLUMN `Density` double NOT NULL default '1000';
|
||||
ALTER TABLE prims ADD COLUMN `GravityModifier` double NOT NULL default '1';
|
||||
ALTER TABLE prims ADD COLUMN `Friction` double NOT NULL default '0.6';
|
||||
ALTER TABLE prims ADD COLUMN `Restitution` double NOT NULL default '0.5';
|
||||
|
||||
COMMIT;
|
||||
|
||||
@@ -1235,6 +1235,12 @@ namespace OpenSim.Data.SQLite
|
||||
|
||||
createCol(prims, "DynAttrs", typeof(String));
|
||||
|
||||
createCol(prims, "PhysicsShapeType", typeof(Byte));
|
||||
createCol(prims, "Density", typeof(Double));
|
||||
createCol(prims, "GravityModifier", typeof(Double));
|
||||
createCol(prims, "Friction", typeof(Double));
|
||||
createCol(prims, "Restitution", typeof(Double));
|
||||
|
||||
// Add in contraints
|
||||
prims.PrimaryKey = new DataColumn[] { prims.Columns["UUID"] };
|
||||
|
||||
@@ -1724,6 +1730,12 @@ namespace OpenSim.Data.SQLite
|
||||
prim.DynAttrs = new DAMap();
|
||||
}
|
||||
|
||||
prim.PhysicsShapeType = Convert.ToByte(row["PhysicsShapeType"]);
|
||||
prim.Density = Convert.ToSingle(row["Density"]);
|
||||
prim.GravityModifier = Convert.ToSingle(row["GravityModifier"]);
|
||||
prim.Friction = Convert.ToSingle(row["Friction"]);
|
||||
prim.Restitution = Convert.ToSingle(row["Restitution"]);
|
||||
|
||||
return prim;
|
||||
}
|
||||
|
||||
@@ -2150,6 +2162,12 @@ namespace OpenSim.Data.SQLite
|
||||
row["DynAttrs"] = prim.DynAttrs.ToXml();
|
||||
else
|
||||
row["DynAttrs"] = null;
|
||||
|
||||
row["PhysicsShapeType"] = prim.PhysicsShapeType;
|
||||
row["Density"] = (double)prim.Density;
|
||||
row["GravityModifier"] = (double)prim.GravityModifier;
|
||||
row["Friction"] = (double)prim.Friction;
|
||||
row["Restitution"] = (double)prim.Restitution;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -359,11 +359,11 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||
inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime,
|
||||
netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime));
|
||||
|
||||
Dictionary<string, Dictionary<string, Stat>> sceneStats;
|
||||
SortedDictionary<string, SortedDictionary<string, Stat>> sceneStats;
|
||||
|
||||
if (StatsManager.TryGetStats("scene", out sceneStats))
|
||||
{
|
||||
foreach (KeyValuePair<string, Dictionary<string, Stat>> kvp in sceneStats)
|
||||
foreach (KeyValuePair<string, SortedDictionary<string, Stat>> kvp in sceneStats)
|
||||
{
|
||||
foreach (Stat stat in kvp.Value.Values)
|
||||
{
|
||||
|
||||
@@ -51,8 +51,8 @@ namespace OpenSim.Framework.Monitoring
|
||||
/// <remarks>
|
||||
/// Do not add or remove directly from this dictionary.
|
||||
/// </remarks>
|
||||
public static Dictionary<string, Dictionary<string, Dictionary<string, Stat>>> RegisteredStats
|
||||
= new Dictionary<string, Dictionary<string, Dictionary<string, Stat>>>();
|
||||
public static SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>> RegisteredStats
|
||||
= new SortedDictionary<string, SortedDictionary<string, SortedDictionary<string, Stat>>>();
|
||||
|
||||
private static AssetStatsCollector assetStats;
|
||||
private static UserStatsCollector userStats;
|
||||
@@ -101,7 +101,7 @@ namespace OpenSim.Framework.Monitoring
|
||||
}
|
||||
else
|
||||
{
|
||||
Dictionary<string, Dictionary<string, Stat>> category;
|
||||
SortedDictionary<string, SortedDictionary<string, Stat>> category;
|
||||
if (!RegisteredStats.TryGetValue(categoryName, out category))
|
||||
{
|
||||
con.OutputFormat("No such category as {0}", categoryName);
|
||||
@@ -120,7 +120,7 @@ namespace OpenSim.Framework.Monitoring
|
||||
}
|
||||
|
||||
private static void OutputCategoryStatsToConsole(
|
||||
ICommandConsole con, Dictionary<string, Dictionary<string, Stat>> category)
|
||||
ICommandConsole con, SortedDictionary<string, SortedDictionary<string, Stat>> category)
|
||||
{
|
||||
foreach (var container in category.Values)
|
||||
{
|
||||
@@ -160,8 +160,8 @@ namespace OpenSim.Framework.Monitoring
|
||||
/// <returns></returns>
|
||||
public static bool RegisterStat(Stat stat)
|
||||
{
|
||||
Dictionary<string, Dictionary<string, Stat>> category = null, newCategory;
|
||||
Dictionary<string, Stat> container = null, newContainer;
|
||||
SortedDictionary<string, SortedDictionary<string, Stat>> category = null, newCategory;
|
||||
SortedDictionary<string, Stat> container = null, newContainer;
|
||||
|
||||
lock (RegisteredStats)
|
||||
{
|
||||
@@ -175,14 +175,14 @@ namespace OpenSim.Framework.Monitoring
|
||||
// This means that we don't need to lock or copy them on iteration, which will be a much more
|
||||
// common operation after startup.
|
||||
if (container != null)
|
||||
newContainer = new Dictionary<string, Stat>(container);
|
||||
newContainer = new SortedDictionary<string, Stat>(container);
|
||||
else
|
||||
newContainer = new Dictionary<string, Stat>();
|
||||
newContainer = new SortedDictionary<string, Stat>();
|
||||
|
||||
if (category != null)
|
||||
newCategory = new Dictionary<string, Dictionary<string, Stat>>(category);
|
||||
newCategory = new SortedDictionary<string, SortedDictionary<string, Stat>>(category);
|
||||
else
|
||||
newCategory = new Dictionary<string, Dictionary<string, Stat>>();
|
||||
newCategory = new SortedDictionary<string, SortedDictionary<string, Stat>>();
|
||||
|
||||
newContainer[stat.ShortName] = stat;
|
||||
newCategory[stat.Container] = newContainer;
|
||||
@@ -196,21 +196,21 @@ namespace OpenSim.Framework.Monitoring
|
||||
/// Deregister a statistic
|
||||
/// </summary>>
|
||||
/// <param name='stat'></param>
|
||||
/// <returns></returns
|
||||
/// <returns></returns>
|
||||
public static bool DeregisterStat(Stat stat)
|
||||
{
|
||||
Dictionary<string, Dictionary<string, Stat>> category = null, newCategory;
|
||||
Dictionary<string, Stat> container = null, newContainer;
|
||||
SortedDictionary<string, SortedDictionary<string, Stat>> category = null, newCategory;
|
||||
SortedDictionary<string, Stat> container = null, newContainer;
|
||||
|
||||
lock (RegisteredStats)
|
||||
{
|
||||
if (!TryGetStat(stat, out category, out container))
|
||||
return false;
|
||||
|
||||
newContainer = new Dictionary<string, Stat>(container);
|
||||
newContainer = new SortedDictionary<string, Stat>(container);
|
||||
newContainer.Remove(stat.ShortName);
|
||||
|
||||
newCategory = new Dictionary<string, Dictionary<string, Stat>>(category);
|
||||
newCategory = new SortedDictionary<string, SortedDictionary<string, Stat>>(category);
|
||||
newCategory.Remove(stat.Container);
|
||||
|
||||
newCategory[stat.Container] = newContainer;
|
||||
@@ -220,15 +220,15 @@ namespace OpenSim.Framework.Monitoring
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryGetStats(string category, out Dictionary<string, Dictionary<string, Stat>> stats)
|
||||
public static bool TryGetStats(string category, out SortedDictionary<string, SortedDictionary<string, Stat>> stats)
|
||||
{
|
||||
return RegisteredStats.TryGetValue(category, out stats);
|
||||
}
|
||||
|
||||
public static bool TryGetStat(
|
||||
Stat stat,
|
||||
out Dictionary<string, Dictionary<string, Stat>> category,
|
||||
out Dictionary<string, Stat> container)
|
||||
out SortedDictionary<string, SortedDictionary<string, Stat>> category,
|
||||
out SortedDictionary<string, Stat> container)
|
||||
{
|
||||
category = null;
|
||||
container = null;
|
||||
@@ -252,9 +252,9 @@ namespace OpenSim.Framework.Monitoring
|
||||
{
|
||||
lock (RegisteredStats)
|
||||
{
|
||||
foreach (Dictionary<string, Dictionary<string, Stat>> category in RegisteredStats.Values)
|
||||
foreach (SortedDictionary<string, SortedDictionary<string, Stat>> category in RegisteredStats.Values)
|
||||
{
|
||||
foreach (Dictionary<string, Stat> container in category.Values)
|
||||
foreach (SortedDictionary<string, Stat> container in category.Values)
|
||||
{
|
||||
foreach (Stat stat in container.Values)
|
||||
{
|
||||
|
||||
@@ -622,6 +622,8 @@ namespace OpenSim.Framework
|
||||
}
|
||||
}
|
||||
|
||||
// This is only used at runtime. For sculpties this holds the texture data, and for meshes
|
||||
// the mesh data.
|
||||
public byte[] SculptData
|
||||
{
|
||||
get
|
||||
@@ -1147,14 +1149,13 @@ namespace OpenSim.Framework
|
||||
|
||||
public void ReadSculptData(byte[] data, int pos)
|
||||
{
|
||||
byte[] SculptTextureUUID = new byte[16];
|
||||
UUID SculptUUID = UUID.Zero;
|
||||
byte SculptTypel = data[16+pos];
|
||||
UUID SculptUUID;
|
||||
byte SculptTypel;
|
||||
|
||||
if (data.Length+pos >= 17)
|
||||
if (data.Length-pos >= 17)
|
||||
{
|
||||
_sculptEntry = true;
|
||||
SculptTextureUUID = new byte[16];
|
||||
byte[] SculptTextureUUID = new byte[16];
|
||||
SculptTypel = data[16 + pos];
|
||||
Array.Copy(data, pos, SculptTextureUUID,0, 16);
|
||||
SculptUUID = new UUID(SculptTextureUUID, 0);
|
||||
|
||||
@@ -535,6 +535,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||
/// <param name="message"></param>
|
||||
public void Close(string message)
|
||||
{
|
||||
if (_networkContext == null)
|
||||
return;
|
||||
if (_networkContext.Stream != null)
|
||||
{
|
||||
if (_networkContext.Stream.CanWrite)
|
||||
|
||||
@@ -102,17 +102,50 @@ namespace OpenSim
|
||||
m_log.InfoFormat(
|
||||
"[OPENSIM MAIN]: Environment variable MONO_THREADS_PER_CPU is {0}", monoThreadsPerCpu ?? "unset");
|
||||
|
||||
// Increase the number of IOCP threads available. Mono defaults to a tragically low number
|
||||
// Verify the Threadpool allocates or uses enough worker and IO completion threads
|
||||
// .NET 2.0 workerthreads default to 50 * numcores
|
||||
// .NET 3.0 workerthreads defaults to 250 * numcores
|
||||
// .NET 4.0 workerthreads are dynamic based on bitness and OS resources
|
||||
// Max IO Completion threads are 1000 on all 3 CLRs.
|
||||
int workerThreadsMin = 500;
|
||||
int workerThreadsMax = 1000; // may need further adjustment to match other CLR
|
||||
int iocpThreadsMin = 1000;
|
||||
int iocpThreadsMax = 2000; // may need further adjustment to match other CLR
|
||||
int workerThreads, iocpThreads;
|
||||
System.Threading.ThreadPool.GetMaxThreads(out workerThreads, out iocpThreads);
|
||||
m_log.InfoFormat("[OPENSIM MAIN]: Runtime gave us {0} worker threads and {1} IOCP threads", workerThreads, iocpThreads);
|
||||
if (workerThreads < 500 || iocpThreads < 1000)
|
||||
if (workerThreads < workerThreadsMin)
|
||||
{
|
||||
workerThreads = 500;
|
||||
iocpThreads = 1000;
|
||||
m_log.Info("[OPENSIM MAIN]: Bumping up to 500 worker threads and 1000 IOCP threads");
|
||||
System.Threading.ThreadPool.SetMaxThreads(workerThreads, iocpThreads);
|
||||
workerThreads = workerThreadsMin;
|
||||
m_log.InfoFormat("[OPENSIM MAIN]: Bumping up to worker threads to {0}",workerThreads);
|
||||
}
|
||||
if (workerThreads > workerThreadsMax)
|
||||
{
|
||||
workerThreads = workerThreadsMax;
|
||||
m_log.InfoFormat("[OPENSIM MAIN]: Limiting worker threads to {0}",workerThreads);
|
||||
}
|
||||
// Increase the number of IOCP threads available.
|
||||
// Mono defaults to a tragically low number (24 on 6-core / 8GB Fedora 17)
|
||||
if (iocpThreads < iocpThreadsMin)
|
||||
{
|
||||
iocpThreads = iocpThreadsMin;
|
||||
m_log.InfoFormat("[OPENSIM MAIN]: Bumping up IO completion threads to {0}",iocpThreads);
|
||||
}
|
||||
// Make sure we don't overallocate IOCP threads and thrash system resources
|
||||
if ( iocpThreads > iocpThreadsMax )
|
||||
{
|
||||
iocpThreads = iocpThreadsMax;
|
||||
m_log.InfoFormat("[OPENSIM MAIN]: Limiting IO completion threads to {0}",iocpThreads);
|
||||
}
|
||||
// set the resulting worker and IO completion thread counts back to ThreadPool
|
||||
if ( System.Threading.ThreadPool.SetMaxThreads(workerThreads, iocpThreads) )
|
||||
{
|
||||
m_log.InfoFormat("[OPENSIM MAIN]: Threadpool set to {0} worker threads and {1} IO completion threads", workerThreads, iocpThreads);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_log.Info("[OPENSIM MAIN]: Threadpool reconfiguration failed, runtime defaults still in effect.");
|
||||
}
|
||||
|
||||
// Check if the system is compatible with OpenSimulator.
|
||||
// Ensures that the minimum system requirements are met
|
||||
|
||||
@@ -59,6 +59,8 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||
// private static readonly ILog m_log =
|
||||
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
public event SimulatorFeaturesRequestDelegate OnSimulatorFeaturesRequest;
|
||||
|
||||
private Scene m_scene;
|
||||
|
||||
/// <summary>
|
||||
@@ -94,6 +96,8 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||
{
|
||||
m_scene = s;
|
||||
m_scene.EventManager.OnRegisterCaps += RegisterCaps;
|
||||
|
||||
m_scene.RegisterModuleInterface<ISimulatorFeaturesModule>(this);
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene s)
|
||||
@@ -156,7 +160,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||
IRequestHandler reqHandler
|
||||
= new RestHTTPHandler(
|
||||
"GET", "/CAPS/" + UUID.Random(),
|
||||
HandleSimulatorFeaturesRequest, "SimulatorFeatures", agentID.ToString());
|
||||
x => { return HandleSimulatorFeaturesRequest(x, agentID); }, "SimulatorFeatures", agentID.ToString());
|
||||
|
||||
caps.RegisterHandler("SimulatorFeatures", reqHandler);
|
||||
}
|
||||
@@ -185,18 +189,33 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||
return new OSDMap(m_features);
|
||||
}
|
||||
|
||||
private Hashtable HandleSimulatorFeaturesRequest(Hashtable mDhttpMethod)
|
||||
private OSDMap DeepCopy()
|
||||
{
|
||||
// This isn't the cheapest way of doing this but the rate
|
||||
// of occurrence is low (on sim entry only) and it's a sure
|
||||
// way to get a true deep copy.
|
||||
OSD copy = OSDParser.DeserializeLLSDXml(OSDParser.SerializeLLSDXmlString(m_features));
|
||||
|
||||
return (OSDMap)copy;
|
||||
}
|
||||
|
||||
private Hashtable HandleSimulatorFeaturesRequest(Hashtable mDhttpMethod, UUID agentID)
|
||||
{
|
||||
// m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request");
|
||||
|
||||
OSDMap copy = DeepCopy();
|
||||
|
||||
SimulatorFeaturesRequestDelegate handlerOnSimulatorFeaturesRequest = OnSimulatorFeaturesRequest;
|
||||
if (handlerOnSimulatorFeaturesRequest != null)
|
||||
handlerOnSimulatorFeaturesRequest(agentID, ref copy);
|
||||
|
||||
//Send back data
|
||||
Hashtable responsedata = new Hashtable();
|
||||
responsedata["int_response_code"] = 200;
|
||||
responsedata["content_type"] = "text/plain";
|
||||
responsedata["keepalive"] = false;
|
||||
|
||||
lock (m_features)
|
||||
responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(m_features);
|
||||
responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(copy);
|
||||
|
||||
return responsedata;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
||||
public class AssetTransactionModule : INonSharedRegionModule,
|
||||
IAgentAssetTransactions
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
protected Scene m_Scene;
|
||||
private bool m_dumpAssetsToFile = false;
|
||||
|
||||
@@ -299,7 +299,7 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
m_log.WarnFormat(
|
||||
"[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}",
|
||||
asset.ID, e.Message, e.StackTrace);
|
||||
}
|
||||
@@ -339,12 +339,13 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||
/// Try to get an asset from the file cache.
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <returns></returns>
|
||||
/// <returns>An asset retrieved from the file cache. null if there was a problem retrieving an asset.</returns>
|
||||
private AssetBase GetFromFileCache(string id)
|
||||
{
|
||||
AssetBase asset = null;
|
||||
|
||||
|
||||
string filename = GetFileName(id);
|
||||
|
||||
if (File.Exists(filename))
|
||||
{
|
||||
FileStream stream = null;
|
||||
@@ -359,7 +360,7 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||
}
|
||||
catch (System.Runtime.Serialization.SerializationException e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
m_log.WarnFormat(
|
||||
"[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
|
||||
filename, id, e.Message, e.StackTrace);
|
||||
|
||||
@@ -371,7 +372,7 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
m_log.WarnFormat(
|
||||
"[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
|
||||
filename, id, e.Message, e.StackTrace);
|
||||
}
|
||||
@@ -469,7 +470,7 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
m_log.WarnFormat(
|
||||
"[FLOTSAM ASSET CACHE]: Failed to expire cached file {0}. Exception {1} {2}",
|
||||
id, e.Message, e.StackTrace);
|
||||
}
|
||||
@@ -520,29 +521,39 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||
/// <param name="purgeLine"></param>
|
||||
private void CleanExpiredFiles(string dir, DateTime purgeLine)
|
||||
{
|
||||
foreach (string file in Directory.GetFiles(dir))
|
||||
try
|
||||
{
|
||||
if (File.GetLastAccessTime(file) < purgeLine)
|
||||
foreach (string file in Directory.GetFiles(dir))
|
||||
{
|
||||
File.Delete(file);
|
||||
if (File.GetLastAccessTime(file) < purgeLine)
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
}
|
||||
|
||||
// Recurse into lower tiers
|
||||
foreach (string subdir in Directory.GetDirectories(dir))
|
||||
{
|
||||
CleanExpiredFiles(subdir, purgeLine);
|
||||
}
|
||||
|
||||
// Check if a tier directory is empty, if so, delete it
|
||||
int dirSize = Directory.GetFiles(dir).Length + Directory.GetDirectories(dir).Length;
|
||||
if (dirSize == 0)
|
||||
{
|
||||
Directory.Delete(dir);
|
||||
}
|
||||
else if (dirSize >= m_CacheWarnAt)
|
||||
{
|
||||
m_log.WarnFormat(
|
||||
"[FLOTSAM ASSET CACHE]: Cache folder exceeded CacheWarnAt limit {0} {1}. Suggest increasing tiers, tier length, or reducing cache expiration",
|
||||
dir, dirSize);
|
||||
}
|
||||
}
|
||||
|
||||
// Recurse into lower tiers
|
||||
foreach (string subdir in Directory.GetDirectories(dir))
|
||||
catch (Exception e)
|
||||
{
|
||||
CleanExpiredFiles(subdir, purgeLine);
|
||||
}
|
||||
|
||||
// Check if a tier directory is empty, if so, delete it
|
||||
int dirSize = Directory.GetFiles(dir).Length + Directory.GetDirectories(dir).Length;
|
||||
if (dirSize == 0)
|
||||
{
|
||||
Directory.Delete(dir);
|
||||
}
|
||||
else if (dirSize >= m_CacheWarnAt)
|
||||
{
|
||||
m_log.WarnFormat("[FLOTSAM ASSET CACHE]: Cache folder exceeded CacheWarnAt limit {0} {1}. Suggest increasing tiers, tier length, or reducing cache expiration", dir, dirSize);
|
||||
m_log.Warn(
|
||||
string.Format("[FLOTSAM ASSET CACHE]: Could not complete clean of expired files in {0}, exception ", dir), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,7 +612,7 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
m_log.WarnFormat(
|
||||
"[FLOTSAM ASSET CACHE]: Failed to write asset {0} to temporary location {1} (final {2}) on cache in {3}. Exception {4} {5}.",
|
||||
asset.ID, tempname, filename, directory, e.Message, e.StackTrace);
|
||||
|
||||
@@ -680,17 +691,31 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||
/// <summary>
|
||||
/// This notes the last time the Region had a deep asset scan performed on it.
|
||||
/// </summary>
|
||||
/// <param name="RegionID"></param>
|
||||
private void StampRegionStatusFile(UUID RegionID)
|
||||
/// <param name="regionID"></param>
|
||||
private void StampRegionStatusFile(UUID regionID)
|
||||
{
|
||||
string RegionCacheStatusFile = Path.Combine(m_CacheDirectory, "RegionStatus_" + RegionID.ToString() + ".fac");
|
||||
if (File.Exists(RegionCacheStatusFile))
|
||||
string RegionCacheStatusFile = Path.Combine(m_CacheDirectory, "RegionStatus_" + regionID.ToString() + ".fac");
|
||||
|
||||
try
|
||||
{
|
||||
File.SetLastWriteTime(RegionCacheStatusFile, DateTime.Now);
|
||||
if (File.Exists(RegionCacheStatusFile))
|
||||
{
|
||||
File.SetLastWriteTime(RegionCacheStatusFile, DateTime.Now);
|
||||
}
|
||||
else
|
||||
{
|
||||
File.WriteAllText(
|
||||
RegionCacheStatusFile,
|
||||
"Please do not delete this file unless you are manually clearing your Flotsam Asset Cache.");
|
||||
}
|
||||
}
|
||||
else
|
||||
catch (Exception e)
|
||||
{
|
||||
File.WriteAllText(RegionCacheStatusFile, "Please do not delete this file unless you are manually clearing your Flotsam Asset Cache.");
|
||||
m_log.Warn(
|
||||
string.Format(
|
||||
"[FLOTSAM ASSET CACHE]: Could not stamp region status file for region {0}. Exception ",
|
||||
regionID),
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -759,7 +784,7 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
m_log.WarnFormat(
|
||||
"[FLOTSAM ASSET CACHE]: Couldn't clear asset cache directory {0} from {1}. Exception {2} {3}",
|
||||
dir, m_CacheDirectory, e.Message, e.StackTrace);
|
||||
}
|
||||
@@ -773,7 +798,7 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
m_log.WarnFormat(
|
||||
"[FLOTSAM ASSET CACHE]: Couldn't clear asset cache file {0} from {1}. Exception {1} {2}",
|
||||
file, m_CacheDirectory, e.Message, e.StackTrace);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DAExampleModule
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")]
|
||||
public class DAExampleModule : INonSharedRegionModule
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private static readonly bool ENABLED = false; // enable for testing
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
|
||||
try
|
||||
{
|
||||
IConfig statConfig = source.Configs["Statistics.Binary"];
|
||||
if (statConfig.Contains("enabled") && statConfig.GetBoolean("enabled"))
|
||||
if (statConfig != null && statConfig.Contains("enabled") && statConfig.GetBoolean("enabled"))
|
||||
{
|
||||
if (statConfig.Contains("collect_region_stats"))
|
||||
{
|
||||
|
||||
@@ -111,13 +111,15 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
|
||||
m_rpcPending = new Dictionary<UUID, RPCRequestInfo>();
|
||||
m_rpcPendingResponses = new Dictionary<UUID, RPCRequestInfo>();
|
||||
m_pendingSRDResponses = new Dictionary<UUID, SendRemoteDataRequest>();
|
||||
|
||||
try
|
||||
{
|
||||
m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort);
|
||||
}
|
||||
catch (Exception)
|
||||
if (config.Configs["XMLRPC"] != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,16 @@ using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Framework.Interfaces
|
||||
{
|
||||
// these could be expanded at some point to provide more type information
|
||||
// for now value accounts for all base types
|
||||
public enum JsonStoreNodeType
|
||||
{
|
||||
Undefined = 0,
|
||||
Object = 1,
|
||||
Array = 2,
|
||||
Value = 3
|
||||
}
|
||||
|
||||
public delegate void TakeValueCallback(string s);
|
||||
|
||||
public interface IJsonStoreModule
|
||||
@@ -38,13 +48,18 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||
bool AttachObjectStore(UUID objectID);
|
||||
bool CreateStore(string value, ref UUID result);
|
||||
bool DestroyStore(UUID storeID);
|
||||
|
||||
JsonStoreNodeType GetPathType(UUID storeID, string path);
|
||||
bool TestStore(UUID storeID);
|
||||
bool TestPath(UUID storeID, string path, bool useJson);
|
||||
|
||||
bool SetValue(UUID storeID, string path, string value, bool useJson);
|
||||
bool RemoveValue(UUID storeID, string path);
|
||||
bool GetValue(UUID storeID, string path, bool useJson, out string value);
|
||||
|
||||
void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback);
|
||||
void ReadValue(UUID storeID, string path, bool useJson, TakeValueCallback cback);
|
||||
|
||||
int GetArrayLength(UUID storeID, string path);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,18 +26,22 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenSim.Region.Framework.Interfaces
|
||||
{
|
||||
public delegate void SimulatorFeaturesRequestDelegate(UUID agentID, ref OSDMap features);
|
||||
|
||||
/// <summary>
|
||||
/// Add remove or retrieve Simulator Features that will be given to a viewer via the SimulatorFeatures capability.
|
||||
/// </summary>
|
||||
public interface ISimulatorFeaturesModule
|
||||
{
|
||||
event SimulatorFeaturesRequestDelegate OnSimulatorFeaturesRequest;
|
||||
void AddFeature(string name, OSD value);
|
||||
bool RemoveFeature(string name);
|
||||
bool TryGetFeature(string name, out OSD value);
|
||||
OSDMap GetFeatures();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -790,6 +790,19 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// <param name="obj">The object being removed from the scene</param>
|
||||
public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object is placed into the physical scene (PhysicsActor created).
|
||||
/// </summary>
|
||||
public event Action<SceneObjectPart> OnObjectAddedToPhysicalScene;
|
||||
/// <summary>
|
||||
/// Triggered when an object is removed from the physical scene (PhysicsActor destroyed).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Note: this is triggered just before the PhysicsActor is removed from the
|
||||
/// physics engine so the receiver can do any necessary cleanup before its destruction.
|
||||
/// </remarks>
|
||||
public event Action<SceneObjectPart> OnObjectRemovedFromPhysicalScene;
|
||||
|
||||
/// <summary>
|
||||
/// Triggered when an object is removed from the scene.
|
||||
/// </summary>
|
||||
@@ -1516,6 +1529,48 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
}
|
||||
|
||||
public void TriggerObjectAddedToPhysicalScene(SceneObjectPart obj)
|
||||
{
|
||||
Action<SceneObjectPart> handler = OnObjectAddedToPhysicalScene;
|
||||
if (handler != null)
|
||||
{
|
||||
foreach (Action<SceneObjectPart> d in handler.GetInvocationList())
|
||||
{
|
||||
try
|
||||
{
|
||||
d(obj);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[EVENT MANAGER]: Delegate for TriggerObjectAddedToPhysicalScene failed - continuing. {0} {1}",
|
||||
e.Message, e.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void TriggerObjectRemovedFromPhysicalScene(SceneObjectPart obj)
|
||||
{
|
||||
Action<SceneObjectPart> handler = OnObjectRemovedFromPhysicalScene;
|
||||
if (handler != null)
|
||||
{
|
||||
foreach (Action<SceneObjectPart> d in handler.GetInvocationList())
|
||||
{
|
||||
try
|
||||
{
|
||||
d(obj);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat(
|
||||
"[EVENT MANAGER]: Delegate for TriggerObjectRemovedFromPhysicalScene failed - continuing. {0} {1}",
|
||||
e.Message, e.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void TriggerShutdown()
|
||||
{
|
||||
Action handlerShutdown = OnShutdown;
|
||||
|
||||
@@ -5506,8 +5506,13 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
|
||||
if (banned)
|
||||
{
|
||||
reason = "No suitable landing point found";
|
||||
return false;
|
||||
if(Permissions.IsAdministrator(agentID) == false || Permissions.IsGridGod(agentID) == false)
|
||||
{
|
||||
reason = "No suitable landing point found";
|
||||
return false;
|
||||
}
|
||||
reason = "Administrative access only";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4316,6 +4316,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
}
|
||||
|
||||
PhysActor = pa;
|
||||
ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -4328,6 +4329,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
/// </remarks>
|
||||
public void RemoveFromPhysics()
|
||||
{
|
||||
ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this);
|
||||
ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor);
|
||||
PhysActor = null;
|
||||
}
|
||||
|
||||
@@ -4021,6 +4021,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
(m_teleportFlags & TeleportFlags.ViaLocation) != 0 ||
|
||||
(m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)
|
||||
{
|
||||
|
||||
if (GodLevel < 200 &&
|
||||
((!m_scene.Permissions.IsGod(m_uuid) &&
|
||||
!m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) ||
|
||||
@@ -4029,7 +4030,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
{
|
||||
SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray();
|
||||
if (spawnPoints.Length == 0)
|
||||
{
|
||||
if(m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid))
|
||||
{
|
||||
pos.X = 128.0f;
|
||||
pos.Y = 128.0f;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int index;
|
||||
bool selected = false;
|
||||
@@ -4038,6 +4046,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
{
|
||||
case "random":
|
||||
|
||||
if (spawnPoints.Length == 0)
|
||||
return;
|
||||
do
|
||||
{
|
||||
index = Util.RandomClass.Next(spawnPoints.Length - 1);
|
||||
@@ -4049,6 +4059,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||
// SpawnPoint sp = spawnPoints[index];
|
||||
|
||||
ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y);
|
||||
|
||||
if (land == null || land.IsEitherBannedOrRestricted(UUID))
|
||||
selected = false;
|
||||
else
|
||||
|
||||
171
OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs
Executable file
171
OpenSim/Region/OptionalModules/Scripting/ExtendedPhysics/ExtendedPhysics.cs
Executable file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Framework;
|
||||
using OpenSim.Region.Framework.Interfaces;
|
||||
using OpenSim.Region.Framework.Scenes;
|
||||
using OpenSim.Region.CoreModules;
|
||||
|
||||
using Mono.Addins;
|
||||
using Nini.Config;
|
||||
using log4net;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.OptionalModules.Scripting
|
||||
{
|
||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")]
|
||||
public class ExtendedPhysics : INonSharedRegionModule
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static string LogHeader = "[EXTENDED PHYSICS]";
|
||||
|
||||
private IConfig Configuration { get; set; }
|
||||
private bool Enabled { get; set; }
|
||||
private Scene BaseScene { get; set; }
|
||||
private IScriptModuleComms Comms { get; set; }
|
||||
|
||||
#region INonSharedRegionModule
|
||||
|
||||
public string Name { get { return this.GetType().Name; } }
|
||||
|
||||
public void Initialise(IConfigSource config)
|
||||
{
|
||||
BaseScene = null;
|
||||
Enabled = false;
|
||||
Configuration = null;
|
||||
Comms = null;
|
||||
|
||||
try
|
||||
{
|
||||
if ((Configuration = config.Configs["ExtendedPhysics"]) != null)
|
||||
{
|
||||
Enabled = Configuration.GetBoolean("Enabled", Enabled);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.ErrorFormat("{0} Initialization error: {0}", LogHeader, e);
|
||||
}
|
||||
|
||||
m_log.InfoFormat("{0} module {1} enabled", LogHeader, (Enabled ? "is" : "is not"));
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
if (BaseScene != null)
|
||||
{
|
||||
BaseScene.EventManager.OnObjectAddedToScene -= EventManager_OnObjectAddedToScene;
|
||||
BaseScene.EventManager.OnSceneObjectPartUpdated -= EventManager_OnSceneObjectPartUpdated;
|
||||
BaseScene = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddRegion(Scene scene)
|
||||
{
|
||||
}
|
||||
|
||||
public void RemoveRegion(Scene scene)
|
||||
{
|
||||
if (BaseScene != null && BaseScene == scene)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
public void RegionLoaded(Scene scene)
|
||||
{
|
||||
if (!Enabled) return;
|
||||
|
||||
BaseScene = scene;
|
||||
|
||||
Comms = BaseScene.RequestModuleInterface<IScriptModuleComms>();
|
||||
if (Comms == null)
|
||||
{
|
||||
m_log.WarnFormat("{0} ScriptModuleComms interface not defined", LogHeader);
|
||||
Enabled = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Register as LSL functions all the [ScriptInvocation] marked methods.
|
||||
Comms.RegisterScriptInvocations(this);
|
||||
|
||||
// When an object is modified, we might need to update its extended physics parameters
|
||||
BaseScene.EventManager.OnObjectAddedToScene += EventManager_OnObjectAddedToScene;
|
||||
BaseScene.EventManager.OnSceneObjectPartUpdated += EventManager_OnSceneObjectPartUpdated;
|
||||
|
||||
}
|
||||
|
||||
public Type ReplaceableInterface { get { return null; } }
|
||||
|
||||
#endregion // INonSharedRegionModule
|
||||
|
||||
private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
// Event generated when some property of a prim changes.
|
||||
private void EventManager_OnSceneObjectPartUpdated(SceneObjectPart sop, bool isFullUpdate)
|
||||
{
|
||||
}
|
||||
|
||||
[ScriptConstant]
|
||||
public static int PHYS_CENTER_OF_MASS = 1 << 0;
|
||||
|
||||
[ScriptConstant]
|
||||
public static int PHYS_LINKSET_TYPE_CONSTRAINT = 1;
|
||||
[ScriptConstant]
|
||||
public static int PHYS_LINKSET_TYPE_COMPOUND = 2;
|
||||
[ScriptConstant]
|
||||
public static int PHYS_LINKSET_TYPE_MANUAL = 3;
|
||||
|
||||
[ScriptInvocation]
|
||||
public string physGetEngineType(UUID hostID, UUID scriptID)
|
||||
{
|
||||
string ret = string.Empty;
|
||||
|
||||
if (BaseScene.PhysicsScene != null)
|
||||
{
|
||||
ret = BaseScene.PhysicsScene.EngineType;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
[ScriptInvocation]
|
||||
public void physSetLinksetType(UUID hostID, UUID scriptID, int linksetType)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,23 +68,20 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
protected List<TakeValueCallbackClass> m_TakeStore;
|
||||
protected List<TakeValueCallbackClass> m_ReadStore;
|
||||
|
||||
// add separators for quoted paths
|
||||
protected static Regex m_ParsePassOne = new Regex("{[^}]+}");
|
||||
|
||||
// add separators for array references
|
||||
protected static Regex m_ParsePassTwo = new Regex("(\\[[0-9]+\\]|\\[\\+\\])");
|
||||
// add separators for quoted paths and array references
|
||||
protected static Regex m_ParsePassOne = new Regex("({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])");
|
||||
|
||||
// add quotes to bare identifiers which are limited to alphabetic characters
|
||||
protected static Regex m_ParsePassThree = new Regex("\\.([a-zA-Z]+)");
|
||||
protected static Regex m_ParsePassThree = new Regex("(?<!{[^}]*)\\.([a-zA-Z]+)(?=\\.)");
|
||||
|
||||
// remove extra separator characters
|
||||
protected static Regex m_ParsePassFour = new Regex("\\.+");
|
||||
|
||||
// expression used to validate the full path, this is canonical representation
|
||||
protected static Regex m_ValidatePath = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)+$");
|
||||
protected static Regex m_ValidatePath = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)*$");
|
||||
|
||||
// expression used to match path components
|
||||
protected static Regex m_PathComponent = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\]+)");
|
||||
protected static Regex m_PathComponent = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])");
|
||||
|
||||
// extract the internals of an array reference
|
||||
protected static Regex m_SimpleArrayPattern = new Regex("\\[([0-9]+)\\]");
|
||||
@@ -107,9 +104,17 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
///
|
||||
/// </summary>
|
||||
// -----------------------------------------------------------------
|
||||
public static string CanonicalPathExpression(string path)
|
||||
public static bool CanonicalPathExpression(string ipath, out string opath)
|
||||
{
|
||||
return PathExpressionToKey(ParsePathExpression(path));
|
||||
Stack<string> path;
|
||||
if (! ParsePathExpression(ipath,out path))
|
||||
{
|
||||
opath = "";
|
||||
return false;
|
||||
}
|
||||
|
||||
opath = PathExpressionToKey(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
@@ -123,15 +128,46 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
m_TakeStore = new List<TakeValueCallbackClass>();
|
||||
m_ReadStore = new List<TakeValueCallbackClass>();
|
||||
}
|
||||
|
||||
|
||||
public JsonStore(string value) : this()
|
||||
{
|
||||
// This is going to throw an exception if the value is not
|
||||
// a valid JSON chunk. Calling routines should catch the
|
||||
// exception and handle it appropriately
|
||||
if (String.IsNullOrEmpty(value))
|
||||
ValueStore = new OSDMap();
|
||||
else
|
||||
ValueStore = OSDParser.DeserializeJson(value);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
// -----------------------------------------------------------------
|
||||
public JsonStoreNodeType PathType(string expr)
|
||||
{
|
||||
Stack<string> path;
|
||||
if (! ParsePathExpression(expr,out path))
|
||||
return JsonStoreNodeType.Undefined;
|
||||
|
||||
OSD result = ProcessPathExpression(ValueStore,path);
|
||||
|
||||
if (result == null)
|
||||
return JsonStoreNodeType.Undefined;
|
||||
|
||||
if (result is OSDMap)
|
||||
return JsonStoreNodeType.Object;
|
||||
|
||||
if (result is OSDArray)
|
||||
return JsonStoreNodeType.Array;
|
||||
|
||||
if (OSDBaseType(result.Type))
|
||||
return JsonStoreNodeType.Value;
|
||||
|
||||
return JsonStoreNodeType.Undefined;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/// <summary>
|
||||
///
|
||||
@@ -139,18 +175,42 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
// -----------------------------------------------------------------
|
||||
public bool TestPath(string expr, bool useJson)
|
||||
{
|
||||
Stack<string> path = ParsePathExpression(expr);
|
||||
Stack<string> path;
|
||||
if (! ParsePathExpression(expr,out path))
|
||||
return false;
|
||||
|
||||
OSD result = ProcessPathExpression(ValueStore,path);
|
||||
|
||||
if (result == null)
|
||||
return false;
|
||||
|
||||
if (useJson || result.Type == OSDType.String)
|
||||
if (useJson || OSDBaseType(result.Type))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
// -----------------------------------------------------------------
|
||||
public int ArrayLength(string expr)
|
||||
{
|
||||
Stack<string> path;
|
||||
if (! ParsePathExpression(expr,out path))
|
||||
return -1;
|
||||
|
||||
OSD result = ProcessPathExpression(ValueStore,path);
|
||||
if (result != null && result.Type == OSDType.Array)
|
||||
{
|
||||
OSDArray arr = result as OSDArray;
|
||||
return arr.Count;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/// <summary>
|
||||
///
|
||||
@@ -158,7 +218,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
// -----------------------------------------------------------------
|
||||
public bool GetValue(string expr, out string value, bool useJson)
|
||||
{
|
||||
Stack<string> path = ParsePathExpression(expr);
|
||||
Stack<string> path;
|
||||
if (! ParsePathExpression(expr,out path))
|
||||
{
|
||||
value = "";
|
||||
return false;
|
||||
}
|
||||
|
||||
OSD result = ProcessPathExpression(ValueStore,path);
|
||||
return ConvertOutputValue(result,out value,useJson);
|
||||
}
|
||||
@@ -181,7 +247,37 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
// -----------------------------------------------------------------
|
||||
public bool SetValue(string expr, string value, bool useJson)
|
||||
{
|
||||
OSD ovalue = useJson ? OSDParser.DeserializeJson(value) : new OSDString(value);
|
||||
OSD ovalue;
|
||||
|
||||
// One note of caution... if you use an empty string in the
|
||||
// structure it will be assumed to be a default value and will
|
||||
// not be seialized in the json
|
||||
|
||||
if (useJson)
|
||||
{
|
||||
// There doesn't appear to be a good way to determine if the
|
||||
// value is valid Json other than to let the parser crash
|
||||
try
|
||||
{
|
||||
ovalue = OSDParser.DeserializeJson(value);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (value.StartsWith("'") && value.EndsWith("'"))
|
||||
{
|
||||
ovalue = new OSDString(value.Substring(1,value.Length - 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ovalue = new OSDString(value);
|
||||
}
|
||||
|
||||
return SetValueFromExpression(expr,ovalue);
|
||||
}
|
||||
|
||||
@@ -192,7 +288,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
// -----------------------------------------------------------------
|
||||
public bool TakeValue(string expr, bool useJson, TakeValueCallback cback)
|
||||
{
|
||||
Stack<string> path = ParsePathExpression(expr);
|
||||
Stack<string> path;
|
||||
if (! ParsePathExpression(expr,out path))
|
||||
return false;
|
||||
|
||||
string pexpr = PathExpressionToKey(path);
|
||||
|
||||
OSD result = ProcessPathExpression(ValueStore,path);
|
||||
@@ -223,7 +322,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
// -----------------------------------------------------------------
|
||||
public bool ReadValue(string expr, bool useJson, TakeValueCallback cback)
|
||||
{
|
||||
Stack<string> path = ParsePathExpression(expr);
|
||||
Stack<string> path;
|
||||
if (! ParsePathExpression(expr,out path))
|
||||
return false;
|
||||
|
||||
string pexpr = PathExpressionToKey(path);
|
||||
|
||||
OSD result = ProcessPathExpression(ValueStore,path);
|
||||
@@ -253,7 +355,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
// -----------------------------------------------------------------
|
||||
protected bool SetValueFromExpression(string expr, OSD ovalue)
|
||||
{
|
||||
Stack<string> path = ParsePathExpression(expr);
|
||||
Stack<string> path;
|
||||
if (! ParsePathExpression(expr,out path))
|
||||
return false;
|
||||
|
||||
if (path.Count == 0)
|
||||
{
|
||||
ValueStore = ovalue;
|
||||
@@ -399,34 +504,33 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
/// use a stack because we process the path in inverse order later
|
||||
/// </summary>
|
||||
// -----------------------------------------------------------------
|
||||
protected static Stack<string> ParsePathExpression(string path)
|
||||
protected static bool ParsePathExpression(string expr, out Stack<string> path)
|
||||
{
|
||||
Stack<string> m_path = new Stack<string>();
|
||||
path = new Stack<string>();
|
||||
|
||||
// add front and rear separators
|
||||
path = "." + path + ".";
|
||||
expr = "." + expr + ".";
|
||||
|
||||
// add separators for quoted paths
|
||||
path = m_ParsePassOne.Replace(path,".$0.",-1,0);
|
||||
|
||||
// add separators for array references
|
||||
path = m_ParsePassTwo.Replace(path,".$0.",-1,0);
|
||||
// add separators for quoted exprs and array references
|
||||
expr = m_ParsePassOne.Replace(expr,".$1.",-1,0);
|
||||
|
||||
// add quotes to bare identifier
|
||||
path = m_ParsePassThree.Replace(path,".{$1}",-1,0);
|
||||
expr = m_ParsePassThree.Replace(expr,".{$1}",-1,0);
|
||||
|
||||
// remove extra separators
|
||||
path = m_ParsePassFour.Replace(path,".",-1,0);
|
||||
expr = m_ParsePassFour.Replace(expr,".",-1,0);
|
||||
|
||||
// validate the results (catches extra quote characters for example)
|
||||
if (m_ValidatePath.IsMatch(path))
|
||||
if (m_ValidatePath.IsMatch(expr))
|
||||
{
|
||||
MatchCollection matches = m_PathComponent.Matches(path,0);
|
||||
MatchCollection matches = m_PathComponent.Matches(expr,0);
|
||||
foreach (Match match in matches)
|
||||
m_path.Push(match.Groups[1].Value);
|
||||
path.Push(match.Groups[1].Value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_path;
|
||||
return false;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
@@ -516,14 +620,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
// The path pointed to an intermediate hash structure
|
||||
if (result.Type == OSDType.Map)
|
||||
{
|
||||
value = OSDParser.SerializeJsonString(result as OSDMap);
|
||||
value = OSDParser.SerializeJsonString(result as OSDMap,true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// The path pointed to an intermediate hash structure
|
||||
if (result.Type == OSDType.Array)
|
||||
{
|
||||
value = OSDParser.SerializeJsonString(result as OSDArray);
|
||||
value = OSDParser.SerializeJsonString(result as OSDArray,true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -531,7 +635,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
return true;
|
||||
}
|
||||
|
||||
if (result.Type == OSDType.String)
|
||||
if (OSDBaseType(result.Type))
|
||||
{
|
||||
value = result.AsString();
|
||||
return true;
|
||||
@@ -557,6 +661,33 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
return pkey;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
// -----------------------------------------------------------------
|
||||
protected static bool OSDBaseType(OSDType type)
|
||||
{
|
||||
// Should be the list of base types for which AsString() returns
|
||||
// something useful
|
||||
if (type == OSDType.Boolean)
|
||||
return true;
|
||||
if (type == OSDType.Integer)
|
||||
return true;
|
||||
if (type == OSDType.Real)
|
||||
return true;
|
||||
if (type == OSDType.String)
|
||||
return true;
|
||||
if (type == OSDType.UUID)
|
||||
return true;
|
||||
if (type == OSDType.Date)
|
||||
return true;
|
||||
if (type == OSDType.URI)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/// <summary>
|
||||
///
|
||||
|
||||
@@ -227,7 +227,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(string.Format("[JsonStore]: Unable to initialize store from {0}", value), e);
|
||||
m_log.ErrorFormat("[JsonStore]: Unable to initialize store from {0}", value);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -265,6 +265,38 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
return m_JsonValueStore.ContainsKey(storeID);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
// -----------------------------------------------------------------
|
||||
public JsonStoreNodeType GetPathType(UUID storeID, string path)
|
||||
{
|
||||
if (! m_enabled) return JsonStoreNodeType.Undefined;
|
||||
|
||||
JsonStore map = null;
|
||||
lock (m_JsonValueStore)
|
||||
{
|
||||
if (! m_JsonValueStore.TryGetValue(storeID,out map))
|
||||
{
|
||||
m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
|
||||
return JsonStoreNodeType.Undefined;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
lock (map)
|
||||
return map.PathType(path);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error(string.Format("[JsonStore]: Path test failed for {0} in {1}", path, storeID), e);
|
||||
}
|
||||
|
||||
return JsonStoreNodeType.Undefined;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/// <summary>
|
||||
///
|
||||
@@ -370,6 +402,37 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
return false;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
// -----------------------------------------------------------------
|
||||
public int GetArrayLength(UUID storeID, string path)
|
||||
{
|
||||
if (! m_enabled) return -1;
|
||||
|
||||
JsonStore map = null;
|
||||
lock (m_JsonValueStore)
|
||||
{
|
||||
if (! m_JsonValueStore.TryGetValue(storeID,out map))
|
||||
return -1;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
lock (map)
|
||||
{
|
||||
return map.ArrayLength(path);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_log.Error("[JsonStore]: unable to retrieve value", e);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/// <summary>
|
||||
///
|
||||
|
||||
@@ -167,7 +167,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
try
|
||||
{
|
||||
m_comms.RegisterScriptInvocations(this);
|
||||
|
||||
m_comms.RegisterConstants(this);
|
||||
|
||||
// m_comms.RegisterScriptInvocation(this, "JsonCreateStore");
|
||||
// m_comms.RegisterScriptInvocation(this, "JsonAttachObjectStore");
|
||||
// m_comms.RegisterScriptInvocation(this, "JsonDestroyStore");
|
||||
@@ -214,6 +215,22 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
|
||||
#endregion
|
||||
|
||||
#region ScriptConstantsInterface
|
||||
|
||||
[ScriptConstant]
|
||||
public static readonly int JSON_TYPE_UNDEF = (int)JsonStoreNodeType.Undefined;
|
||||
|
||||
[ScriptConstant]
|
||||
public static readonly int JSON_TYPE_OBJECT = (int)JsonStoreNodeType.Object;
|
||||
|
||||
[ScriptConstant]
|
||||
public static readonly int JSON_TYPE_ARRAY = (int)JsonStoreNodeType.Array;
|
||||
|
||||
[ScriptConstant]
|
||||
public static readonly int JSON_TYPE_VALUE = (int)JsonStoreNodeType.Value;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ScriptInvocationInteface
|
||||
// -----------------------------------------------------------------
|
||||
/// <summary>
|
||||
@@ -301,7 +318,16 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
[ScriptInvocation]
|
||||
public string JsonList2Path(UUID hostID, UUID scriptID, object[] pathlist)
|
||||
{
|
||||
return JsonStore.CanonicalPathExpression(ConvertList2Path(pathlist));
|
||||
string ipath = ConvertList2Path(pathlist);
|
||||
string opath;
|
||||
|
||||
if (JsonStore.CanonicalPathExpression(ipath,out opath))
|
||||
return opath;
|
||||
|
||||
// This won't parse if passed to the other routines as opposed to
|
||||
// returning an empty string which is a valid path and would overwrite
|
||||
// the entire store
|
||||
return "**INVALID**";
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
@@ -309,6 +335,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
///
|
||||
/// </summary>
|
||||
// -----------------------------------------------------------------
|
||||
[ScriptInvocation]
|
||||
public int JsonGetPathType(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||
{
|
||||
return (int)m_store.GetPathType(storeID,path);
|
||||
}
|
||||
|
||||
[ScriptInvocation]
|
||||
public int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||
{
|
||||
@@ -333,7 +365,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
}
|
||||
|
||||
[ScriptInvocation]
|
||||
public int JsonSetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
|
||||
public int JsonSetJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
|
||||
{
|
||||
return m_store.SetValue(storeID,path,value,true) ? 1 : 0;
|
||||
}
|
||||
@@ -349,6 +381,17 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
return m_store.RemoveValue(storeID,path) ? 1 : 0;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
// -----------------------------------------------------------------
|
||||
[ScriptInvocation]
|
||||
public int JsonGetArrayLength(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||
{
|
||||
return m_store.GetArrayLength(storeID,path);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
/// <summary>
|
||||
///
|
||||
@@ -363,7 +406,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
}
|
||||
|
||||
[ScriptInvocation]
|
||||
public string JsonGetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||
public string JsonGetJson(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||
{
|
||||
string value = String.Empty;
|
||||
m_store.GetValue(storeID,path,true, out value);
|
||||
@@ -421,6 +464,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||
// -----------------------------------------------------------------
|
||||
protected void GenerateRuntimeError(string msg)
|
||||
{
|
||||
m_log.InfoFormat("[JsonStore] runtime error: {0}",msg);
|
||||
throw new Exception("JsonStore Runtime Error: " + msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||
private Scene m_scene;
|
||||
private MockScriptEngine m_engine;
|
||||
private ScriptModuleCommsModule m_smcm;
|
||||
private JsonStoreScriptModule m_jssm;
|
||||
|
||||
[TestFixtureSetUp]
|
||||
public void FixtureInit()
|
||||
@@ -82,10 +83,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||
m_engine = new MockScriptEngine();
|
||||
m_smcm = new ScriptModuleCommsModule();
|
||||
JsonStoreModule jsm = new JsonStoreModule();
|
||||
JsonStoreScriptModule jssm = new JsonStoreScriptModule();
|
||||
m_jssm = new JsonStoreScriptModule();
|
||||
|
||||
m_scene = new SceneHelpers().SetupScene();
|
||||
SceneHelpers.SetupSceneModules(m_scene, configSource, m_engine, m_smcm, jsm, jssm);
|
||||
SceneHelpers.SetupSceneModules(m_scene, configSource, m_engine, m_smcm, jsm, m_jssm);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -115,8 +116,35 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
|
||||
// Test blank store
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
|
||||
}
|
||||
|
||||
// Test single element store
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
|
||||
Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
|
||||
}
|
||||
|
||||
// Test with an integer value
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 42.15 }");
|
||||
Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Hello");
|
||||
Assert.That(value, Is.EqualTo("42.15"));
|
||||
}
|
||||
|
||||
// Test with an array as the root node
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "[ 'one', 'two', 'three' ]");
|
||||
Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "[1]");
|
||||
Assert.That(value, Is.EqualTo("two"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -144,8 +172,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||
|
||||
int dsrv = (int)InvokeOp("JsonDestroyStore", fakeStoreId);
|
||||
|
||||
// XXX: Current returns 'true' even though no such store existed. Need to ask if this is best behaviour.
|
||||
Assert.That(dsrv, Is.EqualTo(1));
|
||||
Assert.That(dsrv, Is.EqualTo(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -154,19 +181,64 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Two' } }");
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Hello");
|
||||
Assert.That(value, Is.EqualTo("World"));
|
||||
{
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Hello.World");
|
||||
Assert.That(value, Is.EqualTo("Two"));
|
||||
}
|
||||
|
||||
// Test get of path section instead of leaf
|
||||
{
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Hello");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// Test get of non-existing value
|
||||
string fakeValueGet = (string)InvokeOp("JsonGetValue", storeId, "foo");
|
||||
Assert.That(fakeValueGet, Is.EqualTo(""));
|
||||
{
|
||||
string fakeValueGet = (string)InvokeOp("JsonGetValue", storeId, "foo");
|
||||
Assert.That(fakeValueGet, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// Test get from non-existing store
|
||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||
string fakeStoreValueGet = (string)InvokeOp("JsonGetValue", fakeStoreId, "Hello");
|
||||
Assert.That(fakeStoreValueGet, Is.EqualTo(""));
|
||||
{
|
||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||
string fakeStoreValueGet = (string)InvokeOp("JsonGetValue", fakeStoreId, "Hello");
|
||||
Assert.That(fakeStoreValueGet, Is.EqualTo(""));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestJsonGetJson()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Two' } }");
|
||||
|
||||
{
|
||||
string value = (string)InvokeOp("JsonGetJson", storeId, "Hello.World");
|
||||
Assert.That(value, Is.EqualTo("'Two'"));
|
||||
}
|
||||
|
||||
// Test get of path section instead of leaf
|
||||
{
|
||||
string value = (string)InvokeOp("JsonGetJson", storeId, "Hello");
|
||||
Assert.That(value, Is.EqualTo("{\"World\":\"Two\"}"));
|
||||
}
|
||||
|
||||
// Test get of non-existing value
|
||||
{
|
||||
string fakeValueGet = (string)InvokeOp("JsonGetJson", storeId, "foo");
|
||||
Assert.That(fakeValueGet, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// Test get from non-existing store
|
||||
{
|
||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||
string fakeStoreValueGet = (string)InvokeOp("JsonGetJson", fakeStoreId, "Hello");
|
||||
Assert.That(fakeStoreValueGet, Is.EqualTo(""));
|
||||
}
|
||||
}
|
||||
|
||||
// [Test]
|
||||
@@ -198,47 +270,237 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
|
||||
// Test remove of node in object pointing to a string
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
|
||||
|
||||
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
|
||||
Assert.That(returnValue, Is.EqualTo(1));
|
||||
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
|
||||
Assert.That(returnValue, Is.EqualTo(1));
|
||||
|
||||
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
|
||||
string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello");
|
||||
Assert.That(returnValue2, Is.EqualTo(""));
|
||||
string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello");
|
||||
Assert.That(returnValue2, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// Test remove of node in object pointing to another object
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Wally' } }");
|
||||
|
||||
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
|
||||
Assert.That(returnValue, Is.EqualTo(1));
|
||||
|
||||
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
|
||||
string returnValue2 = (string)InvokeOp("JsonGetJson", storeId, "Hello");
|
||||
Assert.That(returnValue2, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// Test remove of node in an array
|
||||
{
|
||||
UUID storeId
|
||||
= (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : [ 'value1', 'value2' ] }");
|
||||
|
||||
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello[0]");
|
||||
Assert.That(returnValue, Is.EqualTo(1));
|
||||
|
||||
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello[0]");
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
|
||||
result = (int)InvokeOp("JsonTestPath", storeId, "Hello[1]");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
|
||||
string stringReturnValue = (string)InvokeOp("JsonGetValue", storeId, "Hello[0]");
|
||||
Assert.That(stringReturnValue, Is.EqualTo("value2"));
|
||||
|
||||
stringReturnValue = (string)InvokeOp("JsonGetJson", storeId, "Hello[1]");
|
||||
Assert.That(stringReturnValue, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// Test remove of non-existing value
|
||||
int fakeValueRemove = (int)InvokeOp("JsonRemoveValue", storeId, "Hello");
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
|
||||
|
||||
// XXX: Is this the best response to removing a value that isn't there?
|
||||
Assert.That(fakeValueRemove, Is.EqualTo(1));
|
||||
int fakeValueRemove = (int)InvokeOp("JsonRemoveValue", storeId, "Cheese");
|
||||
Assert.That(fakeValueRemove, Is.EqualTo(0));
|
||||
}
|
||||
|
||||
// Test get from non-existing store
|
||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||
int fakeStoreValueRemove = (int)InvokeOp("JsonRemoveValue", fakeStoreId, "Hello");
|
||||
Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
|
||||
{
|
||||
// Test get from non-existing store
|
||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||
int fakeStoreValueRemove = (int)InvokeOp("JsonRemoveValue", fakeStoreId, "Hello");
|
||||
Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
|
||||
}
|
||||
}
|
||||
|
||||
// [Test]
|
||||
// public void TestJsonTestPath()
|
||||
// {
|
||||
// TestHelpers.InMethod();
|
||||
//// TestHelpers.EnableLogging();
|
||||
//
|
||||
// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }");
|
||||
//
|
||||
// {
|
||||
// int result = (int)InvokeOp("JsonTestPath", storeId, "Hello.World");
|
||||
// Assert.That(result, Is.EqualTo(1));
|
||||
// }
|
||||
//
|
||||
// // Test for path which does not resolve to a value.
|
||||
// {
|
||||
// int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
|
||||
// Assert.That(result, Is.EqualTo(0));
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// int result2 = (int)InvokeOp("JsonTestPath", storeId, "foo");
|
||||
// Assert.That(result2, Is.EqualTo(0));
|
||||
// }
|
||||
//
|
||||
// // Test with fake store
|
||||
// {
|
||||
// UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||
// int fakeStoreValueRemove = (int)InvokeOp("JsonTestPath", fakeStoreId, "Hello");
|
||||
// Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
|
||||
// }
|
||||
// }
|
||||
|
||||
// [Test]
|
||||
// public void TestJsonTestPathJson()
|
||||
// {
|
||||
// TestHelpers.InMethod();
|
||||
//// TestHelpers.EnableLogging();
|
||||
//
|
||||
// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }");
|
||||
//
|
||||
// {
|
||||
// int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello.World");
|
||||
// Assert.That(result, Is.EqualTo(1));
|
||||
// }
|
||||
//
|
||||
// // Test for path which does not resolve to a value.
|
||||
// {
|
||||
// int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello");
|
||||
// Assert.That(result, Is.EqualTo(1));
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// int result2 = (int)InvokeOp("JsonTestPathJson", storeId, "foo");
|
||||
// Assert.That(result2, Is.EqualTo(0));
|
||||
// }
|
||||
//
|
||||
// // Test with fake store
|
||||
// {
|
||||
// UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||
// int fakeStoreValueRemove = (int)InvokeOp("JsonTestPathJson", fakeStoreId, "Hello");
|
||||
// Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
|
||||
// }
|
||||
// }
|
||||
|
||||
[Test]
|
||||
public void TestJsonTestPath()
|
||||
public void TestGetArrayLength()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }");
|
||||
|
||||
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
{
|
||||
int result = (int)InvokeOp("JsonGetArrayLength", storeId, "Hello.World");
|
||||
Assert.That(result, Is.EqualTo(2));
|
||||
}
|
||||
|
||||
int result2 = (int)InvokeOp("JsonTestPath", storeId, "foo");
|
||||
Assert.That(result2, Is.EqualTo(0));
|
||||
// Test path which is not an array
|
||||
{
|
||||
int result = (int)InvokeOp("JsonGetArrayLength", storeId, "Hello");
|
||||
Assert.That(result, Is.EqualTo(-1));
|
||||
}
|
||||
|
||||
// Test with fake store
|
||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||
int fakeStoreValueRemove = (int)InvokeOp("JsonTestPath", fakeStoreId, "Hello");
|
||||
Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
|
||||
// Test fake path
|
||||
{
|
||||
int result = (int)InvokeOp("JsonGetArrayLength", storeId, "foo");
|
||||
Assert.That(result, Is.EqualTo(-1));
|
||||
}
|
||||
|
||||
// Test fake store
|
||||
{
|
||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||
int result = (int)InvokeOp("JsonGetArrayLength", fakeStoreId, "Hello.World");
|
||||
Assert.That(result, Is.EqualTo(-1));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestJsonGetPathType()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }");
|
||||
|
||||
{
|
||||
int result = (int)InvokeOp("JsonGetPathType", storeId, ".");
|
||||
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_OBJECT));
|
||||
}
|
||||
|
||||
{
|
||||
int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello");
|
||||
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_OBJECT));
|
||||
}
|
||||
|
||||
{
|
||||
int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello.World");
|
||||
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_ARRAY));
|
||||
}
|
||||
|
||||
{
|
||||
int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello.World[0]");
|
||||
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_VALUE));
|
||||
}
|
||||
|
||||
{
|
||||
int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello.World[1]");
|
||||
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_VALUE));
|
||||
}
|
||||
|
||||
// Test for non-existant path
|
||||
{
|
||||
int result = (int)InvokeOp("JsonGetPathType", storeId, "foo");
|
||||
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
|
||||
}
|
||||
|
||||
// Test for non-existant store
|
||||
{
|
||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||
int result = (int)InvokeOp("JsonGetPathType", fakeStoreId, ".");
|
||||
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestJsonList2Path()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
// Invoking these methods directly since I just couldn't get comms module invocation to work for some reason
|
||||
// - some confusion with the methods that take a params object[] invocation.
|
||||
{
|
||||
string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo" });
|
||||
Assert.That(result, Is.EqualTo("{foo}"));
|
||||
}
|
||||
|
||||
{
|
||||
string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo", "bar" });
|
||||
Assert.That(result, Is.EqualTo("{foo}.{bar}"));
|
||||
}
|
||||
|
||||
{
|
||||
string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo", 1, "bar" });
|
||||
Assert.That(result, Is.EqualTo("{foo}.[1].{bar}"));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -247,18 +509,237 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetValue", storeId, "Fun", "Times");
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
int result = (int)InvokeOp("JsonSetValue", storeId, "Fun", "Times");
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun");
|
||||
Assert.That(value, Is.EqualTo("Times"));
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun");
|
||||
Assert.That(value, Is.EqualTo("Times"));
|
||||
}
|
||||
|
||||
// Test setting a key containing periods with delineation
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun.Circus}", "Times");
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun.Circus}");
|
||||
Assert.That(value, Is.EqualTo("Times"));
|
||||
}
|
||||
|
||||
// *** Test [] ***
|
||||
|
||||
// Test setting a key containing unbalanced ] without delineation. Expecting failure
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetValue", storeId, "Fun]Circus", "Times");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun]Circus");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// Test setting a key containing unbalanced [ without delineation. Expecting failure
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetValue", storeId, "Fun[Circus", "Times");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun[Circus");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// Test setting a key containing unbalanced [] without delineation. Expecting failure
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetValue", storeId, "Fun[]Circus", "Times");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun[]Circus");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// Test setting a key containing unbalanced ] with delineation
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun]Circus}", "Times");
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun]Circus}");
|
||||
Assert.That(value, Is.EqualTo("Times"));
|
||||
}
|
||||
|
||||
// Test setting a key containing unbalanced [ with delineation
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[Circus}", "Times");
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[Circus}");
|
||||
Assert.That(value, Is.EqualTo("Times"));
|
||||
}
|
||||
|
||||
// Test setting a key containing empty balanced [] with delineation
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[]Circus}", "Times");
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[]Circus}");
|
||||
Assert.That(value, Is.EqualTo("Times"));
|
||||
}
|
||||
|
||||
// // Commented out as this currently unexpectedly fails.
|
||||
// // Test setting a key containing brackets around an integer with delineation
|
||||
// {
|
||||
// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
//
|
||||
// int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[0]Circus}", "Times");
|
||||
// Assert.That(result, Is.EqualTo(1));
|
||||
//
|
||||
// string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[0]Circus}");
|
||||
// Assert.That(value, Is.EqualTo("Times"));
|
||||
// }
|
||||
|
||||
// *** Test {} ***
|
||||
|
||||
// Test setting a key containing unbalanced } without delineation. Expecting failure (?)
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetValue", storeId, "Fun}Circus", "Times");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun}Circus");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// Test setting a key containing unbalanced { without delineation. Expecting failure (?)
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetValue", storeId, "Fun{Circus", "Times");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun}Circus");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// // Commented out as this currently unexpectedly fails.
|
||||
// // Test setting a key containing unbalanced }
|
||||
// {
|
||||
// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
//
|
||||
// int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun}Circus}", "Times");
|
||||
// Assert.That(result, Is.EqualTo(0));
|
||||
// }
|
||||
|
||||
// Test setting a key containing unbalanced { with delineation
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun{Circus}", "Times");
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun{Circus}");
|
||||
Assert.That(value, Is.EqualTo("Times"));
|
||||
}
|
||||
|
||||
// Test setting a key containing balanced {} with delineation. This should fail.
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun{Filled}Circus}", "Times");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun{Filled}Circus}");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// Test setting to location that does not exist. This should fail.
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetValue", storeId, "Fun.Circus", "Times");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Circus");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// Test with fake store
|
||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||
int fakeStoreValueSet = (int)InvokeOp("JsonSetValue", fakeStoreId, "Hello", "World");
|
||||
Assert.That(fakeStoreValueSet, Is.EqualTo(0));
|
||||
{
|
||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||
int fakeStoreValueSet = (int)InvokeOp("JsonSetValue", fakeStoreId, "Hello", "World");
|
||||
Assert.That(fakeStoreValueSet, Is.EqualTo(0));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestJsonSetJson()
|
||||
{
|
||||
TestHelpers.InMethod();
|
||||
// TestHelpers.EnableLogging();
|
||||
|
||||
// Single quoted token case
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "'Times'");
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun");
|
||||
Assert.That(value, Is.EqualTo("Times"));
|
||||
}
|
||||
|
||||
// Sub-tree case
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "{ 'Filled' : 'Times' }");
|
||||
Assert.That(result, Is.EqualTo(1));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Filled");
|
||||
Assert.That(value, Is.EqualTo("Times"));
|
||||
}
|
||||
|
||||
// If setting single strings in JsonSetValueJson, these must be single quoted tokens, not bare strings.
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "Times");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// Test setting to location that does not exist. This should fail.
|
||||
{
|
||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
||||
|
||||
int result = (int)InvokeOp("JsonSetJson", storeId, "Fun.Circus", "'Times'");
|
||||
Assert.That(result, Is.EqualTo(0));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Circus");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
// Test with fake store
|
||||
{
|
||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||
int fakeStoreValueSet = (int)InvokeOp("JsonSetJson", fakeStoreId, "Hello", "'World'");
|
||||
Assert.That(fakeStoreValueSet, Is.EqualTo(0));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -360,8 +841,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||
UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "make", notecardName);
|
||||
Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
|
||||
|
||||
// These don't behave as I expect yet - reading to a path still seems to place the notecard contents at the root.
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
|
||||
@@ -370,27 +850,24 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||
}
|
||||
|
||||
{
|
||||
// Read notecard to new multi-component path
|
||||
// Read notecard to new multi-component path. This should not work.
|
||||
UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||
UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "make.it", notecardName);
|
||||
Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
|
||||
|
||||
// These don't behave as I expect yet - reading to a path still seems to place the notecard contents at the root.
|
||||
string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
|
||||
// TODO: Check that we are not expecting reading to a new path to work.
|
||||
value = (string)InvokeOp("JsonGetValue", receivingStoreId, "make.it.Hello");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
{
|
||||
// Read notecard to existing multi-component path
|
||||
// Read notecard to existing multi-component path. This should work
|
||||
UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{ 'make' : { 'it' : 'so' } }");
|
||||
UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "make.it", notecardName);
|
||||
Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
|
||||
|
||||
// These don't behave as I expect yet - reading to a path still seems to place the notecard contents at the root.
|
||||
string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
|
||||
@@ -398,11 +875,21 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||
Assert.That(value, Is.EqualTo("World"));
|
||||
}
|
||||
|
||||
{
|
||||
// Read notecard to invalid path. This should not work.
|
||||
UUID receivingStoreId = (UUID)InvokeOp("JsonCreateStore", "{ 'make' : { 'it' : 'so' } }");
|
||||
UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, receivingStoreId, "/", notecardName);
|
||||
Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", receivingStoreId, "Hello");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
}
|
||||
|
||||
{
|
||||
// Try read notecard to fake store.
|
||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||
UUID readNotecardRequestId = (UUID)InvokeOpOnHost("JsonReadNotecard", so.UUID, fakeStoreId, "", notecardName);
|
||||
Assert.That(fakeStoreId, Is.Not.EqualTo(UUID.Zero));
|
||||
Assert.That(readNotecardRequestId, Is.Not.EqualTo(UUID.Zero));
|
||||
|
||||
string value = (string)InvokeOp("JsonGetValue", fakeStoreId, "Hello");
|
||||
Assert.That(value, Is.EqualTo(""));
|
||||
|
||||
@@ -183,6 +183,7 @@ public struct ConfigurationParameters
|
||||
public float shouldEnableFrictionCaching;
|
||||
public float numberOfSolverIterations;
|
||||
public float useSingleSidedMeshes;
|
||||
public float globalContactBreakingThreshold;
|
||||
|
||||
public float physicsLoggingFrames;
|
||||
|
||||
@@ -224,9 +225,10 @@ public enum CollisionFlags : uint
|
||||
CF_DISABLE_VISUALIZE_OBJECT = 1 << 5,
|
||||
CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
|
||||
// Following used by BulletSim to control collisions and updates
|
||||
BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
|
||||
BS_FLOATS_ON_WATER = 1 << 11,
|
||||
BS_VEHICLE_COLLISIONS = 1 << 12,
|
||||
BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, // return collision events from unmanaged to managed
|
||||
BS_FLOATS_ON_WATER = 1 << 11, // the object should float at water level
|
||||
BS_VEHICLE_COLLISIONS = 1 << 12, // return collisions for vehicle ground checking
|
||||
BS_RETURN_ROOT_COMPOUND_SHAPE = 1 << 13, // return the pos/rot of the root shape in a compound shape
|
||||
BS_NONE = 0,
|
||||
BS_ALL = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
@@ -45,7 +45,6 @@ public sealed class BSCharacter : BSPhysObject
|
||||
private bool _selected;
|
||||
private OMV.Vector3 _position;
|
||||
private float _mass;
|
||||
private float _avatarDensity;
|
||||
private float _avatarVolume;
|
||||
private OMV.Vector3 _force;
|
||||
private OMV.Vector3 _velocity;
|
||||
@@ -63,9 +62,6 @@ public sealed class BSCharacter : BSPhysObject
|
||||
private bool _kinematic;
|
||||
private float _buoyancy;
|
||||
|
||||
// The friction and velocity of the avatar is modified depending on whether walking or not.
|
||||
private float _currentFriction; // the friction currently being used (changed by setVelocity).
|
||||
|
||||
private BSVMotor _velocityMotor;
|
||||
|
||||
private OMV.Vector3 _PIDTarget;
|
||||
@@ -86,8 +82,8 @@ public sealed class BSCharacter : BSPhysObject
|
||||
_orientation = OMV.Quaternion.Identity;
|
||||
_velocity = OMV.Vector3.Zero;
|
||||
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
|
||||
_currentFriction = BSParam.AvatarStandingFriction;
|
||||
_avatarDensity = BSParam.AvatarDensity;
|
||||
Friction = BSParam.AvatarStandingFriction;
|
||||
Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor;
|
||||
|
||||
// Old versions of ScenePresence passed only the height. If width and/or depth are zero,
|
||||
// replace with the default values.
|
||||
@@ -104,7 +100,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||
SetupMovementMotor();
|
||||
|
||||
DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}",
|
||||
LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
|
||||
LocalID, _size, Scale, Density, _avatarVolume, RawMass);
|
||||
|
||||
// do actual creation in taint time
|
||||
PhysicsScene.TaintedObject("BSCharacter.create", delegate()
|
||||
@@ -140,7 +136,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||
ZeroMotion(true);
|
||||
ForcePosition = _position;
|
||||
|
||||
// Set the velocity and compute the proper friction
|
||||
// Set the velocity
|
||||
_velocityMotor.Reset();
|
||||
_velocityMotor.SetTarget(_velocity);
|
||||
_velocityMotor.SetCurrent(_velocity);
|
||||
@@ -214,35 +210,47 @@ public sealed class BSCharacter : BSPhysObject
|
||||
_velocityMotor.Step(timeStep);
|
||||
|
||||
// If we're not supposed to be moving, make sure things are zero.
|
||||
if (_velocityMotor.ErrorIsZero() && _velocityMotor.TargetValue == OMV.Vector3.Zero && IsColliding)
|
||||
if (_velocityMotor.ErrorIsZero() && _velocityMotor.TargetValue == OMV.Vector3.Zero)
|
||||
{
|
||||
// The avatar shouldn't be moving
|
||||
_velocityMotor.Zero();
|
||||
|
||||
// If we are colliding with a stationary object, presume we're standing and don't move around
|
||||
if (!ColliderIsMoving)
|
||||
if (IsColliding)
|
||||
{
|
||||
DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", LocalID);
|
||||
ZeroMotion(true /* inTaintTime */);
|
||||
// If we are colliding with a stationary object, presume we're standing and don't move around
|
||||
if (!ColliderIsMoving)
|
||||
{
|
||||
DetailLog("{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", LocalID);
|
||||
ZeroMotion(true /* inTaintTime */);
|
||||
}
|
||||
|
||||
// Standing has more friction on the ground
|
||||
if (Friction != BSParam.AvatarStandingFriction)
|
||||
{
|
||||
Friction = BSParam.AvatarStandingFriction;
|
||||
PhysicsScene.PE.SetFriction(PhysBody, Friction);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Flying)
|
||||
{
|
||||
// Flying and not collising and velocity nearly zero.
|
||||
ZeroMotion(true /* inTaintTime */);
|
||||
}
|
||||
}
|
||||
|
||||
// Standing has more friction on the ground
|
||||
if (_currentFriction != BSParam.AvatarStandingFriction)
|
||||
{
|
||||
_currentFriction = BSParam.AvatarStandingFriction;
|
||||
PhysicsScene.PE.SetFriction(PhysBody, _currentFriction);
|
||||
}
|
||||
DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1}", LocalID, _velocityMotor.TargetValue);
|
||||
DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding);
|
||||
}
|
||||
else
|
||||
{
|
||||
OMV.Vector3 stepVelocity = _velocityMotor.CurrentValue;
|
||||
|
||||
if (_currentFriction != BSParam.AvatarFriction)
|
||||
if (Friction != BSParam.AvatarFriction)
|
||||
{
|
||||
// Probably starting up walking. Set friction to moving friction.
|
||||
_currentFriction = BSParam.AvatarFriction;
|
||||
PhysicsScene.PE.SetFriction(PhysBody, _currentFriction);
|
||||
Friction = BSParam.AvatarFriction;
|
||||
PhysicsScene.PE.SetFriction(PhysBody, Friction);
|
||||
}
|
||||
|
||||
// If falling, we keep the world's downward vector no matter what the other axis specify.
|
||||
@@ -275,7 +283,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||
// This test is done if moving forward, not flying and is colliding with something.
|
||||
// DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
|
||||
// LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
|
||||
if (IsColliding && !Flying && TargetSpeed > 0.1f /* && ForwardSpeed < 0.1f */)
|
||||
if (IsColliding && !Flying && TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */)
|
||||
{
|
||||
// The range near the character's feet where we will consider stairs
|
||||
float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f;
|
||||
@@ -342,7 +350,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||
Scale = ComputeAvatarScale(_size);
|
||||
ComputeAvatarVolumeAndMass();
|
||||
DetailLog("{0},BSCharacter.setSize,call,size={1},scale={2},density={3},volume={4},mass={5}",
|
||||
LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass);
|
||||
LocalID, _size, Scale, Density, _avatarVolume, RawMass);
|
||||
|
||||
PhysicsScene.TaintedObject("BSCharacter.setSize", delegate()
|
||||
{
|
||||
@@ -870,7 +878,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||
* Math.Min(Size.X, Size.Y) / 2
|
||||
* Size.Y / 2f // plus the volume of the capsule end caps
|
||||
);
|
||||
_mass = _avatarDensity * _avatarVolume;
|
||||
_mass = Density * BSParam.DensityScaleFactor * _avatarVolume;
|
||||
}
|
||||
|
||||
// The physics engine says that properties have updated. Update same and inform
|
||||
@@ -901,7 +909,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||
CurrentEntityProperties = entprop;
|
||||
|
||||
// Tell the linkset about value changes
|
||||
Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
|
||||
// Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
|
||||
|
||||
// Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop.
|
||||
// base.RequestPhysicsterseUpdate();
|
||||
|
||||
@@ -597,7 +597,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
if (IsActive)
|
||||
{
|
||||
// Remember the mass so we don't have to fetch it every step
|
||||
m_vehicleMass = Prim.Linkset.LinksetMass;
|
||||
m_vehicleMass = Prim.TotalMass;
|
||||
|
||||
// Friction affects are handled by this vehicle code
|
||||
PhysicsScene.PE.SetFriction(Prim.PhysBody, BSParam.VehicleFriction);
|
||||
|
||||
@@ -52,7 +52,7 @@ public abstract class BSLinkset
|
||||
Manual = 2 // linkset tied together manually (code moves all the pieces)
|
||||
}
|
||||
// Create the correct type of linkset for this child
|
||||
public static BSLinkset Factory(BSScene physScene, BSPhysObject parent)
|
||||
public static BSLinkset Factory(BSScene physScene, BSPrimLinkable parent)
|
||||
{
|
||||
BSLinkset ret = null;
|
||||
|
||||
@@ -71,10 +71,14 @@ public abstract class BSLinkset
|
||||
ret = new BSLinksetCompound(physScene, parent);
|
||||
break;
|
||||
}
|
||||
if (ret == null)
|
||||
{
|
||||
physScene.Logger.ErrorFormat("[BULLETSIM LINKSET] Factory could not create linkset. Parent name={1}, ID={2}", parent.Name, parent.LocalID);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public BSPhysObject LinksetRoot { get; protected set; }
|
||||
public BSPrimLinkable LinksetRoot { get; protected set; }
|
||||
|
||||
public BSScene PhysicsScene { get; private set; }
|
||||
|
||||
@@ -82,7 +86,7 @@ public abstract class BSLinkset
|
||||
public int LinksetID { get; private set; }
|
||||
|
||||
// The children under the root in this linkset.
|
||||
protected HashSet<BSPhysObject> m_children;
|
||||
protected HashSet<BSPrimLinkable> m_children;
|
||||
|
||||
// We lock the diddling of linkset classes to prevent any badness.
|
||||
// This locks the modification of the instances of this class. Changes
|
||||
@@ -91,7 +95,7 @@ public abstract class BSLinkset
|
||||
|
||||
// Some linksets have a preferred physical shape.
|
||||
// Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
|
||||
public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
|
||||
public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor)
|
||||
{
|
||||
return BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
}
|
||||
@@ -111,7 +115,7 @@ public abstract class BSLinkset
|
||||
get { return ComputeLinksetGeometricCenter(); }
|
||||
}
|
||||
|
||||
protected BSLinkset(BSScene scene, BSPhysObject parent)
|
||||
protected BSLinkset(BSScene scene, BSPrimLinkable parent)
|
||||
{
|
||||
// A simple linkset of one (no children)
|
||||
LinksetID = m_nextLinksetID++;
|
||||
@@ -120,16 +124,18 @@ public abstract class BSLinkset
|
||||
m_nextLinksetID = 1;
|
||||
PhysicsScene = scene;
|
||||
LinksetRoot = parent;
|
||||
m_children = new HashSet<BSPhysObject>();
|
||||
m_children = new HashSet<BSPrimLinkable>();
|
||||
LinksetMass = parent.RawMass;
|
||||
Rebuilding = false;
|
||||
|
||||
parent.ClearDisplacement();
|
||||
}
|
||||
|
||||
// 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 its membership.
|
||||
// Called at runtime.
|
||||
public BSLinkset AddMeToLinkset(BSPhysObject child)
|
||||
public BSLinkset AddMeToLinkset(BSPrimLinkable child)
|
||||
{
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
@@ -145,14 +151,13 @@ public abstract class BSLinkset
|
||||
// Returns a new linkset for the child which is a linkset of one (just the
|
||||
// orphened child).
|
||||
// Called at runtime.
|
||||
public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
|
||||
public BSLinkset RemoveMeFromLinkset(BSPrimLinkable child)
|
||||
{
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
if (IsRoot(child))
|
||||
{
|
||||
// Cannot remove the root from a linkset.
|
||||
child.PositionDisplacement = OMV.Vector3.Zero;
|
||||
return this;
|
||||
}
|
||||
RemoveChildFromLinkset(child);
|
||||
@@ -160,12 +165,11 @@ public abstract class BSLinkset
|
||||
}
|
||||
|
||||
// The child is down to a linkset of just itself
|
||||
child.PositionDisplacement = OMV.Vector3.Zero;
|
||||
return BSLinkset.Factory(PhysicsScene, child);
|
||||
}
|
||||
|
||||
// Return 'true' if the passed object is the root object of this linkset
|
||||
public bool IsRoot(BSPhysObject requestor)
|
||||
public bool IsRoot(BSPrimLinkable requestor)
|
||||
{
|
||||
return (requestor.LocalID == LinksetRoot.LocalID);
|
||||
}
|
||||
@@ -176,14 +180,14 @@ public abstract class BSLinkset
|
||||
public bool HasAnyChildren { get { return (m_children.Count > 0); } }
|
||||
|
||||
// Return 'true' if this child is in this linkset
|
||||
public bool HasChild(BSPhysObject child)
|
||||
public bool HasChild(BSPrimLinkable child)
|
||||
{
|
||||
bool ret = false;
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
ret = m_children.Contains(child);
|
||||
/* Safer version but the above should work
|
||||
foreach (BSPhysObject bp in m_children)
|
||||
foreach (BSPrimLinkable bp in m_children)
|
||||
{
|
||||
if (child.LocalID == bp.LocalID)
|
||||
{
|
||||
@@ -198,14 +202,14 @@ public abstract class BSLinkset
|
||||
|
||||
// Perform an action on each member of the linkset including root prim.
|
||||
// Depends on the action on whether this should be done at taint time.
|
||||
public delegate bool ForEachMemberAction(BSPhysObject obj);
|
||||
public delegate bool ForEachMemberAction(BSPrimLinkable obj);
|
||||
public virtual bool ForEachMember(ForEachMemberAction action)
|
||||
{
|
||||
bool ret = false;
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
action(LinksetRoot);
|
||||
foreach (BSPhysObject po in m_children)
|
||||
foreach (BSPrimLinkable po in m_children)
|
||||
{
|
||||
if (action(po))
|
||||
break;
|
||||
@@ -216,16 +220,16 @@ public abstract class BSLinkset
|
||||
|
||||
// I am the root of a linkset and a new child is being added
|
||||
// Called while LinkActivity is locked.
|
||||
protected abstract void AddChildToLinkset(BSPhysObject child);
|
||||
protected abstract void AddChildToLinkset(BSPrimLinkable child);
|
||||
|
||||
// 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.
|
||||
protected abstract void RemoveChildFromLinkset(BSPhysObject child);
|
||||
protected abstract void RemoveChildFromLinkset(BSPrimLinkable child);
|
||||
|
||||
// When physical properties are changed the linkset needs to recalculate
|
||||
// its internal properties.
|
||||
// May be called at runtime or taint-time.
|
||||
public virtual void Refresh(BSPhysObject requestor)
|
||||
public virtual void Refresh(BSPrimLinkable requestor)
|
||||
{
|
||||
LinksetMass = ComputeLinksetMass();
|
||||
}
|
||||
@@ -240,26 +244,26 @@ public abstract class BSLinkset
|
||||
// has not yet been fully constructed.
|
||||
// Return 'true' if any properties updated on the passed object.
|
||||
// Called at taint-time!
|
||||
public abstract bool MakeDynamic(BSPhysObject child);
|
||||
public abstract bool MakeDynamic(BSPrimLinkable child);
|
||||
|
||||
// The object is going static (non-physical). Do any setup necessary
|
||||
// for a static linkset.
|
||||
// Return 'true' if any properties updated on the passed object.
|
||||
// Called at taint-time!
|
||||
public abstract bool MakeStatic(BSPhysObject child);
|
||||
public abstract bool MakeStatic(BSPrimLinkable child);
|
||||
|
||||
// Called when a parameter update comes from the physics engine for any object
|
||||
// of the linkset is received.
|
||||
// Passed flag is update came from physics engine (true) or the user (false).
|
||||
// Called at taint-time!!
|
||||
public abstract void UpdateProperties(UpdatedProperties whichUpdated, BSPhysObject physObject);
|
||||
public abstract void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable physObject);
|
||||
|
||||
// Routine used when rebuilding the body of the root of the linkset
|
||||
// Destroy all the constraints have have been made to root.
|
||||
// This is called when the root body is changing.
|
||||
// Returns 'true' of something was actually removed and would need restoring
|
||||
// Called at taint-time!!
|
||||
public abstract bool RemoveBodyDependencies(BSPrim child);
|
||||
public abstract bool RemoveBodyDependencies(BSPrimLinkable child);
|
||||
|
||||
// ================================================================
|
||||
protected virtual float ComputeLinksetMass()
|
||||
@@ -269,7 +273,7 @@ public abstract class BSLinkset
|
||||
{
|
||||
lock (m_linksetActivityLock)
|
||||
{
|
||||
foreach (BSPhysObject bp in m_children)
|
||||
foreach (BSPrimLinkable bp in m_children)
|
||||
{
|
||||
mass += bp.RawMass;
|
||||
}
|
||||
@@ -278,6 +282,7 @@ public abstract class BSLinkset
|
||||
return mass;
|
||||
}
|
||||
|
||||
// Computes linkset's center of mass in world coordinates.
|
||||
protected virtual OMV.Vector3 ComputeLinksetCenterOfMass()
|
||||
{
|
||||
OMV.Vector3 com;
|
||||
@@ -286,7 +291,7 @@ public abstract class BSLinkset
|
||||
com = LinksetRoot.Position * LinksetRoot.RawMass;
|
||||
float totalMass = LinksetRoot.RawMass;
|
||||
|
||||
foreach (BSPhysObject bp in m_children)
|
||||
foreach (BSPrimLinkable bp in m_children)
|
||||
{
|
||||
com += bp.Position * bp.RawMass;
|
||||
totalMass += bp.RawMass;
|
||||
@@ -305,7 +310,7 @@ public abstract class BSLinkset
|
||||
{
|
||||
com = LinksetRoot.Position;
|
||||
|
||||
foreach (BSPhysObject bp in m_children)
|
||||
foreach (BSPrimLinkable bp in m_children)
|
||||
{
|
||||
com += bp.Position;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ sealed class BSLinksetCompoundInfo : BSLinksetInfo
|
||||
OffsetRot = r;
|
||||
}
|
||||
// 'centerDisplacement' is the distance from the root the the center-of-mass (Bullet 'zero' of the shape)
|
||||
public BSLinksetCompoundInfo(int indx, BSPhysObject root, BSPhysObject child, OMV.Vector3 centerDisplacement)
|
||||
public BSLinksetCompoundInfo(int indx, BSPrimLinkable root, BSPrimLinkable child, OMV.Vector3 centerDisplacement)
|
||||
{
|
||||
// Each child position and rotation is given relative to the center-of-mass.
|
||||
OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(root.RawOrientation);
|
||||
@@ -93,12 +93,13 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||
{
|
||||
private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
|
||||
|
||||
public BSLinksetCompound(BSScene scene, BSPhysObject parent) : base(scene, parent)
|
||||
public BSLinksetCompound(BSScene scene, BSPrimLinkable parent)
|
||||
: base(scene, parent)
|
||||
{
|
||||
}
|
||||
|
||||
// For compound implimented linksets, if there are children, use compound shape for the root.
|
||||
public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
|
||||
public override BSPhysicsShapeType PreferredPhysicalShape(BSPrimLinkable requestor)
|
||||
{
|
||||
// Returning 'unknown' means we don't have a preference.
|
||||
BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
|
||||
@@ -112,7 +113,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||
|
||||
// When physical properties are changed the linkset needs to recalculate
|
||||
// its internal properties.
|
||||
public override void Refresh(BSPhysObject requestor)
|
||||
public override void Refresh(BSPrimLinkable requestor)
|
||||
{
|
||||
base.Refresh(requestor);
|
||||
|
||||
@@ -121,7 +122,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||
}
|
||||
|
||||
// Schedule a refresh to happen after all the other taint processing.
|
||||
private void ScheduleRebuild(BSPhysObject requestor)
|
||||
private void ScheduleRebuild(BSPrimLinkable requestor)
|
||||
{
|
||||
DetailLog("{0},BSLinksetCompound.ScheduleRebuild,,rebuilding={1},hasChildren={2},actuallyScheduling={3}",
|
||||
requestor.LocalID, Rebuilding, HasAnyChildren, (!Rebuilding && HasAnyChildren));
|
||||
@@ -143,7 +144,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||
// has not yet been fully constructed.
|
||||
// Return 'true' if any properties updated on the passed object.
|
||||
// Called at taint-time!
|
||||
public override bool MakeDynamic(BSPhysObject child)
|
||||
public override bool MakeDynamic(BSPrimLinkable child)
|
||||
{
|
||||
bool ret = false;
|
||||
DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child));
|
||||
@@ -173,7 +174,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||
// This doesn't normally happen -- OpenSim removes the objects from the physical
|
||||
// world if it is a static linkset.
|
||||
// Called at taint-time!
|
||||
public override bool MakeStatic(BSPhysObject child)
|
||||
public override bool MakeStatic(BSPrimLinkable child)
|
||||
{
|
||||
bool ret = false;
|
||||
DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child));
|
||||
@@ -197,7 +198,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||
|
||||
// 'physicalUpdate' is true if these changes came directly from the physics engine. Don't need to rebuild then.
|
||||
// Called at taint-time.
|
||||
public override void UpdateProperties(UpdatedProperties whichUpdated, BSPhysObject updated)
|
||||
public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable updated)
|
||||
{
|
||||
// The user moving a child around requires the rebuilding of the linkset compound shape
|
||||
// One problem is this happens when a border is crossed -- the simulator implementation
|
||||
@@ -217,59 +218,45 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||
// and that is caused by us updating the object.
|
||||
if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
|
||||
{
|
||||
// Gather the child info. It might not be there if the linkset is in transition.
|
||||
BSLinksetCompoundInfo lsi = updated.LinksetInfo as BSLinksetCompoundInfo;
|
||||
if (lsi != null)
|
||||
{
|
||||
// Since the child moved or rotationed, it needs a new relative position within the linkset
|
||||
BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, LinksetRoot.PositionDisplacement);
|
||||
updated.LinksetInfo = newLsi;
|
||||
|
||||
// Find the physical instance of the child
|
||||
if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape))
|
||||
if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape))
|
||||
{
|
||||
// It is possible that the linkset is still under construction and the child is not yet
|
||||
// inserted into the compound shape. A rebuild of the linkset in a pre-step action will
|
||||
// build the whole thing with the new position or rotation.
|
||||
// The index must be checked because Bullet references the child array but does no validity
|
||||
// checking of the child index passed.
|
||||
int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
|
||||
if (updated.LinksetChildIndex < numLinksetChildren)
|
||||
{
|
||||
// It is possible that the linkset is still under construction and the child is not yet
|
||||
// inserted into the compound shape. A rebuild of the linkset in a pre-step action will
|
||||
// build the whole thing with the new position or rotation.
|
||||
// The index must be checked because Bullet references the child array but does no validity
|
||||
// checking of the child index passed.
|
||||
int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
|
||||
if (lsi.Index < numLinksetChildren)
|
||||
BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, updated.LinksetChildIndex);
|
||||
if (linksetChildShape.HasPhysicalShape)
|
||||
{
|
||||
BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index);
|
||||
if (linksetChildShape.HasPhysicalShape)
|
||||
{
|
||||
// Found the child shape within the compound shape
|
||||
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index,
|
||||
newLsi.OffsetFromCenterOfMass,
|
||||
newLsi.OffsetRot,
|
||||
true /* shouldRecalculateLocalAabb */);
|
||||
updatedChild = true;
|
||||
DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}",
|
||||
updated.LocalID, whichUpdated, newLsi);
|
||||
}
|
||||
else // DEBUG DEBUG
|
||||
{ // DEBUG DEBUG
|
||||
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}",
|
||||
updated.LocalID, linksetChildShape);
|
||||
} // DEBUG DEBUG
|
||||
// Found the child shape within the compound shape
|
||||
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, updated.LinksetChildIndex,
|
||||
updated.RawPosition - LinksetRoot.RawPosition,
|
||||
updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation),
|
||||
true /* shouldRecalculateLocalAabb */);
|
||||
updatedChild = true;
|
||||
DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},pos={2},rot={3}",
|
||||
updated.LocalID, whichUpdated, updated.RawPosition, updated.RawOrientation);
|
||||
}
|
||||
else // DEBUG DEBUG
|
||||
{ // DEBUG DEBUG
|
||||
// the child is not yet in the compound shape. This is non-fatal.
|
||||
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}",
|
||||
updated.LocalID, numLinksetChildren, lsi.Index);
|
||||
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}",
|
||||
updated.LocalID, linksetChildShape);
|
||||
} // DEBUG DEBUG
|
||||
}
|
||||
else // DEBUG DEBUG
|
||||
{ // DEBUG DEBUG
|
||||
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID);
|
||||
// the child is not yet in the compound shape. This is non-fatal.
|
||||
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}",
|
||||
updated.LocalID, numLinksetChildren, updated.LinksetChildIndex);
|
||||
} // DEBUG DEBUG
|
||||
}
|
||||
else // DEBUG DEBUG
|
||||
{ // DEBUG DEBUG
|
||||
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noLinkSetInfo,rootPhysShape={1}",
|
||||
updated.LocalID, LinksetRoot.PhysShape);
|
||||
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID);
|
||||
} // DEBUG DEBUG
|
||||
|
||||
if (!updatedChild)
|
||||
@@ -291,7 +278,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||
// Since we don't keep in world relationships, do nothing unless it's a child changing.
|
||||
// Returns 'true' of something was actually removed and would need restoring
|
||||
// Called at taint-time!!
|
||||
public override bool RemoveBodyDependencies(BSPrim child)
|
||||
public override bool RemoveBodyDependencies(BSPrimLinkable child)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
@@ -316,7 +303,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||
// When the linkset is built, the child shape is added to the compound shape relative to the
|
||||
// root shape. The linkset then moves around but this does not move the actual child
|
||||
// prim. The child prim's location must be recomputed based on the location of the root shape.
|
||||
private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime)
|
||||
private void RecomputeChildWorldPosition(BSPrimLinkable child, bool inTaintTime)
|
||||
{
|
||||
// For the moment (20130201), disable this computation (converting the child physical addr back to
|
||||
// a region address) until we have a good handle on center-of-mass offsets and what the physics
|
||||
@@ -361,7 +348,7 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||
|
||||
// Add a new child to the linkset.
|
||||
// Called while LinkActivity is locked.
|
||||
protected override void AddChildToLinkset(BSPhysObject child)
|
||||
protected override void AddChildToLinkset(BSPrimLinkable child)
|
||||
{
|
||||
if (!HasChild(child))
|
||||
{
|
||||
@@ -377,8 +364,10 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||
|
||||
// Remove the specified child from the linkset.
|
||||
// Safe to call even if the child is not really in the linkset.
|
||||
protected override void RemoveChildFromLinkset(BSPhysObject child)
|
||||
protected override void RemoveChildFromLinkset(BSPrimLinkable child)
|
||||
{
|
||||
child.ClearDisplacement();
|
||||
|
||||
if (m_children.Remove(child))
|
||||
{
|
||||
DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
|
||||
@@ -424,69 +413,65 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||
// The center of mass for the linkset is the geometric center of the group.
|
||||
// Compute a displacement for each component so it is relative to the center-of-mass.
|
||||
// Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
|
||||
OMV.Vector3 centerOfMass;
|
||||
OMV.Vector3 centerDisplacement = OMV.Vector3.Zero;
|
||||
if (disableCOM) // DEBUG DEBUG
|
||||
{ // DEBUG DEBUG
|
||||
centerOfMass = LinksetRoot.RawPosition; // DEBUG DEBUG
|
||||
LinksetRoot.PositionDisplacement = OMV.Vector3.Zero;
|
||||
} // DEBUG DEBUG
|
||||
else
|
||||
OMV.Vector3 centerOfMassW = LinksetRoot.RawPosition;
|
||||
if (!disableCOM) // DEBUG DEBUG
|
||||
{
|
||||
centerOfMass = ComputeLinksetCenterOfMass();
|
||||
// 'centerDisplacement' is the value to *add* to all the shape offsets
|
||||
centerDisplacement = LinksetRoot.RawPosition - centerOfMass;
|
||||
|
||||
// Since we're displacing the center of the shape, we need to move the body in the world
|
||||
LinksetRoot.PositionDisplacement = centerDisplacement;
|
||||
|
||||
// This causes the root prim position to be set properly based on the new PositionDisplacement
|
||||
LinksetRoot.ForcePosition = LinksetRoot.RawPosition;
|
||||
// Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM
|
||||
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0, -centerDisplacement, OMV.Quaternion.Identity, false);
|
||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
|
||||
LinksetRoot.LocalID, centerOfMass, LinksetRoot.RawPosition, centerDisplacement);
|
||||
// Compute a center-of-mass in world coordinates.
|
||||
centerOfMassW = ComputeLinksetCenterOfMass();
|
||||
}
|
||||
|
||||
OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
|
||||
|
||||
// 'centerDisplacement' is the value to subtract from children to give physical offset position
|
||||
OMV.Vector3 centerDisplacement = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation;
|
||||
LinksetRoot.SetEffectiveCenterOfMassW(centerDisplacement);
|
||||
|
||||
// This causes the physical position of the root prim to be offset to accomodate for the displacements
|
||||
LinksetRoot.ForcePosition = LinksetRoot.RawPosition;
|
||||
|
||||
// Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM
|
||||
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0 /* childIndex */,
|
||||
-centerDisplacement,
|
||||
OMV.Quaternion.Identity, // LinksetRoot.RawOrientation,
|
||||
false /* shouldRecalculateLocalAabb (is done later after linkset built) */);
|
||||
|
||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
|
||||
LinksetRoot.LocalID, centerOfMassW, LinksetRoot.RawPosition, centerDisplacement);
|
||||
|
||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
|
||||
LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
|
||||
|
||||
// Add a shape for each of the other children in the linkset
|
||||
int memberIndex = 1;
|
||||
ForEachMember(delegate(BSPhysObject cPrim)
|
||||
ForEachMember(delegate(BSPrimLinkable cPrim)
|
||||
{
|
||||
if (!IsRoot(cPrim))
|
||||
if (IsRoot(cPrim))
|
||||
{
|
||||
// Compute the displacement of the child from the root of the linkset.
|
||||
// This info is saved in the child prim so the relationship does not
|
||||
// change over time and the new child position can be computed
|
||||
// when the linkset is being disassembled (the linkset may have moved).
|
||||
BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo;
|
||||
if (lci == null)
|
||||
{
|
||||
lci = new BSLinksetCompoundInfo(memberIndex, LinksetRoot, cPrim, centerDisplacement);
|
||||
cPrim.LinksetInfo = lci;
|
||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
|
||||
}
|
||||
|
||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},lci={3}",
|
||||
LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci);
|
||||
cPrim.LinksetChildIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cPrim.LinksetChildIndex = memberIndex;
|
||||
|
||||
if (cPrim.PhysShape.isNativeShape)
|
||||
{
|
||||
// A native shape is turned into a hull collision shape because native
|
||||
// shapes are not shared so we have to hullify it so it will be tracked
|
||||
// and freed at the correct time. This also solves the scaling problem
|
||||
// (native shapes scaled but hull/meshes are assumed to not be).
|
||||
// (native shapes scale but hull/meshes are assumed to not be).
|
||||
// TODO: decide of the native shape can just be used in the compound shape.
|
||||
// Use call to CreateGeomNonSpecial().
|
||||
BulletShape saveShape = cPrim.PhysShape;
|
||||
cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
|
||||
// PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null);
|
||||
PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
|
||||
BulletShape newShape = cPrim.PhysShape;
|
||||
cPrim.PhysShape = saveShape;
|
||||
PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetFromCenterOfMass, lci.OffsetRot);
|
||||
|
||||
OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
|
||||
OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
|
||||
PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
|
||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
|
||||
LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -498,9 +483,13 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||
PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
|
||||
LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
|
||||
}
|
||||
PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetFromCenterOfMass, lci.OffsetRot);
|
||||
OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
|
||||
OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
|
||||
PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
|
||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNonNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
|
||||
LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
|
||||
|
||||
}
|
||||
lci.Index = memberIndex;
|
||||
memberIndex++;
|
||||
}
|
||||
return false; // 'false' says to move onto the next child in the list
|
||||
@@ -509,12 +498,16 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||
// With all of the linkset packed into the root prim, it has the mass of everyone.
|
||||
LinksetMass = ComputeLinksetMass();
|
||||
LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
|
||||
|
||||
// Enable the physical position updator to return the position and rotation of the root shape
|
||||
PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Rebuilding = false;
|
||||
}
|
||||
|
||||
// See that the Aabb surrounds the new shape
|
||||
PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||
{
|
||||
// private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";
|
||||
|
||||
public BSLinksetConstraints(BSScene scene, BSPhysObject parent) : base(scene, parent)
|
||||
public BSLinksetConstraints(BSScene scene, BSPrimLinkable parent) : base(scene, parent)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||
// its internal properties.
|
||||
// This is queued in the 'post taint' queue so the
|
||||
// refresh will happen once after all the other taints are applied.
|
||||
public override void Refresh(BSPhysObject requestor)
|
||||
public override void Refresh(BSPrimLinkable requestor)
|
||||
{
|
||||
base.Refresh(requestor);
|
||||
|
||||
@@ -65,7 +65,7 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||
// has not yet been fully constructed.
|
||||
// Return 'true' if any properties updated on the passed object.
|
||||
// Called at taint-time!
|
||||
public override bool MakeDynamic(BSPhysObject child)
|
||||
public override bool MakeDynamic(BSPrimLinkable child)
|
||||
{
|
||||
// What is done for each object in BSPrim is what we want.
|
||||
return false;
|
||||
@@ -76,14 +76,14 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||
// This doesn't normally happen -- OpenSim removes the objects from the physical
|
||||
// world if it is a static linkset.
|
||||
// Called at taint-time!
|
||||
public override bool MakeStatic(BSPhysObject child)
|
||||
public override bool MakeStatic(BSPrimLinkable child)
|
||||
{
|
||||
// What is done for each object in BSPrim is what we want.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Called at taint-time!!
|
||||
public override void UpdateProperties(UpdatedProperties whichUpdated, BSPhysObject pObj)
|
||||
public override void UpdateProperties(UpdatedProperties whichUpdated, BSPrimLinkable pObj)
|
||||
{
|
||||
// Nothing to do for constraints on property updates
|
||||
}
|
||||
@@ -93,7 +93,7 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||
// up to rebuild the constraints before the next simulation step.
|
||||
// Returns 'true' of something was actually removed and would need restoring
|
||||
// Called at taint-time!!
|
||||
public override bool RemoveBodyDependencies(BSPrim child)
|
||||
public override bool RemoveBodyDependencies(BSPrimLinkable child)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
@@ -114,7 +114,7 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||
|
||||
// Add a new child to the linkset.
|
||||
// Called while LinkActivity is locked.
|
||||
protected override void AddChildToLinkset(BSPhysObject child)
|
||||
protected override void AddChildToLinkset(BSPrimLinkable child)
|
||||
{
|
||||
if (!HasChild(child))
|
||||
{
|
||||
@@ -130,12 +130,12 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||
|
||||
// Remove the specified child from the linkset.
|
||||
// Safe to call even if the child is not really in my linkset.
|
||||
protected override void RemoveChildFromLinkset(BSPhysObject child)
|
||||
protected override void RemoveChildFromLinkset(BSPrimLinkable child)
|
||||
{
|
||||
if (m_children.Remove(child))
|
||||
{
|
||||
BSPhysObject rootx = LinksetRoot; // capture the root and body as of now
|
||||
BSPhysObject childx = child;
|
||||
BSPrimLinkable rootx = LinksetRoot; // capture the root and body as of now
|
||||
BSPrimLinkable childx = child;
|
||||
|
||||
DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
|
||||
childx.LocalID,
|
||||
@@ -159,13 +159,13 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||
|
||||
// Create a constraint between me (root of linkset) and the passed prim (the child).
|
||||
// Called at taint time!
|
||||
private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
|
||||
private void PhysicallyLinkAChildToRoot(BSPrimLinkable rootPrim, BSPrimLinkable childPrim)
|
||||
{
|
||||
// Don't build the constraint when asked. Put it off until just before the simulation step.
|
||||
Refresh(rootPrim);
|
||||
}
|
||||
|
||||
private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim)
|
||||
private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSPrimLinkable childPrim)
|
||||
{
|
||||
// Zero motion for children so they don't interpolate
|
||||
childPrim.ZeroMotion(true);
|
||||
@@ -239,7 +239,7 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||
// The root and child bodies are passed in because we need to remove the constraint between
|
||||
// the bodies that were present at unlink time.
|
||||
// Called at taint time!
|
||||
private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
|
||||
private bool PhysicallyUnlinkAChildFromRoot(BSPrimLinkable rootPrim, BSPrimLinkable childPrim)
|
||||
{
|
||||
bool ret = false;
|
||||
DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
|
||||
@@ -261,7 +261,7 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||
// Remove linkage between myself and any possible children I might have.
|
||||
// Returns 'true' of any constraints were destroyed.
|
||||
// Called at taint time!
|
||||
private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
|
||||
private bool PhysicallyUnlinkAllChildrenFromRoot(BSPrimLinkable rootPrim)
|
||||
{
|
||||
DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);
|
||||
|
||||
@@ -281,7 +281,7 @@ public sealed class BSLinksetConstraints : BSLinkset
|
||||
DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}",
|
||||
LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, linksetMass);
|
||||
|
||||
foreach (BSPhysObject child in m_children)
|
||||
foreach (BSPrimLinkable child in m_children)
|
||||
{
|
||||
// A child in the linkset physically shows the mass of the whole linkset.
|
||||
// This allows Bullet to apply enough force on the child to move the whole linkset.
|
||||
|
||||
@@ -49,6 +49,7 @@ public static class BSParam
|
||||
public static float MaxLinearVelocity { get; private set; }
|
||||
public static float MaxAngularVelocity { get; private set; }
|
||||
public static float MaxAddForceMagnitude { get; private set; }
|
||||
public static float DensityScaleFactor { get; private set; }
|
||||
|
||||
public static float LinearDamping { get; private set; }
|
||||
public static float AngularDamping { get; private set; }
|
||||
@@ -87,6 +88,7 @@ public static class BSParam
|
||||
public static float NumberOfSolverIterations;
|
||||
public static bool UseSingleSidedMeshes { get { return UseSingleSidedMeshesF != ConfigurationParameters.numericFalse; } }
|
||||
public static float UseSingleSidedMeshesF;
|
||||
public static float GlobalContactBreakingThreshold;
|
||||
|
||||
// Avatar parameters
|
||||
public static float AvatarFriction { get; private set; }
|
||||
@@ -280,29 +282,35 @@ public static class BSParam
|
||||
new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)",
|
||||
0.0001f,
|
||||
(s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); },
|
||||
(s) => { return (float)MinimumObjectMass; },
|
||||
(s) => { return MinimumObjectMass; },
|
||||
(s,p,l,v) => { MinimumObjectMass = v; } ),
|
||||
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
|
||||
10000.01f,
|
||||
(s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); },
|
||||
(s) => { return (float)MaximumObjectMass; },
|
||||
(s) => { return MaximumObjectMass; },
|
||||
(s,p,l,v) => { MaximumObjectMass = v; } ),
|
||||
new ParameterDefn("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object",
|
||||
1000.0f,
|
||||
(s,cf,p,v) => { MaxLinearVelocity = cf.GetFloat(p, v); },
|
||||
(s) => { return (float)MaxLinearVelocity; },
|
||||
(s) => { return MaxLinearVelocity; },
|
||||
(s,p,l,v) => { MaxLinearVelocity = v; } ),
|
||||
new ParameterDefn("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object",
|
||||
1000.0f,
|
||||
(s,cf,p,v) => { MaxAngularVelocity = cf.GetFloat(p, v); },
|
||||
(s) => { return (float)MaxAngularVelocity; },
|
||||
(s) => { return MaxAngularVelocity; },
|
||||
(s,p,l,v) => { MaxAngularVelocity = v; } ),
|
||||
// LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject
|
||||
new ParameterDefn("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)",
|
||||
20000.0f,
|
||||
(s,cf,p,v) => { MaxAddForceMagnitude = cf.GetFloat(p, v); },
|
||||
(s) => { return (float)MaxAddForceMagnitude; },
|
||||
(s) => { return MaxAddForceMagnitude; },
|
||||
(s,p,l,v) => { MaxAddForceMagnitude = v; } ),
|
||||
// Density is passed around as 100kg/m3. This scales that to 1kg/m3.
|
||||
new ParameterDefn("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)",
|
||||
0.01f,
|
||||
(s,cf,p,v) => { DensityScaleFactor = cf.GetFloat(p, v); },
|
||||
(s) => { return DensityScaleFactor; },
|
||||
(s,p,l,v) => { DensityScaleFactor = v; } ),
|
||||
|
||||
new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
|
||||
2200f,
|
||||
@@ -424,7 +432,7 @@ public static class BSParam
|
||||
(s) => { return AvatarFriction; },
|
||||
(s,p,l,v) => { AvatarFriction = v; } ),
|
||||
new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.",
|
||||
10.0f,
|
||||
0.95f,
|
||||
(s,cf,p,v) => { AvatarStandingFriction = cf.GetFloat(p, v); },
|
||||
(s) => { return AvatarStandingFriction; },
|
||||
(s,p,l,v) => { AvatarStandingFriction = v; } ),
|
||||
@@ -570,6 +578,11 @@ public static class BSParam
|
||||
(s,cf,p,v) => { UseSingleSidedMeshesF = BSParam.NumericBool(cf.GetBoolean(p, BSParam.BoolNumeric(v))); },
|
||||
(s) => { return UseSingleSidedMeshesF; },
|
||||
(s,p,l,v) => { UseSingleSidedMeshesF = v; s.UnmanagedParams[0].useSingleSidedMeshes = v; } ),
|
||||
new ParameterDefn("GlobalContactBreakingThreshold", "Amount of shape radius before breaking a collision contact (0 says Bullet default (0.2))",
|
||||
0f,
|
||||
(s,cf,p,v) => { GlobalContactBreakingThreshold = cf.GetFloat(p, v); },
|
||||
(s) => { return GlobalContactBreakingThreshold; },
|
||||
(s,p,l,v) => { GlobalContactBreakingThreshold = v; s.UnmanagedParams[0].globalContactBreakingThreshold = v; } ),
|
||||
|
||||
new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)",
|
||||
(float)BSLinkset.LinksetImplementation.Compound,
|
||||
|
||||
@@ -86,10 +86,6 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
PhysBody = new BulletBody(localID);
|
||||
PhysShape = new BulletShape();
|
||||
|
||||
// A linkset of just me
|
||||
Linkset = BSLinkset.Factory(PhysicsScene, this);
|
||||
PositionDisplacement = OMV.Vector3.Zero;
|
||||
|
||||
LastAssetBuildFailed = false;
|
||||
|
||||
// Default material type. Also sets Friction, Restitution and Density.
|
||||
@@ -103,6 +99,9 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
CollisionAccumulation = 0;
|
||||
ColliderIsMoving = false;
|
||||
CollisionScore = 0;
|
||||
|
||||
// All axis free.
|
||||
LockedAxis = LockedAxisFree;
|
||||
}
|
||||
|
||||
// Tell the object to clean up.
|
||||
@@ -117,8 +116,6 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
public string PhysObjectName { get; protected set; }
|
||||
public string TypeName { get; protected set; }
|
||||
|
||||
public BSLinkset Linkset { get; set; }
|
||||
public BSLinksetInfo LinksetInfo { get; set; }
|
||||
|
||||
// Return the object mass without calculating it or having side effects
|
||||
public abstract float RawMass { get; }
|
||||
@@ -142,6 +139,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
|
||||
// The objects base shape information. Null if not a prim type shape.
|
||||
public PrimitiveBaseShape BaseShape { get; protected set; }
|
||||
|
||||
// Some types of objects have preferred physical representations.
|
||||
// Returns SHAPE_UNKNOWN if there is no preference.
|
||||
public virtual BSPhysicsShapeType PreferredPhysicalShape
|
||||
@@ -156,15 +154,17 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
public EntityProperties LastEntityProperties { get; set; }
|
||||
|
||||
public virtual OMV.Vector3 Scale { get; set; }
|
||||
public abstract bool IsSolid { get; }
|
||||
public abstract bool IsStatic { get; }
|
||||
public abstract bool IsSelected { get; }
|
||||
|
||||
// It can be confusing for an actor to know if it should move or update an object
|
||||
// depeneding on the setting of 'selected', 'physical, ...
|
||||
// This flag is the true test -- if true, the object is being acted on in the physical world
|
||||
public abstract bool IsPhysicallyActive { get; }
|
||||
|
||||
// Detailed state of the object.
|
||||
public abstract bool IsSolid { get; }
|
||||
public abstract bool IsStatic { get; }
|
||||
public abstract bool IsSelected { get; }
|
||||
|
||||
// Materialness
|
||||
public MaterialAttributes.Material Material { get; private set; }
|
||||
public override void SetMaterial(int material)
|
||||
@@ -175,7 +175,8 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
|
||||
Friction = matAttrib.friction;
|
||||
Restitution = matAttrib.restitution;
|
||||
Density = matAttrib.density;
|
||||
Density = matAttrib.density / BSParam.DensityScaleFactor;
|
||||
DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density);
|
||||
}
|
||||
|
||||
// Stop all physical motion.
|
||||
@@ -188,26 +189,9 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
public abstract OMV.Vector3 RawPosition { get; set; }
|
||||
public abstract OMV.Vector3 ForcePosition { get; set; }
|
||||
|
||||
// 'Position' and 'Orientation' is what the simulator thinks the positions of the prim is.
|
||||
// Because Bullet needs the zero coordinate to be the center of mass of the linkset,
|
||||
// sometimes it is necessary to displace the position the physics engine thinks
|
||||
// the position is. PositionDisplacement must be added and removed from the
|
||||
// position as the simulator position is stored and fetched from the physics
|
||||
// engine. Similar to OrientationDisplacement.
|
||||
public virtual OMV.Vector3 PositionDisplacement { get; set; }
|
||||
public virtual OMV.Quaternion OrientationDisplacement { get; set; }
|
||||
|
||||
public abstract OMV.Quaternion RawOrientation { get; set; }
|
||||
public abstract OMV.Quaternion ForceOrientation { get; set; }
|
||||
|
||||
public virtual float TargetSpeed
|
||||
{
|
||||
get
|
||||
{
|
||||
OMV.Vector3 characterOrientedVelocity = TargetVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
|
||||
return characterOrientedVelocity.X;
|
||||
}
|
||||
}
|
||||
public abstract OMV.Vector3 RawVelocity { get; set; }
|
||||
public abstract OMV.Vector3 ForceVelocity { get; set; }
|
||||
|
||||
@@ -217,6 +201,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
|
||||
public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
|
||||
|
||||
// The current velocity forward
|
||||
public virtual float ForwardSpeed
|
||||
{
|
||||
get
|
||||
@@ -225,6 +210,22 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
return characterOrientedVelocity.X;
|
||||
}
|
||||
}
|
||||
// The forward speed we are trying to achieve (TargetVelocity)
|
||||
public virtual float TargetVelocitySpeed
|
||||
{
|
||||
get
|
||||
{
|
||||
OMV.Vector3 characterOrientedVelocity = TargetVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
|
||||
return characterOrientedVelocity.X;
|
||||
}
|
||||
}
|
||||
|
||||
// The user can optionally set the center of mass. The user's setting will override any
|
||||
// computed center-of-mass (like in linksets).
|
||||
public OMV.Vector3? UserSetCenterOfMass { get; set; }
|
||||
|
||||
public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free.
|
||||
public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free
|
||||
|
||||
#region Collisions
|
||||
|
||||
@@ -302,22 +303,16 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
CollidingObjectStep = PhysicsScene.SimulationStep;
|
||||
}
|
||||
|
||||
// prims in the same linkset cannot collide with each other
|
||||
if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID))
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
CollisionAccumulation++;
|
||||
|
||||
// For movement tests, remember if we are colliding with an object that is moving.
|
||||
ColliderIsMoving = collidee != null ? collidee.RawVelocity != OMV.Vector3.Zero : false;
|
||||
ColliderIsMoving = collidee != null ? (collidee.RawVelocity != OMV.Vector3.Zero) : false;
|
||||
|
||||
// If someone has subscribed for collision events log the collision so it will be reported up
|
||||
if (SubscribedEvents()) {
|
||||
CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
|
||||
DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}",
|
||||
LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth);
|
||||
DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5},colliderMoving={6}",
|
||||
LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth, ColliderIsMoving);
|
||||
|
||||
ret = true;
|
||||
}
|
||||
@@ -428,9 +423,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
{
|
||||
// Clean out any existing action
|
||||
UnRegisterPreStepAction(op, id);
|
||||
|
||||
RegisteredPrestepActions[identifier] = actn;
|
||||
|
||||
PhysicsScene.BeforeStep += actn;
|
||||
}
|
||||
DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
|
||||
@@ -476,9 +469,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
{
|
||||
// Clean out any existing action
|
||||
UnRegisterPostStepAction(op, id);
|
||||
|
||||
RegisteredPoststepActions[identifier] = actn;
|
||||
|
||||
PhysicsScene.AfterStep += actn;
|
||||
}
|
||||
DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier);
|
||||
@@ -515,7 +506,58 @@ public abstract class BSPhysObject : PhysicsActor
|
||||
}
|
||||
DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID);
|
||||
}
|
||||
|
||||
|
||||
// When an update to the physical properties happens, this event is fired to let
|
||||
// different actors to modify the update before it is passed around
|
||||
public delegate void PreUpdatePropertyAction(ref EntityProperties entprop);
|
||||
public event PreUpdatePropertyAction OnPreUpdateProperty;
|
||||
protected void TriggerPreUpdatePropertyAction(ref EntityProperties entprop)
|
||||
{
|
||||
PreUpdatePropertyAction actions = OnPreUpdateProperty;
|
||||
if (actions != null)
|
||||
actions(ref entprop);
|
||||
}
|
||||
|
||||
private Dictionary<string, PreUpdatePropertyAction> RegisteredPreUpdatePropertyActions = new Dictionary<string, PreUpdatePropertyAction>();
|
||||
public void RegisterPreUpdatePropertyAction(string identifier, PreUpdatePropertyAction actn)
|
||||
{
|
||||
lock (RegisteredPreUpdatePropertyActions)
|
||||
{
|
||||
// Clean out any existing action
|
||||
UnRegisterPreUpdatePropertyAction(identifier);
|
||||
RegisteredPreUpdatePropertyActions[identifier] = actn;
|
||||
OnPreUpdateProperty += actn;
|
||||
}
|
||||
DetailLog("{0},BSPhysObject.RegisterPreUpdatePropertyAction,id={1}", LocalID, identifier);
|
||||
}
|
||||
public bool UnRegisterPreUpdatePropertyAction(string identifier)
|
||||
{
|
||||
bool removed = false;
|
||||
lock (RegisteredPreUpdatePropertyActions)
|
||||
{
|
||||
if (RegisteredPreUpdatePropertyActions.ContainsKey(identifier))
|
||||
{
|
||||
OnPreUpdateProperty -= RegisteredPreUpdatePropertyActions[identifier];
|
||||
RegisteredPreUpdatePropertyActions.Remove(identifier);
|
||||
removed = true;
|
||||
}
|
||||
}
|
||||
DetailLog("{0},BSPhysObject.UnRegisterPreUpdatePropertyAction,id={1},removed={2}", LocalID, identifier, removed);
|
||||
return removed;
|
||||
}
|
||||
public void UnRegisterAllPreUpdatePropertyActions()
|
||||
{
|
||||
lock (RegisteredPreUpdatePropertyActions)
|
||||
{
|
||||
foreach (KeyValuePair<string, PreUpdatePropertyAction> kvp in RegisteredPreUpdatePropertyActions)
|
||||
{
|
||||
OnPreUpdateProperty -= kvp.Value;
|
||||
}
|
||||
RegisteredPreUpdatePropertyActions.Clear();
|
||||
}
|
||||
DetailLog("{0},BSPhysObject.UnRegisterAllPreUpdatePropertyAction,", LocalID);
|
||||
}
|
||||
|
||||
#endregion // Per Simulation Step actions
|
||||
|
||||
// High performance detailed logging routine used by the physical objects.
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
|
||||
[Serializable]
|
||||
public sealed class BSPrim : BSPhysObject
|
||||
public class BSPrim : BSPhysObject
|
||||
{
|
||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private static readonly string LogHeader = "[BULLETS PRIM]";
|
||||
@@ -102,9 +102,6 @@ public sealed class BSPrim : BSPhysObject
|
||||
|
||||
_mass = CalculateMass();
|
||||
|
||||
// Cause linkset variables to be initialized (like mass)
|
||||
Linkset.Refresh(this);
|
||||
|
||||
DetailLog("{0},BSPrim.constructor,call", LocalID);
|
||||
// do the actual object creation at taint time
|
||||
PhysicsScene.TaintedObject("BSPrim.create", delegate()
|
||||
@@ -121,15 +118,6 @@ public sealed class BSPrim : BSPhysObject
|
||||
// m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID);
|
||||
base.Destroy();
|
||||
|
||||
// Undo any links between me and any other object
|
||||
BSPhysObject parentBefore = Linkset.LinksetRoot; // DEBUG DEBUG
|
||||
int childrenBefore = Linkset.NumberOfChildren; // DEBUG DEBUG
|
||||
|
||||
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
|
||||
this.VehicleType = (int)Vehicle.TYPE_NONE;
|
||||
|
||||
@@ -166,9 +154,9 @@ public sealed class BSPrim : BSPhysObject
|
||||
ForceBodyShapeRebuild(false);
|
||||
}
|
||||
}
|
||||
// Whatever the linkset wants is what I want.
|
||||
// 'unknown' says to choose the best type
|
||||
public override BSPhysicsShapeType PreferredPhysicalShape
|
||||
{ get { return Linkset.PreferredPhysicalShape(this); } }
|
||||
{ get { return BSPhysicsShapeType.SHAPE_UNKNOWN; } }
|
||||
|
||||
public override bool ForceBodyShapeRebuild(bool inTaintTime)
|
||||
{
|
||||
@@ -213,33 +201,10 @@ public sealed class BSPrim : BSPhysObject
|
||||
|
||||
// link me to the specified parent
|
||||
public override void link(PhysicsActor obj) {
|
||||
BSPrim parent = obj as BSPrim;
|
||||
if (parent != null)
|
||||
{
|
||||
BSPhysObject parentBefore = Linkset.LinksetRoot;
|
||||
int childrenBefore = Linkset.NumberOfChildren;
|
||||
|
||||
Linkset = parent.Linkset.AddMeToLinkset(this);
|
||||
|
||||
DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
|
||||
LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// delink me from my linkset
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Set motion values to zero.
|
||||
@@ -277,6 +242,45 @@ public sealed class BSPrim : BSPhysObject
|
||||
public override void LockAngularMotion(OMV.Vector3 axis)
|
||||
{
|
||||
DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
|
||||
|
||||
OMV.Vector3 locking = new OMV.Vector3(1f, 1f, 1f);
|
||||
if (axis.X != 1) locking.X = 0f;
|
||||
if (axis.Y != 1) locking.Y = 0f;
|
||||
if (axis.Z != 1) locking.Z = 0f;
|
||||
LockedAxis = locking;
|
||||
|
||||
/* Not implemented yet
|
||||
if (LockedAxis != LockedAxisFree)
|
||||
{
|
||||
// Something is locked so start the thingy that keeps that axis from changing
|
||||
RegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion", delegate(ref EntityProperties entprop)
|
||||
{
|
||||
if (LockedAxis != LockedAxisFree)
|
||||
{
|
||||
if (IsPhysicallyActive)
|
||||
{
|
||||
// Bullet can lock axis but it only works for global axis.
|
||||
// Check if this prim is aligned on global axis and use Bullet's
|
||||
// system if so.
|
||||
|
||||
ForceOrientation = entprop.Rotation;
|
||||
ForceRotationalVelocity = entprop.RotationalVelocity;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UnRegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion");
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// Everything seems unlocked
|
||||
UnRegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion");
|
||||
}
|
||||
*/
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -287,15 +291,8 @@ public sealed class BSPrim : BSPhysObject
|
||||
}
|
||||
public override OMV.Vector3 Position {
|
||||
get {
|
||||
/* NOTE: this refetch is not necessary. The simulator knows about linkset children
|
||||
* and does not fetch this position info for children. Thus this is commented out.
|
||||
// child prims move around based on their parent. Need to get the latest location
|
||||
if (!Linkset.IsRoot(this))
|
||||
_position = Linkset.PositionGet(this);
|
||||
*/
|
||||
|
||||
// don't do the GetObjectPosition for root elements because this function is called a zillion times.
|
||||
// _position = PhysicsScene.PE.GetObjectPosition2(PhysicsScene.World, BSBody) - PositionDisplacement;
|
||||
// _position = ForcePosition;
|
||||
return _position;
|
||||
}
|
||||
set {
|
||||
@@ -313,24 +310,20 @@ public sealed class BSPrim : BSPhysObject
|
||||
{
|
||||
DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation);
|
||||
ForcePosition = _position;
|
||||
|
||||
// A linkset might need to know if a component information changed.
|
||||
Linkset.UpdateProperties(UpdatedProperties.Position, this);
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override OMV.Vector3 ForcePosition {
|
||||
get {
|
||||
_position = PhysicsScene.PE.GetPosition(PhysBody) - PositionDisplacement;
|
||||
_position = PhysicsScene.PE.GetPosition(PhysBody);
|
||||
return _position;
|
||||
}
|
||||
set {
|
||||
_position = value;
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
{
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
|
||||
ActivateIfPhysical(false);
|
||||
}
|
||||
}
|
||||
@@ -357,7 +350,8 @@ public sealed class BSPrim : BSPhysObject
|
||||
|
||||
float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
|
||||
OMV.Vector3 upForce = OMV.Vector3.Zero;
|
||||
if (RawPosition.Z < terrainHeight)
|
||||
float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z));
|
||||
if ((RawPosition.Z + approxSize / 2f) < terrainHeight)
|
||||
{
|
||||
DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, RawPosition, terrainHeight);
|
||||
float targetHeight = terrainHeight + (Size.Z / 2f);
|
||||
@@ -398,12 +392,13 @@ public sealed class BSPrim : BSPhysObject
|
||||
// If the simulator cares about the mass of the linkset, it will sum it itself.
|
||||
public override float Mass
|
||||
{
|
||||
get
|
||||
{
|
||||
return _mass;
|
||||
}
|
||||
get { return _mass; }
|
||||
}
|
||||
// TotalMass returns the mass of the large object the prim may be in (overridden by linkset code)
|
||||
public virtual float TotalMass
|
||||
{
|
||||
get { return _mass; }
|
||||
}
|
||||
|
||||
// used when we only want this prim's mass and not the linkset thing
|
||||
public override float RawMass {
|
||||
get { return _mass; }
|
||||
@@ -467,13 +462,13 @@ public sealed class BSPrim : BSPhysObject
|
||||
// Is this used?
|
||||
public override OMV.Vector3 CenterOfMass
|
||||
{
|
||||
get { return Linkset.CenterOfMass; }
|
||||
get { return RawPosition; }
|
||||
}
|
||||
|
||||
// Is this used?
|
||||
public override OMV.Vector3 GeometricCenter
|
||||
{
|
||||
get { return Linkset.GeometricCenter; }
|
||||
get { return RawPosition; }
|
||||
}
|
||||
|
||||
public override OMV.Vector3 Force {
|
||||
@@ -487,7 +482,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
RegisterPreStepAction("BSPrim.setForce", LocalID,
|
||||
delegate(float timeStep)
|
||||
{
|
||||
if (!IsPhysicallyActive)
|
||||
if (!IsPhysicallyActive || _force == OMV.Vector3.Zero)
|
||||
{
|
||||
UnRegisterPreStepAction("BSPrim.setForce", LocalID);
|
||||
return;
|
||||
@@ -621,6 +616,8 @@ public sealed class BSPrim : BSPhysObject
|
||||
}
|
||||
}
|
||||
}
|
||||
// The simulator/viewer keep density as 100kg/m3.
|
||||
// Remember to use BSParam.DensityScaleFactor to create the physical density.
|
||||
public override float Density
|
||||
{
|
||||
get { return base.Density; }
|
||||
@@ -692,7 +689,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
RegisterPreStepAction("BSPrim.setTorque", LocalID,
|
||||
delegate(float timeStep)
|
||||
{
|
||||
if (!IsPhysicallyActive)
|
||||
if (!IsPhysicallyActive || _torque == OMV.Vector3.Zero)
|
||||
{
|
||||
UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
|
||||
return;
|
||||
@@ -721,14 +718,6 @@ public sealed class BSPrim : BSPhysObject
|
||||
}
|
||||
public override OMV.Quaternion Orientation {
|
||||
get {
|
||||
/* NOTE: this refetch is not necessary. The simulator knows about linkset children
|
||||
* and does not fetch this position info for children. Thus this is commented out.
|
||||
// Children move around because tied to parent. Get a fresh value.
|
||||
if (!Linkset.IsRoot(this))
|
||||
{
|
||||
_orientation = Linkset.OrientationGet(this);
|
||||
}
|
||||
*/
|
||||
return _orientation;
|
||||
}
|
||||
set {
|
||||
@@ -739,10 +728,6 @@ public sealed class BSPrim : BSPhysObject
|
||||
PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
|
||||
{
|
||||
ForceOrientation = _orientation;
|
||||
|
||||
// A linkset might need to know if a component information changed.
|
||||
Linkset.UpdateProperties(UpdatedProperties.Orientation, this);
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -758,7 +743,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
{
|
||||
_orientation = value;
|
||||
if (PhysBody.HasPhysicalBody)
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position, _orientation);
|
||||
}
|
||||
}
|
||||
public override int PhysicsActorType {
|
||||
@@ -814,7 +799,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
// isSolid: other objects bounce off of this object
|
||||
// isVolumeDetect: other objects pass through but can generate collisions
|
||||
// collisionEvents: whether this object returns collision events
|
||||
public void UpdatePhysicalParameters()
|
||||
public virtual void UpdatePhysicalParameters()
|
||||
{
|
||||
if (!PhysBody.HasPhysicalBody)
|
||||
{
|
||||
@@ -844,12 +829,6 @@ public sealed class BSPrim : BSPhysObject
|
||||
// Rebuild its shape
|
||||
PhysicsScene.PE.UpdateSingleAabb(PhysicsScene.World, PhysBody);
|
||||
|
||||
// Recompute any linkset parameters.
|
||||
// When going from non-physical to physical, this re-enables the constraints that
|
||||
// had been automatically disabled when the mass was set to zero.
|
||||
// For compound based linksets, this enables and disables interactions of the children.
|
||||
Linkset.Refresh(this);
|
||||
|
||||
DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},cType={6},body={7},shape={8}",
|
||||
LocalID, IsStatic, IsSolid, Mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody.collisionType, PhysBody, PhysShape);
|
||||
}
|
||||
@@ -859,7 +838,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
// When dynamic, the object can fall and be pushed by others.
|
||||
// This is independent of its 'solidness' which controls what passes through
|
||||
// this object and what interacts with it.
|
||||
private void MakeDynamic(bool makeStatic)
|
||||
protected virtual void MakeDynamic(bool makeStatic)
|
||||
{
|
||||
if (makeStatic)
|
||||
{
|
||||
@@ -889,9 +868,6 @@ public sealed class BSPrim : BSPhysObject
|
||||
|
||||
// This collides like a static object
|
||||
PhysBody.collisionType = CollisionType.Static;
|
||||
|
||||
// There can be special things needed for implementing linksets
|
||||
Linkset.MakeStatic(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -908,10 +884,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
// PhysicsScene.PE.ClearAllForces(BSBody);
|
||||
|
||||
// For good measure, make sure the transform is set through to the motion state
|
||||
PhysicsScene.PE.SetTranslation(PhysBody, _position + PositionDisplacement, _orientation);
|
||||
|
||||
// Center of mass is at the center of the object
|
||||
// DEBUG DEBUG PhysicsScene.PE.SetCenterOfMassByPosRot(Linkset.LinksetRoot.PhysBody, _position, _orientation);
|
||||
ForcePosition = _position;
|
||||
|
||||
// A dynamic object has mass
|
||||
UpdatePhysicalMassProperties(RawMass, false);
|
||||
@@ -935,9 +908,6 @@ public sealed class BSPrim : BSPhysObject
|
||||
// Force activation of the object so Bullet will act on it.
|
||||
// Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects.
|
||||
PhysicsScene.PE.ForceActivationState(PhysBody, ActivationState.ACTIVE_TAG);
|
||||
|
||||
// There might be special things needed for implementing linksets.
|
||||
Linkset.MakeDynamic(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1641,17 +1611,8 @@ public sealed class BSPrim : BSPhysObject
|
||||
profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f;
|
||||
volume *= (profileEnd - profileBegin);
|
||||
|
||||
returnMass = Density * volume;
|
||||
|
||||
/* Comment out code that computes the mass of the linkset. That is done in the Linkset class.
|
||||
if (IsRootOfLinkset)
|
||||
{
|
||||
foreach (BSPrim prim in _childrenPrims)
|
||||
{
|
||||
returnMass += prim.CalculateMass();
|
||||
}
|
||||
}
|
||||
*/
|
||||
returnMass = Density * BSParam.DensityScaleFactor * volume;
|
||||
DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass);
|
||||
|
||||
returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass);
|
||||
|
||||
@@ -1672,8 +1633,7 @@ public sealed class BSPrim : BSPhysObject
|
||||
// Called if the current prim body is about to be destroyed.
|
||||
// Remove all the physical dependencies on the old body.
|
||||
// (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...)
|
||||
Linkset.RemoveBodyDependencies(this);
|
||||
VehicleController.RemoveBodyDependencies(this);
|
||||
RemoveBodyDependencies();
|
||||
});
|
||||
|
||||
// Make sure the properties are set on the new object
|
||||
@@ -1681,57 +1641,56 @@ public sealed class BSPrim : BSPhysObject
|
||||
return;
|
||||
}
|
||||
|
||||
protected virtual void RemoveBodyDependencies()
|
||||
{
|
||||
VehicleController.RemoveBodyDependencies(this);
|
||||
}
|
||||
|
||||
// The physics engine says that properties have updated. Update same and inform
|
||||
// the world that things have changed.
|
||||
public override void UpdateProperties(EntityProperties entprop)
|
||||
{
|
||||
// Updates only for individual prims and for the root object of a linkset.
|
||||
if (Linkset.IsRoot(this))
|
||||
TriggerPreUpdatePropertyAction(ref entprop);
|
||||
|
||||
// A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
|
||||
// TODO: handle physics introduced by Bullet with computed vehicle physics.
|
||||
if (VehicleController.IsActive)
|
||||
{
|
||||
// A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
|
||||
// TODO: handle physics introduced by Bullet with computed vehicle physics.
|
||||
if (VehicleController.IsActive)
|
||||
{
|
||||
entprop.RotationalVelocity = OMV.Vector3.Zero;
|
||||
}
|
||||
|
||||
// DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG
|
||||
|
||||
// Undo any center-of-mass displacement that might have been done.
|
||||
if (PositionDisplacement != OMV.Vector3.Zero)
|
||||
{
|
||||
// Correct for any rotation around the center-of-mass
|
||||
// TODO!!!
|
||||
entprop.Position -= PositionDisplacement;
|
||||
}
|
||||
|
||||
// Assign directly to the local variables so the normal set actions do not happen
|
||||
_position = entprop.Position;
|
||||
_orientation = entprop.Rotation;
|
||||
_velocity = entprop.Velocity;
|
||||
_acceleration = entprop.Acceleration;
|
||||
_rotationalVelocity = entprop.RotationalVelocity;
|
||||
|
||||
// DetailLog("{0},BSPrim.UpdateProperties,afterAssign,entprop={1}", LocalID, entprop); // DEBUG DEBUG
|
||||
|
||||
// The sanity check can change the velocity and/or position.
|
||||
if (PositionSanityCheck(true /* inTaintTime */ ))
|
||||
{
|
||||
entprop.Position = _position;
|
||||
entprop.Velocity = _velocity;
|
||||
entprop.RotationalVelocity = _rotationalVelocity;
|
||||
entprop.Acceleration = _acceleration;
|
||||
}
|
||||
|
||||
OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG
|
||||
DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction);
|
||||
|
||||
// remember the current and last set values
|
||||
LastEntityProperties = CurrentEntityProperties;
|
||||
CurrentEntityProperties = entprop;
|
||||
|
||||
base.RequestPhysicsterseUpdate();
|
||||
entprop.RotationalVelocity = OMV.Vector3.Zero;
|
||||
}
|
||||
|
||||
// DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG
|
||||
|
||||
// Assign directly to the local variables so the normal set actions do not happen
|
||||
_position = entprop.Position;
|
||||
_orientation = entprop.Rotation;
|
||||
// _velocity = entprop.Velocity;
|
||||
// DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be
|
||||
// very sensitive to velocity changes.
|
||||
if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f))
|
||||
_velocity = entprop.Velocity;
|
||||
_acceleration = entprop.Acceleration;
|
||||
_rotationalVelocity = entprop.RotationalVelocity;
|
||||
|
||||
// DetailLog("{0},BSPrim.UpdateProperties,afterAssign,entprop={1}", LocalID, entprop); // DEBUG DEBUG
|
||||
|
||||
// The sanity check can change the velocity and/or position.
|
||||
if (PositionSanityCheck(true /* inTaintTime */ ))
|
||||
{
|
||||
entprop.Position = _position;
|
||||
entprop.Velocity = _velocity;
|
||||
entprop.RotationalVelocity = _rotationalVelocity;
|
||||
entprop.Acceleration = _acceleration;
|
||||
}
|
||||
|
||||
OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG
|
||||
DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction);
|
||||
|
||||
// remember the current and last set values
|
||||
LastEntityProperties = CurrentEntityProperties;
|
||||
CurrentEntityProperties = entprop;
|
||||
|
||||
base.RequestPhysicsterseUpdate();
|
||||
/*
|
||||
else
|
||||
{
|
||||
@@ -1741,9 +1700,6 @@ public sealed class BSPrim : BSPhysObject
|
||||
entprop.Acceleration, entprop.RotationalVelocity);
|
||||
}
|
||||
*/
|
||||
|
||||
// The linkset implimentation might want to know about this.
|
||||
Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
153
OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
Executable file
153
OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
Executable file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* The quotations from http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial
|
||||
* are Copyright (c) 2009 Linden Research, Inc and are used under their license
|
||||
* of Creative Commons Attribution-Share Alike 3.0
|
||||
* (http://creativecommons.org/licenses/by-sa/3.0/).
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using OpenMetaverse;
|
||||
using OpenSim.Framework;
|
||||
using OpenSim.Region.Physics.Manager;
|
||||
|
||||
using OMV = OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
public class BSPrimDisplaced : BSPrim
|
||||
{
|
||||
// The purpose of this module is to do any mapping between what the simulator thinks
|
||||
// the prim position and orientation is and what the physical position/orientation.
|
||||
// This difference happens because Bullet assumes the center-of-mass is the <0,0,0>
|
||||
// of the prim/linkset. The simulator tracks the location of the prim/linkset by
|
||||
// the location of the root prim. So, if center-of-mass is anywhere but the origin
|
||||
// of the root prim, the physical origin is displaced from the simulator origin.
|
||||
//
|
||||
// This routine works by capturing the Force* setting of position/orientation/... and
|
||||
// adjusting the simulator values (being set) into the physical values.
|
||||
// The conversion is also done in the opposite direction (physical origin -> simulator origin).
|
||||
//
|
||||
// The updateParameter call is also captured and the values from the physics engine
|
||||
// are converted into simulator origin values before being passed to the base
|
||||
// class.
|
||||
|
||||
public virtual OMV.Vector3 PositionDisplacement { get; set; }
|
||||
public virtual OMV.Quaternion OrientationDisplacement { get; set; }
|
||||
|
||||
public BSPrimDisplaced(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
|
||||
OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
|
||||
: base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical)
|
||||
{
|
||||
ClearDisplacement();
|
||||
}
|
||||
|
||||
public void ClearDisplacement()
|
||||
{
|
||||
PositionDisplacement = OMV.Vector3.Zero;
|
||||
OrientationDisplacement = OMV.Quaternion.Identity;
|
||||
}
|
||||
|
||||
// Set this sets and computes the displacement from the passed prim to the center-of-mass.
|
||||
// A user set value for center-of-mass overrides whatever might be passed in here.
|
||||
// The displacement is in local coordinates (relative to root prim in linkset oriented coordinates).
|
||||
public virtual void SetEffectiveCenterOfMassW(Vector3 centerOfMassDisplacement)
|
||||
{
|
||||
Vector3 comDisp;
|
||||
if (UserSetCenterOfMass.HasValue)
|
||||
comDisp = (OMV.Vector3)UserSetCenterOfMass;
|
||||
else
|
||||
comDisp = centerOfMassDisplacement;
|
||||
|
||||
if (comDisp == Vector3.Zero)
|
||||
{
|
||||
// If there is no diplacement. Things get reset.
|
||||
PositionDisplacement = OMV.Vector3.Zero;
|
||||
OrientationDisplacement = OMV.Quaternion.Identity;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remember the displacement from root as well as the origional rotation of the
|
||||
// new center-of-mass.
|
||||
PositionDisplacement = comDisp;
|
||||
OrientationDisplacement = OMV.Quaternion.Identity;
|
||||
}
|
||||
}
|
||||
|
||||
public override Vector3 ForcePosition
|
||||
{
|
||||
get { return base.ForcePosition; }
|
||||
set
|
||||
{
|
||||
if (PositionDisplacement != OMV.Vector3.Zero)
|
||||
base.ForcePosition = value - (PositionDisplacement * RawOrientation);
|
||||
else
|
||||
base.ForcePosition = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override Quaternion ForceOrientation
|
||||
{
|
||||
get { return base.ForceOrientation; }
|
||||
set
|
||||
{
|
||||
base.ForceOrientation = value;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: decide if this is the right place for these variables.
|
||||
// Somehow incorporate the optional settability by the user.
|
||||
// Is this used?
|
||||
public override OMV.Vector3 CenterOfMass
|
||||
{
|
||||
get { return RawPosition; }
|
||||
}
|
||||
|
||||
// Is this used?
|
||||
public override OMV.Vector3 GeometricCenter
|
||||
{
|
||||
get { return RawPosition; }
|
||||
}
|
||||
|
||||
public override void UpdateProperties(EntityProperties entprop)
|
||||
{
|
||||
// Undo any center-of-mass displacement that might have been done.
|
||||
if (PositionDisplacement != OMV.Vector3.Zero || OrientationDisplacement != OMV.Quaternion.Identity)
|
||||
{
|
||||
// Correct for any rotation around the center-of-mass
|
||||
// TODO!!!
|
||||
entprop.Position = entprop.Position + (PositionDisplacement * entprop.Rotation);
|
||||
// entprop.Rotation = something;
|
||||
}
|
||||
|
||||
base.UpdateProperties(entprop);
|
||||
}
|
||||
}
|
||||
}
|
||||
182
OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
Executable file
182
OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
Executable file
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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.Linq;
|
||||
using System.Text;
|
||||
|
||||
using OpenSim.Framework;
|
||||
|
||||
using OMV = OpenMetaverse;
|
||||
|
||||
namespace OpenSim.Region.Physics.BulletSPlugin
|
||||
{
|
||||
public class BSPrimLinkable : BSPrimDisplaced
|
||||
{
|
||||
public BSLinkset Linkset { get; set; }
|
||||
// The index of this child prim.
|
||||
public int LinksetChildIndex { get; set; }
|
||||
|
||||
public BSLinksetInfo LinksetInfo { get; set; }
|
||||
|
||||
public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
|
||||
OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
|
||||
: base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical)
|
||||
{
|
||||
Linkset = BSLinkset.Factory(PhysicsScene, this);
|
||||
|
||||
PhysicsScene.TaintedObject("BSPrimLinksetCompound.Refresh", delegate()
|
||||
{
|
||||
Linkset.Refresh(this);
|
||||
});
|
||||
}
|
||||
|
||||
public override void Destroy()
|
||||
{
|
||||
Linkset = Linkset.RemoveMeFromLinkset(this);
|
||||
base.Destroy();
|
||||
}
|
||||
|
||||
public override BSPhysicsShapeType PreferredPhysicalShape
|
||||
{ get { return Linkset.PreferredPhysicalShape(this); } }
|
||||
|
||||
public override void link(Manager.PhysicsActor obj)
|
||||
{
|
||||
BSPrimLinkable parent = obj as BSPrimLinkable;
|
||||
if (parent != null)
|
||||
{
|
||||
BSPhysObject parentBefore = Linkset.LinksetRoot;
|
||||
int childrenBefore = Linkset.NumberOfChildren;
|
||||
|
||||
Linkset = parent.Linkset.AddMeToLinkset(this);
|
||||
|
||||
DetailLog("{0},BSPrimLinkset.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}",
|
||||
LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
BSPhysObject parentBefore = Linkset.LinksetRoot;
|
||||
int childrenBefore = Linkset.NumberOfChildren;
|
||||
|
||||
Linkset = Linkset.RemoveMeFromLinkset(this);
|
||||
|
||||
DetailLog("{0},BSPrimLinkset.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
|
||||
LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
|
||||
return;
|
||||
}
|
||||
|
||||
// When simulator changes position, this might be moving a child of the linkset.
|
||||
public override OMV.Vector3 Position
|
||||
{
|
||||
get { return base.Position; }
|
||||
set
|
||||
{
|
||||
base.Position = value;
|
||||
PhysicsScene.TaintedObject("BSPrimLinkset.setPosition", delegate()
|
||||
{
|
||||
Linkset.UpdateProperties(UpdatedProperties.Position, this);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// When simulator changes orientation, this might be moving a child of the linkset.
|
||||
public override OMV.Quaternion Orientation
|
||||
{
|
||||
get { return base.Orientation; }
|
||||
set
|
||||
{
|
||||
base.Orientation = value;
|
||||
PhysicsScene.TaintedObject("BSPrimLinkset.setOrientation", delegate()
|
||||
{
|
||||
Linkset.UpdateProperties(UpdatedProperties.Orientation, this);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public override float TotalMass
|
||||
{
|
||||
get { return Linkset.LinksetMass; }
|
||||
}
|
||||
|
||||
public override void UpdatePhysicalParameters()
|
||||
{
|
||||
base.UpdatePhysicalParameters();
|
||||
// Recompute any linkset parameters.
|
||||
// When going from non-physical to physical, this re-enables the constraints that
|
||||
// had been automatically disabled when the mass was set to zero.
|
||||
// For compound based linksets, this enables and disables interactions of the children.
|
||||
if (Linkset != null) // null can happen during initialization
|
||||
Linkset.Refresh(this);
|
||||
}
|
||||
|
||||
protected override void MakeDynamic(bool makeStatic)
|
||||
{
|
||||
base.MakeDynamic(makeStatic);
|
||||
if (makeStatic)
|
||||
Linkset.MakeStatic(this);
|
||||
else
|
||||
Linkset.MakeDynamic(this);
|
||||
}
|
||||
|
||||
// Body is being taken apart. Remove physical dependencies and schedule a rebuild.
|
||||
protected override void RemoveBodyDependencies()
|
||||
{
|
||||
Linkset.RemoveBodyDependencies(this);
|
||||
base.RemoveBodyDependencies();
|
||||
}
|
||||
|
||||
public override void UpdateProperties(EntityProperties entprop)
|
||||
{
|
||||
if (Linkset.IsRoot(this))
|
||||
{
|
||||
// Properties are only updated for the roots of a linkset.
|
||||
// TODO: this will have to change when linksets are articulated.
|
||||
base.UpdateProperties(entprop);
|
||||
}
|
||||
// The linkset might like to know about changing locations
|
||||
Linkset.UpdateProperties(UpdatedProperties.EntPropUpdates, this);
|
||||
}
|
||||
|
||||
public override bool Collide(uint collidingWith, BSPhysObject collidee,
|
||||
OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth)
|
||||
{
|
||||
// prims in the same linkset cannot collide with each other
|
||||
BSPrimLinkable convCollidee = collidee as BSPrimLinkable;
|
||||
if (convCollidee != null && (this.Linkset.LinksetID == convCollidee.Linkset.LinksetID))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return base.Collide(collidingWith, collidee, contactPoint, contactNormal, pentrationDepth);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -434,7 +434,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||
{
|
||||
if (!m_initialized) return;
|
||||
|
||||
BSPrim bsprim = prim as BSPrim;
|
||||
BSPhysObject bsprim = prim as BSPhysObject;
|
||||
if (bsprim != null)
|
||||
{
|
||||
DetailLog("{0},RemovePrim,call", bsprim.LocalID);
|
||||
@@ -463,9 +463,9 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
|
||||
|
||||
if (!m_initialized) return null;
|
||||
|
||||
DetailLog("{0},AddPrimShape,call", localID);
|
||||
DetailLog("{0},BSScene.AddPrimShape,call", localID);
|
||||
|
||||
BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical);
|
||||
BSPhysObject prim = new BSPrimLinkable(localID, primName, this, position, size, rotation, pbs, isPhysical);
|
||||
lock (PhysObjects) PhysObjects.Add(localID, prim);
|
||||
return prim;
|
||||
}
|
||||
|
||||
@@ -52,7 +52,12 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
|
||||
{
|
||||
bool Cancel();
|
||||
void Abort();
|
||||
bool Wait(TimeSpan t);
|
||||
|
||||
/// <summary>
|
||||
/// Wait for the work item to complete.
|
||||
/// </summary>
|
||||
/// <param name='t'>The number of milliseconds to wait. Must be >= -1 (Timeout.Infinite).</param>
|
||||
bool Wait(int t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -4479,6 +4479,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pushAllowed)
|
||||
{
|
||||
float distance = (PusheePos - m_host.AbsolutePosition).Length();
|
||||
@@ -4507,17 +4508,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||
applied_linear_impulse *= scaling_factor;
|
||||
|
||||
}
|
||||
|
||||
if (pusheeIsAvatar)
|
||||
{
|
||||
if (pusheeav != null)
|
||||
{
|
||||
if (pusheeav.PhysicsActor != null)
|
||||
PhysicsActor pa = pusheeav.PhysicsActor;
|
||||
|
||||
if (pa != null)
|
||||
{
|
||||
if (local != 0)
|
||||
{
|
||||
applied_linear_impulse *= m_host.GetWorldRotation();
|
||||
}
|
||||
pusheeav.PhysicsActor.AddForce(applied_linear_impulse, true);
|
||||
|
||||
pa.AddForce(applied_linear_impulse, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,7 +595,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||
if (!m_coopTermination)
|
||||
{
|
||||
// If we're not co-operative terminating then try and wait for the event to complete before stopping
|
||||
if (workItem.Wait(new TimeSpan((long)timeout * 100000)))
|
||||
if (workItem.Wait(timeout))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -610,7 +610,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||
|
||||
// For now, we will wait forever since the event should always cleanly terminate once LSL loop
|
||||
// checking is implemented. May want to allow a shorter timeout option later.
|
||||
if (workItem.Wait(TimeSpan.MaxValue))
|
||||
if (workItem.Wait(Timeout.Infinite))
|
||||
{
|
||||
if (DebugLevel >= 1)
|
||||
m_log.DebugFormat(
|
||||
|
||||
@@ -57,8 +57,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||
wr.Abort();
|
||||
}
|
||||
|
||||
public bool Wait(TimeSpan t)
|
||||
public bool Wait(int t)
|
||||
{
|
||||
// We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the
|
||||
// TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an
|
||||
// int (32-bit) we can end up with bad values. This occurs on Windows though curious not on Mono 2.10.8
|
||||
// (or very likely other versions of Mono at least up until 3.0.3).
|
||||
return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace OpenSim.Services.Connectors
|
||||
|
||||
if (replyData != null)
|
||||
{
|
||||
if (replyData.ContainsKey("result") && replyData.ContainsKey("result").ToString() == "null")
|
||||
if (replyData.ContainsKey("result") && replyData["result"].ToString() == "null")
|
||||
{
|
||||
return accounts;
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user