Merge branch 'master' of git://opensimulator.org/git/opensim
commit
e09467b30d
|
@ -535,6 +535,8 @@ namespace OpenSim.Framework.Servers.HttpServer
|
||||||
/// <param name="message"></param>
|
/// <param name="message"></param>
|
||||||
public void Close(string message)
|
public void Close(string message)
|
||||||
{
|
{
|
||||||
|
if (_networkContext == null)
|
||||||
|
return;
|
||||||
if (_networkContext.Stream != null)
|
if (_networkContext.Stream != null)
|
||||||
{
|
{
|
||||||
if (_networkContext.Stream.CanWrite)
|
if (_networkContext.Stream.CanWrite)
|
||||||
|
|
|
@ -59,6 +59,8 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
// private static readonly ILog m_log =
|
// private static readonly ILog m_log =
|
||||||
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
public event SimulatorFeaturesRequestDelegate OnSimulatorFeaturesRequest;
|
||||||
|
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -94,6 +96,8 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
{
|
{
|
||||||
m_scene = s;
|
m_scene = s;
|
||||||
m_scene.EventManager.OnRegisterCaps += RegisterCaps;
|
m_scene.EventManager.OnRegisterCaps += RegisterCaps;
|
||||||
|
|
||||||
|
m_scene.RegisterModuleInterface<ISimulatorFeaturesModule>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveRegion(Scene s)
|
public void RemoveRegion(Scene s)
|
||||||
|
@ -156,7 +160,7 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
IRequestHandler reqHandler
|
IRequestHandler reqHandler
|
||||||
= new RestHTTPHandler(
|
= new RestHTTPHandler(
|
||||||
"GET", "/CAPS/" + UUID.Random(),
|
"GET", "/CAPS/" + UUID.Random(),
|
||||||
HandleSimulatorFeaturesRequest, "SimulatorFeatures", agentID.ToString());
|
x => { return HandleSimulatorFeaturesRequest(x, agentID); }, "SimulatorFeatures", agentID.ToString());
|
||||||
|
|
||||||
caps.RegisterHandler("SimulatorFeatures", reqHandler);
|
caps.RegisterHandler("SimulatorFeatures", reqHandler);
|
||||||
}
|
}
|
||||||
|
@ -185,18 +189,33 @@ namespace OpenSim.Region.ClientStack.Linden
|
||||||
return new OSDMap(m_features);
|
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");
|
// m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request");
|
||||||
|
|
||||||
|
OSDMap copy = DeepCopy();
|
||||||
|
|
||||||
|
SimulatorFeaturesRequestDelegate handlerOnSimulatorFeaturesRequest = OnSimulatorFeaturesRequest;
|
||||||
|
if (handlerOnSimulatorFeaturesRequest != null)
|
||||||
|
handlerOnSimulatorFeaturesRequest(agentID, ref copy);
|
||||||
|
|
||||||
//Send back data
|
//Send back data
|
||||||
Hashtable responsedata = new Hashtable();
|
Hashtable responsedata = new Hashtable();
|
||||||
responsedata["int_response_code"] = 200;
|
responsedata["int_response_code"] = 200;
|
||||||
responsedata["content_type"] = "text/plain";
|
responsedata["content_type"] = "text/plain";
|
||||||
responsedata["keepalive"] = false;
|
responsedata["keepalive"] = false;
|
||||||
|
|
||||||
lock (m_features)
|
responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(copy);
|
||||||
responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(m_features);
|
|
||||||
|
|
||||||
return responsedata;
|
return responsedata;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
|
||||||
public class AssetTransactionModule : INonSharedRegionModule,
|
public class AssetTransactionModule : INonSharedRegionModule,
|
||||||
IAgentAssetTransactions
|
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;
|
protected Scene m_Scene;
|
||||||
private bool m_dumpAssetsToFile = false;
|
private bool m_dumpAssetsToFile = false;
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DAExampleModule
|
||||||
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")]
|
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")]
|
||||||
public class DAExampleModule : INonSharedRegionModule
|
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
|
private static readonly bool ENABLED = false; // enable for testing
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IConfig statConfig = source.Configs["Statistics.Binary"];
|
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"))
|
if (statConfig.Contains("collect_region_stats"))
|
||||||
{
|
{
|
||||||
|
|
|
@ -111,7 +111,8 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
|
||||||
m_rpcPending = new Dictionary<UUID, RPCRequestInfo>();
|
m_rpcPending = new Dictionary<UUID, RPCRequestInfo>();
|
||||||
m_rpcPendingResponses = new Dictionary<UUID, RPCRequestInfo>();
|
m_rpcPendingResponses = new Dictionary<UUID, RPCRequestInfo>();
|
||||||
m_pendingSRDResponses = new Dictionary<UUID, SendRemoteDataRequest>();
|
m_pendingSRDResponses = new Dictionary<UUID, SendRemoteDataRequest>();
|
||||||
|
if (config.Configs["XMLRPC"] != null)
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort);
|
m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort);
|
||||||
|
@ -120,6 +121,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void PostInitialise()
|
public void PostInitialise()
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,6 +31,16 @@ using OpenMetaverse;
|
||||||
|
|
||||||
namespace OpenSim.Region.Framework.Interfaces
|
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 delegate void TakeValueCallback(string s);
|
||||||
|
|
||||||
public interface IJsonStoreModule
|
public interface IJsonStoreModule
|
||||||
|
@ -38,13 +48,18 @@ namespace OpenSim.Region.Framework.Interfaces
|
||||||
bool AttachObjectStore(UUID objectID);
|
bool AttachObjectStore(UUID objectID);
|
||||||
bool CreateStore(string value, ref UUID result);
|
bool CreateStore(string value, ref UUID result);
|
||||||
bool DestroyStore(UUID storeID);
|
bool DestroyStore(UUID storeID);
|
||||||
|
|
||||||
|
JsonStoreNodeType GetPathType(UUID storeID, string path);
|
||||||
bool TestStore(UUID storeID);
|
bool TestStore(UUID storeID);
|
||||||
bool TestPath(UUID storeID, string path, bool useJson);
|
bool TestPath(UUID storeID, string path, bool useJson);
|
||||||
|
|
||||||
bool SetValue(UUID storeID, string path, string value, bool useJson);
|
bool SetValue(UUID storeID, string path, string value, bool useJson);
|
||||||
bool RemoveValue(UUID storeID, string path);
|
bool RemoveValue(UUID storeID, string path);
|
||||||
bool GetValue(UUID storeID, string path, bool useJson, out string value);
|
bool GetValue(UUID storeID, string path, bool useJson, out string value);
|
||||||
|
|
||||||
void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback);
|
void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback);
|
||||||
void ReadValue(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,15 +26,19 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using OpenMetaverse;
|
||||||
using OpenMetaverse.StructuredData;
|
using OpenMetaverse.StructuredData;
|
||||||
|
|
||||||
namespace OpenSim.Region.Framework.Interfaces
|
namespace OpenSim.Region.Framework.Interfaces
|
||||||
{
|
{
|
||||||
|
public delegate void SimulatorFeaturesRequestDelegate(UUID agentID, ref OSDMap features);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add remove or retrieve Simulator Features that will be given to a viewer via the SimulatorFeatures capability.
|
/// Add remove or retrieve Simulator Features that will be given to a viewer via the SimulatorFeatures capability.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISimulatorFeaturesModule
|
public interface ISimulatorFeaturesModule
|
||||||
{
|
{
|
||||||
|
event SimulatorFeaturesRequestDelegate OnSimulatorFeaturesRequest;
|
||||||
void AddFeature(string name, OSD value);
|
void AddFeature(string name, OSD value);
|
||||||
bool RemoveFeature(string name);
|
bool RemoveFeature(string name);
|
||||||
bool TryGetFeature(string name, out OSD value);
|
bool TryGetFeature(string name, out OSD value);
|
||||||
|
|
|
@ -790,6 +790,19 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <param name="obj">The object being removed from the scene</param>
|
/// <param name="obj">The object being removed from the scene</param>
|
||||||
public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
|
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>
|
/// <summary>
|
||||||
/// Triggered when an object is removed from the scene.
|
/// Triggered when an object is removed from the scene.
|
||||||
/// </summary>
|
/// </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()
|
public void TriggerShutdown()
|
||||||
{
|
{
|
||||||
Action handlerShutdown = OnShutdown;
|
Action handlerShutdown = OnShutdown;
|
||||||
|
|
|
@ -4316,6 +4316,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysActor = pa;
|
PhysActor = pa;
|
||||||
|
ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -4328,6 +4329,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public void RemoveFromPhysics()
|
public void RemoveFromPhysics()
|
||||||
{
|
{
|
||||||
|
ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this);
|
||||||
ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor);
|
ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor);
|
||||||
PhysActor = null;
|
PhysActor = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,14 +68,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
protected List<TakeValueCallbackClass> m_TakeStore;
|
protected List<TakeValueCallbackClass> m_TakeStore;
|
||||||
protected List<TakeValueCallbackClass> m_ReadStore;
|
protected List<TakeValueCallbackClass> m_ReadStore;
|
||||||
|
|
||||||
// add separators for quoted paths
|
// add separators for quoted paths and array references
|
||||||
protected static Regex m_ParsePassOne = new Regex("{[^}]+}");
|
protected static Regex m_ParsePassOne = new Regex("({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])");
|
||||||
|
|
||||||
// add separators for array references
|
|
||||||
protected static Regex m_ParsePassTwo = new Regex("(\\[[0-9]+\\]|\\[\\+\\])");
|
|
||||||
|
|
||||||
// add quotes to bare identifiers which are limited to alphabetic characters
|
// 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
|
// remove extra separator characters
|
||||||
protected static Regex m_ParsePassFour = new Regex("\\.+");
|
protected static Regex m_ParsePassFour = new Regex("\\.+");
|
||||||
|
@ -84,7 +81,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
protected static Regex m_ValidatePath = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)*$");
|
protected static Regex m_ValidatePath = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)*$");
|
||||||
|
|
||||||
// expression used to match path components
|
// 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
|
// extract the internals of an array reference
|
||||||
protected static Regex m_SimpleArrayPattern = new Regex("\\[([0-9]+)\\]");
|
protected static Regex m_SimpleArrayPattern = new Regex("\\[([0-9]+)\\]");
|
||||||
|
@ -134,12 +131,43 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
|
|
||||||
public JsonStore(string value) : this()
|
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))
|
if (String.IsNullOrEmpty(value))
|
||||||
ValueStore = new OSDMap();
|
ValueStore = new OSDMap();
|
||||||
else
|
else
|
||||||
ValueStore = OSDParser.DeserializeJson(value);
|
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>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
@ -162,6 +190,27 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
return false;
|
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>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
@ -462,11 +511,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
// add front and rear separators
|
// add front and rear separators
|
||||||
expr = "." + expr + ".";
|
expr = "." + expr + ".";
|
||||||
|
|
||||||
// add separators for quoted exprs
|
// add separators for quoted exprs and array references
|
||||||
expr = m_ParsePassOne.Replace(expr,".$0.",-1,0);
|
expr = m_ParsePassOne.Replace(expr,".$1.",-1,0);
|
||||||
|
|
||||||
// add separators for array references
|
|
||||||
expr = m_ParsePassTwo.Replace(expr,".$0.",-1,0);
|
|
||||||
|
|
||||||
// add quotes to bare identifier
|
// add quotes to bare identifier
|
||||||
expr = m_ParsePassThree.Replace(expr,".{$1}",-1,0);
|
expr = m_ParsePassThree.Replace(expr,".{$1}",-1,0);
|
||||||
|
@ -574,14 +620,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
// The path pointed to an intermediate hash structure
|
// The path pointed to an intermediate hash structure
|
||||||
if (result.Type == OSDType.Map)
|
if (result.Type == OSDType.Map)
|
||||||
{
|
{
|
||||||
value = OSDParser.SerializeJsonString(result as OSDMap);
|
value = OSDParser.SerializeJsonString(result as OSDMap,true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The path pointed to an intermediate hash structure
|
// The path pointed to an intermediate hash structure
|
||||||
if (result.Type == OSDType.Array)
|
if (result.Type == OSDType.Array)
|
||||||
{
|
{
|
||||||
value = OSDParser.SerializeJsonString(result as OSDArray);
|
value = OSDParser.SerializeJsonString(result as OSDArray,true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -227,7 +227,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,6 +265,38 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
return m_JsonValueStore.ContainsKey(storeID);
|
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>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
@ -370,6 +402,37 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
return false;
|
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>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
|
|
@ -167,6 +167,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_comms.RegisterScriptInvocations(this);
|
m_comms.RegisterScriptInvocations(this);
|
||||||
|
m_comms.RegisterConstants(this);
|
||||||
|
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonCreateStore");
|
// m_comms.RegisterScriptInvocation(this, "JsonCreateStore");
|
||||||
// m_comms.RegisterScriptInvocation(this, "JsonAttachObjectStore");
|
// m_comms.RegisterScriptInvocation(this, "JsonAttachObjectStore");
|
||||||
|
@ -214,6 +215,22 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
|
|
||||||
#endregion
|
#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
|
#region ScriptInvocationInteface
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -318,6 +335,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
// -----------------------------------------------------------------
|
// -----------------------------------------------------------------
|
||||||
|
[ScriptInvocation]
|
||||||
|
public int JsonGetPathType(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||||
|
{
|
||||||
|
return (int)m_store.GetPathType(storeID,path);
|
||||||
|
}
|
||||||
|
|
||||||
[ScriptInvocation]
|
[ScriptInvocation]
|
||||||
public int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path)
|
public int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path)
|
||||||
{
|
{
|
||||||
|
@ -342,7 +365,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
}
|
}
|
||||||
|
|
||||||
[ScriptInvocation]
|
[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;
|
return m_store.SetValue(storeID,path,value,true) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
@ -358,6 +381,17 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
return m_store.RemoveValue(storeID,path) ? 1 : 0;
|
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>
|
/// <summary>
|
||||||
///
|
///
|
||||||
|
@ -372,7 +406,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
|
||||||
}
|
}
|
||||||
|
|
||||||
[ScriptInvocation]
|
[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;
|
string value = String.Empty;
|
||||||
m_store.GetValue(storeID,path,true, out value);
|
m_store.GetValue(storeID,path,true, out value);
|
||||||
|
|
|
@ -53,6 +53,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
private MockScriptEngine m_engine;
|
private MockScriptEngine m_engine;
|
||||||
private ScriptModuleCommsModule m_smcm;
|
private ScriptModuleCommsModule m_smcm;
|
||||||
|
private JsonStoreScriptModule m_jssm;
|
||||||
|
|
||||||
[TestFixtureSetUp]
|
[TestFixtureSetUp]
|
||||||
public void FixtureInit()
|
public void FixtureInit()
|
||||||
|
@ -82,10 +83,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
m_engine = new MockScriptEngine();
|
m_engine = new MockScriptEngine();
|
||||||
m_smcm = new ScriptModuleCommsModule();
|
m_smcm = new ScriptModuleCommsModule();
|
||||||
JsonStoreModule jsm = new JsonStoreModule();
|
JsonStoreModule jsm = new JsonStoreModule();
|
||||||
JsonStoreScriptModule jssm = new JsonStoreScriptModule();
|
m_jssm = new JsonStoreScriptModule();
|
||||||
|
|
||||||
m_scene = new SceneHelpers().SetupScene();
|
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
|
try
|
||||||
{
|
{
|
||||||
|
@ -115,10 +116,37 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// TestHelpers.EnableLogging();
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
|
// Test blank store
|
||||||
|
{
|
||||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||||
Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
|
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]
|
[Test]
|
||||||
public void TestJsonDestroyStore()
|
public void TestJsonDestroyStore()
|
||||||
{
|
{
|
||||||
|
@ -181,7 +209,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestJsonGetValueJson()
|
public void TestJsonGetJson()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// TestHelpers.EnableLogging();
|
// TestHelpers.EnableLogging();
|
||||||
|
@ -189,26 +217,26 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Two' } }");
|
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Two' } }");
|
||||||
|
|
||||||
{
|
{
|
||||||
string value = (string)InvokeOp("JsonGetValueJson", storeId, "Hello.World");
|
string value = (string)InvokeOp("JsonGetJson", storeId, "Hello.World");
|
||||||
Assert.That(value, Is.EqualTo("'Two'"));
|
Assert.That(value, Is.EqualTo("'Two'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test get of path section instead of leaf
|
// Test get of path section instead of leaf
|
||||||
{
|
{
|
||||||
string value = (string)InvokeOp("JsonGetValueJson", storeId, "Hello");
|
string value = (string)InvokeOp("JsonGetJson", storeId, "Hello");
|
||||||
Assert.That(value, Is.EqualTo("{\"World\":\"Two\"}"));
|
Assert.That(value, Is.EqualTo("{\"World\":\"Two\"}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test get of non-existing value
|
// Test get of non-existing value
|
||||||
{
|
{
|
||||||
string fakeValueGet = (string)InvokeOp("JsonGetValueJson", storeId, "foo");
|
string fakeValueGet = (string)InvokeOp("JsonGetJson", storeId, "foo");
|
||||||
Assert.That(fakeValueGet, Is.EqualTo(""));
|
Assert.That(fakeValueGet, Is.EqualTo(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test get from non-existing store
|
// Test get from non-existing store
|
||||||
{
|
{
|
||||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||||
string fakeStoreValueGet = (string)InvokeOp("JsonGetValueJson", fakeStoreId, "Hello");
|
string fakeStoreValueGet = (string)InvokeOp("JsonGetJson", fakeStoreId, "Hello");
|
||||||
Assert.That(fakeStoreValueGet, Is.EqualTo(""));
|
Assert.That(fakeStoreValueGet, Is.EqualTo(""));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,6 +270,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// TestHelpers.EnableLogging();
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
|
// Test remove of node in object pointing to a string
|
||||||
|
{
|
||||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
|
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
|
||||||
|
|
||||||
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
|
int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
|
||||||
|
@ -252,78 +282,224 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
|
|
||||||
string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello");
|
string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello");
|
||||||
Assert.That(returnValue2, Is.EqualTo(""));
|
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
|
// Test remove of non-existing value
|
||||||
int fakeValueRemove = (int)InvokeOp("JsonRemoveValue", storeId, "Hello");
|
{
|
||||||
Assert.That(fakeValueRemove, Is.EqualTo(0));
|
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
|
||||||
|
|
||||||
|
int fakeValueRemove = (int)InvokeOp("JsonRemoveValue", storeId, "Cheese");
|
||||||
|
Assert.That(fakeValueRemove, Is.EqualTo(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
// Test get from non-existing store
|
// Test get from non-existing store
|
||||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||||
int fakeStoreValueRemove = (int)InvokeOp("JsonRemoveValue", fakeStoreId, "Hello");
|
int fakeStoreValueRemove = (int)InvokeOp("JsonRemoveValue", fakeStoreId, "Hello");
|
||||||
Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
|
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]
|
[Test]
|
||||||
public void TestJsonTestPath()
|
public void TestGetArrayLength()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// TestHelpers.EnableLogging();
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }");
|
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }");
|
||||||
|
|
||||||
{
|
{
|
||||||
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello.World");
|
int result = (int)InvokeOp("JsonGetArrayLength", storeId, "Hello.World");
|
||||||
Assert.That(result, Is.EqualTo(1));
|
Assert.That(result, Is.EqualTo(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for path which does not resolve to a value.
|
// Test path which is not an array
|
||||||
{
|
{
|
||||||
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
|
int result = (int)InvokeOp("JsonGetArrayLength", storeId, "Hello");
|
||||||
Assert.That(result, Is.EqualTo(0));
|
Assert.That(result, Is.EqualTo(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test fake path
|
||||||
{
|
{
|
||||||
int result2 = (int)InvokeOp("JsonTestPath", storeId, "foo");
|
int result = (int)InvokeOp("JsonGetArrayLength", storeId, "foo");
|
||||||
Assert.That(result2, Is.EqualTo(0));
|
Assert.That(result, Is.EqualTo(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test with fake store
|
// Test fake store
|
||||||
{
|
{
|
||||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||||
int fakeStoreValueRemove = (int)InvokeOp("JsonTestPath", fakeStoreId, "Hello");
|
int result = (int)InvokeOp("JsonGetArrayLength", fakeStoreId, "Hello.World");
|
||||||
Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
|
Assert.That(result, Is.EqualTo(-1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestJsonTestPathJson()
|
public void TestJsonGetPathType()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// TestHelpers.EnableLogging();
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }");
|
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }");
|
||||||
|
|
||||||
{
|
{
|
||||||
int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello.World");
|
int result = (int)InvokeOp("JsonGetPathType", storeId, ".");
|
||||||
Assert.That(result, Is.EqualTo(1));
|
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_OBJECT));
|
||||||
}
|
|
||||||
|
|
||||||
// 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");
|
int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello");
|
||||||
Assert.That(result2, Is.EqualTo(0));
|
Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_OBJECT));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test with fake store
|
{
|
||||||
|
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);
|
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||||
int fakeStoreValueRemove = (int)InvokeOp("JsonTestPathJson", fakeStoreId, "Hello");
|
int result = (int)InvokeOp("JsonGetPathType", fakeStoreId, ".");
|
||||||
Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
|
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}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +510,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
// TestHelpers.EnableLogging();
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
{
|
{
|
||||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||||
|
|
||||||
int result = (int)InvokeOp("JsonSetValue", storeId, "Fun", "Times");
|
int result = (int)InvokeOp("JsonSetValue", storeId, "Fun", "Times");
|
||||||
Assert.That(result, Is.EqualTo(1));
|
Assert.That(result, Is.EqualTo(1));
|
||||||
|
@ -343,9 +519,155 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
Assert.That(value, Is.EqualTo("Times"));
|
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.
|
// Test setting to location that does not exist. This should fail.
|
||||||
{
|
{
|
||||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
|
||||||
|
|
||||||
int result = (int)InvokeOp("JsonSetValue", storeId, "Fun.Circus", "Times");
|
int result = (int)InvokeOp("JsonSetValue", storeId, "Fun.Circus", "Times");
|
||||||
Assert.That(result, Is.EqualTo(0));
|
Assert.That(result, Is.EqualTo(0));
|
||||||
|
@ -363,27 +685,27 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestJsonSetValueJson()
|
public void TestJsonSetJson()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// TestHelpers.EnableLogging();
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
// Single quoted token case
|
// Single quoted token case
|
||||||
// {
|
{
|
||||||
// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
||||||
//
|
|
||||||
// int result = (int)InvokeOp("JsonSetValueJson", storeId, "Fun", "'Times'");
|
int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "'Times'");
|
||||||
// Assert.That(result, Is.EqualTo(1));
|
Assert.That(result, Is.EqualTo(1));
|
||||||
//
|
|
||||||
// string value = (string)InvokeOp("JsonGetValue", storeId, "Fun");
|
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun");
|
||||||
// Assert.That(value, Is.EqualTo("Times"));
|
Assert.That(value, Is.EqualTo("Times"));
|
||||||
// }
|
}
|
||||||
|
|
||||||
// Sub-tree case
|
// Sub-tree case
|
||||||
{
|
{
|
||||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
||||||
|
|
||||||
int result = (int)InvokeOp("JsonSetValueJson", storeId, "Fun", "{ 'Filled' : 'Times' }");
|
int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "{ 'Filled' : 'Times' }");
|
||||||
Assert.That(result, Is.EqualTo(1));
|
Assert.That(result, Is.EqualTo(1));
|
||||||
|
|
||||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Filled");
|
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Filled");
|
||||||
|
@ -394,7 +716,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
{
|
{
|
||||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
||||||
|
|
||||||
int result = (int)InvokeOp("JsonSetValueJson", storeId, "Fun", "Times");
|
int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "Times");
|
||||||
Assert.That(result, Is.EqualTo(0));
|
Assert.That(result, Is.EqualTo(0));
|
||||||
|
|
||||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun");
|
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun");
|
||||||
|
@ -405,7 +727,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
{
|
{
|
||||||
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
|
||||||
|
|
||||||
int result = (int)InvokeOp("JsonSetValueJson", storeId, "Fun.Circus", "'Times'");
|
int result = (int)InvokeOp("JsonSetJson", storeId, "Fun.Circus", "'Times'");
|
||||||
Assert.That(result, Is.EqualTo(0));
|
Assert.That(result, Is.EqualTo(0));
|
||||||
|
|
||||||
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Circus");
|
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Circus");
|
||||||
|
@ -415,7 +737,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
|
||||||
// Test with fake store
|
// Test with fake store
|
||||||
{
|
{
|
||||||
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
|
||||||
int fakeStoreValueSet = (int)InvokeOp("JsonSetValueJson", fakeStoreId, "Hello", "'World'");
|
int fakeStoreValueSet = (int)InvokeOp("JsonSetJson", fakeStoreId, "Hello", "'World'");
|
||||||
Assert.That(fakeStoreValueSet, Is.EqualTo(0));
|
Assert.That(fakeStoreValueSet, Is.EqualTo(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,9 +225,10 @@ public enum CollisionFlags : uint
|
||||||
CF_DISABLE_VISUALIZE_OBJECT = 1 << 5,
|
CF_DISABLE_VISUALIZE_OBJECT = 1 << 5,
|
||||||
CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
|
CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
|
||||||
// Following used by BulletSim to control collisions and updates
|
// Following used by BulletSim to control collisions and updates
|
||||||
BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
|
BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, // return collision events from unmanaged to managed
|
||||||
BS_FLOATS_ON_WATER = 1 << 11,
|
BS_FLOATS_ON_WATER = 1 << 11, // the object should float at water level
|
||||||
BS_VEHICLE_COLLISIONS = 1 << 12,
|
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_NONE = 0,
|
||||||
BS_ALL = 0xFFFFFFFF
|
BS_ALL = 0xFFFFFFFF
|
||||||
};
|
};
|
||||||
|
|
|
@ -83,7 +83,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
_velocity = OMV.Vector3.Zero;
|
_velocity = OMV.Vector3.Zero;
|
||||||
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
|
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
|
||||||
Friction = BSParam.AvatarStandingFriction;
|
Friction = BSParam.AvatarStandingFriction;
|
||||||
Density = BSParam.AvatarDensity;
|
Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor;
|
||||||
|
|
||||||
// Old versions of ScenePresence passed only the height. If width and/or depth are zero,
|
// Old versions of ScenePresence passed only the height. If width and/or depth are zero,
|
||||||
// replace with the default values.
|
// replace with the default values.
|
||||||
|
@ -231,6 +231,15 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
PhysicsScene.PE.SetFriction(PhysBody, Friction);
|
PhysicsScene.PE.SetFriction(PhysBody, Friction);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (Flying)
|
||||||
|
{
|
||||||
|
// Flying and not collising and velocity nearly zero.
|
||||||
|
ZeroMotion(true /* inTaintTime */);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding);
|
DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -274,7 +283,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
// This test is done if moving forward, not flying and is colliding with something.
|
// 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}",
|
// DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
|
||||||
// LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
|
// 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
|
// The range near the character's feet where we will consider stairs
|
||||||
float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f;
|
float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f;
|
||||||
|
@ -869,7 +878,7 @@ public sealed class BSCharacter : BSPhysObject
|
||||||
* Math.Min(Size.X, Size.Y) / 2
|
* Math.Min(Size.X, Size.Y) / 2
|
||||||
* Size.Y / 2f // plus the volume of the capsule end caps
|
* Size.Y / 2f // plus the volume of the capsule end caps
|
||||||
);
|
);
|
||||||
_mass = Density * _avatarVolume;
|
_mass = Density * BSParam.DensityScaleFactor * _avatarVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The physics engine says that properties have updated. Update same and inform
|
// The physics engine says that properties have updated. Update same and inform
|
||||||
|
|
|
@ -127,6 +127,8 @@ public abstract class BSLinkset
|
||||||
m_children = new HashSet<BSPrimLinkable>();
|
m_children = new HashSet<BSPrimLinkable>();
|
||||||
LinksetMass = parent.RawMass;
|
LinksetMass = parent.RawMass;
|
||||||
Rebuilding = false;
|
Rebuilding = false;
|
||||||
|
|
||||||
|
parent.ClearDisplacement();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link to a linkset where the child knows the parent.
|
// Link to a linkset where the child knows the parent.
|
||||||
|
@ -280,6 +282,7 @@ public abstract class BSLinkset
|
||||||
return mass;
|
return mass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Computes linkset's center of mass in world coordinates.
|
||||||
protected virtual OMV.Vector3 ComputeLinksetCenterOfMass()
|
protected virtual OMV.Vector3 ComputeLinksetCenterOfMass()
|
||||||
{
|
{
|
||||||
OMV.Vector3 com;
|
OMV.Vector3 com;
|
||||||
|
|
|
@ -93,7 +93,8 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
{
|
{
|
||||||
private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
|
private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
|
||||||
|
|
||||||
public BSLinksetCompound(BSScene scene, BSPrimLinkable parent) : base(scene, parent)
|
public BSLinksetCompound(BSScene scene, BSPrimLinkable parent)
|
||||||
|
: base(scene, parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,14 +218,6 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
// and that is caused by us updating the object.
|
// and that is caused by us updating the object.
|
||||||
if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
|
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, OMV.Vector3.Zero);
|
|
||||||
updated.LinksetInfo = newLsi;
|
|
||||||
|
|
||||||
// Find the physical instance of the child
|
// 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))
|
||||||
{
|
{
|
||||||
|
@ -234,19 +227,19 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
// The index must be checked because Bullet references the child array but does no validity
|
// The index must be checked because Bullet references the child array but does no validity
|
||||||
// checking of the child index passed.
|
// checking of the child index passed.
|
||||||
int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
|
int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
|
||||||
if (lsi.Index < numLinksetChildren)
|
if (updated.LinksetChildIndex < numLinksetChildren)
|
||||||
{
|
{
|
||||||
BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index);
|
BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, updated.LinksetChildIndex);
|
||||||
if (linksetChildShape.HasPhysicalShape)
|
if (linksetChildShape.HasPhysicalShape)
|
||||||
{
|
{
|
||||||
// Found the child shape within the compound shape
|
// Found the child shape within the compound shape
|
||||||
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index,
|
PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, updated.LinksetChildIndex,
|
||||||
newLsi.OffsetFromCenterOfMass,
|
updated.RawPosition - LinksetRoot.RawPosition,
|
||||||
newLsi.OffsetRot,
|
updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation),
|
||||||
true /* shouldRecalculateLocalAabb */);
|
true /* shouldRecalculateLocalAabb */);
|
||||||
updatedChild = true;
|
updatedChild = true;
|
||||||
DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}",
|
DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},pos={2},rot={3}",
|
||||||
updated.LocalID, whichUpdated, newLsi);
|
updated.LocalID, whichUpdated, updated.RawPosition, updated.RawOrientation);
|
||||||
}
|
}
|
||||||
else // DEBUG DEBUG
|
else // DEBUG DEBUG
|
||||||
{ // DEBUG DEBUG
|
{ // DEBUG DEBUG
|
||||||
|
@ -258,19 +251,13 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
{ // DEBUG DEBUG
|
{ // DEBUG DEBUG
|
||||||
// the child is not yet in the compound shape. This is non-fatal.
|
// the child is not yet in the compound shape. This is non-fatal.
|
||||||
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}",
|
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}",
|
||||||
updated.LocalID, numLinksetChildren, lsi.Index);
|
updated.LocalID, numLinksetChildren, updated.LinksetChildIndex);
|
||||||
} // DEBUG DEBUG
|
} // DEBUG DEBUG
|
||||||
}
|
}
|
||||||
else // DEBUG DEBUG
|
else // DEBUG DEBUG
|
||||||
{ // DEBUG DEBUG
|
{ // DEBUG DEBUG
|
||||||
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID);
|
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID);
|
||||||
} // DEBUG DEBUG
|
} // DEBUG DEBUG
|
||||||
}
|
|
||||||
else // DEBUG DEBUG
|
|
||||||
{ // DEBUG DEBUG
|
|
||||||
DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noLinkSetInfo,rootPhysShape={1}",
|
|
||||||
updated.LocalID, LinksetRoot.PhysShape);
|
|
||||||
} // DEBUG DEBUG
|
|
||||||
|
|
||||||
if (!updatedChild)
|
if (!updatedChild)
|
||||||
{
|
{
|
||||||
|
@ -379,6 +366,8 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
// Safe to call even if the child is not really in the linkset.
|
// Safe to call even if the child is not really in the linkset.
|
||||||
protected override void RemoveChildFromLinkset(BSPrimLinkable child)
|
protected override void RemoveChildFromLinkset(BSPrimLinkable child)
|
||||||
{
|
{
|
||||||
|
child.ClearDisplacement();
|
||||||
|
|
||||||
if (m_children.Remove(child))
|
if (m_children.Remove(child))
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
|
DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
|
||||||
|
@ -424,30 +413,31 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
// The center of mass for the linkset is the geometric center of the group.
|
// 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.
|
// 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
|
// Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
|
||||||
OMV.Vector3 centerOfMass;
|
OMV.Vector3 centerOfMassW = LinksetRoot.RawPosition;
|
||||||
OMV.Vector3 centerDisplacement = OMV.Vector3.Zero;
|
if (!disableCOM) // DEBUG DEBUG
|
||||||
if (disableCOM) // DEBUG DEBUG
|
|
||||||
{ // DEBUG DEBUG
|
|
||||||
centerOfMass = LinksetRoot.RawPosition; // DEBUG DEBUG
|
|
||||||
// LinksetRoot.PositionDisplacement = OMV.Vector3.Zero;
|
|
||||||
} // DEBUG DEBUG
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
centerOfMass = ComputeLinksetCenterOfMass();
|
// Compute a center-of-mass in world coordinates.
|
||||||
// 'centerDisplacement' is the value to *add* to all the shape offsets
|
centerOfMassW = ComputeLinksetCenterOfMass();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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}",
|
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
|
||||||
LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
|
LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
|
||||||
|
|
||||||
|
@ -455,38 +445,33 @@ public sealed class BSLinksetCompound : BSLinkset
|
||||||
int memberIndex = 1;
|
int memberIndex = 1;
|
||||||
ForEachMember(delegate(BSPrimLinkable cPrim)
|
ForEachMember(delegate(BSPrimLinkable cPrim)
|
||||||
{
|
{
|
||||||
if (!IsRoot(cPrim))
|
if (IsRoot(cPrim))
|
||||||
{
|
{
|
||||||
// Compute the displacement of the child from the root of the linkset.
|
cPrim.LinksetChildIndex = 0;
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},lci={3}",
|
{
|
||||||
LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci);
|
cPrim.LinksetChildIndex = memberIndex;
|
||||||
|
|
||||||
if (cPrim.PhysShape.isNativeShape)
|
if (cPrim.PhysShape.isNativeShape)
|
||||||
{
|
{
|
||||||
// A native shape is turned into a hull collision shape because native
|
// 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
|
// 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
|
// 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.
|
// TODO: decide of the native shape can just be used in the compound shape.
|
||||||
// Use call to CreateGeomNonSpecial().
|
// Use call to CreateGeomNonSpecial().
|
||||||
BulletShape saveShape = cPrim.PhysShape;
|
BulletShape saveShape = cPrim.PhysShape;
|
||||||
cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
|
cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
|
||||||
// PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null);
|
|
||||||
PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
|
PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
|
||||||
BulletShape newShape = cPrim.PhysShape;
|
BulletShape newShape = cPrim.PhysShape;
|
||||||
cPrim.PhysShape = saveShape;
|
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
|
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}",
|
PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
|
||||||
LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
|
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++;
|
memberIndex++;
|
||||||
}
|
}
|
||||||
return false; // 'false' says to move onto the next child in the list
|
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.
|
// With all of the linkset packed into the root prim, it has the mass of everyone.
|
||||||
LinksetMass = ComputeLinksetMass();
|
LinksetMass = ComputeLinksetMass();
|
||||||
LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
|
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
|
finally
|
||||||
{
|
{
|
||||||
Rebuilding = false;
|
Rebuilding = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See that the Aabb surrounds the new shape
|
||||||
PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape);
|
PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,7 @@ public static class BSParam
|
||||||
public static float MaxLinearVelocity { get; private set; }
|
public static float MaxLinearVelocity { get; private set; }
|
||||||
public static float MaxAngularVelocity { get; private set; }
|
public static float MaxAngularVelocity { get; private set; }
|
||||||
public static float MaxAddForceMagnitude { 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 LinearDamping { get; private set; }
|
||||||
public static float AngularDamping { get; private set; }
|
public static float AngularDamping { get; private set; }
|
||||||
|
@ -281,29 +282,35 @@ public static class BSParam
|
||||||
new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)",
|
new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)",
|
||||||
0.0001f,
|
0.0001f,
|
||||||
(s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); },
|
||||||
(s) => { return (float)MinimumObjectMass; },
|
(s) => { return MinimumObjectMass; },
|
||||||
(s,p,l,v) => { MinimumObjectMass = v; } ),
|
(s,p,l,v) => { MinimumObjectMass = v; } ),
|
||||||
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
|
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
|
||||||
10000.01f,
|
10000.01f,
|
||||||
(s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); },
|
||||||
(s) => { return (float)MaximumObjectMass; },
|
(s) => { return MaximumObjectMass; },
|
||||||
(s,p,l,v) => { MaximumObjectMass = v; } ),
|
(s,p,l,v) => { MaximumObjectMass = v; } ),
|
||||||
new ParameterDefn("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object",
|
new ParameterDefn("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object",
|
||||||
1000.0f,
|
1000.0f,
|
||||||
(s,cf,p,v) => { MaxLinearVelocity = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { MaxLinearVelocity = cf.GetFloat(p, v); },
|
||||||
(s) => { return (float)MaxLinearVelocity; },
|
(s) => { return MaxLinearVelocity; },
|
||||||
(s,p,l,v) => { MaxLinearVelocity = v; } ),
|
(s,p,l,v) => { MaxLinearVelocity = v; } ),
|
||||||
new ParameterDefn("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object",
|
new ParameterDefn("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object",
|
||||||
1000.0f,
|
1000.0f,
|
||||||
(s,cf,p,v) => { MaxAngularVelocity = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { MaxAngularVelocity = cf.GetFloat(p, v); },
|
||||||
(s) => { return (float)MaxAngularVelocity; },
|
(s) => { return MaxAngularVelocity; },
|
||||||
(s,p,l,v) => { MaxAngularVelocity = v; } ),
|
(s,p,l,v) => { MaxAngularVelocity = v; } ),
|
||||||
// LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject
|
// 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)",
|
new ParameterDefn("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)",
|
||||||
20000.0f,
|
20000.0f,
|
||||||
(s,cf,p,v) => { MaxAddForceMagnitude = cf.GetFloat(p, v); },
|
(s,cf,p,v) => { MaxAddForceMagnitude = cf.GetFloat(p, v); },
|
||||||
(s) => { return (float)MaxAddForceMagnitude; },
|
(s) => { return MaxAddForceMagnitude; },
|
||||||
(s,p,l,v) => { MaxAddForceMagnitude = v; } ),
|
(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",
|
new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
|
||||||
2200f,
|
2200f,
|
||||||
|
|
|
@ -99,6 +99,9 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
CollisionAccumulation = 0;
|
CollisionAccumulation = 0;
|
||||||
ColliderIsMoving = false;
|
ColliderIsMoving = false;
|
||||||
CollisionScore = 0;
|
CollisionScore = 0;
|
||||||
|
|
||||||
|
// All axis free.
|
||||||
|
LockedAxis = LockedAxisFree;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell the object to clean up.
|
// Tell the object to clean up.
|
||||||
|
@ -136,6 +139,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
|
|
||||||
// The objects base shape information. Null if not a prim type shape.
|
// The objects base shape information. Null if not a prim type shape.
|
||||||
public PrimitiveBaseShape BaseShape { get; protected set; }
|
public PrimitiveBaseShape BaseShape { get; protected set; }
|
||||||
|
|
||||||
// Some types of objects have preferred physical representations.
|
// Some types of objects have preferred physical representations.
|
||||||
// Returns SHAPE_UNKNOWN if there is no preference.
|
// Returns SHAPE_UNKNOWN if there is no preference.
|
||||||
public virtual BSPhysicsShapeType PreferredPhysicalShape
|
public virtual BSPhysicsShapeType PreferredPhysicalShape
|
||||||
|
@ -150,15 +154,17 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
public EntityProperties LastEntityProperties { get; set; }
|
public EntityProperties LastEntityProperties { get; set; }
|
||||||
|
|
||||||
public virtual OMV.Vector3 Scale { 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
|
// It can be confusing for an actor to know if it should move or update an object
|
||||||
// depeneding on the setting of 'selected', 'physical, ...
|
// 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
|
// This flag is the true test -- if true, the object is being acted on in the physical world
|
||||||
public abstract bool IsPhysicallyActive { get; }
|
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
|
// Materialness
|
||||||
public MaterialAttributes.Material Material { get; private set; }
|
public MaterialAttributes.Material Material { get; private set; }
|
||||||
public override void SetMaterial(int material)
|
public override void SetMaterial(int material)
|
||||||
|
@ -169,7 +175,8 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
|
MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
|
||||||
Friction = matAttrib.friction;
|
Friction = matAttrib.friction;
|
||||||
Restitution = matAttrib.restitution;
|
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.
|
// Stop all physical motion.
|
||||||
|
@ -185,14 +192,6 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
public abstract OMV.Quaternion RawOrientation { get; set; }
|
public abstract OMV.Quaternion RawOrientation { get; set; }
|
||||||
public abstract OMV.Quaternion ForceOrientation { 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 RawVelocity { get; set; }
|
||||||
public abstract OMV.Vector3 ForceVelocity { get; set; }
|
public abstract OMV.Vector3 ForceVelocity { get; set; }
|
||||||
|
|
||||||
|
@ -202,6 +201,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
|
|
||||||
public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
|
public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
|
||||||
|
|
||||||
|
// The current velocity forward
|
||||||
public virtual float ForwardSpeed
|
public virtual float ForwardSpeed
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -210,6 +210,22 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
return characterOrientedVelocity.X;
|
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
|
#region Collisions
|
||||||
|
|
||||||
|
@ -407,9 +423,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
{
|
{
|
||||||
// Clean out any existing action
|
// Clean out any existing action
|
||||||
UnRegisterPreStepAction(op, id);
|
UnRegisterPreStepAction(op, id);
|
||||||
|
|
||||||
RegisteredPrestepActions[identifier] = actn;
|
RegisteredPrestepActions[identifier] = actn;
|
||||||
|
|
||||||
PhysicsScene.BeforeStep += actn;
|
PhysicsScene.BeforeStep += actn;
|
||||||
}
|
}
|
||||||
DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
|
DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
|
||||||
|
@ -455,9 +469,7 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
{
|
{
|
||||||
// Clean out any existing action
|
// Clean out any existing action
|
||||||
UnRegisterPostStepAction(op, id);
|
UnRegisterPostStepAction(op, id);
|
||||||
|
|
||||||
RegisteredPoststepActions[identifier] = actn;
|
RegisteredPoststepActions[identifier] = actn;
|
||||||
|
|
||||||
PhysicsScene.AfterStep += actn;
|
PhysicsScene.AfterStep += actn;
|
||||||
}
|
}
|
||||||
DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier);
|
DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier);
|
||||||
|
@ -495,6 +507,57 @@ public abstract class BSPhysObject : PhysicsActor
|
||||||
DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID);
|
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
|
#endregion // Per Simulation Step actions
|
||||||
|
|
||||||
// High performance detailed logging routine used by the physical objects.
|
// High performance detailed logging routine used by the physical objects.
|
||||||
|
|
|
@ -242,6 +242,45 @@ public class BSPrim : BSPhysObject
|
||||||
public override void LockAngularMotion(OMV.Vector3 axis)
|
public override void LockAngularMotion(OMV.Vector3 axis)
|
||||||
{
|
{
|
||||||
DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,7 +350,8 @@ public class BSPrim : BSPhysObject
|
||||||
|
|
||||||
float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
|
float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
|
||||||
OMV.Vector3 upForce = OMV.Vector3.Zero;
|
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);
|
DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, RawPosition, terrainHeight);
|
||||||
float targetHeight = terrainHeight + (Size.Z / 2f);
|
float targetHeight = terrainHeight + (Size.Z / 2f);
|
||||||
|
@ -442,7 +482,7 @@ public class BSPrim : BSPhysObject
|
||||||
RegisterPreStepAction("BSPrim.setForce", LocalID,
|
RegisterPreStepAction("BSPrim.setForce", LocalID,
|
||||||
delegate(float timeStep)
|
delegate(float timeStep)
|
||||||
{
|
{
|
||||||
if (!IsPhysicallyActive)
|
if (!IsPhysicallyActive || _force == OMV.Vector3.Zero)
|
||||||
{
|
{
|
||||||
UnRegisterPreStepAction("BSPrim.setForce", LocalID);
|
UnRegisterPreStepAction("BSPrim.setForce", LocalID);
|
||||||
return;
|
return;
|
||||||
|
@ -576,6 +616,8 @@ public 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
|
public override float Density
|
||||||
{
|
{
|
||||||
get { return base.Density; }
|
get { return base.Density; }
|
||||||
|
@ -647,7 +689,7 @@ public class BSPrim : BSPhysObject
|
||||||
RegisterPreStepAction("BSPrim.setTorque", LocalID,
|
RegisterPreStepAction("BSPrim.setTorque", LocalID,
|
||||||
delegate(float timeStep)
|
delegate(float timeStep)
|
||||||
{
|
{
|
||||||
if (!IsPhysicallyActive)
|
if (!IsPhysicallyActive || _torque == OMV.Vector3.Zero)
|
||||||
{
|
{
|
||||||
UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
|
UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
|
||||||
return;
|
return;
|
||||||
|
@ -1569,7 +1611,8 @@ public class BSPrim : BSPhysObject
|
||||||
profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f;
|
profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f;
|
||||||
volume *= (profileEnd - profileBegin);
|
volume *= (profileEnd - profileBegin);
|
||||||
|
|
||||||
returnMass = Density * volume;
|
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);
|
returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass);
|
||||||
|
|
||||||
|
@ -1607,6 +1650,8 @@ public class BSPrim : BSPhysObject
|
||||||
// the world that things have changed.
|
// the world that things have changed.
|
||||||
public override void UpdateProperties(EntityProperties entprop)
|
public override void UpdateProperties(EntityProperties entprop)
|
||||||
{
|
{
|
||||||
|
TriggerPreUpdatePropertyAction(ref entprop);
|
||||||
|
|
||||||
// A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
|
// A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
|
||||||
// TODO: handle physics introduced by Bullet with computed vehicle physics.
|
// TODO: handle physics introduced by Bullet with computed vehicle physics.
|
||||||
if (VehicleController.IsActive)
|
if (VehicleController.IsActive)
|
||||||
|
@ -1619,6 +1664,10 @@ public class BSPrim : BSPhysObject
|
||||||
// Assign directly to the local variables so the normal set actions do not happen
|
// Assign directly to the local variables so the normal set actions do not happen
|
||||||
_position = entprop.Position;
|
_position = entprop.Position;
|
||||||
_orientation = entprop.Rotation;
|
_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;
|
_velocity = entprop.Velocity;
|
||||||
_acceleration = entprop.Acceleration;
|
_acceleration = entprop.Acceleration;
|
||||||
_rotationalVelocity = entprop.RotationalVelocity;
|
_rotationalVelocity = entprop.RotationalVelocity;
|
||||||
|
|
|
@ -44,72 +44,107 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
{
|
{
|
||||||
public class BSPrimDisplaced : BSPrim
|
public class BSPrimDisplaced : BSPrim
|
||||||
{
|
{
|
||||||
// 'Position' and 'Orientation' is what the simulator thinks the positions of the prim is.
|
// The purpose of this module is to do any mapping between what the simulator thinks
|
||||||
// Because Bullet needs the zero coordinate to be the center of mass of the linkset,
|
// the prim position and orientation is and what the physical position/orientation.
|
||||||
// sometimes it is necessary to displace the position the physics engine thinks
|
// This difference happens because Bullet assumes the center-of-mass is the <0,0,0>
|
||||||
// the position is. PositionDisplacement must be added and removed from the
|
// of the prim/linkset. The simulator tracks the location of the prim/linkset by
|
||||||
// position as the simulator position is stored and fetched from the physics
|
// the location of the root prim. So, if center-of-mass is anywhere but the origin
|
||||||
// engine. Similar to OrientationDisplacement.
|
// 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.Vector3 PositionDisplacement { get; set; }
|
||||||
public virtual OMV.Quaternion OrientationDisplacement { get; set; }
|
public virtual OMV.Quaternion OrientationDisplacement { get; set; }
|
||||||
public virtual OMV.Vector3 CenterOfMassLocation { get; set; }
|
|
||||||
public virtual OMV.Vector3 GeometricCenterLocation { get; set; }
|
|
||||||
|
|
||||||
public BSPrimDisplaced(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
|
public BSPrimDisplaced(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
|
||||||
OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
|
OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
|
||||||
: base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical)
|
: base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical)
|
||||||
{
|
{
|
||||||
CenterOfMassLocation = RawPosition;
|
ClearDisplacement();
|
||||||
GeometricCenterLocation = RawPosition;
|
}
|
||||||
|
|
||||||
|
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
|
public override Vector3 ForcePosition
|
||||||
{
|
{
|
||||||
get
|
get { return base.ForcePosition; }
|
||||||
{
|
|
||||||
return base.ForcePosition;
|
|
||||||
}
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
|
if (PositionDisplacement != OMV.Vector3.Zero)
|
||||||
|
base.ForcePosition = value - (PositionDisplacement * RawOrientation);
|
||||||
|
else
|
||||||
base.ForcePosition = value;
|
base.ForcePosition = value;
|
||||||
CenterOfMassLocation = RawPosition;
|
|
||||||
GeometricCenterLocation = RawPosition;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Quaternion ForceOrientation
|
public override Quaternion ForceOrientation
|
||||||
{
|
{
|
||||||
get
|
get { return base.ForceOrientation; }
|
||||||
{
|
|
||||||
return base.ForceOrientation;
|
|
||||||
}
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
base.ForceOrientation = value;
|
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?
|
// Is this used?
|
||||||
public override OMV.Vector3 CenterOfMass
|
public override OMV.Vector3 CenterOfMass
|
||||||
{
|
{
|
||||||
get { return CenterOfMassLocation; }
|
get { return RawPosition; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is this used?
|
// Is this used?
|
||||||
public override OMV.Vector3 GeometricCenter
|
public override OMV.Vector3 GeometricCenter
|
||||||
{
|
{
|
||||||
get { return GeometricCenterLocation; }
|
get { return RawPosition; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override void UpdateProperties(EntityProperties entprop)
|
public override void UpdateProperties(EntityProperties entprop)
|
||||||
{
|
{
|
||||||
// Undo any center-of-mass displacement that might have been done.
|
// Undo any center-of-mass displacement that might have been done.
|
||||||
if (PositionDisplacement != OMV.Vector3.Zero)
|
if (PositionDisplacement != OMV.Vector3.Zero || OrientationDisplacement != OMV.Quaternion.Identity)
|
||||||
{
|
{
|
||||||
// Correct for any rotation around the center-of-mass
|
// Correct for any rotation around the center-of-mass
|
||||||
// TODO!!!
|
// TODO!!!
|
||||||
entprop.Position -= PositionDisplacement;
|
entprop.Position = entprop.Position + (PositionDisplacement * entprop.Rotation);
|
||||||
|
// entprop.Rotation = something;
|
||||||
}
|
}
|
||||||
|
|
||||||
base.UpdateProperties(entprop);
|
base.UpdateProperties(entprop);
|
||||||
|
|
|
@ -38,6 +38,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
public class BSPrimLinkable : BSPrimDisplaced
|
public class BSPrimLinkable : BSPrimDisplaced
|
||||||
{
|
{
|
||||||
public BSLinkset Linkset { get; set; }
|
public BSLinkset Linkset { get; set; }
|
||||||
|
// The index of this child prim.
|
||||||
|
public int LinksetChildIndex { get; set; }
|
||||||
|
|
||||||
public BSLinksetInfo LinksetInfo { get; set; }
|
public BSLinksetInfo LinksetInfo { get; set; }
|
||||||
|
|
||||||
public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
|
public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
|
||||||
|
@ -90,7 +93,6 @@ public class BSPrimLinkable : BSPrimDisplaced
|
||||||
DetailLog("{0},BSPrimLinkset.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
|
DetailLog("{0},BSPrimLinkset.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
|
||||||
LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
|
LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
|
||||||
return;
|
return;
|
||||||
base.delink();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// When simulator changes position, this might be moving a child of the linkset.
|
// When simulator changes position, this might be moving a child of the linkset.
|
||||||
|
@ -133,6 +135,7 @@ public class BSPrimLinkable : BSPrimDisplaced
|
||||||
// When going from non-physical to physical, this re-enables the constraints that
|
// When going from non-physical to physical, this re-enables the constraints that
|
||||||
// had been automatically disabled when the mass was set to zero.
|
// had been automatically disabled when the mass was set to zero.
|
||||||
// For compound based linksets, this enables and disables interactions of the children.
|
// For compound based linksets, this enables and disables interactions of the children.
|
||||||
|
if (Linkset != null) // null can happen during initialization
|
||||||
Linkset.Refresh(this);
|
Linkset.Refresh(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,12 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
|
||||||
{
|
{
|
||||||
bool Cancel();
|
bool Cancel();
|
||||||
void Abort();
|
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>
|
/// <summary>
|
||||||
|
|
|
@ -4479,6 +4479,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pushAllowed)
|
if (pushAllowed)
|
||||||
{
|
{
|
||||||
float distance = (PusheePos - m_host.AbsolutePosition).Length();
|
float distance = (PusheePos - m_host.AbsolutePosition).Length();
|
||||||
|
@ -4507,17 +4508,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
applied_linear_impulse *= scaling_factor;
|
applied_linear_impulse *= scaling_factor;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pusheeIsAvatar)
|
if (pusheeIsAvatar)
|
||||||
{
|
{
|
||||||
if (pusheeav != null)
|
if (pusheeav != null)
|
||||||
{
|
{
|
||||||
if (pusheeav.PhysicsActor != null)
|
PhysicsActor pa = pusheeav.PhysicsActor;
|
||||||
|
|
||||||
|
if (pa != null)
|
||||||
{
|
{
|
||||||
if (local != 0)
|
if (local != 0)
|
||||||
{
|
{
|
||||||
applied_linear_impulse *= m_host.GetWorldRotation();
|
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 (!m_coopTermination)
|
||||||
{
|
{
|
||||||
// If we're not co-operative terminating then try and wait for the event to complete before stopping
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
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
|
// 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.
|
// 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)
|
if (DebugLevel >= 1)
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
|
|
|
@ -57,8 +57,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
wr.Abort();
|
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);
|
return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue