diff options
author | Dan Lake | 2013-02-14 20:06:22 -0800 |
---|---|---|
committer | Dan Lake | 2013-02-14 20:06:22 -0800 |
commit | e09467b30d5d27181c158961e95df25cd6001be5 (patch) | |
tree | 439acb650990a3495187f55d8a69b9a78f359c00 /OpenSim | |
parent | Use SortedDictionary in StatsManager instead of regular Dictionary so stats w... (diff) | |
parent | Enable one sub-test in TestJsonSetValue() which now works (using identifier w... (diff) | |
download | opensim-SC-e09467b30d5d27181c158961e95df25cd6001be5.zip opensim-SC-e09467b30d5d27181c158961e95df25cd6001be5.tar.gz opensim-SC-e09467b30d5d27181c158961e95df25cd6001be5.tar.bz2 opensim-SC-e09467b30d5d27181c158961e95df25cd6001be5.tar.xz |
Merge branch 'master' of git://opensimulator.org/git/opensim
Diffstat (limited to 'OpenSim')
27 files changed, 983 insertions, 242 deletions
diff --git a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs index cfb1605..bb8825b 100644 --- a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs +++ b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs | |||
@@ -535,6 +535,8 @@ namespace OpenSim.Framework.Servers.HttpServer | |||
535 | /// <param name="message"></param> | 535 | /// <param name="message"></param> |
536 | public void Close(string message) | 536 | public void Close(string message) |
537 | { | 537 | { |
538 | if (_networkContext == null) | ||
539 | return; | ||
538 | if (_networkContext.Stream != null) | 540 | if (_networkContext.Stream != null) |
539 | { | 541 | { |
540 | if (_networkContext.Stream.CanWrite) | 542 | if (_networkContext.Stream.CanWrite) |
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs index 191bccf..6ef8815 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs | |||
@@ -59,6 +59,8 @@ namespace OpenSim.Region.ClientStack.Linden | |||
59 | // private static readonly ILog m_log = | 59 | // private static readonly ILog m_log = |
60 | // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 60 | // LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
61 | 61 | ||
62 | public event SimulatorFeaturesRequestDelegate OnSimulatorFeaturesRequest; | ||
63 | |||
62 | private Scene m_scene; | 64 | private Scene m_scene; |
63 | 65 | ||
64 | /// <summary> | 66 | /// <summary> |
@@ -94,6 +96,8 @@ namespace OpenSim.Region.ClientStack.Linden | |||
94 | { | 96 | { |
95 | m_scene = s; | 97 | m_scene = s; |
96 | m_scene.EventManager.OnRegisterCaps += RegisterCaps; | 98 | m_scene.EventManager.OnRegisterCaps += RegisterCaps; |
99 | |||
100 | m_scene.RegisterModuleInterface<ISimulatorFeaturesModule>(this); | ||
97 | } | 101 | } |
98 | 102 | ||
99 | public void RemoveRegion(Scene s) | 103 | public void RemoveRegion(Scene s) |
@@ -156,7 +160,7 @@ namespace OpenSim.Region.ClientStack.Linden | |||
156 | IRequestHandler reqHandler | 160 | IRequestHandler reqHandler |
157 | = new RestHTTPHandler( | 161 | = new RestHTTPHandler( |
158 | "GET", "/CAPS/" + UUID.Random(), | 162 | "GET", "/CAPS/" + UUID.Random(), |
159 | HandleSimulatorFeaturesRequest, "SimulatorFeatures", agentID.ToString()); | 163 | x => { return HandleSimulatorFeaturesRequest(x, agentID); }, "SimulatorFeatures", agentID.ToString()); |
160 | 164 | ||
161 | caps.RegisterHandler("SimulatorFeatures", reqHandler); | 165 | caps.RegisterHandler("SimulatorFeatures", reqHandler); |
162 | } | 166 | } |
@@ -185,18 +189,33 @@ namespace OpenSim.Region.ClientStack.Linden | |||
185 | return new OSDMap(m_features); | 189 | return new OSDMap(m_features); |
186 | } | 190 | } |
187 | 191 | ||
188 | private Hashtable HandleSimulatorFeaturesRequest(Hashtable mDhttpMethod) | 192 | private OSDMap DeepCopy() |
193 | { | ||
194 | // This isn't the cheapest way of doing this but the rate | ||
195 | // of occurrence is low (on sim entry only) and it's a sure | ||
196 | // way to get a true deep copy. | ||
197 | OSD copy = OSDParser.DeserializeLLSDXml(OSDParser.SerializeLLSDXmlString(m_features)); | ||
198 | |||
199 | return (OSDMap)copy; | ||
200 | } | ||
201 | |||
202 | private Hashtable HandleSimulatorFeaturesRequest(Hashtable mDhttpMethod, UUID agentID) | ||
189 | { | 203 | { |
190 | // m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request"); | 204 | // m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request"); |
191 | 205 | ||
206 | OSDMap copy = DeepCopy(); | ||
207 | |||
208 | SimulatorFeaturesRequestDelegate handlerOnSimulatorFeaturesRequest = OnSimulatorFeaturesRequest; | ||
209 | if (handlerOnSimulatorFeaturesRequest != null) | ||
210 | handlerOnSimulatorFeaturesRequest(agentID, ref copy); | ||
211 | |||
192 | //Send back data | 212 | //Send back data |
193 | Hashtable responsedata = new Hashtable(); | 213 | Hashtable responsedata = new Hashtable(); |
194 | responsedata["int_response_code"] = 200; | 214 | responsedata["int_response_code"] = 200; |
195 | responsedata["content_type"] = "text/plain"; | 215 | responsedata["content_type"] = "text/plain"; |
196 | responsedata["keepalive"] = false; | 216 | responsedata["keepalive"] = false; |
197 | 217 | ||
198 | lock (m_features) | 218 | responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(copy); |
199 | responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(m_features); | ||
200 | 219 | ||
201 | return responsedata; | 220 | return responsedata; |
202 | } | 221 | } |
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index d1ad74f..b67c0df 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs | |||
@@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
42 | public class AssetTransactionModule : INonSharedRegionModule, | 42 | public class AssetTransactionModule : INonSharedRegionModule, |
43 | IAgentAssetTransactions | 43 | IAgentAssetTransactions |
44 | { | 44 | { |
45 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 45 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
46 | 46 | ||
47 | protected Scene m_Scene; | 47 | protected Scene m_Scene; |
48 | private bool m_dumpAssetsToFile = false; | 48 | private bool m_dumpAssetsToFile = false; |
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs index d36f65a..37131b9 100644 --- a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs +++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs | |||
@@ -44,7 +44,7 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DAExampleModule | |||
44 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")] | 44 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")] |
45 | public class DAExampleModule : INonSharedRegionModule | 45 | public class DAExampleModule : INonSharedRegionModule |
46 | { | 46 | { |
47 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 47 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
48 | 48 | ||
49 | private static readonly bool ENABLED = false; // enable for testing | 49 | private static readonly bool ENABLED = false; // enable for testing |
50 | 50 | ||
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs index fb74cc6..f3436d1 100644 --- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs | |||
@@ -57,7 +57,7 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging | |||
57 | try | 57 | try |
58 | { | 58 | { |
59 | IConfig statConfig = source.Configs["Statistics.Binary"]; | 59 | IConfig statConfig = source.Configs["Statistics.Binary"]; |
60 | if (statConfig.Contains("enabled") && statConfig.GetBoolean("enabled")) | 60 | if (statConfig != null && statConfig.Contains("enabled") && statConfig.GetBoolean("enabled")) |
61 | { | 61 | { |
62 | if (statConfig.Contains("collect_region_stats")) | 62 | if (statConfig.Contains("collect_region_stats")) |
63 | { | 63 | { |
diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs index 385f5ad..cbffca7 100644 --- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs | |||
@@ -111,13 +111,15 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC | |||
111 | m_rpcPending = new Dictionary<UUID, RPCRequestInfo>(); | 111 | m_rpcPending = new Dictionary<UUID, RPCRequestInfo>(); |
112 | m_rpcPendingResponses = new Dictionary<UUID, RPCRequestInfo>(); | 112 | m_rpcPendingResponses = new Dictionary<UUID, RPCRequestInfo>(); |
113 | m_pendingSRDResponses = new Dictionary<UUID, SendRemoteDataRequest>(); | 113 | m_pendingSRDResponses = new Dictionary<UUID, SendRemoteDataRequest>(); |
114 | 114 | if (config.Configs["XMLRPC"] != null) | |
115 | try | ||
116 | { | ||
117 | m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort); | ||
118 | } | ||
119 | catch (Exception) | ||
120 | { | 115 | { |
116 | try | ||
117 | { | ||
118 | m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort); | ||
119 | } | ||
120 | catch (Exception) | ||
121 | { | ||
122 | } | ||
121 | } | 123 | } |
122 | } | 124 | } |
123 | 125 | ||
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs index cc7885a..b40d24f 100644 --- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs | |||
@@ -31,6 +31,16 @@ using OpenMetaverse; | |||
31 | 31 | ||
32 | namespace OpenSim.Region.Framework.Interfaces | 32 | namespace OpenSim.Region.Framework.Interfaces |
33 | { | 33 | { |
34 | // these could be expanded at some point to provide more type information | ||
35 | // for now value accounts for all base types | ||
36 | public enum JsonStoreNodeType | ||
37 | { | ||
38 | Undefined = 0, | ||
39 | Object = 1, | ||
40 | Array = 2, | ||
41 | Value = 3 | ||
42 | } | ||
43 | |||
34 | public delegate void TakeValueCallback(string s); | 44 | public delegate void TakeValueCallback(string s); |
35 | 45 | ||
36 | public interface IJsonStoreModule | 46 | public interface IJsonStoreModule |
@@ -38,13 +48,18 @@ namespace OpenSim.Region.Framework.Interfaces | |||
38 | bool AttachObjectStore(UUID objectID); | 48 | bool AttachObjectStore(UUID objectID); |
39 | bool CreateStore(string value, ref UUID result); | 49 | bool CreateStore(string value, ref UUID result); |
40 | bool DestroyStore(UUID storeID); | 50 | bool DestroyStore(UUID storeID); |
51 | |||
52 | JsonStoreNodeType GetPathType(UUID storeID, string path); | ||
41 | bool TestStore(UUID storeID); | 53 | bool TestStore(UUID storeID); |
42 | bool TestPath(UUID storeID, string path, bool useJson); | 54 | bool TestPath(UUID storeID, string path, bool useJson); |
55 | |||
43 | bool SetValue(UUID storeID, string path, string value, bool useJson); | 56 | bool SetValue(UUID storeID, string path, string value, bool useJson); |
44 | bool RemoveValue(UUID storeID, string path); | 57 | bool RemoveValue(UUID storeID, string path); |
45 | bool GetValue(UUID storeID, string path, bool useJson, out string value); | 58 | bool GetValue(UUID storeID, string path, bool useJson, out string value); |
46 | 59 | ||
47 | void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback); | 60 | void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback); |
48 | void ReadValue(UUID storeID, string path, bool useJson, TakeValueCallback cback); | 61 | void ReadValue(UUID storeID, string path, bool useJson, TakeValueCallback cback); |
62 | |||
63 | int GetArrayLength(UUID storeID, string path); | ||
49 | } | 64 | } |
50 | } | 65 | } |
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulatorFeaturesModule.cs b/OpenSim/Region/Framework/Interfaces/ISimulatorFeaturesModule.cs index 8cef14e..6effcc1 100644 --- a/OpenSim/Region/Framework/Interfaces/ISimulatorFeaturesModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISimulatorFeaturesModule.cs | |||
@@ -26,18 +26,22 @@ | |||
26 | */ | 26 | */ |
27 | 27 | ||
28 | using System; | 28 | using System; |
29 | using OpenMetaverse; | ||
29 | using OpenMetaverse.StructuredData; | 30 | using OpenMetaverse.StructuredData; |
30 | 31 | ||
31 | namespace OpenSim.Region.Framework.Interfaces | 32 | namespace OpenSim.Region.Framework.Interfaces |
32 | { | 33 | { |
34 | public delegate void SimulatorFeaturesRequestDelegate(UUID agentID, ref OSDMap features); | ||
35 | |||
33 | /// <summary> | 36 | /// <summary> |
34 | /// Add remove or retrieve Simulator Features that will be given to a viewer via the SimulatorFeatures capability. | 37 | /// Add remove or retrieve Simulator Features that will be given to a viewer via the SimulatorFeatures capability. |
35 | /// </summary> | 38 | /// </summary> |
36 | public interface ISimulatorFeaturesModule | 39 | public interface ISimulatorFeaturesModule |
37 | { | 40 | { |
41 | event SimulatorFeaturesRequestDelegate OnSimulatorFeaturesRequest; | ||
38 | void AddFeature(string name, OSD value); | 42 | void AddFeature(string name, OSD value); |
39 | bool RemoveFeature(string name); | 43 | bool RemoveFeature(string name); |
40 | bool TryGetFeature(string name, out OSD value); | 44 | bool TryGetFeature(string name, out OSD value); |
41 | OSDMap GetFeatures(); | 45 | OSDMap GetFeatures(); |
42 | } | 46 | } |
43 | } \ No newline at end of file | 47 | } |
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 9ee1520..59d0148 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs | |||
@@ -791,6 +791,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
791 | public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); | 791 | public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); |
792 | 792 | ||
793 | /// <summary> | 793 | /// <summary> |
794 | /// Triggered when an object is placed into the physical scene (PhysicsActor created). | ||
795 | /// </summary> | ||
796 | public event Action<SceneObjectPart> OnObjectAddedToPhysicalScene; | ||
797 | /// <summary> | ||
798 | /// Triggered when an object is removed from the physical scene (PhysicsActor destroyed). | ||
799 | /// </summary> | ||
800 | /// <remarks> | ||
801 | /// Note: this is triggered just before the PhysicsActor is removed from the | ||
802 | /// physics engine so the receiver can do any necessary cleanup before its destruction. | ||
803 | /// </remarks> | ||
804 | public event Action<SceneObjectPart> OnObjectRemovedFromPhysicalScene; | ||
805 | |||
806 | /// <summary> | ||
794 | /// Triggered when an object is removed from the scene. | 807 | /// Triggered when an object is removed from the scene. |
795 | /// </summary> | 808 | /// </summary> |
796 | /// <remarks> | 809 | /// <remarks> |
@@ -1516,6 +1529,48 @@ namespace OpenSim.Region.Framework.Scenes | |||
1516 | } | 1529 | } |
1517 | } | 1530 | } |
1518 | 1531 | ||
1532 | public void TriggerObjectAddedToPhysicalScene(SceneObjectPart obj) | ||
1533 | { | ||
1534 | Action<SceneObjectPart> handler = OnObjectAddedToPhysicalScene; | ||
1535 | if (handler != null) | ||
1536 | { | ||
1537 | foreach (Action<SceneObjectPart> d in handler.GetInvocationList()) | ||
1538 | { | ||
1539 | try | ||
1540 | { | ||
1541 | d(obj); | ||
1542 | } | ||
1543 | catch (Exception e) | ||
1544 | { | ||
1545 | m_log.ErrorFormat( | ||
1546 | "[EVENT MANAGER]: Delegate for TriggerObjectAddedToPhysicalScene failed - continuing. {0} {1}", | ||
1547 | e.Message, e.StackTrace); | ||
1548 | } | ||
1549 | } | ||
1550 | } | ||
1551 | } | ||
1552 | |||
1553 | public void TriggerObjectRemovedFromPhysicalScene(SceneObjectPart obj) | ||
1554 | { | ||
1555 | Action<SceneObjectPart> handler = OnObjectRemovedFromPhysicalScene; | ||
1556 | if (handler != null) | ||
1557 | { | ||
1558 | foreach (Action<SceneObjectPart> d in handler.GetInvocationList()) | ||
1559 | { | ||
1560 | try | ||
1561 | { | ||
1562 | d(obj); | ||
1563 | } | ||
1564 | catch (Exception e) | ||
1565 | { | ||
1566 | m_log.ErrorFormat( | ||
1567 | "[EVENT MANAGER]: Delegate for TriggerObjectRemovedFromPhysicalScene failed - continuing. {0} {1}", | ||
1568 | e.Message, e.StackTrace); | ||
1569 | } | ||
1570 | } | ||
1571 | } | ||
1572 | } | ||
1573 | |||
1519 | public void TriggerShutdown() | 1574 | public void TriggerShutdown() |
1520 | { | 1575 | { |
1521 | Action handlerShutdown = OnShutdown; | 1576 | Action handlerShutdown = OnShutdown; |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 9b29973..cce8b21 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | |||
@@ -4316,6 +4316,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4316 | } | 4316 | } |
4317 | 4317 | ||
4318 | PhysActor = pa; | 4318 | PhysActor = pa; |
4319 | ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this); | ||
4319 | } | 4320 | } |
4320 | 4321 | ||
4321 | /// <summary> | 4322 | /// <summary> |
@@ -4328,6 +4329,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
4328 | /// </remarks> | 4329 | /// </remarks> |
4329 | public void RemoveFromPhysics() | 4330 | public void RemoveFromPhysics() |
4330 | { | 4331 | { |
4332 | ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this); | ||
4331 | ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); | 4333 | ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); |
4332 | PhysActor = null; | 4334 | PhysActor = null; |
4333 | } | 4335 | } |
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs index 82a4da7..ca3989a 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs | |||
@@ -68,14 +68,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
68 | protected List<TakeValueCallbackClass> m_TakeStore; | 68 | protected List<TakeValueCallbackClass> m_TakeStore; |
69 | protected List<TakeValueCallbackClass> m_ReadStore; | 69 | protected List<TakeValueCallbackClass> m_ReadStore; |
70 | 70 | ||
71 | // add separators for quoted paths | 71 | // add separators for quoted paths and array references |
72 | protected static Regex m_ParsePassOne = new Regex("{[^}]+}"); | 72 | protected static Regex m_ParsePassOne = new Regex("({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])"); |
73 | |||
74 | // add separators for array references | ||
75 | protected static Regex m_ParsePassTwo = new Regex("(\\[[0-9]+\\]|\\[\\+\\])"); | ||
76 | 73 | ||
77 | // add quotes to bare identifiers which are limited to alphabetic characters | 74 | // add quotes to bare identifiers which are limited to alphabetic characters |
78 | protected static Regex m_ParsePassThree = new Regex("\\.([a-zA-Z]+)"); | 75 | protected static Regex m_ParsePassThree = new Regex("(?<!{[^}]*)\\.([a-zA-Z]+)(?=\\.)"); |
79 | 76 | ||
80 | // remove extra separator characters | 77 | // remove extra separator characters |
81 | protected static Regex m_ParsePassFour = new Regex("\\.+"); | 78 | protected static Regex m_ParsePassFour = new Regex("\\.+"); |
@@ -84,7 +81,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
84 | protected static Regex m_ValidatePath = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)*$"); | 81 | protected static Regex m_ValidatePath = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)*$"); |
85 | 82 | ||
86 | // expression used to match path components | 83 | // expression used to match path components |
87 | protected static Regex m_PathComponent = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\]+)"); | 84 | protected static Regex m_PathComponent = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])"); |
88 | 85 | ||
89 | // extract the internals of an array reference | 86 | // extract the internals of an array reference |
90 | protected static Regex m_SimpleArrayPattern = new Regex("\\[([0-9]+)\\]"); | 87 | protected static Regex m_SimpleArrayPattern = new Regex("\\[([0-9]+)\\]"); |
@@ -131,15 +128,46 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
131 | m_TakeStore = new List<TakeValueCallbackClass>(); | 128 | m_TakeStore = new List<TakeValueCallbackClass>(); |
132 | m_ReadStore = new List<TakeValueCallbackClass>(); | 129 | m_ReadStore = new List<TakeValueCallbackClass>(); |
133 | } | 130 | } |
134 | 131 | ||
135 | public JsonStore(string value) : this() | 132 | public JsonStore(string value) : this() |
136 | { | 133 | { |
134 | // This is going to throw an exception if the value is not | ||
135 | // a valid JSON chunk. Calling routines should catch the | ||
136 | // exception and handle it appropriately | ||
137 | if (String.IsNullOrEmpty(value)) | 137 | if (String.IsNullOrEmpty(value)) |
138 | ValueStore = new OSDMap(); | 138 | ValueStore = new OSDMap(); |
139 | else | 139 | else |
140 | ValueStore = OSDParser.DeserializeJson(value); | 140 | ValueStore = OSDParser.DeserializeJson(value); |
141 | } | 141 | } |
142 | |||
143 | // ----------------------------------------------------------------- | ||
144 | /// <summary> | ||
145 | /// | ||
146 | /// </summary> | ||
147 | // ----------------------------------------------------------------- | ||
148 | public JsonStoreNodeType PathType(string expr) | ||
149 | { | ||
150 | Stack<string> path; | ||
151 | if (! ParsePathExpression(expr,out path)) | ||
152 | return JsonStoreNodeType.Undefined; | ||
153 | |||
154 | OSD result = ProcessPathExpression(ValueStore,path); | ||
142 | 155 | ||
156 | if (result == null) | ||
157 | return JsonStoreNodeType.Undefined; | ||
158 | |||
159 | if (result is OSDMap) | ||
160 | return JsonStoreNodeType.Object; | ||
161 | |||
162 | if (result is OSDArray) | ||
163 | return JsonStoreNodeType.Array; | ||
164 | |||
165 | if (OSDBaseType(result.Type)) | ||
166 | return JsonStoreNodeType.Value; | ||
167 | |||
168 | return JsonStoreNodeType.Undefined; | ||
169 | } | ||
170 | |||
143 | // ----------------------------------------------------------------- | 171 | // ----------------------------------------------------------------- |
144 | /// <summary> | 172 | /// <summary> |
145 | /// | 173 | /// |
@@ -167,6 +195,27 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
167 | /// | 195 | /// |
168 | /// </summary> | 196 | /// </summary> |
169 | // ----------------------------------------------------------------- | 197 | // ----------------------------------------------------------------- |
198 | public int ArrayLength(string expr) | ||
199 | { | ||
200 | Stack<string> path; | ||
201 | if (! ParsePathExpression(expr,out path)) | ||
202 | return -1; | ||
203 | |||
204 | OSD result = ProcessPathExpression(ValueStore,path); | ||
205 | if (result != null && result.Type == OSDType.Array) | ||
206 | { | ||
207 | OSDArray arr = result as OSDArray; | ||
208 | return arr.Count; | ||
209 | } | ||
210 | |||
211 | return -1; | ||
212 | } | ||
213 | |||
214 | // ----------------------------------------------------------------- | ||
215 | /// <summary> | ||
216 | /// | ||
217 | /// </summary> | ||
218 | // ----------------------------------------------------------------- | ||
170 | public bool GetValue(string expr, out string value, bool useJson) | 219 | public bool GetValue(string expr, out string value, bool useJson) |
171 | { | 220 | { |
172 | Stack<string> path; | 221 | Stack<string> path; |
@@ -462,11 +511,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
462 | // add front and rear separators | 511 | // add front and rear separators |
463 | expr = "." + expr + "."; | 512 | expr = "." + expr + "."; |
464 | 513 | ||
465 | // add separators for quoted exprs | 514 | // add separators for quoted exprs and array references |
466 | expr = m_ParsePassOne.Replace(expr,".$0.",-1,0); | 515 | expr = m_ParsePassOne.Replace(expr,".$1.",-1,0); |
467 | |||
468 | // add separators for array references | ||
469 | expr = m_ParsePassTwo.Replace(expr,".$0.",-1,0); | ||
470 | 516 | ||
471 | // add quotes to bare identifier | 517 | // add quotes to bare identifier |
472 | expr = m_ParsePassThree.Replace(expr,".{$1}",-1,0); | 518 | expr = m_ParsePassThree.Replace(expr,".{$1}",-1,0); |
@@ -574,14 +620,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
574 | // The path pointed to an intermediate hash structure | 620 | // The path pointed to an intermediate hash structure |
575 | if (result.Type == OSDType.Map) | 621 | if (result.Type == OSDType.Map) |
576 | { | 622 | { |
577 | value = OSDParser.SerializeJsonString(result as OSDMap); | 623 | value = OSDParser.SerializeJsonString(result as OSDMap,true); |
578 | return true; | 624 | return true; |
579 | } | 625 | } |
580 | 626 | ||
581 | // The path pointed to an intermediate hash structure | 627 | // The path pointed to an intermediate hash structure |
582 | if (result.Type == OSDType.Array) | 628 | if (result.Type == OSDType.Array) |
583 | { | 629 | { |
584 | value = OSDParser.SerializeJsonString(result as OSDArray); | 630 | value = OSDParser.SerializeJsonString(result as OSDArray,true); |
585 | return true; | 631 | return true; |
586 | } | 632 | } |
587 | 633 | ||
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs index f1ce856..fb35068 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs | |||
@@ -227,7 +227,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
227 | } | 227 | } |
228 | catch (Exception e) | 228 | catch (Exception e) |
229 | { | 229 | { |
230 | m_log.Error(string.Format("[JsonStore]: Unable to initialize store from {0}", value), e); | 230 | m_log.ErrorFormat("[JsonStore]: Unable to initialize store from {0}", value); |
231 | return false; | 231 | return false; |
232 | } | 232 | } |
233 | 233 | ||
@@ -270,6 +270,38 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
270 | /// | 270 | /// |
271 | /// </summary> | 271 | /// </summary> |
272 | // ----------------------------------------------------------------- | 272 | // ----------------------------------------------------------------- |
273 | public JsonStoreNodeType GetPathType(UUID storeID, string path) | ||
274 | { | ||
275 | if (! m_enabled) return JsonStoreNodeType.Undefined; | ||
276 | |||
277 | JsonStore map = null; | ||
278 | lock (m_JsonValueStore) | ||
279 | { | ||
280 | if (! m_JsonValueStore.TryGetValue(storeID,out map)) | ||
281 | { | ||
282 | m_log.InfoFormat("[JsonStore] Missing store {0}",storeID); | ||
283 | return JsonStoreNodeType.Undefined; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | try | ||
288 | { | ||
289 | lock (map) | ||
290 | return map.PathType(path); | ||
291 | } | ||
292 | catch (Exception e) | ||
293 | { | ||
294 | m_log.Error(string.Format("[JsonStore]: Path test failed for {0} in {1}", path, storeID), e); | ||
295 | } | ||
296 | |||
297 | return JsonStoreNodeType.Undefined; | ||
298 | } | ||
299 | |||
300 | // ----------------------------------------------------------------- | ||
301 | /// <summary> | ||
302 | /// | ||
303 | /// </summary> | ||
304 | // ----------------------------------------------------------------- | ||
273 | public bool TestPath(UUID storeID, string path, bool useJson) | 305 | public bool TestPath(UUID storeID, string path, bool useJson) |
274 | { | 306 | { |
275 | if (! m_enabled) return false; | 307 | if (! m_enabled) return false; |
@@ -375,6 +407,37 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
375 | /// | 407 | /// |
376 | /// </summary> | 408 | /// </summary> |
377 | // ----------------------------------------------------------------- | 409 | // ----------------------------------------------------------------- |
410 | public int GetArrayLength(UUID storeID, string path) | ||
411 | { | ||
412 | if (! m_enabled) return -1; | ||
413 | |||
414 | JsonStore map = null; | ||
415 | lock (m_JsonValueStore) | ||
416 | { | ||
417 | if (! m_JsonValueStore.TryGetValue(storeID,out map)) | ||
418 | return -1; | ||
419 | } | ||
420 | |||
421 | try | ||
422 | { | ||
423 | lock (map) | ||
424 | { | ||
425 | return map.ArrayLength(path); | ||
426 | } | ||
427 | } | ||
428 | catch (Exception e) | ||
429 | { | ||
430 | m_log.Error("[JsonStore]: unable to retrieve value", e); | ||
431 | } | ||
432 | |||
433 | return -1; | ||
434 | } | ||
435 | |||
436 | // ----------------------------------------------------------------- | ||
437 | /// <summary> | ||
438 | /// | ||
439 | /// </summary> | ||
440 | // ----------------------------------------------------------------- | ||
378 | public bool GetValue(UUID storeID, string path, bool useJson, out string value) | 441 | public bool GetValue(UUID storeID, string path, bool useJson, out string value) |
379 | { | 442 | { |
380 | value = String.Empty; | 443 | value = String.Empty; |
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs index e436304..ef08c05 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs | |||
@@ -167,7 +167,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
167 | try | 167 | try |
168 | { | 168 | { |
169 | m_comms.RegisterScriptInvocations(this); | 169 | m_comms.RegisterScriptInvocations(this); |
170 | 170 | m_comms.RegisterConstants(this); | |
171 | |||
171 | // m_comms.RegisterScriptInvocation(this, "JsonCreateStore"); | 172 | // m_comms.RegisterScriptInvocation(this, "JsonCreateStore"); |
172 | // m_comms.RegisterScriptInvocation(this, "JsonAttachObjectStore"); | 173 | // m_comms.RegisterScriptInvocation(this, "JsonAttachObjectStore"); |
173 | // m_comms.RegisterScriptInvocation(this, "JsonDestroyStore"); | 174 | // m_comms.RegisterScriptInvocation(this, "JsonDestroyStore"); |
@@ -214,6 +215,22 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
214 | 215 | ||
215 | #endregion | 216 | #endregion |
216 | 217 | ||
218 | #region ScriptConstantsInterface | ||
219 | |||
220 | [ScriptConstant] | ||
221 | public static readonly int JSON_TYPE_UNDEF = (int)JsonStoreNodeType.Undefined; | ||
222 | |||
223 | [ScriptConstant] | ||
224 | public static readonly int JSON_TYPE_OBJECT = (int)JsonStoreNodeType.Object; | ||
225 | |||
226 | [ScriptConstant] | ||
227 | public static readonly int JSON_TYPE_ARRAY = (int)JsonStoreNodeType.Array; | ||
228 | |||
229 | [ScriptConstant] | ||
230 | public static readonly int JSON_TYPE_VALUE = (int)JsonStoreNodeType.Value; | ||
231 | |||
232 | #endregion | ||
233 | |||
217 | #region ScriptInvocationInteface | 234 | #region ScriptInvocationInteface |
218 | // ----------------------------------------------------------------- | 235 | // ----------------------------------------------------------------- |
219 | /// <summary> | 236 | /// <summary> |
@@ -319,6 +336,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
319 | /// </summary> | 336 | /// </summary> |
320 | // ----------------------------------------------------------------- | 337 | // ----------------------------------------------------------------- |
321 | [ScriptInvocation] | 338 | [ScriptInvocation] |
339 | public int JsonGetPathType(UUID hostID, UUID scriptID, UUID storeID, string path) | ||
340 | { | ||
341 | return (int)m_store.GetPathType(storeID,path); | ||
342 | } | ||
343 | |||
344 | [ScriptInvocation] | ||
322 | public int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path) | 345 | public int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path) |
323 | { | 346 | { |
324 | return m_store.TestPath(storeID,path,false) ? 1 : 0; | 347 | return m_store.TestPath(storeID,path,false) ? 1 : 0; |
@@ -342,7 +365,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
342 | } | 365 | } |
343 | 366 | ||
344 | [ScriptInvocation] | 367 | [ScriptInvocation] |
345 | public int JsonSetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value) | 368 | public int JsonSetJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value) |
346 | { | 369 | { |
347 | return m_store.SetValue(storeID,path,value,true) ? 1 : 0; | 370 | return m_store.SetValue(storeID,path,value,true) ? 1 : 0; |
348 | } | 371 | } |
@@ -364,6 +387,17 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
364 | /// </summary> | 387 | /// </summary> |
365 | // ----------------------------------------------------------------- | 388 | // ----------------------------------------------------------------- |
366 | [ScriptInvocation] | 389 | [ScriptInvocation] |
390 | public int JsonGetArrayLength(UUID hostID, UUID scriptID, UUID storeID, string path) | ||
391 | { | ||
392 | return m_store.GetArrayLength(storeID,path); | ||
393 | } | ||
394 | |||
395 | // ----------------------------------------------------------------- | ||
396 | /// <summary> | ||
397 | /// | ||
398 | /// </summary> | ||
399 | // ----------------------------------------------------------------- | ||
400 | [ScriptInvocation] | ||
367 | public string JsonGetValue(UUID hostID, UUID scriptID, UUID storeID, string path) | 401 | public string JsonGetValue(UUID hostID, UUID scriptID, UUID storeID, string path) |
368 | { | 402 | { |
369 | string value = String.Empty; | 403 | string value = String.Empty; |
@@ -372,7 +406,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore | |||
372 | } | 406 | } |
373 | 407 | ||
374 | [ScriptInvocation] | 408 | [ScriptInvocation] |
375 | public string JsonGetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) | 409 | public string JsonGetJson(UUID hostID, UUID scriptID, UUID storeID, string path) |
376 | { | 410 | { |
377 | string value = String.Empty; | 411 | string value = String.Empty; |
378 | m_store.GetValue(storeID,path,true, out value); | 412 | m_store.GetValue(storeID,path,true, out value); |
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs index 717484c..3d9ad16 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs | |||
@@ -53,6 +53,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
53 | private Scene m_scene; | 53 | private Scene m_scene; |
54 | private MockScriptEngine m_engine; | 54 | private MockScriptEngine m_engine; |
55 | private ScriptModuleCommsModule m_smcm; | 55 | private ScriptModuleCommsModule m_smcm; |
56 | private JsonStoreScriptModule m_jssm; | ||
56 | 57 | ||
57 | [TestFixtureSetUp] | 58 | [TestFixtureSetUp] |
58 | public void FixtureInit() | 59 | public void FixtureInit() |
@@ -82,10 +83,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
82 | m_engine = new MockScriptEngine(); | 83 | m_engine = new MockScriptEngine(); |
83 | m_smcm = new ScriptModuleCommsModule(); | 84 | m_smcm = new ScriptModuleCommsModule(); |
84 | JsonStoreModule jsm = new JsonStoreModule(); | 85 | JsonStoreModule jsm = new JsonStoreModule(); |
85 | JsonStoreScriptModule jssm = new JsonStoreScriptModule(); | 86 | m_jssm = new JsonStoreScriptModule(); |
86 | 87 | ||
87 | m_scene = new SceneHelpers().SetupScene(); | 88 | m_scene = new SceneHelpers().SetupScene(); |
88 | SceneHelpers.SetupSceneModules(m_scene, configSource, m_engine, m_smcm, jsm, jssm); | 89 | SceneHelpers.SetupSceneModules(m_scene, configSource, m_engine, m_smcm, jsm, m_jssm); |
89 | 90 | ||
90 | try | 91 | try |
91 | { | 92 | { |
@@ -115,8 +116,35 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
115 | TestHelpers.InMethod(); | 116 | TestHelpers.InMethod(); |
116 | // TestHelpers.EnableLogging(); | 117 | // TestHelpers.EnableLogging(); |
117 | 118 | ||
118 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | 119 | // Test blank store |
119 | Assert.That(storeId, Is.Not.EqualTo(UUID.Zero)); | 120 | { |
121 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
122 | Assert.That(storeId, Is.Not.EqualTo(UUID.Zero)); | ||
123 | } | ||
124 | |||
125 | // Test single element store | ||
126 | { | ||
127 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); | ||
128 | Assert.That(storeId, Is.Not.EqualTo(UUID.Zero)); | ||
129 | } | ||
130 | |||
131 | // Test with an integer value | ||
132 | { | ||
133 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 42.15 }"); | ||
134 | Assert.That(storeId, Is.Not.EqualTo(UUID.Zero)); | ||
135 | |||
136 | string value = (string)InvokeOp("JsonGetValue", storeId, "Hello"); | ||
137 | Assert.That(value, Is.EqualTo("42.15")); | ||
138 | } | ||
139 | |||
140 | // Test with an array as the root node | ||
141 | { | ||
142 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "[ 'one', 'two', 'three' ]"); | ||
143 | Assert.That(storeId, Is.Not.EqualTo(UUID.Zero)); | ||
144 | |||
145 | string value = (string)InvokeOp("JsonGetValue", storeId, "[1]"); | ||
146 | Assert.That(value, Is.EqualTo("two")); | ||
147 | } | ||
120 | } | 148 | } |
121 | 149 | ||
122 | [Test] | 150 | [Test] |
@@ -181,7 +209,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
181 | } | 209 | } |
182 | 210 | ||
183 | [Test] | 211 | [Test] |
184 | public void TestJsonGetValueJson() | 212 | public void TestJsonGetJson() |
185 | { | 213 | { |
186 | TestHelpers.InMethod(); | 214 | TestHelpers.InMethod(); |
187 | // TestHelpers.EnableLogging(); | 215 | // TestHelpers.EnableLogging(); |
@@ -189,26 +217,26 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
189 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Two' } }"); | 217 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Two' } }"); |
190 | 218 | ||
191 | { | 219 | { |
192 | string value = (string)InvokeOp("JsonGetValueJson", storeId, "Hello.World"); | 220 | string value = (string)InvokeOp("JsonGetJson", storeId, "Hello.World"); |
193 | Assert.That(value, Is.EqualTo("'Two'")); | 221 | Assert.That(value, Is.EqualTo("'Two'")); |
194 | } | 222 | } |
195 | 223 | ||
196 | // Test get of path section instead of leaf | 224 | // Test get of path section instead of leaf |
197 | { | 225 | { |
198 | string value = (string)InvokeOp("JsonGetValueJson", storeId, "Hello"); | 226 | string value = (string)InvokeOp("JsonGetJson", storeId, "Hello"); |
199 | Assert.That(value, Is.EqualTo("{\"World\":\"Two\"}")); | 227 | Assert.That(value, Is.EqualTo("{\"World\":\"Two\"}")); |
200 | } | 228 | } |
201 | 229 | ||
202 | // Test get of non-existing value | 230 | // Test get of non-existing value |
203 | { | 231 | { |
204 | string fakeValueGet = (string)InvokeOp("JsonGetValueJson", storeId, "foo"); | 232 | string fakeValueGet = (string)InvokeOp("JsonGetJson", storeId, "foo"); |
205 | Assert.That(fakeValueGet, Is.EqualTo("")); | 233 | Assert.That(fakeValueGet, Is.EqualTo("")); |
206 | } | 234 | } |
207 | 235 | ||
208 | // Test get from non-existing store | 236 | // Test get from non-existing store |
209 | { | 237 | { |
210 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | 238 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); |
211 | string fakeStoreValueGet = (string)InvokeOp("JsonGetValueJson", fakeStoreId, "Hello"); | 239 | string fakeStoreValueGet = (string)InvokeOp("JsonGetJson", fakeStoreId, "Hello"); |
212 | Assert.That(fakeStoreValueGet, Is.EqualTo("")); | 240 | Assert.That(fakeStoreValueGet, Is.EqualTo("")); |
213 | } | 241 | } |
214 | } | 242 | } |
@@ -242,88 +270,236 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
242 | TestHelpers.InMethod(); | 270 | TestHelpers.InMethod(); |
243 | // TestHelpers.EnableLogging(); | 271 | // TestHelpers.EnableLogging(); |
244 | 272 | ||
245 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); | 273 | // Test remove of node in object pointing to a string |
274 | { | ||
275 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); | ||
276 | |||
277 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); | ||
278 | Assert.That(returnValue, Is.EqualTo(1)); | ||
279 | |||
280 | int result = (int)InvokeOp("JsonTestPath", storeId, "Hello"); | ||
281 | Assert.That(result, Is.EqualTo(0)); | ||
282 | |||
283 | string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello"); | ||
284 | Assert.That(returnValue2, Is.EqualTo("")); | ||
285 | } | ||
286 | |||
287 | // Test remove of node in object pointing to another object | ||
288 | { | ||
289 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Wally' } }"); | ||
290 | |||
291 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); | ||
292 | Assert.That(returnValue, Is.EqualTo(1)); | ||
293 | |||
294 | int result = (int)InvokeOp("JsonTestPath", storeId, "Hello"); | ||
295 | Assert.That(result, Is.EqualTo(0)); | ||
296 | |||
297 | string returnValue2 = (string)InvokeOp("JsonGetJson", storeId, "Hello"); | ||
298 | Assert.That(returnValue2, Is.EqualTo("")); | ||
299 | } | ||
300 | |||
301 | // Test remove of node in an array | ||
302 | { | ||
303 | UUID storeId | ||
304 | = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : [ 'value1', 'value2' ] }"); | ||
305 | |||
306 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello[0]"); | ||
307 | Assert.That(returnValue, Is.EqualTo(1)); | ||
246 | 308 | ||
247 | int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello"); | 309 | int result = (int)InvokeOp("JsonTestPath", storeId, "Hello[0]"); |
248 | Assert.That(returnValue, Is.EqualTo(1)); | 310 | Assert.That(result, Is.EqualTo(1)); |
311 | |||
312 | result = (int)InvokeOp("JsonTestPath", storeId, "Hello[1]"); | ||
313 | Assert.That(result, Is.EqualTo(0)); | ||
249 | 314 | ||
250 | int result = (int)InvokeOp("JsonTestPath", storeId, "Hello"); | 315 | string stringReturnValue = (string)InvokeOp("JsonGetValue", storeId, "Hello[0]"); |
251 | Assert.That(result, Is.EqualTo(0)); | 316 | Assert.That(stringReturnValue, Is.EqualTo("value2")); |
252 | 317 | ||
253 | string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello"); | 318 | stringReturnValue = (string)InvokeOp("JsonGetJson", storeId, "Hello[1]"); |
254 | Assert.That(returnValue2, Is.EqualTo("")); | 319 | Assert.That(stringReturnValue, Is.EqualTo("")); |
320 | } | ||
255 | 321 | ||
256 | // Test remove of non-existing value | 322 | // Test remove of non-existing value |
257 | int fakeValueRemove = (int)InvokeOp("JsonRemoveValue", storeId, "Hello"); | 323 | { |
258 | Assert.That(fakeValueRemove, Is.EqualTo(0)); | 324 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }"); |
259 | 325 | ||
260 | // Test get from non-existing store | 326 | int fakeValueRemove = (int)InvokeOp("JsonRemoveValue", storeId, "Cheese"); |
261 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | 327 | Assert.That(fakeValueRemove, Is.EqualTo(0)); |
262 | int fakeStoreValueRemove = (int)InvokeOp("JsonRemoveValue", fakeStoreId, "Hello"); | 328 | } |
263 | Assert.That(fakeStoreValueRemove, Is.EqualTo(0)); | 329 | |
330 | { | ||
331 | // Test get from non-existing store | ||
332 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
333 | int fakeStoreValueRemove = (int)InvokeOp("JsonRemoveValue", fakeStoreId, "Hello"); | ||
334 | Assert.That(fakeStoreValueRemove, Is.EqualTo(0)); | ||
335 | } | ||
264 | } | 336 | } |
265 | 337 | ||
338 | // [Test] | ||
339 | // public void TestJsonTestPath() | ||
340 | // { | ||
341 | // TestHelpers.InMethod(); | ||
342 | //// TestHelpers.EnableLogging(); | ||
343 | // | ||
344 | // UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }"); | ||
345 | // | ||
346 | // { | ||
347 | // int result = (int)InvokeOp("JsonTestPath", storeId, "Hello.World"); | ||
348 | // Assert.That(result, Is.EqualTo(1)); | ||
349 | // } | ||
350 | // | ||
351 | // // Test for path which does not resolve to a value. | ||
352 | // { | ||
353 | // int result = (int)InvokeOp("JsonTestPath", storeId, "Hello"); | ||
354 | // Assert.That(result, Is.EqualTo(0)); | ||
355 | // } | ||
356 | // | ||
357 | // { | ||
358 | // int result2 = (int)InvokeOp("JsonTestPath", storeId, "foo"); | ||
359 | // Assert.That(result2, Is.EqualTo(0)); | ||
360 | // } | ||
361 | // | ||
362 | // // Test with fake store | ||
363 | // { | ||
364 | // UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
365 | // int fakeStoreValueRemove = (int)InvokeOp("JsonTestPath", fakeStoreId, "Hello"); | ||
366 | // Assert.That(fakeStoreValueRemove, Is.EqualTo(0)); | ||
367 | // } | ||
368 | // } | ||
369 | |||
370 | // [Test] | ||
371 | // public void TestJsonTestPathJson() | ||
372 | // { | ||
373 | // TestHelpers.InMethod(); | ||
374 | //// TestHelpers.EnableLogging(); | ||
375 | // | ||
376 | // UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }"); | ||
377 | // | ||
378 | // { | ||
379 | // int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello.World"); | ||
380 | // Assert.That(result, Is.EqualTo(1)); | ||
381 | // } | ||
382 | // | ||
383 | // // Test for path which does not resolve to a value. | ||
384 | // { | ||
385 | // int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello"); | ||
386 | // Assert.That(result, Is.EqualTo(1)); | ||
387 | // } | ||
388 | // | ||
389 | // { | ||
390 | // int result2 = (int)InvokeOp("JsonTestPathJson", storeId, "foo"); | ||
391 | // Assert.That(result2, Is.EqualTo(0)); | ||
392 | // } | ||
393 | // | ||
394 | // // Test with fake store | ||
395 | // { | ||
396 | // UUID fakeStoreId = TestHelpers.ParseTail(0x500); | ||
397 | // int fakeStoreValueRemove = (int)InvokeOp("JsonTestPathJson", fakeStoreId, "Hello"); | ||
398 | // Assert.That(fakeStoreValueRemove, Is.EqualTo(0)); | ||
399 | // } | ||
400 | // } | ||
401 | |||
266 | [Test] | 402 | [Test] |
267 | public void TestJsonTestPath() | 403 | public void TestGetArrayLength() |
268 | { | 404 | { |
269 | TestHelpers.InMethod(); | 405 | TestHelpers.InMethod(); |
270 | // TestHelpers.EnableLogging(); | 406 | // TestHelpers.EnableLogging(); |
271 | 407 | ||
272 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }"); | 408 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }"); |
273 | 409 | ||
274 | { | 410 | { |
275 | int result = (int)InvokeOp("JsonTestPath", storeId, "Hello.World"); | 411 | int result = (int)InvokeOp("JsonGetArrayLength", storeId, "Hello.World"); |
276 | Assert.That(result, Is.EqualTo(1)); | 412 | Assert.That(result, Is.EqualTo(2)); |
277 | } | 413 | } |
278 | 414 | ||
279 | // Test for path which does not resolve to a value. | 415 | // Test path which is not an array |
280 | { | 416 | { |
281 | int result = (int)InvokeOp("JsonTestPath", storeId, "Hello"); | 417 | int result = (int)InvokeOp("JsonGetArrayLength", storeId, "Hello"); |
282 | Assert.That(result, Is.EqualTo(0)); | 418 | Assert.That(result, Is.EqualTo(-1)); |
283 | } | 419 | } |
284 | 420 | ||
421 | // Test fake path | ||
285 | { | 422 | { |
286 | int result2 = (int)InvokeOp("JsonTestPath", storeId, "foo"); | 423 | int result = (int)InvokeOp("JsonGetArrayLength", storeId, "foo"); |
287 | Assert.That(result2, Is.EqualTo(0)); | 424 | Assert.That(result, Is.EqualTo(-1)); |
288 | } | 425 | } |
289 | 426 | ||
290 | // Test with fake store | 427 | // Test fake store |
291 | { | 428 | { |
292 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | 429 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); |
293 | int fakeStoreValueRemove = (int)InvokeOp("JsonTestPath", fakeStoreId, "Hello"); | 430 | int result = (int)InvokeOp("JsonGetArrayLength", fakeStoreId, "Hello.World"); |
294 | Assert.That(fakeStoreValueRemove, Is.EqualTo(0)); | 431 | Assert.That(result, Is.EqualTo(-1)); |
295 | } | 432 | } |
296 | } | 433 | } |
297 | 434 | ||
298 | [Test] | 435 | [Test] |
299 | public void TestJsonTestPathJson() | 436 | public void TestJsonGetPathType() |
300 | { | 437 | { |
301 | TestHelpers.InMethod(); | 438 | TestHelpers.InMethod(); |
302 | // TestHelpers.EnableLogging(); | 439 | // TestHelpers.EnableLogging(); |
303 | 440 | ||
304 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }"); | 441 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }"); |
305 | 442 | ||
306 | { | 443 | { |
307 | int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello.World"); | 444 | int result = (int)InvokeOp("JsonGetPathType", storeId, "."); |
308 | Assert.That(result, Is.EqualTo(1)); | 445 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_OBJECT)); |
309 | } | 446 | } |
310 | 447 | ||
311 | // Test for path which does not resolve to a value. | ||
312 | { | 448 | { |
313 | int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello"); | 449 | int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello"); |
314 | Assert.That(result, Is.EqualTo(1)); | 450 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_OBJECT)); |
315 | } | 451 | } |
316 | 452 | ||
317 | { | 453 | { |
318 | int result2 = (int)InvokeOp("JsonTestPathJson", storeId, "foo"); | 454 | int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello.World"); |
319 | Assert.That(result2, Is.EqualTo(0)); | 455 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_ARRAY)); |
320 | } | 456 | } |
321 | 457 | ||
322 | // Test with fake store | 458 | { |
459 | int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello.World[0]"); | ||
460 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_VALUE)); | ||
461 | } | ||
462 | |||
463 | { | ||
464 | int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello.World[1]"); | ||
465 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_VALUE)); | ||
466 | } | ||
467 | |||
468 | // Test for non-existant path | ||
469 | { | ||
470 | int result = (int)InvokeOp("JsonGetPathType", storeId, "foo"); | ||
471 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF)); | ||
472 | } | ||
473 | |||
474 | // Test for non-existant store | ||
323 | { | 475 | { |
324 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | 476 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); |
325 | int fakeStoreValueRemove = (int)InvokeOp("JsonTestPathJson", fakeStoreId, "Hello"); | 477 | int result = (int)InvokeOp("JsonGetPathType", fakeStoreId, "."); |
326 | Assert.That(fakeStoreValueRemove, Is.EqualTo(0)); | 478 | Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF)); |
479 | } | ||
480 | } | ||
481 | |||
482 | [Test] | ||
483 | public void TestJsonList2Path() | ||
484 | { | ||
485 | TestHelpers.InMethod(); | ||
486 | // TestHelpers.EnableLogging(); | ||
487 | |||
488 | // Invoking these methods directly since I just couldn't get comms module invocation to work for some reason | ||
489 | // - some confusion with the methods that take a params object[] invocation. | ||
490 | { | ||
491 | string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo" }); | ||
492 | Assert.That(result, Is.EqualTo("{foo}")); | ||
493 | } | ||
494 | |||
495 | { | ||
496 | string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo", "bar" }); | ||
497 | Assert.That(result, Is.EqualTo("{foo}.{bar}")); | ||
498 | } | ||
499 | |||
500 | { | ||
501 | string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo", 1, "bar" }); | ||
502 | Assert.That(result, Is.EqualTo("{foo}.[1].{bar}")); | ||
327 | } | 503 | } |
328 | } | 504 | } |
329 | 505 | ||
@@ -334,7 +510,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
334 | // TestHelpers.EnableLogging(); | 510 | // TestHelpers.EnableLogging(); |
335 | 511 | ||
336 | { | 512 | { |
337 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); | 513 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); |
338 | 514 | ||
339 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun", "Times"); | 515 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun", "Times"); |
340 | Assert.That(result, Is.EqualTo(1)); | 516 | Assert.That(result, Is.EqualTo(1)); |
@@ -343,9 +519,155 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
343 | Assert.That(value, Is.EqualTo("Times")); | 519 | Assert.That(value, Is.EqualTo("Times")); |
344 | } | 520 | } |
345 | 521 | ||
522 | // Test setting a key containing periods with delineation | ||
523 | { | ||
524 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
525 | |||
526 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun.Circus}", "Times"); | ||
527 | Assert.That(result, Is.EqualTo(1)); | ||
528 | |||
529 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun.Circus}"); | ||
530 | Assert.That(value, Is.EqualTo("Times")); | ||
531 | } | ||
532 | |||
533 | // *** Test [] *** | ||
534 | |||
535 | // Test setting a key containing unbalanced ] without delineation. Expecting failure | ||
536 | { | ||
537 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
538 | |||
539 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun]Circus", "Times"); | ||
540 | Assert.That(result, Is.EqualTo(0)); | ||
541 | |||
542 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun]Circus"); | ||
543 | Assert.That(value, Is.EqualTo("")); | ||
544 | } | ||
545 | |||
546 | // Test setting a key containing unbalanced [ without delineation. Expecting failure | ||
547 | { | ||
548 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
549 | |||
550 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun[Circus", "Times"); | ||
551 | Assert.That(result, Is.EqualTo(0)); | ||
552 | |||
553 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun[Circus"); | ||
554 | Assert.That(value, Is.EqualTo("")); | ||
555 | } | ||
556 | |||
557 | // Test setting a key containing unbalanced [] without delineation. Expecting failure | ||
558 | { | ||
559 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
560 | |||
561 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun[]Circus", "Times"); | ||
562 | Assert.That(result, Is.EqualTo(0)); | ||
563 | |||
564 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun[]Circus"); | ||
565 | Assert.That(value, Is.EqualTo("")); | ||
566 | } | ||
567 | |||
568 | // Test setting a key containing unbalanced ] with delineation | ||
569 | { | ||
570 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
571 | |||
572 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun]Circus}", "Times"); | ||
573 | Assert.That(result, Is.EqualTo(1)); | ||
574 | |||
575 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun]Circus}"); | ||
576 | Assert.That(value, Is.EqualTo("Times")); | ||
577 | } | ||
578 | |||
579 | // Test setting a key containing unbalanced [ with delineation | ||
580 | { | ||
581 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
582 | |||
583 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[Circus}", "Times"); | ||
584 | Assert.That(result, Is.EqualTo(1)); | ||
585 | |||
586 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[Circus}"); | ||
587 | Assert.That(value, Is.EqualTo("Times")); | ||
588 | } | ||
589 | |||
590 | // Test setting a key containing empty balanced [] with delineation | ||
591 | { | ||
592 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
593 | |||
594 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[]Circus}", "Times"); | ||
595 | Assert.That(result, Is.EqualTo(1)); | ||
596 | |||
597 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[]Circus}"); | ||
598 | Assert.That(value, Is.EqualTo("Times")); | ||
599 | } | ||
600 | |||
601 | // // Commented out as this currently unexpectedly fails. | ||
602 | // // Test setting a key containing brackets around an integer with delineation | ||
603 | // { | ||
604 | // UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
605 | // | ||
606 | // int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[0]Circus}", "Times"); | ||
607 | // Assert.That(result, Is.EqualTo(1)); | ||
608 | // | ||
609 | // string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[0]Circus}"); | ||
610 | // Assert.That(value, Is.EqualTo("Times")); | ||
611 | // } | ||
612 | |||
613 | // *** Test {} *** | ||
614 | |||
615 | // Test setting a key containing unbalanced } without delineation. Expecting failure (?) | ||
616 | { | ||
617 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
618 | |||
619 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun}Circus", "Times"); | ||
620 | Assert.That(result, Is.EqualTo(0)); | ||
621 | |||
622 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun}Circus"); | ||
623 | Assert.That(value, Is.EqualTo("")); | ||
624 | } | ||
625 | |||
626 | // Test setting a key containing unbalanced { without delineation. Expecting failure (?) | ||
627 | { | ||
628 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
629 | |||
630 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun{Circus", "Times"); | ||
631 | Assert.That(result, Is.EqualTo(0)); | ||
632 | |||
633 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun}Circus"); | ||
634 | Assert.That(value, Is.EqualTo("")); | ||
635 | } | ||
636 | |||
637 | // // Commented out as this currently unexpectedly fails. | ||
638 | // // Test setting a key containing unbalanced } | ||
639 | // { | ||
640 | // UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
641 | // | ||
642 | // int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun}Circus}", "Times"); | ||
643 | // Assert.That(result, Is.EqualTo(0)); | ||
644 | // } | ||
645 | |||
646 | // Test setting a key containing unbalanced { with delineation | ||
647 | { | ||
648 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
649 | |||
650 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun{Circus}", "Times"); | ||
651 | Assert.That(result, Is.EqualTo(1)); | ||
652 | |||
653 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun{Circus}"); | ||
654 | Assert.That(value, Is.EqualTo("Times")); | ||
655 | } | ||
656 | |||
657 | // Test setting a key containing balanced {} with delineation. This should fail. | ||
658 | { | ||
659 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); | ||
660 | |||
661 | int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun{Filled}Circus}", "Times"); | ||
662 | Assert.That(result, Is.EqualTo(0)); | ||
663 | |||
664 | string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun{Filled}Circus}"); | ||
665 | Assert.That(value, Is.EqualTo("")); | ||
666 | } | ||
667 | |||
346 | // Test setting to location that does not exist. This should fail. | 668 | // Test setting to location that does not exist. This should fail. |
347 | { | 669 | { |
348 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); | 670 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}"); |
349 | 671 | ||
350 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun.Circus", "Times"); | 672 | int result = (int)InvokeOp("JsonSetValue", storeId, "Fun.Circus", "Times"); |
351 | Assert.That(result, Is.EqualTo(0)); | 673 | Assert.That(result, Is.EqualTo(0)); |
@@ -363,27 +685,27 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
363 | } | 685 | } |
364 | 686 | ||
365 | [Test] | 687 | [Test] |
366 | public void TestJsonSetValueJson() | 688 | public void TestJsonSetJson() |
367 | { | 689 | { |
368 | TestHelpers.InMethod(); | 690 | TestHelpers.InMethod(); |
369 | // TestHelpers.EnableLogging(); | 691 | // TestHelpers.EnableLogging(); |
370 | 692 | ||
371 | // Single quoted token case | 693 | // Single quoted token case |
372 | // { | 694 | { |
373 | // UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); | 695 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); |
374 | // | 696 | |
375 | // int result = (int)InvokeOp("JsonSetValueJson", storeId, "Fun", "'Times'"); | 697 | int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "'Times'"); |
376 | // Assert.That(result, Is.EqualTo(1)); | 698 | Assert.That(result, Is.EqualTo(1)); |
377 | // | 699 | |
378 | // string value = (string)InvokeOp("JsonGetValue", storeId, "Fun"); | 700 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun"); |
379 | // Assert.That(value, Is.EqualTo("Times")); | 701 | Assert.That(value, Is.EqualTo("Times")); |
380 | // } | 702 | } |
381 | 703 | ||
382 | // Sub-tree case | 704 | // Sub-tree case |
383 | { | 705 | { |
384 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); | 706 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); |
385 | 707 | ||
386 | int result = (int)InvokeOp("JsonSetValueJson", storeId, "Fun", "{ 'Filled' : 'Times' }"); | 708 | int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "{ 'Filled' : 'Times' }"); |
387 | Assert.That(result, Is.EqualTo(1)); | 709 | Assert.That(result, Is.EqualTo(1)); |
388 | 710 | ||
389 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Filled"); | 711 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Filled"); |
@@ -394,7 +716,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
394 | { | 716 | { |
395 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); | 717 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); |
396 | 718 | ||
397 | int result = (int)InvokeOp("JsonSetValueJson", storeId, "Fun", "Times"); | 719 | int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "Times"); |
398 | Assert.That(result, Is.EqualTo(0)); | 720 | Assert.That(result, Is.EqualTo(0)); |
399 | 721 | ||
400 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun"); | 722 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun"); |
@@ -405,7 +727,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
405 | { | 727 | { |
406 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); | 728 | UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }"); |
407 | 729 | ||
408 | int result = (int)InvokeOp("JsonSetValueJson", storeId, "Fun.Circus", "'Times'"); | 730 | int result = (int)InvokeOp("JsonSetJson", storeId, "Fun.Circus", "'Times'"); |
409 | Assert.That(result, Is.EqualTo(0)); | 731 | Assert.That(result, Is.EqualTo(0)); |
410 | 732 | ||
411 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Circus"); | 733 | string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Circus"); |
@@ -415,7 +737,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests | |||
415 | // Test with fake store | 737 | // Test with fake store |
416 | { | 738 | { |
417 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); | 739 | UUID fakeStoreId = TestHelpers.ParseTail(0x500); |
418 | int fakeStoreValueSet = (int)InvokeOp("JsonSetValueJson", fakeStoreId, "Hello", "'World'"); | 740 | int fakeStoreValueSet = (int)InvokeOp("JsonSetJson", fakeStoreId, "Hello", "'World'"); |
419 | Assert.That(fakeStoreValueSet, Is.EqualTo(0)); | 741 | Assert.That(fakeStoreValueSet, Is.EqualTo(0)); |
420 | } | 742 | } |
421 | } | 743 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs index 7ab86d2..3f83ef0 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs | |||
@@ -225,9 +225,10 @@ public enum CollisionFlags : uint | |||
225 | CF_DISABLE_VISUALIZE_OBJECT = 1 << 5, | 225 | CF_DISABLE_VISUALIZE_OBJECT = 1 << 5, |
226 | CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, | 226 | CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, |
227 | // Following used by BulletSim to control collisions and updates | 227 | // Following used by BulletSim to control collisions and updates |
228 | BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, | 228 | BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, // return collision events from unmanaged to managed |
229 | BS_FLOATS_ON_WATER = 1 << 11, | 229 | BS_FLOATS_ON_WATER = 1 << 11, // the object should float at water level |
230 | BS_VEHICLE_COLLISIONS = 1 << 12, | 230 | BS_VEHICLE_COLLISIONS = 1 << 12, // return collisions for vehicle ground checking |
231 | BS_RETURN_ROOT_COMPOUND_SHAPE = 1 << 13, // return the pos/rot of the root shape in a compound shape | ||
231 | BS_NONE = 0, | 232 | BS_NONE = 0, |
232 | BS_ALL = 0xFFFFFFFF | 233 | BS_ALL = 0xFFFFFFFF |
233 | }; | 234 | }; |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index f781aea..8dca7c6 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -83,7 +83,7 @@ public sealed class BSCharacter : BSPhysObject | |||
83 | _velocity = OMV.Vector3.Zero; | 83 | _velocity = OMV.Vector3.Zero; |
84 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); | 84 | _buoyancy = ComputeBuoyancyFromFlying(isFlying); |
85 | Friction = BSParam.AvatarStandingFriction; | 85 | Friction = BSParam.AvatarStandingFriction; |
86 | Density = BSParam.AvatarDensity; | 86 | Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor; |
87 | 87 | ||
88 | // Old versions of ScenePresence passed only the height. If width and/or depth are zero, | 88 | // Old versions of ScenePresence passed only the height. If width and/or depth are zero, |
89 | // replace with the default values. | 89 | // replace with the default values. |
@@ -231,6 +231,15 @@ public sealed class BSCharacter : BSPhysObject | |||
231 | PhysicsScene.PE.SetFriction(PhysBody, Friction); | 231 | PhysicsScene.PE.SetFriction(PhysBody, Friction); |
232 | } | 232 | } |
233 | } | 233 | } |
234 | else | ||
235 | { | ||
236 | if (Flying) | ||
237 | { | ||
238 | // Flying and not collising and velocity nearly zero. | ||
239 | ZeroMotion(true /* inTaintTime */); | ||
240 | } | ||
241 | } | ||
242 | |||
234 | DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding); | 243 | DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding); |
235 | } | 244 | } |
236 | else | 245 | else |
@@ -274,7 +283,7 @@ public sealed class BSCharacter : BSPhysObject | |||
274 | // This test is done if moving forward, not flying and is colliding with something. | 283 | // This test is done if moving forward, not flying and is colliding with something. |
275 | // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}", | 284 | // DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}", |
276 | // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count); | 285 | // LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count); |
277 | if (IsColliding && !Flying && TargetSpeed > 0.1f /* && ForwardSpeed < 0.1f */) | 286 | if (IsColliding && !Flying && TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */) |
278 | { | 287 | { |
279 | // The range near the character's feet where we will consider stairs | 288 | // The range near the character's feet where we will consider stairs |
280 | float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f; | 289 | float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f; |
@@ -869,7 +878,7 @@ public sealed class BSCharacter : BSPhysObject | |||
869 | * Math.Min(Size.X, Size.Y) / 2 | 878 | * Math.Min(Size.X, Size.Y) / 2 |
870 | * Size.Y / 2f // plus the volume of the capsule end caps | 879 | * Size.Y / 2f // plus the volume of the capsule end caps |
871 | ); | 880 | ); |
872 | _mass = Density * _avatarVolume; | 881 | _mass = Density * BSParam.DensityScaleFactor * _avatarVolume; |
873 | } | 882 | } |
874 | 883 | ||
875 | // The physics engine says that properties have updated. Update same and inform | 884 | // The physics engine says that properties have updated. Update same and inform |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index e35311f..4ece1eb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -127,6 +127,8 @@ public abstract class BSLinkset | |||
127 | m_children = new HashSet<BSPrimLinkable>(); | 127 | m_children = new HashSet<BSPrimLinkable>(); |
128 | LinksetMass = parent.RawMass; | 128 | LinksetMass = parent.RawMass; |
129 | Rebuilding = false; | 129 | Rebuilding = false; |
130 | |||
131 | parent.ClearDisplacement(); | ||
130 | } | 132 | } |
131 | 133 | ||
132 | // Link to a linkset where the child knows the parent. | 134 | // Link to a linkset where the child knows the parent. |
@@ -280,6 +282,7 @@ public abstract class BSLinkset | |||
280 | return mass; | 282 | return mass; |
281 | } | 283 | } |
282 | 284 | ||
285 | // Computes linkset's center of mass in world coordinates. | ||
283 | protected virtual OMV.Vector3 ComputeLinksetCenterOfMass() | 286 | protected virtual OMV.Vector3 ComputeLinksetCenterOfMass() |
284 | { | 287 | { |
285 | OMV.Vector3 com; | 288 | OMV.Vector3 com; |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 36bae9b..4ce58c7 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs | |||
@@ -93,7 +93,8 @@ public sealed class BSLinksetCompound : BSLinkset | |||
93 | { | 93 | { |
94 | private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; | 94 | private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; |
95 | 95 | ||
96 | public BSLinksetCompound(BSScene scene, BSPrimLinkable parent) : base(scene, parent) | 96 | public BSLinksetCompound(BSScene scene, BSPrimLinkable parent) |
97 | : base(scene, parent) | ||
97 | { | 98 | { |
98 | } | 99 | } |
99 | 100 | ||
@@ -217,59 +218,45 @@ public sealed class BSLinksetCompound : BSLinkset | |||
217 | // and that is caused by us updating the object. | 218 | // and that is caused by us updating the object. |
218 | if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0) | 219 | if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0) |
219 | { | 220 | { |
220 | // Gather the child info. It might not be there if the linkset is in transition. | ||
221 | BSLinksetCompoundInfo lsi = updated.LinksetInfo as BSLinksetCompoundInfo; | ||
222 | if (lsi != null) | ||
223 | { | ||
224 | // Since the child moved or rotationed, it needs a new relative position within the linkset | ||
225 | BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, OMV.Vector3.Zero); | ||
226 | updated.LinksetInfo = newLsi; | ||
227 | |||
228 | // Find the physical instance of the child | 221 | // Find the physical instance of the child |
229 | if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) | 222 | if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) |
223 | { | ||
224 | // It is possible that the linkset is still under construction and the child is not yet | ||
225 | // inserted into the compound shape. A rebuild of the linkset in a pre-step action will | ||
226 | // build the whole thing with the new position or rotation. | ||
227 | // The index must be checked because Bullet references the child array but does no validity | ||
228 | // checking of the child index passed. | ||
229 | int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape); | ||
230 | if (updated.LinksetChildIndex < numLinksetChildren) | ||
230 | { | 231 | { |
231 | // It is possible that the linkset is still under construction and the child is not yet | 232 | BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, updated.LinksetChildIndex); |
232 | // inserted into the compound shape. A rebuild of the linkset in a pre-step action will | 233 | if (linksetChildShape.HasPhysicalShape) |
233 | // build the whole thing with the new position or rotation. | ||
234 | // The index must be checked because Bullet references the child array but does no validity | ||
235 | // checking of the child index passed. | ||
236 | int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape); | ||
237 | if (lsi.Index < numLinksetChildren) | ||
238 | { | 234 | { |
239 | BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index); | 235 | // Found the child shape within the compound shape |
240 | if (linksetChildShape.HasPhysicalShape) | 236 | PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, updated.LinksetChildIndex, |
241 | { | 237 | updated.RawPosition - LinksetRoot.RawPosition, |
242 | // Found the child shape within the compound shape | 238 | updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation), |
243 | PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index, | 239 | true /* shouldRecalculateLocalAabb */); |
244 | newLsi.OffsetFromCenterOfMass, | 240 | updatedChild = true; |
245 | newLsi.OffsetRot, | 241 | DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},pos={2},rot={3}", |
246 | true /* shouldRecalculateLocalAabb */); | 242 | updated.LocalID, whichUpdated, updated.RawPosition, updated.RawOrientation); |
247 | updatedChild = true; | ||
248 | DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}", | ||
249 | updated.LocalID, whichUpdated, newLsi); | ||
250 | } | ||
251 | else // DEBUG DEBUG | ||
252 | { // DEBUG DEBUG | ||
253 | DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}", | ||
254 | updated.LocalID, linksetChildShape); | ||
255 | } // DEBUG DEBUG | ||
256 | } | 243 | } |
257 | else // DEBUG DEBUG | 244 | else // DEBUG DEBUG |
258 | { // DEBUG DEBUG | 245 | { // DEBUG DEBUG |
259 | // the child is not yet in the compound shape. This is non-fatal. | 246 | DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}", |
260 | DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}", | 247 | updated.LocalID, linksetChildShape); |
261 | updated.LocalID, numLinksetChildren, lsi.Index); | ||
262 | } // DEBUG DEBUG | 248 | } // DEBUG DEBUG |
263 | } | 249 | } |
264 | else // DEBUG DEBUG | 250 | else // DEBUG DEBUG |
265 | { // DEBUG DEBUG | 251 | { // DEBUG DEBUG |
266 | DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID); | 252 | // the child is not yet in the compound shape. This is non-fatal. |
253 | DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}", | ||
254 | updated.LocalID, numLinksetChildren, updated.LinksetChildIndex); | ||
267 | } // DEBUG DEBUG | 255 | } // DEBUG DEBUG |
268 | } | 256 | } |
269 | else // DEBUG DEBUG | 257 | else // DEBUG DEBUG |
270 | { // DEBUG DEBUG | 258 | { // DEBUG DEBUG |
271 | DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noLinkSetInfo,rootPhysShape={1}", | 259 | DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID); |
272 | updated.LocalID, LinksetRoot.PhysShape); | ||
273 | } // DEBUG DEBUG | 260 | } // DEBUG DEBUG |
274 | 261 | ||
275 | if (!updatedChild) | 262 | if (!updatedChild) |
@@ -379,6 +366,8 @@ public sealed class BSLinksetCompound : BSLinkset | |||
379 | // Safe to call even if the child is not really in the linkset. | 366 | // Safe to call even if the child is not really in the linkset. |
380 | protected override void RemoveChildFromLinkset(BSPrimLinkable child) | 367 | protected override void RemoveChildFromLinkset(BSPrimLinkable child) |
381 | { | 368 | { |
369 | child.ClearDisplacement(); | ||
370 | |||
382 | if (m_children.Remove(child)) | 371 | if (m_children.Remove(child)) |
383 | { | 372 | { |
384 | DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", | 373 | DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", |
@@ -424,30 +413,31 @@ public sealed class BSLinksetCompound : BSLinkset | |||
424 | // The center of mass for the linkset is the geometric center of the group. | 413 | // The center of mass for the linkset is the geometric center of the group. |
425 | // Compute a displacement for each component so it is relative to the center-of-mass. | 414 | // Compute a displacement for each component so it is relative to the center-of-mass. |
426 | // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass | 415 | // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass |
427 | OMV.Vector3 centerOfMass; | 416 | OMV.Vector3 centerOfMassW = LinksetRoot.RawPosition; |
428 | OMV.Vector3 centerDisplacement = OMV.Vector3.Zero; | 417 | if (!disableCOM) // DEBUG DEBUG |
429 | if (disableCOM) // DEBUG DEBUG | ||
430 | { // DEBUG DEBUG | ||
431 | centerOfMass = LinksetRoot.RawPosition; // DEBUG DEBUG | ||
432 | // LinksetRoot.PositionDisplacement = OMV.Vector3.Zero; | ||
433 | } // DEBUG DEBUG | ||
434 | else | ||
435 | { | 418 | { |
436 | centerOfMass = ComputeLinksetCenterOfMass(); | 419 | // Compute a center-of-mass in world coordinates. |
437 | // 'centerDisplacement' is the value to *add* to all the shape offsets | 420 | centerOfMassW = ComputeLinksetCenterOfMass(); |
438 | centerDisplacement = LinksetRoot.RawPosition - centerOfMass; | ||
439 | |||
440 | // Since we're displacing the center of the shape, we need to move the body in the world | ||
441 | // LinksetRoot.PositionDisplacement = centerDisplacement; | ||
442 | |||
443 | // This causes the root prim position to be set properly based on the new PositionDisplacement | ||
444 | LinksetRoot.ForcePosition = LinksetRoot.RawPosition; | ||
445 | // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM | ||
446 | PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0, -centerDisplacement, OMV.Quaternion.Identity, false); | ||
447 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}", | ||
448 | LinksetRoot.LocalID, centerOfMass, LinksetRoot.RawPosition, centerDisplacement); | ||
449 | } | 421 | } |
450 | 422 | ||
423 | OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); | ||
424 | |||
425 | // 'centerDisplacement' is the value to subtract from children to give physical offset position | ||
426 | OMV.Vector3 centerDisplacement = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation; | ||
427 | LinksetRoot.SetEffectiveCenterOfMassW(centerDisplacement); | ||
428 | |||
429 | // This causes the physical position of the root prim to be offset to accomodate for the displacements | ||
430 | LinksetRoot.ForcePosition = LinksetRoot.RawPosition; | ||
431 | |||
432 | // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM | ||
433 | PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0 /* childIndex */, | ||
434 | -centerDisplacement, | ||
435 | OMV.Quaternion.Identity, // LinksetRoot.RawOrientation, | ||
436 | false /* shouldRecalculateLocalAabb (is done later after linkset built) */); | ||
437 | |||
438 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}", | ||
439 | LinksetRoot.LocalID, centerOfMassW, LinksetRoot.RawPosition, centerDisplacement); | ||
440 | |||
451 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", | 441 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", |
452 | LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); | 442 | LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); |
453 | 443 | ||
@@ -455,38 +445,33 @@ public sealed class BSLinksetCompound : BSLinkset | |||
455 | int memberIndex = 1; | 445 | int memberIndex = 1; |
456 | ForEachMember(delegate(BSPrimLinkable cPrim) | 446 | ForEachMember(delegate(BSPrimLinkable cPrim) |
457 | { | 447 | { |
458 | if (!IsRoot(cPrim)) | 448 | if (IsRoot(cPrim)) |
459 | { | 449 | { |
460 | // Compute the displacement of the child from the root of the linkset. | 450 | cPrim.LinksetChildIndex = 0; |
461 | // This info is saved in the child prim so the relationship does not | 451 | } |
462 | // change over time and the new child position can be computed | 452 | else |
463 | // when the linkset is being disassembled (the linkset may have moved). | 453 | { |
464 | BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo; | 454 | cPrim.LinksetChildIndex = memberIndex; |
465 | if (lci == null) | ||
466 | { | ||
467 | lci = new BSLinksetCompoundInfo(memberIndex, LinksetRoot, cPrim, centerDisplacement); | ||
468 | cPrim.LinksetInfo = lci; | ||
469 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci); | ||
470 | } | ||
471 | |||
472 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},lci={3}", | ||
473 | LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci); | ||
474 | 455 | ||
475 | if (cPrim.PhysShape.isNativeShape) | 456 | if (cPrim.PhysShape.isNativeShape) |
476 | { | 457 | { |
477 | // A native shape is turned into a hull collision shape because native | 458 | // A native shape is turned into a hull collision shape because native |
478 | // shapes are not shared so we have to hullify it so it will be tracked | 459 | // shapes are not shared so we have to hullify it so it will be tracked |
479 | // and freed at the correct time. This also solves the scaling problem | 460 | // and freed at the correct time. This also solves the scaling problem |
480 | // (native shapes scaled but hull/meshes are assumed to not be). | 461 | // (native shapes scale but hull/meshes are assumed to not be). |
481 | // TODO: decide of the native shape can just be used in the compound shape. | 462 | // TODO: decide of the native shape can just be used in the compound shape. |
482 | // Use call to CreateGeomNonSpecial(). | 463 | // Use call to CreateGeomNonSpecial(). |
483 | BulletShape saveShape = cPrim.PhysShape; | 464 | BulletShape saveShape = cPrim.PhysShape; |
484 | cPrim.PhysShape.Clear(); // Don't let the create free the child's shape | 465 | cPrim.PhysShape.Clear(); // Don't let the create free the child's shape |
485 | // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null); | ||
486 | PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); | 466 | PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); |
487 | BulletShape newShape = cPrim.PhysShape; | 467 | BulletShape newShape = cPrim.PhysShape; |
488 | cPrim.PhysShape = saveShape; | 468 | cPrim.PhysShape = saveShape; |
489 | PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetFromCenterOfMass, lci.OffsetRot); | 469 | |
470 | OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement; | ||
471 | OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation; | ||
472 | PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, offsetPos, offsetRot); | ||
473 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}", | ||
474 | LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, newShape, offsetPos, offsetRot); | ||
490 | } | 475 | } |
491 | else | 476 | else |
492 | { | 477 | { |
@@ -498,9 +483,13 @@ public sealed class BSLinksetCompound : BSLinkset | |||
498 | PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", | 483 | PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", |
499 | LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); | 484 | LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); |
500 | } | 485 | } |
501 | PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetFromCenterOfMass, lci.OffsetRot); | 486 | OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement; |
487 | OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation; | ||
488 | PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot); | ||
489 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNonNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}", | ||
490 | LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot); | ||
491 | |||
502 | } | 492 | } |
503 | lci.Index = memberIndex; | ||
504 | memberIndex++; | 493 | memberIndex++; |
505 | } | 494 | } |
506 | return false; // 'false' says to move onto the next child in the list | 495 | return false; // 'false' says to move onto the next child in the list |
@@ -509,12 +498,16 @@ public sealed class BSLinksetCompound : BSLinkset | |||
509 | // With all of the linkset packed into the root prim, it has the mass of everyone. | 498 | // With all of the linkset packed into the root prim, it has the mass of everyone. |
510 | LinksetMass = ComputeLinksetMass(); | 499 | LinksetMass = ComputeLinksetMass(); |
511 | LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); | 500 | LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); |
501 | |||
502 | // Enable the physical position updator to return the position and rotation of the root shape | ||
503 | PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE); | ||
512 | } | 504 | } |
513 | finally | 505 | finally |
514 | { | 506 | { |
515 | Rebuilding = false; | 507 | Rebuilding = false; |
516 | } | 508 | } |
517 | 509 | ||
510 | // See that the Aabb surrounds the new shape | ||
518 | PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape); | 511 | PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape); |
519 | } | 512 | } |
520 | } | 513 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs index 3e0b4bc..329169f 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs | |||
@@ -49,6 +49,7 @@ public static class BSParam | |||
49 | public static float MaxLinearVelocity { get; private set; } | 49 | public static float MaxLinearVelocity { get; private set; } |
50 | public static float MaxAngularVelocity { get; private set; } | 50 | public static float MaxAngularVelocity { get; private set; } |
51 | public static float MaxAddForceMagnitude { get; private set; } | 51 | public static float MaxAddForceMagnitude { get; private set; } |
52 | public static float DensityScaleFactor { get; private set; } | ||
52 | 53 | ||
53 | public static float LinearDamping { get; private set; } | 54 | public static float LinearDamping { get; private set; } |
54 | public static float AngularDamping { get; private set; } | 55 | public static float AngularDamping { get; private set; } |
@@ -281,29 +282,35 @@ public static class BSParam | |||
281 | new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)", | 282 | new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)", |
282 | 0.0001f, | 283 | 0.0001f, |
283 | (s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); }, | 284 | (s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); }, |
284 | (s) => { return (float)MinimumObjectMass; }, | 285 | (s) => { return MinimumObjectMass; }, |
285 | (s,p,l,v) => { MinimumObjectMass = v; } ), | 286 | (s,p,l,v) => { MinimumObjectMass = v; } ), |
286 | new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", | 287 | new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", |
287 | 10000.01f, | 288 | 10000.01f, |
288 | (s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); }, | 289 | (s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); }, |
289 | (s) => { return (float)MaximumObjectMass; }, | 290 | (s) => { return MaximumObjectMass; }, |
290 | (s,p,l,v) => { MaximumObjectMass = v; } ), | 291 | (s,p,l,v) => { MaximumObjectMass = v; } ), |
291 | new ParameterDefn("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object", | 292 | new ParameterDefn("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object", |
292 | 1000.0f, | 293 | 1000.0f, |
293 | (s,cf,p,v) => { MaxLinearVelocity = cf.GetFloat(p, v); }, | 294 | (s,cf,p,v) => { MaxLinearVelocity = cf.GetFloat(p, v); }, |
294 | (s) => { return (float)MaxLinearVelocity; }, | 295 | (s) => { return MaxLinearVelocity; }, |
295 | (s,p,l,v) => { MaxLinearVelocity = v; } ), | 296 | (s,p,l,v) => { MaxLinearVelocity = v; } ), |
296 | new ParameterDefn("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object", | 297 | new ParameterDefn("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object", |
297 | 1000.0f, | 298 | 1000.0f, |
298 | (s,cf,p,v) => { MaxAngularVelocity = cf.GetFloat(p, v); }, | 299 | (s,cf,p,v) => { MaxAngularVelocity = cf.GetFloat(p, v); }, |
299 | (s) => { return (float)MaxAngularVelocity; }, | 300 | (s) => { return MaxAngularVelocity; }, |
300 | (s,p,l,v) => { MaxAngularVelocity = v; } ), | 301 | (s,p,l,v) => { MaxAngularVelocity = v; } ), |
301 | // LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject | 302 | // LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject |
302 | new ParameterDefn("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)", | 303 | new ParameterDefn("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)", |
303 | 20000.0f, | 304 | 20000.0f, |
304 | (s,cf,p,v) => { MaxAddForceMagnitude = cf.GetFloat(p, v); }, | 305 | (s,cf,p,v) => { MaxAddForceMagnitude = cf.GetFloat(p, v); }, |
305 | (s) => { return (float)MaxAddForceMagnitude; }, | 306 | (s) => { return MaxAddForceMagnitude; }, |
306 | (s,p,l,v) => { MaxAddForceMagnitude = v; } ), | 307 | (s,p,l,v) => { MaxAddForceMagnitude = v; } ), |
308 | // Density is passed around as 100kg/m3. This scales that to 1kg/m3. | ||
309 | new ParameterDefn("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)", | ||
310 | 0.01f, | ||
311 | (s,cf,p,v) => { DensityScaleFactor = cf.GetFloat(p, v); }, | ||
312 | (s) => { return DensityScaleFactor; }, | ||
313 | (s,p,l,v) => { DensityScaleFactor = v; } ), | ||
307 | 314 | ||
308 | new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", | 315 | new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", |
309 | 2200f, | 316 | 2200f, |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index de69fa0..f953c1e 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | |||
@@ -99,6 +99,9 @@ public abstract class BSPhysObject : PhysicsActor | |||
99 | CollisionAccumulation = 0; | 99 | CollisionAccumulation = 0; |
100 | ColliderIsMoving = false; | 100 | ColliderIsMoving = false; |
101 | CollisionScore = 0; | 101 | CollisionScore = 0; |
102 | |||
103 | // All axis free. | ||
104 | LockedAxis = LockedAxisFree; | ||
102 | } | 105 | } |
103 | 106 | ||
104 | // Tell the object to clean up. | 107 | // Tell the object to clean up. |
@@ -136,6 +139,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
136 | 139 | ||
137 | // The objects base shape information. Null if not a prim type shape. | 140 | // The objects base shape information. Null if not a prim type shape. |
138 | public PrimitiveBaseShape BaseShape { get; protected set; } | 141 | public PrimitiveBaseShape BaseShape { get; protected set; } |
142 | |||
139 | // Some types of objects have preferred physical representations. | 143 | // Some types of objects have preferred physical representations. |
140 | // Returns SHAPE_UNKNOWN if there is no preference. | 144 | // Returns SHAPE_UNKNOWN if there is no preference. |
141 | public virtual BSPhysicsShapeType PreferredPhysicalShape | 145 | public virtual BSPhysicsShapeType PreferredPhysicalShape |
@@ -150,15 +154,17 @@ public abstract class BSPhysObject : PhysicsActor | |||
150 | public EntityProperties LastEntityProperties { get; set; } | 154 | public EntityProperties LastEntityProperties { get; set; } |
151 | 155 | ||
152 | public virtual OMV.Vector3 Scale { get; set; } | 156 | public virtual OMV.Vector3 Scale { get; set; } |
153 | public abstract bool IsSolid { get; } | ||
154 | public abstract bool IsStatic { get; } | ||
155 | public abstract bool IsSelected { get; } | ||
156 | 157 | ||
157 | // It can be confusing for an actor to know if it should move or update an object | 158 | // It can be confusing for an actor to know if it should move or update an object |
158 | // depeneding on the setting of 'selected', 'physical, ... | 159 | // depeneding on the setting of 'selected', 'physical, ... |
159 | // This flag is the true test -- if true, the object is being acted on in the physical world | 160 | // This flag is the true test -- if true, the object is being acted on in the physical world |
160 | public abstract bool IsPhysicallyActive { get; } | 161 | public abstract bool IsPhysicallyActive { get; } |
161 | 162 | ||
163 | // Detailed state of the object. | ||
164 | public abstract bool IsSolid { get; } | ||
165 | public abstract bool IsStatic { get; } | ||
166 | public abstract bool IsSelected { get; } | ||
167 | |||
162 | // Materialness | 168 | // Materialness |
163 | public MaterialAttributes.Material Material { get; private set; } | 169 | public MaterialAttributes.Material Material { get; private set; } |
164 | public override void SetMaterial(int material) | 170 | public override void SetMaterial(int material) |
@@ -169,7 +175,8 @@ public abstract class BSPhysObject : PhysicsActor | |||
169 | MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false); | 175 | MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false); |
170 | Friction = matAttrib.friction; | 176 | Friction = matAttrib.friction; |
171 | Restitution = matAttrib.restitution; | 177 | Restitution = matAttrib.restitution; |
172 | Density = matAttrib.density; | 178 | Density = matAttrib.density / BSParam.DensityScaleFactor; |
179 | DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density); | ||
173 | } | 180 | } |
174 | 181 | ||
175 | // Stop all physical motion. | 182 | // Stop all physical motion. |
@@ -185,14 +192,6 @@ public abstract class BSPhysObject : PhysicsActor | |||
185 | public abstract OMV.Quaternion RawOrientation { get; set; } | 192 | public abstract OMV.Quaternion RawOrientation { get; set; } |
186 | public abstract OMV.Quaternion ForceOrientation { get; set; } | 193 | public abstract OMV.Quaternion ForceOrientation { get; set; } |
187 | 194 | ||
188 | public virtual float TargetSpeed | ||
189 | { | ||
190 | get | ||
191 | { | ||
192 | OMV.Vector3 characterOrientedVelocity = TargetVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation)); | ||
193 | return characterOrientedVelocity.X; | ||
194 | } | ||
195 | } | ||
196 | public abstract OMV.Vector3 RawVelocity { get; set; } | 195 | public abstract OMV.Vector3 RawVelocity { get; set; } |
197 | public abstract OMV.Vector3 ForceVelocity { get; set; } | 196 | public abstract OMV.Vector3 ForceVelocity { get; set; } |
198 | 197 | ||
@@ -202,6 +201,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
202 | 201 | ||
203 | public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } | 202 | public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } |
204 | 203 | ||
204 | // The current velocity forward | ||
205 | public virtual float ForwardSpeed | 205 | public virtual float ForwardSpeed |
206 | { | 206 | { |
207 | get | 207 | get |
@@ -210,6 +210,22 @@ public abstract class BSPhysObject : PhysicsActor | |||
210 | return characterOrientedVelocity.X; | 210 | return characterOrientedVelocity.X; |
211 | } | 211 | } |
212 | } | 212 | } |
213 | // The forward speed we are trying to achieve (TargetVelocity) | ||
214 | public virtual float TargetVelocitySpeed | ||
215 | { | ||
216 | get | ||
217 | { | ||
218 | OMV.Vector3 characterOrientedVelocity = TargetVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation)); | ||
219 | return characterOrientedVelocity.X; | ||
220 | } | ||
221 | } | ||
222 | |||
223 | // The user can optionally set the center of mass. The user's setting will override any | ||
224 | // computed center-of-mass (like in linksets). | ||
225 | public OMV.Vector3? UserSetCenterOfMass { get; set; } | ||
226 | |||
227 | public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free. | ||
228 | public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free | ||
213 | 229 | ||
214 | #region Collisions | 230 | #region Collisions |
215 | 231 | ||
@@ -407,9 +423,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
407 | { | 423 | { |
408 | // Clean out any existing action | 424 | // Clean out any existing action |
409 | UnRegisterPreStepAction(op, id); | 425 | UnRegisterPreStepAction(op, id); |
410 | |||
411 | RegisteredPrestepActions[identifier] = actn; | 426 | RegisteredPrestepActions[identifier] = actn; |
412 | |||
413 | PhysicsScene.BeforeStep += actn; | 427 | PhysicsScene.BeforeStep += actn; |
414 | } | 428 | } |
415 | DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier); | 429 | DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier); |
@@ -455,9 +469,7 @@ public abstract class BSPhysObject : PhysicsActor | |||
455 | { | 469 | { |
456 | // Clean out any existing action | 470 | // Clean out any existing action |
457 | UnRegisterPostStepAction(op, id); | 471 | UnRegisterPostStepAction(op, id); |
458 | |||
459 | RegisteredPoststepActions[identifier] = actn; | 472 | RegisteredPoststepActions[identifier] = actn; |
460 | |||
461 | PhysicsScene.AfterStep += actn; | 473 | PhysicsScene.AfterStep += actn; |
462 | } | 474 | } |
463 | DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier); | 475 | DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier); |
@@ -494,7 +506,58 @@ public abstract class BSPhysObject : PhysicsActor | |||
494 | } | 506 | } |
495 | DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID); | 507 | DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID); |
496 | } | 508 | } |
497 | 509 | ||
510 | // When an update to the physical properties happens, this event is fired to let | ||
511 | // different actors to modify the update before it is passed around | ||
512 | public delegate void PreUpdatePropertyAction(ref EntityProperties entprop); | ||
513 | public event PreUpdatePropertyAction OnPreUpdateProperty; | ||
514 | protected void TriggerPreUpdatePropertyAction(ref EntityProperties entprop) | ||
515 | { | ||
516 | PreUpdatePropertyAction actions = OnPreUpdateProperty; | ||
517 | if (actions != null) | ||
518 | actions(ref entprop); | ||
519 | } | ||
520 | |||
521 | private Dictionary<string, PreUpdatePropertyAction> RegisteredPreUpdatePropertyActions = new Dictionary<string, PreUpdatePropertyAction>(); | ||
522 | public void RegisterPreUpdatePropertyAction(string identifier, PreUpdatePropertyAction actn) | ||
523 | { | ||
524 | lock (RegisteredPreUpdatePropertyActions) | ||
525 | { | ||
526 | // Clean out any existing action | ||
527 | UnRegisterPreUpdatePropertyAction(identifier); | ||
528 | RegisteredPreUpdatePropertyActions[identifier] = actn; | ||
529 | OnPreUpdateProperty += actn; | ||
530 | } | ||
531 | DetailLog("{0},BSPhysObject.RegisterPreUpdatePropertyAction,id={1}", LocalID, identifier); | ||
532 | } | ||
533 | public bool UnRegisterPreUpdatePropertyAction(string identifier) | ||
534 | { | ||
535 | bool removed = false; | ||
536 | lock (RegisteredPreUpdatePropertyActions) | ||
537 | { | ||
538 | if (RegisteredPreUpdatePropertyActions.ContainsKey(identifier)) | ||
539 | { | ||
540 | OnPreUpdateProperty -= RegisteredPreUpdatePropertyActions[identifier]; | ||
541 | RegisteredPreUpdatePropertyActions.Remove(identifier); | ||
542 | removed = true; | ||
543 | } | ||
544 | } | ||
545 | DetailLog("{0},BSPhysObject.UnRegisterPreUpdatePropertyAction,id={1},removed={2}", LocalID, identifier, removed); | ||
546 | return removed; | ||
547 | } | ||
548 | public void UnRegisterAllPreUpdatePropertyActions() | ||
549 | { | ||
550 | lock (RegisteredPreUpdatePropertyActions) | ||
551 | { | ||
552 | foreach (KeyValuePair<string, PreUpdatePropertyAction> kvp in RegisteredPreUpdatePropertyActions) | ||
553 | { | ||
554 | OnPreUpdateProperty -= kvp.Value; | ||
555 | } | ||
556 | RegisteredPreUpdatePropertyActions.Clear(); | ||
557 | } | ||
558 | DetailLog("{0},BSPhysObject.UnRegisterAllPreUpdatePropertyAction,", LocalID); | ||
559 | } | ||
560 | |||
498 | #endregion // Per Simulation Step actions | 561 | #endregion // Per Simulation Step actions |
499 | 562 | ||
500 | // High performance detailed logging routine used by the physical objects. | 563 | // High performance detailed logging routine used by the physical objects. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index cf7aa0f..0323b0d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -242,6 +242,45 @@ public class BSPrim : BSPhysObject | |||
242 | public override void LockAngularMotion(OMV.Vector3 axis) | 242 | public override void LockAngularMotion(OMV.Vector3 axis) |
243 | { | 243 | { |
244 | DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); | 244 | DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); |
245 | |||
246 | OMV.Vector3 locking = new OMV.Vector3(1f, 1f, 1f); | ||
247 | if (axis.X != 1) locking.X = 0f; | ||
248 | if (axis.Y != 1) locking.Y = 0f; | ||
249 | if (axis.Z != 1) locking.Z = 0f; | ||
250 | LockedAxis = locking; | ||
251 | |||
252 | /* Not implemented yet | ||
253 | if (LockedAxis != LockedAxisFree) | ||
254 | { | ||
255 | // Something is locked so start the thingy that keeps that axis from changing | ||
256 | RegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion", delegate(ref EntityProperties entprop) | ||
257 | { | ||
258 | if (LockedAxis != LockedAxisFree) | ||
259 | { | ||
260 | if (IsPhysicallyActive) | ||
261 | { | ||
262 | // Bullet can lock axis but it only works for global axis. | ||
263 | // Check if this prim is aligned on global axis and use Bullet's | ||
264 | // system if so. | ||
265 | |||
266 | ForceOrientation = entprop.Rotation; | ||
267 | ForceRotationalVelocity = entprop.RotationalVelocity; | ||
268 | } | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | UnRegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion"); | ||
273 | } | ||
274 | |||
275 | }); | ||
276 | } | ||
277 | else | ||
278 | { | ||
279 | // Everything seems unlocked | ||
280 | UnRegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion"); | ||
281 | } | ||
282 | */ | ||
283 | |||
245 | return; | 284 | return; |
246 | } | 285 | } |
247 | 286 | ||
@@ -311,7 +350,8 @@ public class BSPrim : BSPhysObject | |||
311 | 350 | ||
312 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); | 351 | float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); |
313 | OMV.Vector3 upForce = OMV.Vector3.Zero; | 352 | OMV.Vector3 upForce = OMV.Vector3.Zero; |
314 | if (RawPosition.Z < terrainHeight) | 353 | float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z)); |
354 | if ((RawPosition.Z + approxSize / 2f) < terrainHeight) | ||
315 | { | 355 | { |
316 | DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, RawPosition, terrainHeight); | 356 | DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, RawPosition, terrainHeight); |
317 | float targetHeight = terrainHeight + (Size.Z / 2f); | 357 | float targetHeight = terrainHeight + (Size.Z / 2f); |
@@ -442,7 +482,7 @@ public class BSPrim : BSPhysObject | |||
442 | RegisterPreStepAction("BSPrim.setForce", LocalID, | 482 | RegisterPreStepAction("BSPrim.setForce", LocalID, |
443 | delegate(float timeStep) | 483 | delegate(float timeStep) |
444 | { | 484 | { |
445 | if (!IsPhysicallyActive) | 485 | if (!IsPhysicallyActive || _force == OMV.Vector3.Zero) |
446 | { | 486 | { |
447 | UnRegisterPreStepAction("BSPrim.setForce", LocalID); | 487 | UnRegisterPreStepAction("BSPrim.setForce", LocalID); |
448 | return; | 488 | return; |
@@ -576,6 +616,8 @@ public class BSPrim : BSPhysObject | |||
576 | } | 616 | } |
577 | } | 617 | } |
578 | } | 618 | } |
619 | // The simulator/viewer keep density as 100kg/m3. | ||
620 | // Remember to use BSParam.DensityScaleFactor to create the physical density. | ||
579 | public override float Density | 621 | public override float Density |
580 | { | 622 | { |
581 | get { return base.Density; } | 623 | get { return base.Density; } |
@@ -647,7 +689,7 @@ public class BSPrim : BSPhysObject | |||
647 | RegisterPreStepAction("BSPrim.setTorque", LocalID, | 689 | RegisterPreStepAction("BSPrim.setTorque", LocalID, |
648 | delegate(float timeStep) | 690 | delegate(float timeStep) |
649 | { | 691 | { |
650 | if (!IsPhysicallyActive) | 692 | if (!IsPhysicallyActive || _torque == OMV.Vector3.Zero) |
651 | { | 693 | { |
652 | UnRegisterPreStepAction("BSPrim.setTorque", LocalID); | 694 | UnRegisterPreStepAction("BSPrim.setTorque", LocalID); |
653 | return; | 695 | return; |
@@ -1569,7 +1611,8 @@ public class BSPrim : BSPhysObject | |||
1569 | profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f; | 1611 | profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f; |
1570 | volume *= (profileEnd - profileBegin); | 1612 | volume *= (profileEnd - profileBegin); |
1571 | 1613 | ||
1572 | returnMass = Density * volume; | 1614 | returnMass = Density * BSParam.DensityScaleFactor * volume; |
1615 | DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass); | ||
1573 | 1616 | ||
1574 | returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); | 1617 | returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass); |
1575 | 1618 | ||
@@ -1607,6 +1650,8 @@ public class BSPrim : BSPhysObject | |||
1607 | // the world that things have changed. | 1650 | // the world that things have changed. |
1608 | public override void UpdateProperties(EntityProperties entprop) | 1651 | public override void UpdateProperties(EntityProperties entprop) |
1609 | { | 1652 | { |
1653 | TriggerPreUpdatePropertyAction(ref entprop); | ||
1654 | |||
1610 | // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet | 1655 | // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet |
1611 | // TODO: handle physics introduced by Bullet with computed vehicle physics. | 1656 | // TODO: handle physics introduced by Bullet with computed vehicle physics. |
1612 | if (VehicleController.IsActive) | 1657 | if (VehicleController.IsActive) |
@@ -1619,7 +1664,11 @@ public class BSPrim : BSPhysObject | |||
1619 | // Assign directly to the local variables so the normal set actions do not happen | 1664 | // Assign directly to the local variables so the normal set actions do not happen |
1620 | _position = entprop.Position; | 1665 | _position = entprop.Position; |
1621 | _orientation = entprop.Rotation; | 1666 | _orientation = entprop.Rotation; |
1622 | _velocity = entprop.Velocity; | 1667 | // _velocity = entprop.Velocity; |
1668 | // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be | ||
1669 | // very sensitive to velocity changes. | ||
1670 | if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f)) | ||
1671 | _velocity = entprop.Velocity; | ||
1623 | _acceleration = entprop.Acceleration; | 1672 | _acceleration = entprop.Acceleration; |
1624 | _rotationalVelocity = entprop.RotationalVelocity; | 1673 | _rotationalVelocity = entprop.RotationalVelocity; |
1625 | 1674 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs index 6401308..f1c3b5c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs | |||
@@ -44,72 +44,107 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
44 | { | 44 | { |
45 | public class BSPrimDisplaced : BSPrim | 45 | public class BSPrimDisplaced : BSPrim |
46 | { | 46 | { |
47 | // 'Position' and 'Orientation' is what the simulator thinks the positions of the prim is. | 47 | // The purpose of this module is to do any mapping between what the simulator thinks |
48 | // Because Bullet needs the zero coordinate to be the center of mass of the linkset, | 48 | // the prim position and orientation is and what the physical position/orientation. |
49 | // sometimes it is necessary to displace the position the physics engine thinks | 49 | // This difference happens because Bullet assumes the center-of-mass is the <0,0,0> |
50 | // the position is. PositionDisplacement must be added and removed from the | 50 | // of the prim/linkset. The simulator tracks the location of the prim/linkset by |
51 | // position as the simulator position is stored and fetched from the physics | 51 | // the location of the root prim. So, if center-of-mass is anywhere but the origin |
52 | // engine. Similar to OrientationDisplacement. | 52 | // of the root prim, the physical origin is displaced from the simulator origin. |
53 | // | ||
54 | // This routine works by capturing the Force* setting of position/orientation/... and | ||
55 | // adjusting the simulator values (being set) into the physical values. | ||
56 | // The conversion is also done in the opposite direction (physical origin -> simulator origin). | ||
57 | // | ||
58 | // The updateParameter call is also captured and the values from the physics engine | ||
59 | // are converted into simulator origin values before being passed to the base | ||
60 | // class. | ||
61 | |||
53 | public virtual OMV.Vector3 PositionDisplacement { get; set; } | 62 | public virtual OMV.Vector3 PositionDisplacement { get; set; } |
54 | public virtual OMV.Quaternion OrientationDisplacement { get; set; } | 63 | public virtual OMV.Quaternion OrientationDisplacement { get; set; } |
55 | public virtual OMV.Vector3 CenterOfMassLocation { get; set; } | ||
56 | public virtual OMV.Vector3 GeometricCenterLocation { get; set; } | ||
57 | 64 | ||
58 | public BSPrimDisplaced(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, | 65 | public BSPrimDisplaced(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, |
59 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) | 66 | OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) |
60 | : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical) | 67 | : base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical) |
61 | { | 68 | { |
62 | CenterOfMassLocation = RawPosition; | 69 | ClearDisplacement(); |
63 | GeometricCenterLocation = RawPosition; | ||
64 | } | 70 | } |
65 | 71 | ||
66 | public override Vector3 ForcePosition | 72 | public void ClearDisplacement() |
73 | { | ||
74 | PositionDisplacement = OMV.Vector3.Zero; | ||
75 | OrientationDisplacement = OMV.Quaternion.Identity; | ||
76 | } | ||
77 | |||
78 | // Set this sets and computes the displacement from the passed prim to the center-of-mass. | ||
79 | // A user set value for center-of-mass overrides whatever might be passed in here. | ||
80 | // The displacement is in local coordinates (relative to root prim in linkset oriented coordinates). | ||
81 | public virtual void SetEffectiveCenterOfMassW(Vector3 centerOfMassDisplacement) | ||
67 | { | 82 | { |
68 | get | 83 | Vector3 comDisp; |
84 | if (UserSetCenterOfMass.HasValue) | ||
85 | comDisp = (OMV.Vector3)UserSetCenterOfMass; | ||
86 | else | ||
87 | comDisp = centerOfMassDisplacement; | ||
88 | |||
89 | if (comDisp == Vector3.Zero) | ||
69 | { | 90 | { |
70 | return base.ForcePosition; | 91 | // If there is no diplacement. Things get reset. |
92 | PositionDisplacement = OMV.Vector3.Zero; | ||
93 | OrientationDisplacement = OMV.Quaternion.Identity; | ||
71 | } | 94 | } |
72 | set | 95 | else |
73 | { | 96 | { |
74 | base.ForcePosition = value; | 97 | // Remember the displacement from root as well as the origional rotation of the |
75 | CenterOfMassLocation = RawPosition; | 98 | // new center-of-mass. |
76 | GeometricCenterLocation = RawPosition; | 99 | PositionDisplacement = comDisp; |
100 | OrientationDisplacement = OMV.Quaternion.Identity; | ||
77 | } | 101 | } |
78 | } | 102 | } |
79 | 103 | ||
80 | public override Quaternion ForceOrientation | 104 | public override Vector3 ForcePosition |
81 | { | 105 | { |
82 | get | 106 | get { return base.ForcePosition; } |
107 | set | ||
83 | { | 108 | { |
84 | return base.ForceOrientation; | 109 | if (PositionDisplacement != OMV.Vector3.Zero) |
110 | base.ForcePosition = value - (PositionDisplacement * RawOrientation); | ||
111 | else | ||
112 | base.ForcePosition = value; | ||
85 | } | 113 | } |
114 | } | ||
115 | |||
116 | public override Quaternion ForceOrientation | ||
117 | { | ||
118 | get { return base.ForceOrientation; } | ||
86 | set | 119 | set |
87 | { | 120 | { |
88 | base.ForceOrientation = value; | 121 | base.ForceOrientation = value; |
89 | } | 122 | } |
90 | } | 123 | } |
91 | 124 | ||
125 | // TODO: decide if this is the right place for these variables. | ||
126 | // Somehow incorporate the optional settability by the user. | ||
92 | // Is this used? | 127 | // Is this used? |
93 | public override OMV.Vector3 CenterOfMass | 128 | public override OMV.Vector3 CenterOfMass |
94 | { | 129 | { |
95 | get { return CenterOfMassLocation; } | 130 | get { return RawPosition; } |
96 | } | 131 | } |
97 | 132 | ||
98 | // Is this used? | 133 | // Is this used? |
99 | public override OMV.Vector3 GeometricCenter | 134 | public override OMV.Vector3 GeometricCenter |
100 | { | 135 | { |
101 | get { return GeometricCenterLocation; } | 136 | get { return RawPosition; } |
102 | } | 137 | } |
103 | 138 | ||
104 | |||
105 | public override void UpdateProperties(EntityProperties entprop) | 139 | public override void UpdateProperties(EntityProperties entprop) |
106 | { | 140 | { |
107 | // Undo any center-of-mass displacement that might have been done. | 141 | // Undo any center-of-mass displacement that might have been done. |
108 | if (PositionDisplacement != OMV.Vector3.Zero) | 142 | if (PositionDisplacement != OMV.Vector3.Zero || OrientationDisplacement != OMV.Quaternion.Identity) |
109 | { | 143 | { |
110 | // Correct for any rotation around the center-of-mass | 144 | // Correct for any rotation around the center-of-mass |
111 | // TODO!!! | 145 | // TODO!!! |
112 | entprop.Position -= PositionDisplacement; | 146 | entprop.Position = entprop.Position + (PositionDisplacement * entprop.Rotation); |
147 | // entprop.Rotation = something; | ||
113 | } | 148 | } |
114 | 149 | ||
115 | base.UpdateProperties(entprop); | 150 | base.UpdateProperties(entprop); |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs index 9898562..d65d407 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs | |||
@@ -38,6 +38,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin | |||
38 | public class BSPrimLinkable : BSPrimDisplaced | 38 | public class BSPrimLinkable : BSPrimDisplaced |
39 | { | 39 | { |
40 | public BSLinkset Linkset { get; set; } | 40 | public BSLinkset Linkset { get; set; } |
41 | // The index of this child prim. | ||
42 | public int LinksetChildIndex { get; set; } | ||
43 | |||
41 | public BSLinksetInfo LinksetInfo { get; set; } | 44 | public BSLinksetInfo LinksetInfo { get; set; } |
42 | 45 | ||
43 | public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, | 46 | public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, |
@@ -90,7 +93,6 @@ public class BSPrimLinkable : BSPrimDisplaced | |||
90 | DetailLog("{0},BSPrimLinkset.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", | 93 | DetailLog("{0},BSPrimLinkset.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", |
91 | LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); | 94 | LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); |
92 | return; | 95 | return; |
93 | base.delink(); | ||
94 | } | 96 | } |
95 | 97 | ||
96 | // When simulator changes position, this might be moving a child of the linkset. | 98 | // When simulator changes position, this might be moving a child of the linkset. |
@@ -133,7 +135,8 @@ public class BSPrimLinkable : BSPrimDisplaced | |||
133 | // When going from non-physical to physical, this re-enables the constraints that | 135 | // When going from non-physical to physical, this re-enables the constraints that |
134 | // had been automatically disabled when the mass was set to zero. | 136 | // had been automatically disabled when the mass was set to zero. |
135 | // For compound based linksets, this enables and disables interactions of the children. | 137 | // For compound based linksets, this enables and disables interactions of the children. |
136 | Linkset.Refresh(this); | 138 | if (Linkset != null) // null can happen during initialization |
139 | Linkset.Refresh(this); | ||
137 | } | 140 | } |
138 | 141 | ||
139 | protected override void MakeDynamic(bool makeStatic) | 142 | protected override void MakeDynamic(bool makeStatic) |
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs index f68612c..35ae44c 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs | |||
@@ -52,7 +52,12 @@ namespace OpenSim.Region.ScriptEngine.Interfaces | |||
52 | { | 52 | { |
53 | bool Cancel(); | 53 | bool Cancel(); |
54 | void Abort(); | 54 | void Abort(); |
55 | bool Wait(TimeSpan t); | 55 | |
56 | /// <summary> | ||
57 | /// Wait for the work item to complete. | ||
58 | /// </summary> | ||
59 | /// <param name='t'>The number of milliseconds to wait. Must be >= -1 (Timeout.Infinite).</param> | ||
60 | bool Wait(int t); | ||
56 | } | 61 | } |
57 | 62 | ||
58 | /// <summary> | 63 | /// <summary> |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index be6ac0a..96f650e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -4479,6 +4479,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4479 | } | 4479 | } |
4480 | } | 4480 | } |
4481 | } | 4481 | } |
4482 | |||
4482 | if (pushAllowed) | 4483 | if (pushAllowed) |
4483 | { | 4484 | { |
4484 | float distance = (PusheePos - m_host.AbsolutePosition).Length(); | 4485 | float distance = (PusheePos - m_host.AbsolutePosition).Length(); |
@@ -4507,17 +4508,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4507 | applied_linear_impulse *= scaling_factor; | 4508 | applied_linear_impulse *= scaling_factor; |
4508 | 4509 | ||
4509 | } | 4510 | } |
4511 | |||
4510 | if (pusheeIsAvatar) | 4512 | if (pusheeIsAvatar) |
4511 | { | 4513 | { |
4512 | if (pusheeav != null) | 4514 | if (pusheeav != null) |
4513 | { | 4515 | { |
4514 | if (pusheeav.PhysicsActor != null) | 4516 | PhysicsActor pa = pusheeav.PhysicsActor; |
4517 | |||
4518 | if (pa != null) | ||
4515 | { | 4519 | { |
4516 | if (local != 0) | 4520 | if (local != 0) |
4517 | { | 4521 | { |
4518 | applied_linear_impulse *= m_host.GetWorldRotation(); | 4522 | applied_linear_impulse *= m_host.GetWorldRotation(); |
4519 | } | 4523 | } |
4520 | pusheeav.PhysicsActor.AddForce(applied_linear_impulse, true); | 4524 | |
4525 | pa.AddForce(applied_linear_impulse, true); | ||
4521 | } | 4526 | } |
4522 | } | 4527 | } |
4523 | } | 4528 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 669cc37..bf19a42 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | |||
@@ -595,7 +595,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
595 | if (!m_coopTermination) | 595 | if (!m_coopTermination) |
596 | { | 596 | { |
597 | // If we're not co-operative terminating then try and wait for the event to complete before stopping | 597 | // If we're not co-operative terminating then try and wait for the event to complete before stopping |
598 | if (workItem.Wait(new TimeSpan((long)timeout * 100000))) | 598 | if (workItem.Wait(timeout)) |
599 | return true; | 599 | return true; |
600 | } | 600 | } |
601 | else | 601 | else |
@@ -610,7 +610,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
610 | 610 | ||
611 | // For now, we will wait forever since the event should always cleanly terminate once LSL loop | 611 | // For now, we will wait forever since the event should always cleanly terminate once LSL loop |
612 | // checking is implemented. May want to allow a shorter timeout option later. | 612 | // checking is implemented. May want to allow a shorter timeout option later. |
613 | if (workItem.Wait(TimeSpan.MaxValue)) | 613 | if (workItem.Wait(Timeout.Infinite)) |
614 | { | 614 | { |
615 | if (DebugLevel >= 1) | 615 | if (DebugLevel >= 1) |
616 | m_log.DebugFormat( | 616 | m_log.DebugFormat( |
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs b/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs index 2ac5c31..8dd7677 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs | |||
@@ -57,8 +57,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine | |||
57 | wr.Abort(); | 57 | wr.Abort(); |
58 | } | 58 | } |
59 | 59 | ||
60 | public bool Wait(TimeSpan t) | 60 | public bool Wait(int t) |
61 | { | 61 | { |
62 | // We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the | ||
63 | // TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an | ||
64 | // int (32-bit) we can end up with bad values. This occurs on Windows though curious not on Mono 2.10.8 | ||
65 | // (or very likely other versions of Mono at least up until 3.0.3). | ||
62 | return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false); | 66 | return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false); |
63 | } | 67 | } |
64 | } | 68 | } |