aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs10
-rw-r--r--OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs5
-rw-r--r--OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs5
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs5
-rw-r--r--OpenSim/Region/Framework/Interfaces/IHttpRequests.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/INPCModule.cs12
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRegionConsole.cs4
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRestartModule.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISearchModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs47
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISoundModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ITerrainModule.cs9
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs33
-rw-r--r--OpenSim/Region/Framework/Interfaces/IWorldComm.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs101
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs382
-rw-r--r--OpenSim/Region/Framework/Scenes/CollisionSounds.cs304
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs71
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs280
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs72
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPMaterial.cs95
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPVehicle.cs792
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs440
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs160
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs6
-rwxr-xr-xOpenSim/Region/Framework/Scenes/Scene.cs1339
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs57
-rwxr-xr-xOpenSim/Region/Framework/Scenes/SceneGraph.cs542
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs246
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs2042
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs1669
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs813
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs2845
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs137
-rwxr-xr-xOpenSim/Region/Framework/Scenes/SimStatsReporter.cs629
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainChannel.cs30
-rw-r--r--OpenSim/Region/Framework/Scenes/TerrainCompressor.cs1589
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs25
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs367
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs1
58 files changed, 10551 insertions, 4709 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs b/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
index 0cc8fb6..e0aad2b 100644
--- a/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAgentAssetTransactions.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.Framework.Interfaces
36 void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID, 36 void HandleItemUpdateFromTransaction(IClientAPI remoteClient, UUID transactionID,
37 InventoryItemBase item); 37 InventoryItemBase item);
38 38
39 void HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID, 39 bool HandleItemCreationFromTransaction(IClientAPI remoteClient, UUID transactionID, UUID folderID,
40 uint callbackID, string description, string name, sbyte invType, 40 uint callbackID, string description, string name, sbyte invType,
41 sbyte type, byte wearableType, uint nextOwnerMask); 41 sbyte type, byte wearableType, uint nextOwnerMask);
42 42
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index d9901bd..3c1247f 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using OpenMetaverse; 31using OpenMetaverse;
31using OpenSim.Framework; 32using OpenSim.Framework;
@@ -89,7 +90,7 @@ namespace OpenSim.Region.Framework.Interfaces
89 /// <param name="addToInventory">If true then add object to user inventory</param> 90 /// <param name="addToInventory">If true then add object to user inventory</param>
90 /// <param name="append">Append to attachment point rather than replace.</param> 91 /// <param name="append">Append to attachment point rather than replace.</param>
91 /// <returns>true if the object was successfully attached, false otherwise</returns> 92 /// <returns>true if the object was successfully attached, false otherwise</returns>
92 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool addToInventory, bool append); 93 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo, bool addToInventory, bool append);
93 94
94 /// <summary> 95 /// <summary>
95 /// Rez an attachment from user inventory and change inventory status to match. 96 /// Rez an attachment from user inventory and change inventory status to match.
@@ -98,7 +99,11 @@ namespace OpenSim.Region.Framework.Interfaces
98 /// <param name="itemID"></param> 99 /// <param name="itemID"></param>
99 /// <param name="AttachmentPt"></param> 100 /// <param name="AttachmentPt"></param>
100 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns> 101 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns>
101 SceneObjectGroup RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt); 102 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt);
103
104 // Same as above, but also load script states from a separate doc
105 ISceneEntity RezSingleAttachmentFromInventory(
106 IScenePresence presence, UUID itemID, uint AttachmentPt, XmlDocument doc);
102 107
103 /// <summary> 108 /// <summary>
104 /// Rez multiple attachments from a user's inventory 109 /// Rez multiple attachments from a user's inventory
@@ -130,7 +135,6 @@ namespace OpenSim.Region.Framework.Interfaces
130 /// <param name="grp">The attachment to detach.</param> 135 /// <param name="grp">The attachment to detach.</param>
131 void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup grp); 136 void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup grp);
132 137
133 /// <summary>
134 /// Update the position of an attachment. 138 /// Update the position of an attachment.
135 /// </summary> 139 /// </summary>
136 /// <param name="sog"></param> 140 /// <param name="sog"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
index b536a49..4d8409be 100644
--- a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs
@@ -35,6 +35,9 @@ namespace OpenSim.Services.Interfaces
35 public interface IBakedTextureModule 35 public interface IBakedTextureModule
36 { 36 {
37 WearableCacheItem[] Get(UUID id); 37 WearableCacheItem[] Get(UUID id);
38 void Store(UUID id, WearableCacheItem[] data); 38
39 void Store(UUID id);
40 void Store(UUID id, WearableCacheItem[] WearableCache);
41 void UpdateMeshAvatar(UUID id);
39 } 42 }
40} 43}
diff --git a/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs b/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
index 522c82d..30d404e 100644
--- a/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
@@ -40,19 +40,19 @@ namespace OpenSim.Region.Framework.Interfaces
40 /// </summary> 40 /// </summary>
41 /// <param name="agentId"></param> 41 /// <param name="agentId"></param>
42 /// <param name="capsObjectPath"></param> 42 /// <param name="capsObjectPath"></param>
43 void CreateCaps(UUID agentId); 43 void CreateCaps(UUID agentId, uint circuitCode);
44 44
45 /// <summary> 45 /// <summary>
46 /// Remove the caps handler for a given agent. 46 /// Remove the caps handler for a given agent.
47 /// </summary> 47 /// </summary>
48 /// <param name="agentId"></param> 48 /// <param name="agentId"></param>
49 void RemoveCaps(UUID agentId); 49 void RemoveCaps(UUID agentId, uint circuitCode);
50 50
51 /// <summary> 51 /// <summary>
52 /// Will return null if the agent doesn't have a caps handler registered 52 /// Will return null if the agent doesn't have a caps handler registered
53 /// </summary> 53 /// </summary>
54 /// <param name="agentId"></param> 54 /// <param name="agentId"></param>
55 Caps GetCapsForUser(UUID agentId); 55 Caps GetCapsForUser(uint circuitCode);
56 56
57 void SetAgentCapsSeeds(AgentCircuitData agent); 57 void SetAgentCapsSeeds(AgentCircuitData agent);
58 58
@@ -65,5 +65,7 @@ namespace OpenSim.Region.Framework.Interfaces
65 void DropChildSeed(UUID agentID, ulong handle); 65 void DropChildSeed(UUID agentID, ulong handle);
66 66
67 string GetCapsPath(UUID agentId); 67 string GetCapsPath(UUID agentId);
68
69 void ActivateCaps(uint circuitCode);
68 } 70 }
69} 71}
diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs b/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs
index 08b71e4..4d000b6 100644
--- a/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IDynamicMenuModule.cs
@@ -43,6 +43,7 @@ namespace OpenSim.Region.Framework.Interfaces
43 public enum UserMode : int 43 public enum UserMode : int
44 { 44 {
45 Normal = 0, 45 Normal = 0,
46 RegionManager = 2,
46 God = 3 47 God = 3
47 } 48 }
48 49
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 9ffda51..b85fd8b 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -133,6 +133,8 @@ namespace OpenSim.Region.Framework.Interfaces
133 /// </returns> 133 /// </returns>
134 bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 134 bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
135 135
136 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
137
136 /// <summary> 138 /// <summary>
137 /// Stop and remove a script which is in this prim's inventory from the scene. 139 /// Stop and remove a script which is in this prim's inventory from the scene.
138 /// </summary> 140 /// </summary>
@@ -244,7 +246,7 @@ namespace OpenSim.Region.Framework.Interfaces
244 /// <param name="objlist">The scene objects</param> 246 /// <param name="objlist">The scene objects</param>
245 /// <param name="veclist">Relative offsets for each object</param> 247 /// <param name="veclist">Relative offsets for each object</param>
246 /// <returns>true = success, false = the scene object asset couldn't be found</returns> 248 /// <returns>true = success, false = the scene object asset couldn't be found</returns>
247 bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist); 249 bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist, out Vector3 bbox, out float offsetHeight);
248 250
249 /// <summary> 251 /// <summary>
250 /// Update an existing inventory item. 252 /// Update an existing inventory item.
@@ -318,5 +320,6 @@ namespace OpenSim.Region.Framework.Interfaces
318 /// A <see cref="Dictionary`2"/> 320 /// A <see cref="Dictionary`2"/>
319 /// </returns> 321 /// </returns>
320 Dictionary<UUID, string> GetScriptStates(); 322 Dictionary<UUID, string> GetScriptStates();
323 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
321 } 324 }
322} 325}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index d07b15a..d172780 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -36,6 +36,7 @@ using OpenSim.Region.Framework.Scenes;
36namespace OpenSim.Region.Framework.Interfaces 36namespace OpenSim.Region.Framework.Interfaces
37{ 37{
38 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx); 38 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx);
39 public delegate ScenePresence CrossAsyncDelegate(ScenePresence agent, bool isFlying);
39 40
40 public interface IEntityTransferModule 41 public interface IEntityTransferModule
41 { 42 {
@@ -94,8 +95,10 @@ namespace OpenSim.Region.Framework.Interfaces
94 95
95 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, EntityTransferContext ctx, 96 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, EntityTransferContext ctx,
96 out Vector3 newpos, out string reason); 97 out Vector3 newpos, out string reason);
98 GridRegion GetObjectDestination(SceneObjectGroup grp, Vector3 targetPosition, out Vector3 newpos);
99 bool checkAgentAccessToRegion(ScenePresence agent, GridRegion destiny, Vector3 position, EntityTransferContext ctx, out string reason);
97 100
98 void Cross(SceneObjectGroup sog, Vector3 position, bool silent); 101 bool CrossPrimGroupIntoNewRegion(GridRegion destination, Vector3 newPosition, SceneObjectGroup grp, bool silent, bool removeScripts);
99 102
100 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx); 103 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx);
101 104
diff --git a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
index 124504c..efc9ddc 100644
--- a/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
+++ b/OpenSim/Region/Framework/Interfaces/IHttpRequests.cs
@@ -58,7 +58,6 @@ namespace OpenSim.Region.Framework.Interfaces
58 public interface IHttpRequestModule 58 public interface IHttpRequestModule
59 { 59 {
60 UUID MakeHttpRequest(string url, string parameters, string body); 60 UUID MakeHttpRequest(string url, string parameters, string body);
61
62 /// <summary> 61 /// <summary>
63 /// Starts the http request. 62 /// Starts the http request.
64 /// </summary> 63 /// </summary>
@@ -85,8 +84,7 @@ namespace OpenSim.Region.Framework.Interfaces
85 /// Stop and remove all http requests for the given script. 84 /// Stop and remove all http requests for the given script.
86 /// </summary> 85 /// </summary>
87 /// <param name='id'></param> 86 /// <param name='id'></param>
88 void StopHttpRequestsForScript(UUID id); 87 void StopHttpRequest(uint m_localID, UUID m_itemID);
89
90 IServiceRequest GetNextCompletedRequest(); 88 IServiceRequest GetNextCompletedRequest();
91 void RemoveCompletedRequest(UUID id); 89 void RemoveCompletedRequest(UUID id);
92 } 90 }
diff --git a/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs b/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs
index 6a7d4a1..5151567 100644
--- a/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IMapImageUploadModule.cs
@@ -25,13 +25,18 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System.Drawing; 28using OpenMetaverse;
29using OpenSim.Framework; 29using OpenSim.Framework;
30using System.Drawing;
30 31
31namespace OpenSim.Region.Framework.Interfaces 32namespace OpenSim.Region.Framework.Interfaces
32{ 33{
33 public interface IMapImageUploadModule 34 public interface IMapImageUploadModule
34 { 35 {
36 /// <summary>
37 /// Upload a new maptile
38 /// </summary>
39 void UploadMapTile(IScene scene);
35 void UploadMapTile(IScene scene, Bitmap mapTile); 40 void UploadMapTile(IScene scene, Bitmap mapTile);
36 } 41 }
37} \ No newline at end of file 42}
diff --git a/OpenSim/Region/Framework/Interfaces/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
index 478833e..8f9a13c 100644
--- a/OpenSim/Region/Framework/Interfaces/INPCModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs
@@ -31,6 +31,16 @@ using OpenSim.Region.Framework.Scenes;
31 31
32namespace OpenSim.Region.Framework.Interfaces 32namespace OpenSim.Region.Framework.Interfaces
33{ 33{
34 // option flags for NPCs
35 public enum NPCOptionsFlags : int
36 {
37 None = 0x00, // no flags (max restriction)
38 AllowNotOwned = 0x01, // allow NPCs to be created not Owned
39 AllowSenseAsAvatar = 0x02, // allow NPCs to set to be sensed as Avatars
40 AllowCloneOtherAvatars = 0x04, // allow NPCs to created cloning a avatar in region
41 NoNPCGroup = 0x08 // NPCs will have no group title, otherwise will have "- NPC -"
42 }
43
34 /// <summary> 44 /// <summary>
35 /// Temporary interface. More methods to come at some point to make NPCs 45 /// Temporary interface. More methods to come at some point to make NPCs
36 /// more object oriented rather than controlling purely through module 46 /// more object oriented rather than controlling purely through module
@@ -284,5 +294,7 @@ namespace OpenSim.Region.Framework.Interfaces
284 /// agent, the agent is unowned or the agent was not an NPC. 294 /// agent, the agent is unowned or the agent was not an NPC.
285 /// </returns> 295 /// </returns>
286 UUID GetOwner(UUID agentID); 296 UUID GetOwner(UUID agentID);
297
298 NPCOptionsFlags NPCOptionFlags {get;}
287 } 299 }
288} 300}
diff --git a/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs b/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs
index 4d261d6..5d5ce34 100644
--- a/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRegionConsole.cs
@@ -30,8 +30,12 @@ using OpenSim.Framework;
30 30
31namespace OpenSim.Region.Framework.Interfaces 31namespace OpenSim.Region.Framework.Interfaces
32{ 32{
33 public delegate void ConsoleMessage(UUID toAgentID, string message);
34
33 public interface IRegionConsole 35 public interface IRegionConsole
34 { 36 {
37 event ConsoleMessage OnConsoleMessage;
38
35 bool RunCommand(string command, UUID invokerID); 39 bool RunCommand(string command, UUID invokerID);
36 void SendConsoleOutput(UUID agentID, string message); 40 void SendConsoleOutput(UUID agentID, string message);
37 void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn); 41 void AddCommand(string module, bool shared, string command, string help, string longhelp, CommandDelegate fn);
diff --git a/OpenSim/Region/Framework/Interfaces/IRestartModule.cs b/OpenSim/Region/Framework/Interfaces/IRestartModule.cs
index c68550f..9b25beb 100644
--- a/OpenSim/Region/Framework/Interfaces/IRestartModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IRestartModule.cs
@@ -35,5 +35,6 @@ namespace OpenSim.Region.Framework.Interfaces
35 TimeSpan TimeUntilRestart { get; } 35 TimeSpan TimeUntilRestart { get; }
36 void ScheduleRestart(UUID initiator, string message, int[] alerts, bool notice); 36 void ScheduleRestart(UUID initiator, string message, int[] alerts, bool notice);
37 void AbortRestart(string message); 37 void AbortRestart(string message);
38 void DelayRestart(int seconds, string message);
38 } 39 }
39} 40}
diff --git a/OpenSim/Region/Framework/Interfaces/ISearchModule.cs b/OpenSim/Region/Framework/Interfaces/ISearchModule.cs
index 64bf72c..d56d188 100644
--- a/OpenSim/Region/Framework/Interfaces/ISearchModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISearchModule.cs
@@ -31,6 +31,6 @@ namespace OpenSim.Framework
31{ 31{
32 public interface ISearchModule 32 public interface ISearchModule
33 { 33 {
34 34 void Refresh();
35 } 35 }
36} 36}
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
index 8948f04..13358cb 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
@@ -125,6 +125,8 @@ namespace OpenSim.Region.Framework.Interfaces
125 /// <param name="regionUUID">the region UUID</param> 125 /// <param name="regionUUID">the region UUID</param>
126 void RemoveRegionEnvironmentSettings(UUID regionUUID); 126 void RemoveRegionEnvironmentSettings(UUID regionUUID);
127 127
128 UUID[] GetObjectIDs(UUID regionID);
129
128 void SaveExtra(UUID regionID, string name, string value); 130 void SaveExtra(UUID regionID, string name, string value);
129 131
130 void RemoveExtra(UUID regionID, string name); 132 void RemoveExtra(UUID regionID, string name);
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
index 917b5d1..e09f775 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
@@ -115,6 +115,7 @@ namespace OpenSim.Region.Framework.Interfaces
115 RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID); 115 RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID);
116 void StoreRegionWindlightSettings(RegionLightShareData wl); 116 void StoreRegionWindlightSettings(RegionLightShareData wl);
117 void RemoveRegionWindlightSettings(UUID regionID); 117 void RemoveRegionWindlightSettings(UUID regionID);
118 UUID[] GetObjectIDs(UUID regionID);
118 119
119 /// <summary> 120 /// <summary>
120 /// Load Environment settings from region storage 121 /// Load Environment settings from region storage
diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
new file mode 100644
index 0000000..f805863
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
@@ -0,0 +1,47 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using OpenSim.Region.Framework.Scenes;
29
30public interface ISnmpModule
31{
32 void Trap(int code, string Message, Scene scene);
33 void Critical(string Message, Scene scene);
34 void Warning(string Message, Scene scene);
35 void Major(string Message, Scene scene);
36 void ColdStart(int step , Scene scene);
37 void Shutdown(int step , Scene scene);
38 //
39 // Node Start/stop events
40 //
41 void LinkUp(Scene scene);
42 void LinkDown(Scene scene);
43 void BootInfo(string data, Scene scene);
44 void trapDebug(string Module,string data, Scene scene);
45 void trapXMRE(int data, string Message, Scene scene);
46
47}
diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
index 8372ddd..f7c6513 100644
--- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs
@@ -95,7 +95,7 @@ namespace OpenSim.Region.Framework.Interfaces
95 /// <param name="radius">Sound radius</param> 95 /// <param name="radius">Sound radius</param>
96 /// <param name="isMaster">Set object to sync master if true</param> 96 /// <param name="isMaster">Set object to sync master if true</param>
97 void LoopSound(UUID objectID, UUID soundID, double gain, 97 void LoopSound(UUID objectID, UUID soundID, double gain,
98 double radius, bool isMaster); 98 double radius, bool isMaster, bool isSlave);
99 99
100 /// <summary> 100 /// <summary>
101 /// Trigger or play an attached sound in this part's inventory. 101 /// Trigger or play an attached sound in this part's inventory.
diff --git a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
index 28f797a..472e5a5d 100644
--- a/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ITerrainModule.cs
@@ -28,6 +28,8 @@ using System.IO;
28 28
29using OpenSim.Framework; 29using OpenSim.Framework;
30 30
31using System.IO;
32using OpenSim.Framework;
31using OpenMetaverse; 33using OpenMetaverse;
32 34
33namespace OpenSim.Region.Framework.Interfaces 35namespace OpenSim.Region.Framework.Interfaces
@@ -43,13 +45,13 @@ namespace OpenSim.Region.Framework.Interfaces
43 /// Use this if you change terrain data outside of the terrain module (e.g. in osTerrainSetHeight) 45 /// Use this if you change terrain data outside of the terrain module (e.g. in osTerrainSetHeight)
44 /// </summary> 46 /// </summary>
45 void TaintTerrain(); 47 void TaintTerrain();
46 48
47 /// <summary> 49 /// <summary>
48 /// When a client initially connects, all the terrain must be pushed to the viewer. 50 /// When a client initially connects, all the terrain must be pushed to the viewer.
49 /// This call causes all the terrain patches to be sent to the client. 51 /// This call causes all the terrain patches to be sent to the client.
50 /// </summary> 52 /// </summary>
51 void PushTerrain(IClientAPI pClient); 53 void PushTerrain(IClientAPI pClient);
52 54
53 /// <summary> 55 /// <summary>
54 /// Load a terrain from a stream. 56 /// Load a terrain from a stream.
55 /// </summary> 57 /// </summary>
@@ -58,8 +60,9 @@ namespace OpenSim.Region.Framework.Interfaces
58 /// </param> 60 /// </param>
59 /// <param name="stream"></param> 61 /// <param name="stream"></param>
60 void LoadFromStream(string filename, Stream stream); 62 void LoadFromStream(string filename, Stream stream);
61 void LoadFromStream(string filename, Vector3 displacement, float radianRotation, Vector2 rotationDisplacement, Stream stream);
62 void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap); 63 void LoadFromStream(string filename, System.Uri pathToTerrainHeightmap);
64 void LoadFromStream(string filename, Vector3 displacement,
65 float radianRotation, Vector2 rotationDisplacement, Stream stream);
63 /// <summary> 66 /// <summary>
64 /// Save a terrain to a stream. 67 /// Save a terrain to a stream.
65 /// </summary> 68 /// </summary>
diff --git a/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
new file mode 100644
index 0000000..ed26989
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
@@ -0,0 +1,33 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using OpenSim.Region.Framework.Scenes;
29
30public interface IUserAccountCacheModule
31{
32 void Remove(string name);
33}
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
index d76a0d7..c01c56d 100644
--- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
@@ -127,7 +127,7 @@ namespace OpenSim.Region.Framework.Interfaces
127 /// <param name='msg'> 127 /// <param name='msg'>
128 /// Message. 128 /// Message.
129 /// </param> 129 /// </param>
130 void DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg); 130 bool DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg);
131 131
132 /// <summary> 132 /// <summary>
133 /// Are there any listen events ready to be dispatched? 133 /// Are there any listen events ready to be dispatched?
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs b/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs
index 9c781e1..ee7c4ec 100644
--- a/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWorldMapModule.cs
@@ -36,7 +36,6 @@ namespace OpenSim.Region.Framework.Interfaces
36 /// Generate a map tile for the scene. a terrain texture for this scene 36 /// Generate a map tile for the scene. a terrain texture for this scene
37 /// </summary> 37 /// </summary>
38 void GenerateMaptile(); 38 void GenerateMaptile();
39 List<MapBlockData> Map2BlockFromGridRegion(GridRegion r, uint flag); 39 void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag);
40 MapBlockData MapBlockFromGridRegion(GridRegion r, uint flag);
41 } 40 }
42} 41}
diff --git a/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs b/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs
new file mode 100644
index 0000000..d59678b
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Animation/MovementAnimationOverrides.cs
@@ -0,0 +1,101 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Xml;
30using System.Collections.Generic;
31using System.Reflection;
32using System.Threading;
33using System.Timers;
34using Timer = System.Timers.Timer;
35using OpenMetaverse;
36using log4net;
37using Nini.Config;
38using OpenSim.Framework;
39using OpenSim.Framework.Client;
40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes.Animation;
42using OpenSim.Region.Framework.Scenes.Types;
43using OpenSim.Region.PhysicsModules.SharedBase;
44using GridRegion = OpenSim.Services.Interfaces.GridRegion;
45using OpenSim.Services.Interfaces;
46using TeleportFlags = OpenSim.Framework.Constants.TeleportFlags;
47
48namespace OpenSim.Region.Framework.Scenes
49{
50 public class MovementAnimationOverrides
51 {
52 private static readonly ILog m_log =
53 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54
55 private Dictionary<string, UUID> m_overrides = new Dictionary<string, UUID>();
56 public void SetOverride(string state, UUID animID)
57 {
58 if (animID == UUID.Zero)
59 {
60 if (state == "ALL")
61 m_overrides.Clear();
62 else
63 m_overrides.Remove(state);
64 return;
65 }
66
67 m_log.DebugFormat("Setting override for {0} to {1}", state, animID);
68
69 lock (m_overrides)
70 m_overrides[state] = animID;
71 }
72
73 public UUID GetOverriddenAnimation(string state)
74 {
75 lock (m_overrides)
76 {
77 if (m_overrides.ContainsKey(state))
78 return m_overrides[state];
79 }
80
81 return UUID.Zero;
82 }
83
84 public Dictionary<string, UUID> CloneAOPairs()
85 {
86 lock (m_overrides)
87 {
88 return new Dictionary<string, UUID>(m_overrides);
89 }
90 }
91
92 public void CopyAOPairsFrom(Dictionary<string, UUID> src)
93 {
94 lock (m_overrides)
95 {
96 m_overrides.Clear();
97 m_overrides = new Dictionary<string, UUID>(src);
98 }
99 }
100 }
101}
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 6d51029..13d4562 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
48 48
49 public AnimationSet Animations 49 public AnimationSet Animations
50 { 50 {
51 get { return m_animations; } 51 get { return m_animations; }
52 } 52 }
53 protected AnimationSet m_animations = new AnimationSet(); 53 protected AnimationSet m_animations = new AnimationSet();
54 54
@@ -56,39 +56,42 @@ namespace OpenSim.Region.Framework.Scenes.Animation
56 /// The current movement animation 56 /// The current movement animation
57 /// </value> 57 /// </value>
58 public string CurrentMovementAnimation { get; private set; } 58 public string CurrentMovementAnimation { get; private set; }
59 59
60 private int m_animTickFall; 60 private int m_animTickFall;
61 public int m_animTickJump; // ScenePresence has to see this to control +Z force 61 private int m_animTickLand;
62 public bool m_jumping = false; 62 private int m_animTickJump;
63 public float m_jumpVelocity = 0f; 63
64// private int m_landing = 0; 64 public bool m_jumping = false;
65
66 // private int m_landing = 0;
65 67
66 /// <summary> 68 /// <summary>
67 /// Is the avatar falling? 69 /// Is the avatar falling?
68 /// </summary> 70 /// </summary>
69 public bool Falling { get; private set; } 71 public bool Falling { get; private set; }
70 72
71 private float m_fallHeight; 73 private float m_lastFallVelocity;
72 74
73 /// <value> 75 /// <value>
74 /// The scene presence that this animator applies to 76 /// The scene presence that this animator applies to
75 /// </value> 77 /// </value>
76 protected ScenePresence m_scenePresence; 78 protected ScenePresence m_scenePresence;
77 79
78 public ScenePresenceAnimator(ScenePresence sp) 80 public ScenePresenceAnimator(ScenePresence sp)
79 { 81 {
80 m_scenePresence = sp; 82 m_scenePresence = sp;
81 CurrentMovementAnimation = "CROUCH"; 83 CurrentMovementAnimation = "CROUCH";
82 } 84 }
83 85
84 public void AddAnimation(UUID animID, UUID objectID) 86 public void AddAnimation(UUID animID, UUID objectID)
85 { 87 {
86 if (m_scenePresence.IsChildAgent) 88 if (m_scenePresence.IsChildAgent)
87 return; 89 return;
88 90
91 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} for {1}", animID, m_scenePresence.Name);
89 if (m_scenePresence.Scene.DebugAnimations) 92 if (m_scenePresence.Scene.DebugAnimations)
90 m_log.DebugFormat( 93 m_log.DebugFormat(
91 "[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", 94 "[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}",
92 GetAnimName(animID), animID, m_scenePresence.Name); 95 GetAnimName(animID), animID, m_scenePresence.Name);
93 96
94 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) 97 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
@@ -110,7 +113,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
110 if (animID == UUID.Zero) 113 if (animID == UUID.Zero)
111 return; 114 return;
112 115
113// m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", animID, name, m_scenePresence.Name); 116 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} {1} for {2}", animID, name, m_scenePresence.Name);
114 117
115 AddAnimation(animID, objectID); 118 AddAnimation(animID, objectID);
116 } 119 }
@@ -130,7 +133,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
130 133
131 if (m_scenePresence.Scene.DebugAnimations) 134 if (m_scenePresence.Scene.DebugAnimations)
132 m_log.DebugFormat( 135 m_log.DebugFormat(
133 "[SCENE PRESENCE ANIMATOR]: Removing animation {0} {1} for {2}", 136 "[SCENE PRESENCE ANIMATOR]: Removing animation {0} {1} for {2}",
134 GetAnimName(animID), animID, m_scenePresence.Name); 137 GetAnimName(animID), animID, m_scenePresence.Name);
135 138
136 if (m_animations.Remove(animID, allowNoDefault)) 139 if (m_animations.Remove(animID, allowNoDefault))
@@ -140,6 +143,22 @@ namespace OpenSim.Region.Framework.Scenes.Animation
140 } 143 }
141 } 144 }
142 145
146 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack)
147 {
148 if (m_scenePresence.IsChildAgent)
149 return;
150
151 if (animID != UUID.Zero)
152 {
153 if (addRemove)
154 m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero);
155 else
156 m_animations.Remove(animID, false);
157 }
158 if (sendPack)
159 SendAnimPack();
160 }
161
143 // Called from scripts 162 // Called from scripts
144 public void RemoveAnimation(string name) 163 public void RemoveAnimation(string name)
145 { 164 {
@@ -164,12 +183,19 @@ namespace OpenSim.Region.Framework.Scenes.Animation
164 183
165 m_animations.Clear(); 184 m_animations.Clear();
166 } 185 }
167 186
187
188 UUID aoSitGndAnim = UUID.Zero;
189
168 /// <summary> 190 /// <summary>
169 /// The movement animation is reserved for "main" animations 191 /// The movement animation is reserved for "main" animations
170 /// that are mutually exclusive, e.g. flying and sitting. 192 /// that are mutually exclusive, e.g. flying and sitting.
171 /// </summary> 193 /// </summary>
172 /// <returns>'true' if the animation was updated</returns> 194 /// <returns>'true' if the animation was updated</returns>
195 ///
196
197
198
173 public bool TrySetMovementAnimation(string anim) 199 public bool TrySetMovementAnimation(string anim)
174 { 200 {
175 bool ret = false; 201 bool ret = false;
@@ -179,17 +205,50 @@ namespace OpenSim.Region.Framework.Scenes.Animation
179// "[SCENE PRESENCE ANIMATOR]: Setting movement animation {0} for {1}", 205// "[SCENE PRESENCE ANIMATOR]: Setting movement animation {0} for {1}",
180// anim, m_scenePresence.Name); 206// anim, m_scenePresence.Name);
181 207
182 if (m_animations.TrySetDefaultAnimation( 208 if (aoSitGndAnim != UUID.Zero)
183 anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID)) 209 {
210 avnChangeAnim(aoSitGndAnim, false, true);
211 aoSitGndAnim = UUID.Zero;
212 }
213
214 UUID overridenAnim = m_scenePresence.Overrides.GetOverriddenAnimation(anim);
215 if (overridenAnim != UUID.Zero)
184 { 216 {
217 if (anim == "SITGROUND")
218 {
219 UUID defsit = DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"];
220 if (defsit == UUID.Zero)
221 return false;
222 m_animations.SetDefaultAnimation(defsit, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID);
223 aoSitGndAnim = overridenAnim;
224 avnChangeAnim(overridenAnim, true, false);
225 }
226 else
227 {
228 m_animations.SetDefaultAnimation(overridenAnim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID);
229 }
230 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION });
231 SendAnimPack();
232 ret = true;
233 }
234 else
235 {
236 // translate sit and sitground state animations
237 if (anim == "SIT" || anim == "SITGROUND")
238 anim = m_scenePresence.sitAnimation;
239
240 if (m_animations.TrySetDefaultAnimation(
241 anim, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, m_scenePresence.UUID))
242 {
185// m_log.DebugFormat( 243// m_log.DebugFormat(
186// "[SCENE PRESENCE ANIMATOR]: Updating movement animation to {0} for {1}", 244// "[SCENE PRESENCE ANIMATOR]: Updating movement animation to {0} for {1}",
187// anim, m_scenePresence.Name); 245// anim, m_scenePresence.Name);
188 246
189 // 16384 is CHANGED_ANIMATION 247 // 16384 is CHANGED_ANIMATION
190 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION}); 248 m_scenePresence.SendScriptEventToAttachments("changed", new Object[] { (int)Changed.ANIMATION });
191 SendAnimPack(); 249 SendAnimPack();
192 ret = true; 250 ret = true;
251 }
193 } 252 }
194 } 253 }
195 else 254 else
@@ -201,78 +260,119 @@ namespace OpenSim.Region.Framework.Scenes.Animation
201 return ret; 260 return ret;
202 } 261 }
203 262
263 public enum motionControlStates : byte
264 {
265 sitted = 0,
266 flying,
267 falling,
268 jumping,
269 landing,
270 onsurface
271 }
272
273 public motionControlStates currentControlState = motionControlStates.onsurface;
274
204 /// <summary> 275 /// <summary>
205 /// This method determines the proper movement related animation 276 /// This method determines the proper movement related animation
206 /// </summary> 277 /// </summary>
207 private string DetermineMovementAnimation() 278 private string DetermineMovementAnimation()
208 { 279 {
209 const float FALL_DELAY = 800f; 280 const int FALL_DELAY = 800;
210 const float PREJUMP_DELAY = 200f; 281 const int PREJUMP_DELAY = 200;
211 const float JUMP_PERIOD = 800f; 282 const int JUMP_PERIOD = 800;
212 #region Inputs 283 #region Inputs
213 284
285 if (m_scenePresence.IsInTransit)
286 return CurrentMovementAnimation;
287
288 if (m_scenePresence.SitGround)
289 {
290 currentControlState = motionControlStates.sitted;
291 return "SITGROUND";
292 }
293 if (m_scenePresence.ParentID != 0 || m_scenePresence.ParentUUID != UUID.Zero)
294 {
295 currentControlState = motionControlStates.sitted;
296 return "SIT";
297 }
298
214 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; 299 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
215 PhysicsActor actor = m_scenePresence.PhysicsActor; 300 PhysicsActor actor = m_scenePresence.PhysicsActor;
216 301
217 // Create forward and left vectors from the current avatar rotation 302 const AgentManager.ControlFlags ANYXYMASK = (
218 Matrix4 rotMatrix = Matrix4.CreateFromQuaternion(m_scenePresence.Rotation); 303 AgentManager.ControlFlags.AGENT_CONTROL_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS |
219 Vector3 fwd = Vector3.Transform(Vector3.UnitX, rotMatrix); 304 AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG |
220 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 305 AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS |
306 AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG
307 );
221 308
222 // Check control flags 309 // Check control flags
223 bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS); 310 /* not in use
224 bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); 311 bool heldForward = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS)) != 0);
225 bool heldLeft = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS); 312 bool heldBack = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG)) != 0);
226 bool heldRight = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG); 313 bool heldLeft = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS)) != 0);
314 bool heldRight = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG)) != 0);
315 */
227 bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; 316 bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
228 bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; 317 bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
229 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; 318 // bool heldUp = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS)) != 0);
230 bool heldDown = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG; 319 // excluded nudge up so it doesn't trigger jump state
320 bool heldUp = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_UP_POS)) != 0);
321 bool heldDown = ((controlFlags & (AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG)) != 0);
231 //bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY; 322 //bool flying = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) == AgentManager.ControlFlags.AGENT_CONTROL_FLY;
232 //bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK; 323 //bool mouselook = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) == AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK;
233 if (heldForward || heldBack || heldLeft || heldRight || heldUp || heldDown) 324
325 bool heldOnXY = ((controlFlags & ANYXYMASK) != 0);
326 if (heldOnXY || heldUp || heldDown)
234 { 327 {
235 heldTurnLeft = false; 328 heldTurnLeft = false;
236 heldTurnRight = false; 329 heldTurnRight = false;
237 } 330 }
238 331
239 // Direction in which the avatar is trying to move
240 Vector3 move = Vector3.Zero;
241 if (heldForward) { move.X += fwd.X; move.Y += fwd.Y; }
242 if (heldBack) { move.X -= fwd.X; move.Y -= fwd.Y; }
243 if (heldLeft) { move.X += left.X; move.Y += left.Y; }
244 if (heldRight) { move.X -= left.X; move.Y -= left.Y; }
245 if (heldUp) { move.Z += 1; }
246 if (heldDown) { move.Z -= 1; }
247
248 // Is the avatar trying to move?
249// bool moving = (move != Vector3.Zero);
250 #endregion Inputs 332 #endregion Inputs
251 333
334 // no physics actor case
335 if (actor == null)
336 {
337 // well what to do?
338
339 currentControlState = motionControlStates.onsurface;
340 if (heldOnXY)
341 return "WALK";
342
343 return "STAND";
344 }
345
252 #region Flying 346 #region Flying
253 347
254 if (actor != null && actor.Flying) 348 bool isColliding = actor.IsColliding;
349
350 if (actor.Flying)
255 { 351 {
256 m_animTickFall = 0; 352 m_animTickFall = 0;
257 m_animTickJump = 0; 353 m_animTickJump = 0;
258 m_jumping = false; 354 m_jumping = false;
259 Falling = false; 355 Falling = false;
260 m_jumpVelocity = 0f;
261 actor.Selected = false;
262 m_fallHeight = actor.Position.Z; // save latest flying height
263 356
264 if (move.X != 0f || move.Y != 0f) 357 currentControlState = motionControlStates.flying;
358
359 if (heldOnXY)
265 { 360 {
266 return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY"); 361 return (m_scenePresence.Scene.m_useFlySlow ? "FLYSLOW" : "FLY");
267 } 362 }
268 else if (move.Z > 0f) 363 else if (heldUp)
269 { 364 {
270 return "HOVER_UP"; 365 return "HOVER_UP";
271 } 366 }
272 else if (move.Z < 0f) 367 else if (heldDown)
273 { 368 {
274 if (actor != null && actor.IsColliding) 369 if (isColliding)
370 {
371 actor.Flying = false;
372 currentControlState = motionControlStates.landing;
373 m_animTickLand = Environment.TickCount;
275 return "LAND"; 374 return "LAND";
375 }
276 else 376 else
277 return "HOVER_DOWN"; 377 return "HOVER_DOWN";
278 } 378 }
@@ -281,128 +381,151 @@ namespace OpenSim.Region.Framework.Scenes.Animation
281 return "HOVER"; 381 return "HOVER";
282 } 382 }
283 } 383 }
384 else
385 {
386 if (isColliding && currentControlState == motionControlStates.flying)
387 {
388 currentControlState = motionControlStates.landing;
389 m_animTickLand = Environment.TickCount;
390 return "LAND";
391 }
392 }
284 393
285 #endregion Flying 394 #endregion Flying
286 395
287 #region Falling/Floating/Landing 396 #region Falling/Floating/Landing
288 397
289 if ((actor == null || !actor.IsColliding) && !m_jumping) 398 if (!isColliding && currentControlState != motionControlStates.jumping)
290 { 399 {
291 float fallElapsed = (float)(Environment.TickCount - m_animTickFall); 400 float fallVelocity = actor.Velocity.Z;
292 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
293 401
294 if (!m_jumping && (fallVelocity < -3.0f)) 402 // if stable on Hover assume falling
403 if(actor.PIDHoverActive && fallVelocity < 0.05f)
404 {
405 Falling = true;
406 currentControlState = motionControlStates.falling;
407 m_lastFallVelocity = fallVelocity;
408 return "FALLDOWN";
409 }
410
411 if (fallVelocity < -2.5f)
295 Falling = true; 412 Falling = true;
296 413
297 if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) 414 if (m_animTickFall == 0 || (fallVelocity >= -0.5f))
298 { 415 {
299 // not falling yet, or going up
300 // reset start of fall time
301 m_animTickFall = Environment.TickCount; 416 m_animTickFall = Environment.TickCount;
302 } 417 }
303 else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.WasFlying)) 418 else
304 { 419 {
305 // Falling long enough to trigger the animation 420 int fallElapsed = (Environment.TickCount - m_animTickFall);
306 return "FALLDOWN"; 421 if ((fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f))
422 {
423 currentControlState = motionControlStates.falling;
424 m_lastFallVelocity = fallVelocity;
425 // Falling long enough to trigger the animation
426 return "FALLDOWN";
427 }
307 } 428 }
308 429
309 // Check if the user has stopped walking just now 430 // Check if the user has stopped walking just now
310 if (CurrentMovementAnimation == "WALK" && (move == Vector3.Zero)) 431 if (CurrentMovementAnimation == "WALK" && !heldOnXY && !heldDown && !heldUp)
311 return "STAND"; 432 return "STAND";
312 433
313 return CurrentMovementAnimation; 434 return CurrentMovementAnimation;
314 } 435 }
315 436
316 #endregion Falling/Floating/Landing 437 m_animTickFall = 0;
317 438
439 #endregion Falling/Floating/Landing
318 440
319 #region Jumping // section added for jumping... 441 #region Jumping // section added for jumping...
320 442
321 int jumptime; 443 if (isColliding && heldUp && currentControlState != motionControlStates.jumping && !actor.PIDHoverActive)
322 jumptime = Environment.TickCount - m_animTickJump;
323
324 if ((move.Z > 0f) && (!m_jumping))
325 { 444 {
326 // Start jumping, prejump 445 // Start jumping, prejump
327 m_animTickFall = 0; 446 currentControlState = motionControlStates.jumping;
328 m_jumping = true; 447 m_jumping = true;
329 Falling = false; 448 Falling = false;
330 actor.Selected = true; // borrowed for jumping flag
331 m_animTickJump = Environment.TickCount; 449 m_animTickJump = Environment.TickCount;
332 m_jumpVelocity = 0.35f;
333 return "PREJUMP"; 450 return "PREJUMP";
334 } 451 }
335 452
336 if (m_jumping) 453 if (currentControlState == motionControlStates.jumping)
337 { 454 {
455 int jumptime = Environment.TickCount - m_animTickJump;
338 if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding) 456 if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding)
339 { 457 {
340 // end jumping 458 // end jumping
341 m_jumping = false; 459 m_jumping = false;
342 Falling = false; 460 Falling = false;
343 actor.Selected = false; // borrowed for jumping flag 461 actor.Selected = false; // borrowed for jumping flag
344 m_jumpVelocity = 0f; 462 m_animTickLand = Environment.TickCount;
345 m_animTickFall = Environment.TickCount; 463 currentControlState = motionControlStates.landing;
346 return "LAND"; 464 return "LAND";
347 } 465 }
348 else if (jumptime > JUMP_PERIOD) 466 else if (jumptime > JUMP_PERIOD)
349 { 467 {
350 // jump down 468 // jump down
351 m_jumpVelocity = 0f;
352 return "JUMP"; 469 return "JUMP";
353 } 470 }
354 else if (jumptime > PREJUMP_DELAY) 471 else if (jumptime > PREJUMP_DELAY)
355 { 472 {
356 // jump up 473 // jump up
357 m_jumping = true; 474 m_jumping = true;
358 m_jumpVelocity = 10f;
359 return "JUMP"; 475 return "JUMP";
360 } 476 }
477 return CurrentMovementAnimation;
361 } 478 }
362 479
363 #endregion Jumping 480 #endregion Jumping
364 481
365 #region Ground Movement 482 #region Ground Movement
366 483
367 if (CurrentMovementAnimation == "FALLDOWN") 484 if (currentControlState == motionControlStates.falling)
368 { 485 {
369 Falling = false; 486 Falling = false;
370 m_animTickFall = Environment.TickCount; 487 currentControlState = motionControlStates.landing;
488 m_animTickLand = Environment.TickCount;
371 // TODO: SOFT_LAND support 489 // TODO: SOFT_LAND support
372 float fallHeight = m_fallHeight - actor.Position.Z; 490 float fallVsq = m_lastFallVelocity * m_lastFallVelocity;
373 if (fallHeight > 15.0f) 491 if (fallVsq > 300f) // aprox 20*h
374 return "STANDUP"; 492 return "STANDUP";
375 else if (fallHeight > 8.0f) 493 else if (fallVsq > 160f)
376 return "SOFT_LAND"; 494 return "SOFT_LAND";
377 else 495 else
378 return "LAND"; 496 return "LAND";
379 } 497 }
380 else if ((CurrentMovementAnimation == "LAND") || (CurrentMovementAnimation == "SOFT_LAND") || (CurrentMovementAnimation == "STANDUP")) 498
499
500 if (currentControlState == motionControlStates.landing)
381 { 501 {
382 int landElapsed = Environment.TickCount - m_animTickFall; 502 Falling = false;
503 int landElapsed = Environment.TickCount - m_animTickLand;
383 int limit = 1000; 504 int limit = 1000;
384 if (CurrentMovementAnimation == "LAND") 505 if (CurrentMovementAnimation == "LAND")
385 limit = 350; 506 limit = 350;
386 // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client 507 // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client
387 508
388 if ((m_animTickFall != 0) && (landElapsed <= limit)) 509 if ((m_animTickLand != 0) && (landElapsed <= limit))
389 { 510 {
390 return CurrentMovementAnimation; 511 return CurrentMovementAnimation;
391 } 512 }
392 else 513 else
393 { 514 {
394 m_fallHeight = actor.Position.Z; // save latest flying height 515 currentControlState = motionControlStates.onsurface;
516 m_animTickLand = 0;
395 return "STAND"; 517 return "STAND";
396 } 518 }
397 } 519 }
398 520
399 // next section moved outside paren. and realigned for jumping 521 // next section moved outside paren. and realigned for jumping
400 if (move.X != 0f || move.Y != 0f) 522
523 if (heldOnXY)
401 { 524 {
402 m_fallHeight = actor.Position.Z; // save latest flying height 525 currentControlState = motionControlStates.onsurface;
403 Falling = false; 526 Falling = false;
404 // Walking / crouchwalking / running 527 // Walking / crouchwalking / running
405 if (move.Z < 0f) 528 if (heldDown)
406 { 529 {
407 return "CROUCHWALK"; 530 return "CROUCHWALK";
408 } 531 }
@@ -416,11 +539,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
416 return "WALK"; 539 return "WALK";
417 } 540 }
418 } 541 }
419 else if (!m_jumping) 542 else
420 { 543 {
544 currentControlState = motionControlStates.onsurface;
421 Falling = false; 545 Falling = false;
422 // Not walking 546 // Not walking
423 if (move.Z < 0) 547 if (heldDown)
424 return "CROUCH"; 548 return "CROUCH";
425 else if (heldTurnLeft) 549 else if (heldTurnLeft)
426 return "TURNLEFT"; 550 return "TURNLEFT";
@@ -431,8 +555,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation
431 } 555 }
432 #endregion Ground Movement 556 #endregion Ground Movement
433 557
434 Falling = false;
435
436 return CurrentMovementAnimation; 558 return CurrentMovementAnimation;
437 } 559 }
438 560
@@ -442,7 +564,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
442 /// <returns>'true' if the animation was changed</returns> 564 /// <returns>'true' if the animation was changed</returns>
443 public bool UpdateMovementAnimations() 565 public bool UpdateMovementAnimations()
444 { 566 {
445// m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Updating movement animations for {0}", m_scenePresence.Name); 567 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Updating movement animations for {0}", m_scenePresence.Name);
446 568
447 bool ret = false; 569 bool ret = false;
448 lock (m_animations) 570 lock (m_animations)
@@ -450,7 +572,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
450 string newMovementAnimation = DetermineMovementAnimation(); 572 string newMovementAnimation = DetermineMovementAnimation();
451 if (CurrentMovementAnimation != newMovementAnimation) 573 if (CurrentMovementAnimation != newMovementAnimation)
452 { 574 {
453 CurrentMovementAnimation = DetermineMovementAnimation(); 575 CurrentMovementAnimation = newMovementAnimation;
454 576
455// m_log.DebugFormat( 577// m_log.DebugFormat(
456// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()", 578// "[SCENE PRESENCE ANIMATOR]: Determined animation {0} for {1} in UpdateMovementAnimations()",
@@ -464,6 +586,24 @@ namespace OpenSim.Region.Framework.Scenes.Animation
464 return ret; 586 return ret;
465 } 587 }
466 588
589 public bool ForceUpdateMovementAnimations()
590 {
591 lock (m_animations)
592 {
593 CurrentMovementAnimation = DetermineMovementAnimation();
594 return TrySetMovementAnimation(CurrentMovementAnimation);
595 }
596 }
597
598 public bool SetMovementAnimations(string motionState)
599 {
600 lock (m_animations)
601 {
602 CurrentMovementAnimation = motionState;
603 return TrySetMovementAnimation(CurrentMovementAnimation);
604 }
605 }
606
467 public UUID[] GetAnimationArray() 607 public UUID[] GetAnimationArray()
468 { 608 {
469 UUID[] animIDs; 609 UUID[] animIDs;
@@ -472,19 +612,19 @@ namespace OpenSim.Region.Framework.Scenes.Animation
472 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); 612 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
473 return animIDs; 613 return animIDs;
474 } 614 }
475 615
476 public BinBVHAnimation GenerateRandomAnimation() 616 public BinBVHAnimation GenerateRandomAnimation()
477 { 617 {
478 int rnditerations = 3; 618 int rnditerations = 3;
479 BinBVHAnimation anim = new BinBVHAnimation(); 619 BinBVHAnimation anim = new BinBVHAnimation();
480 List<string> parts = new List<string>(); 620 List<string> parts = new List<string>();
481 parts.Add("mPelvis");parts.Add("mHead");parts.Add("mTorso"); 621 parts.Add("mPelvis"); parts.Add("mHead"); parts.Add("mTorso");
482 parts.Add("mHipLeft");parts.Add("mHipRight");parts.Add("mHipLeft");parts.Add("mKneeLeft"); 622 parts.Add("mHipLeft"); parts.Add("mHipRight"); parts.Add("mHipLeft"); parts.Add("mKneeLeft");
483 parts.Add("mKneeRight");parts.Add("mCollarLeft");parts.Add("mCollarRight");parts.Add("mNeck"); 623 parts.Add("mKneeRight"); parts.Add("mCollarLeft"); parts.Add("mCollarRight"); parts.Add("mNeck");
484 parts.Add("mElbowLeft");parts.Add("mElbowRight");parts.Add("mWristLeft");parts.Add("mWristRight"); 624 parts.Add("mElbowLeft"); parts.Add("mElbowRight"); parts.Add("mWristLeft"); parts.Add("mWristRight");
485 parts.Add("mShoulderLeft");parts.Add("mShoulderRight");parts.Add("mAnkleLeft");parts.Add("mAnkleRight"); 625 parts.Add("mShoulderLeft"); parts.Add("mShoulderRight"); parts.Add("mAnkleLeft"); parts.Add("mAnkleRight");
486 parts.Add("mEyeRight");parts.Add("mChest");parts.Add("mToeLeft");parts.Add("mToeRight"); 626 parts.Add("mEyeRight"); parts.Add("mChest"); parts.Add("mToeLeft"); parts.Add("mToeRight");
487 parts.Add("mFootLeft");parts.Add("mFootRight");parts.Add("mEyeLeft"); 627 parts.Add("mFootLeft"); parts.Add("mFootRight"); parts.Add("mEyeLeft");
488 anim.HandPose = 1; 628 anim.HandPose = 1;
489 anim.InPoint = 0; 629 anim.InPoint = 0;
490 anim.OutPoint = (rnditerations * .10f); 630 anim.OutPoint = (rnditerations * .10f);
@@ -508,12 +648,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation
508 for (int i = 0; i < rnditerations; i++) 648 for (int i = 0; i < rnditerations; i++)
509 { 649 {
510 anim.Joints[j].rotationkeys[i] = new binBVHJointKey(); 650 anim.Joints[j].rotationkeys[i] = new binBVHJointKey();
511 anim.Joints[j].rotationkeys[i].time = (i*.10f); 651 anim.Joints[j].rotationkeys[i].time = (i * .10f);
512 anim.Joints[j].rotationkeys[i].key_element.X = ((float) rnd.NextDouble()*2 - 1); 652 anim.Joints[j].rotationkeys[i].key_element.X = ((float)rnd.NextDouble() * 2 - 1);
513 anim.Joints[j].rotationkeys[i].key_element.Y = ((float) rnd.NextDouble()*2 - 1); 653 anim.Joints[j].rotationkeys[i].key_element.Y = ((float)rnd.NextDouble() * 2 - 1);
514 anim.Joints[j].rotationkeys[i].key_element.Z = ((float) rnd.NextDouble()*2 - 1); 654 anim.Joints[j].rotationkeys[i].key_element.Z = ((float)rnd.NextDouble() * 2 - 1);
515 anim.Joints[j].positionkeys[i] = new binBVHJointKey(); 655 anim.Joints[j].positionkeys[i] = new binBVHJointKey();
516 anim.Joints[j].positionkeys[i].time = (i*.10f); 656 anim.Joints[j].positionkeys[i].time = (i * .10f);
517 anim.Joints[j].positionkeys[i].key_element.X = 0; 657 anim.Joints[j].positionkeys[i].key_element.X = 0;
518 anim.Joints[j].positionkeys[i].key_element.Y = 0; 658 anim.Joints[j].positionkeys[i].key_element.Y = 0;
519 anim.Joints[j].positionkeys[i].key_element.Z = 0; 659 anim.Joints[j].positionkeys[i].key_element.Z = 0;
@@ -540,20 +680,17 @@ namespace OpenSim.Region.Framework.Scenes.Animation
540 /// <param name="objectIDs"></param> 680 /// <param name="objectIDs"></param>
541 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs) 681 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
542 { 682 {
543 if (m_scenePresence.IsChildAgent) 683 m_scenePresence.SendAnimPack(animations, seqs, objectIDs);
544 return; 684 }
545 685
546// m_log.DebugFormat( 686 public void GetArrays(out UUID[] animIDs, out int[] sequenceNums, out UUID[] objectIDs)
547// "[SCENE PRESENCE ANIMATOR]: Sending anim pack with animations '{0}', sequence '{1}', uuids '{2}'", 687 {
548// string.Join(",", Array.ConvertAll<UUID, string>(animations, a => a.ToString())), 688 animIDs = null;
549// string.Join(",", Array.ConvertAll<int, string>(seqs, s => s.ToString())), 689 sequenceNums = null;
550// string.Join(",", Array.ConvertAll<UUID, string>(objectIDs, o => o.ToString()))); 690 objectIDs = null;
551 691
552 m_scenePresence.Scene.ForEachClient( 692 if (m_animations != null)
553 delegate(IClientAPI client) 693 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
554 {
555 client.SendAnimations(animations, seqs, m_scenePresence.ControllingClient.AgentId, objectIDs);
556 });
557 } 694 }
558 695
559 public void SendAnimPackToClient(IClientAPI client) 696 public void SendAnimPackToClient(IClientAPI client)
@@ -575,7 +712,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
575 public void SendAnimPack() 712 public void SendAnimPack()
576 { 713 {
577 //m_log.Debug("Sending animation pack to all"); 714 //m_log.Debug("Sending animation pack to all");
578 715
579 if (m_scenePresence.IsChildAgent) 716 if (m_scenePresence.IsChildAgent)
580 return; 717 return;
581 718
@@ -585,7 +722,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation
585 722
586 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs); 723 m_animations.GetArrays(out animIDs, out sequenceNums, out objectIDs);
587 724
588 SendAnimPack(animIDs, sequenceNums, objectIDs); 725 // SendAnimPack(animIDs, sequenceNums, objectIDs);
726 m_scenePresence.SendAnimPack(animIDs, sequenceNums, objectIDs);
589 } 727 }
590 728
591 public string GetAnimName(UUID animId) 729 public string GetAnimName(UUID animId)
diff --git a/OpenSim/Region/Framework/Scenes/CollisionSounds.cs b/OpenSim/Region/Framework/Scenes/CollisionSounds.cs
new file mode 100644
index 0000000..075724e
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/CollisionSounds.cs
@@ -0,0 +1,304 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27// Ubit 2012
28
29using System;
30using System.Reflection;
31using System.Collections.Generic;
32using OpenMetaverse;
33using OpenSim.Framework;
34using log4net;
35
36namespace OpenSim.Region.Framework.Scenes
37{
38 public struct CollisionForSoundInfo
39 {
40 public uint colliderID;
41 public Vector3 position;
42 public float relativeVel;
43 }
44
45 public static class CollisionSounds
46 {
47 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48
49 private const int MaxMaterials = 7;
50 // part part
51
52 private static UUID snd_StoneStone = new UUID("be7295c0-a158-11e1-b3dd-0800200c9a66");
53 private static UUID snd_StoneMetal = new UUID("be7295c0-a158-11e1-b3dd-0800201c9a66");
54 private static UUID snd_StoneGlass = new UUID("be7295c0-a158-11e1-b3dd-0800202c9a66");
55 private static UUID snd_StoneWood = new UUID("be7295c0-a158-11e1-b3dd-0800203c9a66");
56 private static UUID snd_StoneFlesh = new UUID("be7295c0-a158-11e1-b3dd-0800204c9a66");
57 private static UUID snd_StonePlastic = new UUID("be7295c0-a158-11e1-b3dd-0800205c9a66");
58 private static UUID snd_StoneRubber = new UUID("be7295c0-a158-11e1-b3dd-0800206c9a66");
59
60 private static UUID snd_MetalMetal = new UUID("be7295c0-a158-11e1-b3dd-0801201c9a66");
61 private static UUID snd_MetalGlass = new UUID("be7295c0-a158-11e1-b3dd-0801202c9a66");
62 private static UUID snd_MetalWood = new UUID("be7295c0-a158-11e1-b3dd-0801203c9a66");
63 private static UUID snd_MetalFlesh = new UUID("be7295c0-a158-11e1-b3dd-0801204c9a66");
64 private static UUID snd_MetalPlastic = new UUID("be7295c0-a158-11e1-b3dd-0801205c9a66");
65 private static UUID snd_MetalRubber = new UUID("be7295c0-a158-11e1-b3dd-0801206c9a66");
66
67 private static UUID snd_GlassGlass = new UUID("be7295c0-a158-11e1-b3dd-0802202c9a66");
68 private static UUID snd_GlassWood = new UUID("be7295c0-a158-11e1-b3dd-0802203c9a66");
69 private static UUID snd_GlassFlesh = new UUID("be7295c0-a158-11e1-b3dd-0802204c9a66");
70 private static UUID snd_GlassPlastic = new UUID("be7295c0-a158-11e1-b3dd-0802205c9a66");
71 private static UUID snd_GlassRubber = new UUID("be7295c0-a158-11e1-b3dd-0802206c9a66");
72
73 private static UUID snd_WoodWood = new UUID("be7295c0-a158-11e1-b3dd-0803203c9a66");
74 private static UUID snd_WoodFlesh = new UUID("be7295c0-a158-11e1-b3dd-0803204c9a66");
75 private static UUID snd_WoodPlastic = new UUID("be7295c0-a158-11e1-b3dd-0803205c9a66");
76 private static UUID snd_WoodRubber = new UUID("be7295c0-a158-11e1-b3dd-0803206c9a66");
77
78 private static UUID snd_FleshFlesh = new UUID("be7295c0-a158-11e1-b3dd-0804204c9a66");
79 private static UUID snd_FleshPlastic = new UUID("be7295c0-a158-11e1-b3dd-0804205c9a66");
80 private static UUID snd_FleshRubber = new UUID("be7295c0-a158-11e1-b3dd-0804206c9a66");
81
82 private static UUID snd_PlasticPlastic = new UUID("be7295c0-a158-11e1-b3dd-0805205c9a66");
83 private static UUID snd_PlasticRubber = new UUID("be7295c0-a158-11e1-b3dd-0805206c9a66");
84
85 private static UUID snd_RubberRubber = new UUID("be7295c0-a158-11e1-b3dd-0806206c9a66");
86
87 // terrain part
88 private static UUID snd_TerrainStone = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
89 private static UUID snd_TerrainMetal = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
90 private static UUID snd_TerrainGlass = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
91 private static UUID snd_TerrainWood = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
92 private static UUID snd_TerrainFlesh = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
93 private static UUID snd_TerrainPlastic = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
94 private static UUID snd_TerrainRubber = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
95
96 public static UUID[] m_TerrainPart = {
97 snd_TerrainStone,
98 snd_TerrainMetal,
99 snd_TerrainGlass,
100 snd_TerrainWood,
101 snd_TerrainFlesh,
102 snd_TerrainPlastic,
103 snd_TerrainRubber
104 };
105
106 // simetric sounds
107 public static UUID[] m_PartPart = {
108 snd_StoneStone, snd_StoneMetal, snd_StoneGlass, snd_StoneWood, snd_StoneFlesh, snd_StonePlastic, snd_StoneRubber,
109 snd_StoneMetal, snd_MetalMetal, snd_MetalGlass, snd_MetalWood, snd_MetalFlesh, snd_MetalPlastic, snd_MetalRubber,
110 snd_StoneGlass, snd_MetalGlass, snd_GlassGlass, snd_GlassWood, snd_GlassFlesh, snd_GlassPlastic, snd_GlassRubber,
111 snd_StoneWood, snd_MetalWood, snd_GlassWood, snd_WoodWood, snd_WoodFlesh, snd_WoodPlastic, snd_WoodRubber,
112 snd_StoneFlesh, snd_MetalFlesh, snd_GlassFlesh, snd_WoodFlesh, snd_FleshFlesh, snd_FleshPlastic, snd_FleshRubber,
113 snd_StonePlastic, snd_MetalPlastic, snd_GlassPlastic, snd_WoodPlastic, snd_FleshPlastic, snd_PlasticPlastic, snd_PlasticRubber,
114 snd_StoneRubber, snd_MetalRubber, snd_GlassRubber, snd_WoodRubber, snd_FleshRubber, snd_PlasticRubber, snd_RubberRubber
115 };
116
117 public static void PartCollisionSound(SceneObjectPart part, List<CollisionForSoundInfo> collidersinfolist)
118 {
119 if (collidersinfolist.Count == 0 || part == null)
120 return;
121
122 if (part.VolumeDetectActive || (part.Flags & PrimFlags.Physics) == 0)
123 return;
124
125 if (part.ParentGroup == null)
126 return;
127
128 if (part.CollisionSoundType < 0)
129 return;
130
131 float volume = 0.0f;
132 bool HaveSound = false;
133
134 UUID soundID = part.CollisionSound;
135
136 if (part.CollisionSoundType > 0)
137 {
138 // soundID = part.CollisionSound;
139 volume = part.CollisionSoundVolume;
140 if (volume == 0.0f)
141 return;
142 HaveSound = true;
143 }
144
145 bool doneownsound = false;
146
147 int thisMaterial = (int)part.Material;
148 if (thisMaterial >= MaxMaterials)
149 thisMaterial = 3;
150 int thisMatScaled = thisMaterial * MaxMaterials;
151
152 CollisionForSoundInfo colInfo;
153 uint id;
154
155 for(int i = 0; i< collidersinfolist.Count; i++)
156 {
157 colInfo = collidersinfolist[i];
158
159 id = colInfo.colliderID;
160 if (id == 0) // terrain collision
161 {
162 if (!doneownsound)
163 {
164 if (!HaveSound)
165 {
166 volume = Math.Abs(colInfo.relativeVel);
167 if (volume < 0.2f)
168 continue;
169
170 volume *= volume * .0625f; // 4m/s == full volume
171 if (volume > 1.0f)
172 volume = 1.0f;
173
174 soundID = m_TerrainPart[thisMaterial];
175 }
176 part.SendCollisionSound(soundID, volume, colInfo.position);
177 doneownsound = true;
178 }
179 continue;
180 }
181
182 SceneObjectPart otherPart = part.ParentGroup.Scene.GetSceneObjectPart(id);
183 if (otherPart != null)
184 {
185 if (otherPart.CollisionSoundType < 0 || otherPart.VolumeDetectActive)
186 continue;
187
188 if (!HaveSound)
189 {
190 if (otherPart.CollisionSoundType > 0)
191 {
192 soundID = otherPart.CollisionSound;
193 volume = otherPart.CollisionSoundVolume;
194 if (volume == 0.0f)
195 continue;
196 }
197 else
198 {
199 volume = Math.Abs(colInfo.relativeVel);
200 if (volume < 0.2f)
201 continue;
202
203 volume *= volume * .0625f; // 4m/s == full volume
204 if (volume > 1.0f)
205 volume = 1.0f;
206
207 int otherMaterial = (int)otherPart.Material;
208 if (otherMaterial >= MaxMaterials)
209 otherMaterial = 3;
210
211 soundID = m_PartPart[thisMatScaled + otherMaterial];
212 }
213 }
214
215 if (doneownsound)
216 otherPart.SendCollisionSound(soundID, volume, colInfo.position);
217 else
218 {
219 part.SendCollisionSound(soundID, volume, colInfo.position);
220 doneownsound = true;
221 }
222 }
223 }
224 }
225
226 public static void AvatarCollisionSound(ScenePresence av, List<CollisionForSoundInfo> collidersinfolist)
227 {
228 if (collidersinfolist.Count == 0 || av == null)
229 return;
230
231 UUID soundID;
232 int otherMaterial;
233
234 int thisMaterial = 4; // flesh
235
236 int thisMatScaled = thisMaterial * MaxMaterials;
237
238 // bool doneownsound = false;
239
240 CollisionForSoundInfo colInfo;
241 uint id;
242 float volume;
243
244 for(int i = 0; i< collidersinfolist.Count; i++)
245 {
246 colInfo = collidersinfolist[i];
247
248 id = colInfo.colliderID;
249
250 if (id == 0) // no terrain collision sounds for now
251 {
252 continue;
253// volume = Math.Abs(colInfo.relativeVel);
254// if (volume < 0.2f)
255// continue;
256
257 }
258
259 SceneObjectPart otherPart = av.Scene.GetSceneObjectPart(id);
260 if (otherPart != null)
261 {
262 if (otherPart.CollisionSoundType < 0)
263 continue;
264 if (otherPart.CollisionSoundType > 0 && otherPart.CollisionSoundVolume > 0f)
265 otherPart.SendCollisionSound(otherPart.CollisionSound, otherPart.CollisionSoundVolume, colInfo.position);
266 else
267 {
268 volume = Math.Abs(colInfo.relativeVel);
269 // Most noral collisions (running into walls, stairs)
270 // should never be heard.
271 if (volume < 3.2f)
272 continue;
273// m_log.DebugFormat("Collision speed was {0}", volume);
274
275 // Cap to 0.2 times volume because climbing stairs should not be noisy
276 // Also changed scaling
277 volume *= volume * .0125f; // 4m/s == volume 0.2
278 if (volume > 0.2f)
279 volume = 0.2f;
280 otherMaterial = (int)otherPart.Material;
281 if (otherMaterial >= MaxMaterials)
282 otherMaterial = 3;
283
284 soundID = m_PartPart[thisMatScaled + otherMaterial];
285 otherPart.SendCollisionSound(soundID, volume, colInfo.position);
286 }
287 continue;
288 }
289/*
290 else if (!doneownsound)
291 {
292 ScenePresence otherav = av.Scene.GetScenePresence(Id);
293 if (otherav != null && (!otherav.IsChildAgent))
294 {
295 soundID = snd_FleshFlesh;
296 av.SendCollisionSound(soundID, 1.0);
297 doneownsound = true;
298 }
299 }
300 */
301 }
302 }
303 }
304}
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 97b9482..0a6bca4 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -80,6 +80,7 @@ namespace OpenSim.Region.Framework.Scenes
80 public event OnTerrainTaintedDelegate OnTerrainTainted; 80 public event OnTerrainTaintedDelegate OnTerrainTainted;
81 81
82 public delegate void OnTerrainTickDelegate(); 82 public delegate void OnTerrainTickDelegate();
83 public delegate void OnTerrainCheckUpdatesDelegate();
83 84
84 /// <summary> 85 /// <summary>
85 /// Triggered if the terrain has been edited 86 /// Triggered if the terrain has been edited
@@ -89,6 +90,11 @@ namespace OpenSim.Region.Framework.Scenes
89 /// but is used by core solely to update the physics engine. 90 /// but is used by core solely to update the physics engine.
90 /// </remarks> 91 /// </remarks>
91 public event OnTerrainTickDelegate OnTerrainTick; 92 public event OnTerrainTickDelegate OnTerrainTick;
93 public event OnTerrainCheckUpdatesDelegate OnTerrainCheckUpdates;
94
95 public delegate void OnTerrainUpdateDelegate();
96
97 public event OnTerrainUpdateDelegate OnTerrainUpdate;
92 98
93 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 99 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
94 100
@@ -339,8 +345,6 @@ namespace OpenSim.Region.Framework.Scenes
339 /// in <see cref="Scene.SetScriptRunning"/> 345 /// in <see cref="Scene.SetScriptRunning"/>
340 /// via <see cref="OpenSim.Framework.IClientAPI.OnSetScriptRunning"/>, 346 /// via <see cref="OpenSim.Framework.IClientAPI.OnSetScriptRunning"/>,
341 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.HandleSetScriptRunning"/> 347 /// via <see cref="OpenSim.Region.ClientStack.LindenUDP.HandleSetScriptRunning"/>
342 /// XXX: This is only triggered when it is the client that starts the script, not in other situations where
343 /// a script is started, unlike OnStopScript!
344 /// </remarks> 348 /// </remarks>
345 public event StartScript OnStartScript; 349 public event StartScript OnStartScript;
346 350
@@ -354,7 +358,6 @@ namespace OpenSim.Region.Framework.Scenes
354 /// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/>, 358 /// in <see cref="SceneObjectPartInventory.CreateScriptInstance"/>,
355 /// <see cref="SceneObjectPartInventory.StopScriptInstance"/>, 359 /// <see cref="SceneObjectPartInventory.StopScriptInstance"/>,
356 /// <see cref="Scene.SetScriptRunning"/> 360 /// <see cref="Scene.SetScriptRunning"/>
357 /// XXX: This is triggered when a sciprt is stopped for any reason, unlike OnStartScript!
358 /// </remarks> 361 /// </remarks>
359 public event StopScript OnStopScript; 362 public event StopScript OnStopScript;
360 363
@@ -858,6 +861,10 @@ namespace OpenSim.Region.Framework.Scenes
858 public event ParcelPrimCountTainted OnParcelPrimCountTainted; 861 public event ParcelPrimCountTainted OnParcelPrimCountTainted;
859 public event GetScriptRunning OnGetScriptRunning; 862 public event GetScriptRunning OnGetScriptRunning;
860 863
864 public delegate void ThrottleUpdate(ScenePresence scenePresence);
865
866 public event ThrottleUpdate OnThrottleUpdate;
867
861 /// <summary> 868 /// <summary>
862 /// RegisterCapsEvent is called by Scene after the Caps object 869 /// RegisterCapsEvent is called by Scene after the Caps object
863 /// has been instantiated and before it is return to the 870 /// has been instantiated and before it is return to the
@@ -1377,7 +1384,9 @@ namespace OpenSim.Region.Framework.Scenes
1377 { 1384 {
1378 try 1385 try
1379 { 1386 {
1387// m_log.ErrorFormat("[EVENT MANAGER]: OnRemovePresenceDelegate: {0}",d.Target.ToString());
1380 d(agentId); 1388 d(agentId);
1389// m_log.ErrorFormat("[EVENT MANAGER]: OnRemovePresenceDelegate done ");
1381 } 1390 }
1382 catch (Exception e) 1391 catch (Exception e)
1383 { 1392 {
@@ -1451,6 +1460,26 @@ namespace OpenSim.Region.Framework.Scenes
1451 } 1460 }
1452 } 1461 }
1453 } 1462 }
1463 public void TriggerTerrainUpdate()
1464 {
1465 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
1466 if (handlerTerrainUpdate != null)
1467 {
1468 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
1469 {
1470 try
1471 {
1472 d();
1473 }
1474 catch (Exception e)
1475 {
1476 m_log.ErrorFormat(
1477 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
1478 e.Message, e.StackTrace);
1479 }
1480 }
1481 }
1482 }
1454 1483
1455 public void TriggerTerrainTick() 1484 public void TriggerTerrainTick()
1456 { 1485 {
@@ -1473,6 +1502,27 @@ namespace OpenSim.Region.Framework.Scenes
1473 } 1502 }
1474 } 1503 }
1475 1504
1505 public void TriggerTerrainCheckUpdates()
1506 {
1507 OnTerrainCheckUpdatesDelegate TerrainCheckUpdates = OnTerrainCheckUpdates;
1508 if (TerrainCheckUpdates != null)
1509 {
1510 foreach (OnTerrainCheckUpdatesDelegate d in TerrainCheckUpdates.GetInvocationList())
1511 {
1512 try
1513 {
1514 d();
1515 }
1516 catch (Exception e)
1517 {
1518 m_log.ErrorFormat(
1519 "[EVENT MANAGER]: Delegate for TerrainCheckUpdates failed - continuing. {0} {1}",
1520 e.Message, e.StackTrace);
1521 }
1522 }
1523 }
1524 }
1525
1476 public void TriggerTerrainTainted() 1526 public void TriggerTerrainTainted()
1477 { 1527 {
1478 OnTerrainTaintedDelegate handlerTerrainTainted = OnTerrainTainted; 1528 OnTerrainTaintedDelegate handlerTerrainTainted = OnTerrainTainted;
@@ -1808,6 +1858,7 @@ namespace OpenSim.Region.Framework.Scenes
1808 m_log.ErrorFormat( 1858 m_log.ErrorFormat(
1809 "[EVENT MANAGER]: Delegate for TriggerRemoveScript failed - continuing. {0} {1}", 1859 "[EVENT MANAGER]: Delegate for TriggerRemoveScript failed - continuing. {0} {1}",
1810 e.Message, e.StackTrace); 1860 e.Message, e.StackTrace);
1861 m_log.ErrorFormat(Environment.StackTrace);
1811 } 1862 }
1812 } 1863 }
1813 } 1864 }
@@ -2073,7 +2124,10 @@ namespace OpenSim.Region.Framework.Scenes
2073 { 2124 {
2074 try 2125 try
2075 { 2126 {
2127// m_log.ErrorFormat("[EVENT MANAGER]: TriggerClientClosed: {0}", d.Target.ToString());
2076 d(ClientID, scene); 2128 d(ClientID, scene);
2129// m_log.ErrorFormat("[EVENT MANAGER]: TriggerClientClosed done ");
2130
2077 } 2131 }
2078 catch (Exception e) 2132 catch (Exception e)
2079 { 2133 {
@@ -3107,6 +3161,7 @@ namespace OpenSim.Region.Framework.Scenes
3107 { 3161 {
3108 foreach (Action<Scene> d in handler.GetInvocationList()) 3162 foreach (Action<Scene> d in handler.GetInvocationList())
3109 { 3163 {
3164 m_log.InfoFormat("[EVENT MANAGER]: TriggerSceneShuttingDown invoque {0}", d.Method.Name.ToString());
3110 try 3165 try
3111 { 3166 {
3112 d(s); 3167 d(s);
@@ -3119,6 +3174,7 @@ namespace OpenSim.Region.Framework.Scenes
3119 } 3174 }
3120 } 3175 }
3121 } 3176 }
3177 m_log.Info("[EVENT MANAGER]: TriggerSceneShuttingDown done");
3122 } 3178 }
3123 3179
3124 public void TriggerOnRegionStarted(Scene scene) 3180 public void TriggerOnRegionStarted(Scene scene)
@@ -3310,6 +3366,15 @@ namespace OpenSim.Region.Framework.Scenes
3310 } 3366 }
3311 } 3367 }
3312 3368
3369 public void TriggerThrottleUpdate(ScenePresence scenePresence)
3370 {
3371 ThrottleUpdate handler = OnThrottleUpdate;
3372 if (handler != null)
3373 {
3374 handler(scenePresence);
3375 }
3376 }
3377
3313// public void TriggerGatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids) 3378// public void TriggerGatherUuids(SceneObjectPart sop, IDictionary<UUID, AssetType> assetUuids)
3314// { 3379// {
3315// GatherUuids handler = OnGatherUuids; 3380// GatherUuids handler = OnGatherUuids;
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index bbf3b51..cdd8d2d 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -292,14 +292,17 @@ namespace OpenSim.Region.Framework.Scenes
292 292
293 private void StartTimer() 293 private void StartTimer()
294 { 294 {
295 KeyframeTimer.Add(this); 295 lock (m_frames)
296 m_timerStopped = false; 296 {
297 KeyframeTimer.Add(this);
298 m_timerStopped = false;
299 }
297 } 300 }
298 301
299 private void StopTimer() 302 private void StopTimer()
300 { 303 {
301 m_timerStopped = true; 304 lock (m_frames)
302 KeyframeTimer.Remove(this); 305 m_timerStopped = true;
303 } 306 }
304 307
305 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) 308 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
@@ -348,24 +351,26 @@ namespace OpenSim.Region.Framework.Scenes
348 m_group = grp; 351 m_group = grp;
349 m_scene = grp.Scene; 352 m_scene = grp.Scene;
350 353
351 Vector3 grppos = grp.AbsolutePosition;
352 Vector3 offset = grppos - m_serializedPosition;
353 // avoid doing it more than once
354 // current this will happen dragging a prim to other region
355 m_serializedPosition = grppos;
356 354
357 m_basePosition += offset; 355 lock (m_frames)
358 m_nextPosition += offset;
359
360 m_currentFrame.StartPosition += offset;
361 m_currentFrame.Position += offset;
362
363 for (int i = 0; i < m_frames.Count; i++)
364 { 356 {
365 Keyframe k = m_frames[i]; 357 Vector3 grppos = grp.AbsolutePosition;
366 k.StartPosition += offset; 358 Vector3 offset = grppos - m_serializedPosition;
367 k.Position += offset; 359 // avoid doing it more than once
368 m_frames[i]=k; 360 // current this will happen draging a prim to other region
361 m_serializedPosition = grppos;
362
363 m_basePosition += offset;
364 m_currentFrame.Position += offset;
365
366 m_nextPosition += offset;
367
368 for (int i = 0; i < m_frames.Count; i++)
369 {
370 Keyframe k = m_frames[i];
371 k.Position += offset;
372 m_frames[i] = k;
373 }
369 } 374 }
370 375
371 if (m_running) 376 if (m_running)
@@ -410,25 +415,28 @@ namespace OpenSim.Region.Framework.Scenes
410 m_keyframes.CopyTo(newmotion.m_keyframes, 0); 415 m_keyframes.CopyTo(newmotion.m_keyframes, 0);
411 } 416 }
412 417
413 newmotion.m_frames = new List<Keyframe>(m_frames); 418 lock (m_frames)
419 {
420 newmotion.m_frames = new List<Keyframe>(m_frames);
414 421
415 newmotion.m_basePosition = m_basePosition; 422 newmotion.m_basePosition = m_basePosition;
416 newmotion.m_baseRotation = m_baseRotation; 423 newmotion.m_baseRotation = m_baseRotation;
417 424
418 if (m_selected) 425 if (m_selected)
419 newmotion.m_serializedPosition = m_serializedPosition;
420 else
421 {
422 if (m_group != null)
423 newmotion.m_serializedPosition = m_group.AbsolutePosition;
424 else
425 newmotion.m_serializedPosition = m_serializedPosition; 426 newmotion.m_serializedPosition = m_serializedPosition;
426 } 427 else
428 {
429 if (m_group != null)
430 newmotion.m_serializedPosition = m_group.AbsolutePosition;
431 else
432 newmotion.m_serializedPosition = m_serializedPosition;
433 }
427 434
428 newmotion.m_currentFrame = m_currentFrame; 435 newmotion.m_currentFrame = m_currentFrame;
429 436
430 newmotion.m_iterations = m_iterations; 437 newmotion.m_iterations = m_iterations;
431 newmotion.m_running = m_running; 438 newmotion.m_running = m_running;
439 }
432 440
433 if (m_running && !m_waitingCrossing) 441 if (m_running && !m_waitingCrossing)
434 StartTimer(); 442 StartTimer();
@@ -458,19 +466,18 @@ namespace OpenSim.Region.Framework.Scenes
458 } 466 }
459 else 467 else
460 { 468 {
461 m_running = false;
462 StopTimer(); 469 StopTimer();
470 m_running = false;
463 } 471 }
464 } 472 }
465 473
466 public void Stop() 474 public void Stop()
467 { 475 {
476 StopTimer();
468 m_running = false; 477 m_running = false;
469 m_isCrossing = false; 478 m_isCrossing = false;
470 m_waitingCrossing = false; 479 m_waitingCrossing = false;
471 480
472 StopTimer();
473
474 m_basePosition = m_group.AbsolutePosition; 481 m_basePosition = m_group.AbsolutePosition;
475 m_baseRotation = m_group.GroupRotation; 482 m_baseRotation = m_group.GroupRotation;
476 483
@@ -483,14 +490,34 @@ namespace OpenSim.Region.Framework.Scenes
483 490
484 public void Pause() 491 public void Pause()
485 { 492 {
486 m_running = false;
487 StopTimer(); 493 StopTimer();
494 m_running = false;
488 495
489 m_group.RootPart.Velocity = Vector3.Zero; 496 m_group.RootPart.Velocity = Vector3.Zero;
490 m_group.RootPart.AngularVelocity = Vector3.Zero; 497 m_group.RootPart.AngularVelocity = Vector3.Zero;
491 m_group.SendGroupRootTerseUpdate(); 498 m_group.SendGroupRootTerseUpdate();
492// m_group.RootPart.ScheduleTerseUpdate(); 499// m_group.RootPart.ScheduleTerseUpdate();
500 }
493 501
502 public void Suspend()
503 {
504 lock (m_frames)
505 {
506 if (m_timerStopped)
507 return;
508 m_timerStopped = true;
509 }
510 }
511
512 public void Resume()
513 {
514 lock (m_frames)
515 {
516 if (!m_timerStopped)
517 return;
518 if (m_running && !m_waitingCrossing)
519 StartTimer();
520 }
494 } 521 }
495 522
496 private void GetNextList() 523 private void GetNextList()
@@ -581,6 +608,7 @@ namespace OpenSim.Region.Framework.Scenes
581 608
582 pos = (Vector3)k.Position; 609 pos = (Vector3)k.Position;
583 rot = (Quaternion)k.Rotation; 610 rot = (Quaternion)k.Rotation;
611
584 } 612 }
585 613
586 m_basePosition = pos; 614 m_basePosition = pos;
@@ -592,15 +620,41 @@ namespace OpenSim.Region.Framework.Scenes
592 620
593 public void OnTimer(double tickDuration) 621 public void OnTimer(double tickDuration)
594 { 622 {
623 if (!Monitor.TryEnter(m_frames))
624 return;
625 if (m_timerStopped)
626 KeyframeTimer.Remove(this);
627 else
628 DoOnTimer(tickDuration);
629 Monitor.Exit(m_frames);
630 }
631
632 private void Done()
633 {
634 KeyframeTimer.Remove(this);
635 m_timerStopped = true;
636 m_running = false;
637 m_isCrossing = false;
638 m_waitingCrossing = false;
639
640 m_basePosition = m_group.AbsolutePosition;
641 m_baseRotation = m_group.GroupRotation;
642
643 m_group.RootPart.Velocity = Vector3.Zero;
644 m_group.RootPart.AngularVelocity = Vector3.Zero;
645 m_group.SendGroupRootTerseUpdate();
646 // m_group.RootPart.ScheduleTerseUpdate();
647 m_frames.Clear();
648 }
649
650 private void DoOnTimer(double tickDuration)
651 {
595 if (m_skipLoops > 0) 652 if (m_skipLoops > 0)
596 { 653 {
597 m_skipLoops--; 654 m_skipLoops--;
598 return; 655 return;
599 } 656 }
600 657
601 if (m_timerStopped) // trap events still in air even after a timer.stop
602 return;
603
604 if (m_group == null) 658 if (m_group == null)
605 return; 659 return;
606 660
@@ -612,7 +666,6 @@ namespace OpenSim.Region.Framework.Scenes
612 { 666 {
613 m_group.RootPart.Velocity = Vector3.Zero; 667 m_group.RootPart.Velocity = Vector3.Zero;
614 m_group.SendGroupRootTerseUpdate(); 668 m_group.SendGroupRootTerseUpdate();
615
616 } 669 }
617 return; 670 return;
618 } 671 }
@@ -635,32 +688,22 @@ namespace OpenSim.Region.Framework.Scenes
635 688
636 if (m_frames.Count == 0) 689 if (m_frames.Count == 0)
637 { 690 {
638 if (!m_running) return; 691 lock (m_frames)
639
640 GetNextList();
641
642 if (m_frames.Count == 0)
643 { 692 {
644 Stop(); 693 GetNextList();
645// Scene scene = m_group.Scene;
646//
647// IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>();
648// foreach (IScriptModule m in scriptModules)
649// {
650// if (m == null)
651// continue;
652// m.PostObjectEvent(m_group.RootPart.UUID, "moving_end", new object[0]);
653// }
654
655 m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
656
657 return;
658 }
659 694
660 m_currentFrame = m_frames[0]; 695 if (m_frames.Count == 0)
661 m_currentFrame.TimeMS += (int)tickDuration; 696 {
697 Done();
698 m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId);
699 return;
700 }
662 701
702 m_currentFrame = m_frames[0];
703 m_currentFrame.TimeMS += (int)tickDuration;
704 }
663 //force a update on a keyframe transition 705 //force a update on a keyframe transition
706 m_nextPosition = m_group.AbsolutePosition;
664 update = true; 707 update = true;
665 } 708 }
666 709
@@ -681,9 +724,13 @@ namespace OpenSim.Region.Framework.Scenes
681 // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); 724 // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
682 725
683 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; 726 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation;
684 m_frames.RemoveAt(0); 727
685 if (m_frames.Count > 0) 728 lock (m_frames)
686 m_currentFrame = m_frames[0]; 729 {
730 m_frames.RemoveAt(0);
731 if (m_frames.Count > 0)
732 m_currentFrame = m_frames[0];
733 }
687 734
688 update = true; 735 update = true;
689 } 736 }
@@ -692,17 +739,14 @@ namespace OpenSim.Region.Framework.Scenes
692 float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; 739 float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
693 bool lastStep = m_currentFrame.TimeMS <= tickDuration; 740 bool lastStep = m_currentFrame.TimeMS <= tickDuration;
694 741
695 Vector3 positionThisStep = m_currentFrame.StartPosition + (m_currentFrame.Position.Value - m_currentFrame.StartPosition) * completed; 742 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
696 Vector3 motionThisStep = positionThisStep - m_group.AbsolutePosition; 743 Vector3 motionThisFrame = v / (float)remainingSteps;
744 v = v * 1000 / m_currentFrame.TimeMS;
697 745
698 float mag = Vector3.Mag(motionThisStep); 746 m_nextPosition = m_group.AbsolutePosition + motionThisFrame;
699 747
700 if ((mag >= 0.02f) || lastStep) 748 if (Vector3.Mag(motionThisFrame) >= 0.05f)
701 {
702 m_nextPosition = m_group.AbsolutePosition + motionThisStep;
703 m_group.AbsolutePosition = m_nextPosition;
704 update = true; 749 update = true;
705 }
706 750
707 //int totalSteps = m_currentFrame.TimeTotal / (int)tickDuration; 751 //int totalSteps = m_currentFrame.TimeTotal / (int)tickDuration;
708 //m_log.DebugFormat("KeyframeMotion.OnTimer: step {0}/{1}, curPosition={2}, finalPosition={3}, motionThisStep={4} (scene {5})", 752 //m_log.DebugFormat("KeyframeMotion.OnTimer: step {0}/{1}, curPosition={2}, finalPosition={3}, motionThisStep={4} (scene {5})",
@@ -714,43 +758,41 @@ namespace OpenSim.Region.Framework.Scenes
714 758
715 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed); 759 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed);
716 step.Normalize(); 760 step.Normalize();
717/* use simpler change detection 761 /* use simpler change detection
718* float angle = 0; 762 * float angle = 0;
719 763
720 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; 764 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
721 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; 765 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
722 float aa_bb = aa * bb; 766 float aa_bb = aa * bb;
723 767
724 if (aa_bb == 0) 768 if (aa_bb == 0)
725 { 769 {
726 angle = 0; 770 angle = 0;
727 } 771 }
728 else 772 else
729 { 773 {
730 float ab = current.X * step.X + 774 float ab = current.X * step.X +
731 current.Y * step.Y + 775 current.Y * step.Y +
732 current.Z * step.Z + 776 current.Z * step.Z +
733 current.W * step.W; 777 current.W * step.W;
734 float q = (ab * ab) / aa_bb; 778 float q = (ab * ab) / aa_bb;
735 779
736 if (q > 1.0f) 780 if (q > 1.0f)
737 { 781 {
738 angle = 0; 782 angle = 0;
739 } 783 }
740 else 784 else
741 { 785 {
742 angle = (float)Math.Acos(2 * q - 1); 786 angle = (float)Math.Acos(2 * q - 1);
743 } 787 }
744 } 788 }
745 789
746 if (angle > 0.01f) 790 if (angle > 0.01f)
747*/ 791 */
748 if(Math.Abs(step.X - current.X) > 0.001f 792 if (Math.Abs(step.X - current.X) > 0.001f
749 || Math.Abs(step.Y - current.Y) > 0.001f 793 || Math.Abs(step.Y - current.Y) > 0.001f
750 || Math.Abs(step.Z - current.Z) > 0.001f 794 || Math.Abs(step.Z - current.Z) > 0.001f)
751 || lastStep) 795 // assuming w is a dependente var
752 // assuming w is a dependente var
753
754 { 796 {
755// m_group.UpdateGroupRotationR(step); 797// m_group.UpdateGroupRotationR(step);
756 m_group.RootPart.RotationOffset = step; 798 m_group.RootPart.RotationOffset = step;
@@ -763,25 +805,31 @@ namespace OpenSim.Region.Framework.Scenes
763 805
764 if (update) 806 if (update)
765 { 807 {
808 m_group.AbsolutePosition = m_nextPosition;
766 m_group.SendGroupRootTerseUpdate(); 809 m_group.SendGroupRootTerseUpdate();
767 } 810 }
768 } 811 }
769 812
770 public Byte[] Serialize() 813 public Byte[] Serialize()
771 { 814 {
815 bool timerWasStopped;
816 lock (m_frames)
817 {
818 timerWasStopped = m_timerStopped;
819 }
772 StopTimer(); 820 StopTimer();
773 821
774 SceneObjectGroup tmp = m_group; 822 SceneObjectGroup tmp = m_group;
775 m_group = null; 823 m_group = null;
776 if (!m_selected && tmp != null) 824
777 m_serializedPosition = tmp.AbsolutePosition;
778
779 using (MemoryStream ms = new MemoryStream()) 825 using (MemoryStream ms = new MemoryStream())
780 { 826 {
781 BinaryFormatter fmt = new BinaryFormatter(); 827 BinaryFormatter fmt = new BinaryFormatter();
828 if (!m_selected && tmp != null)
829 m_serializedPosition = tmp.AbsolutePosition;
782 fmt.Serialize(ms, this); 830 fmt.Serialize(ms, this);
783 m_group = tmp; 831 m_group = tmp;
784 if (m_running && !m_waitingCrossing) 832 if (!timerWasStopped && m_running && !m_waitingCrossing)
785 StartTimer(); 833 StartTimer();
786 834
787 return ms.ToArray(); 835 return ms.ToArray();
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index ae85560..bd9d580 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -91,6 +91,11 @@ namespace OpenSim.Region.Framework.Scenes
91 return 0; 91 return 0;
92 92
93 uint priority; 93 uint priority;
94
95
96 // HACK
97 return GetPriorityByBestAvatarResponsiveness(client, entity);
98
94 99
95 switch (m_scene.UpdatePrioritizationScheme) 100 switch (m_scene.UpdatePrioritizationScheme)
96 { 101 {
@@ -157,30 +162,31 @@ namespace OpenSim.Region.Framework.Scenes
157 162
158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 163 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
159 { 164 {
160 uint pqueue = ComputeDistancePriority(client,entity,true); 165 uint pqueue = 2; // keep compiler happy
161 166
162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 167 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
163 if (presence != null) 168 if (presence != null)
164 { 169 {
165 if (!presence.IsChildAgent) 170 // All avatars other than our own go into pqueue 1
171 if (entity is ScenePresence)
172 return 1;
173
174 if (entity is SceneObjectPart)
166 { 175 {
167 // All avatars other than our own go into pqueue 1 176 // Attachments are high priority,
168 if (entity is ScenePresence) 177 if (((SceneObjectPart)entity).ParentGroup.IsAttachment)
169 return 1; 178 return 2;
170 179
171 if (entity is SceneObjectPart) 180 pqueue = ComputeDistancePriority(client, entity, false);
172 { 181
173 // Attachments are high priority, 182 // Non physical prims are lower priority than physical prims
174 if (((SceneObjectPart)entity).ParentGroup.IsAttachment) 183 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
175 return 1; 184 if (physActor == null || !physActor.IsPhysical)
176 185 pqueue++;
177 // Non physical prims are lower priority than physical prims
178 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
179 if (physActor == null || !physActor.IsPhysical)
180 pqueue++;
181 }
182 } 186 }
183 } 187 }
188 else
189 pqueue = ComputeDistancePriority(client, entity, false);
184 190
185 return pqueue; 191 return pqueue;
186 } 192 }
@@ -212,25 +218,43 @@ namespace OpenSim.Region.Framework.Scenes
212 } 218 }
213 219
214 // Use the camera position for local agents and avatar position for remote agents 220 // Use the camera position for local agents and avatar position for remote agents
215 Vector3 presencePos = (presence.IsChildAgent) ? 221 // Why would I want that? They could be camming but I still see them at the
216 presence.AbsolutePosition : 222 // avatar position, so why should I update them as if they were at their
217 presence.CameraPosition; 223 // camera positions? Makes no sense!
224 // TODO: Fix this mess
225 //Vector3 presencePos = (presence.IsChildAgent) ?
226 // presence.AbsolutePosition :
227 // presence.CameraPosition;
228
229 Vector3 presencePos = presence.AbsolutePosition;
218 230
219 // Compute the distance... 231 // Compute the distance...
220 double distance = Vector3.Distance(presencePos, entityPos); 232 double distance = Vector3.Distance(presencePos, entityPos);
221 233
222 // And convert the distance to a priority queue, this computation gives queues 234 // And convert the distance to a priority queue, this computation gives queues
223 // at 10, 20, 40, 80, 160, 320, 640, and 1280m 235 // at 10, 20, 40, 80, 160, 320, 640, and 1280m
224 uint pqueue = PriorityQueue.NumberOfImmediateQueues; 236 uint pqueue = PriorityQueue.NumberOfImmediateQueues + 1; // reserve attachments queue
225 uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues; 237 uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues;
226 238/*
227 for (int i = 0; i < queues - 1; i++) 239 for (int i = 0; i < queues - 1; i++)
228 { 240 {
229 if (distance < 10 * Math.Pow(2.0,i)) 241 if (distance < 30 * Math.Pow(2.0,i))
230 break; 242 break;
231 pqueue++; 243 pqueue++;
232 } 244 }
233 245*/
246 if (distance > 10f)
247 {
248 float tmp = (float)Math.Log((double)distance) * 1.4426950408889634073599246810019f - 3.3219280948873623478703194294894f;
249 // for a map identical to original:
250 // now
251 // 1st constant is 1/(log(2)) (natural log) so we get log2(distance)
252 // 2st constant makes it be log2(distance/10)
253 pqueue += (uint)tmp;
254 if (pqueue > queues - 1)
255 pqueue = queues - 1;
256 }
257
234 // If this is a root agent, then determine front & back 258 // If this is a root agent, then determine front & back
235 // Bump up the priority queue (drop the priority) for any objects behind the avatar 259 // Bump up the priority queue (drop the priority) for any objects behind the avatar
236 if (useFrontBack && ! presence.IsChildAgent) 260 if (useFrontBack && ! presence.IsChildAgent)
diff --git a/OpenSim/Region/Framework/Scenes/SOPMaterial.cs b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
new file mode 100644
index 0000000..10ac37c
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
@@ -0,0 +1,95 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework;
32
33namespace OpenSim.Region.Framework.Scenes
34{
35 public static class SOPMaterialData
36 {
37 public enum SopMaterial : int // redundante and not in use for now
38 {
39 Stone = 0,
40 Metal = 1,
41 Glass = 2,
42 Wood = 3,
43 Flesh = 4,
44 Plastic = 5,
45 Rubber = 6,
46 light = 7 // compatibility with old viewers
47 }
48
49 private struct MaterialData
50 {
51 public float friction;
52 public float bounce;
53 public MaterialData(float f, float b)
54 {
55 friction = f;
56 bounce = b;
57 }
58 }
59
60 private static MaterialData[] m_materialdata = {
61 new MaterialData(0.8f,0.4f), // Stone
62 new MaterialData(0.3f,0.4f), // Metal
63 new MaterialData(0.2f,0.7f), // Glass
64 new MaterialData(0.6f,0.5f), // Wood
65 new MaterialData(0.9f,0.3f), // Flesh
66 new MaterialData(0.4f,0.7f), // Plastic
67 new MaterialData(0.9f,0.95f), // Rubber
68 new MaterialData(0.0f,0.0f) // light ??
69 };
70
71 public static Material MaxMaterial
72 {
73 get { return (Material)(m_materialdata.Length - 1); }
74 }
75
76 public static float friction(Material material)
77 {
78 int indx = (int)material;
79 if (indx < m_materialdata.Length)
80 return (m_materialdata[indx].friction);
81 else
82 return 0;
83 }
84
85 public static float bounce(Material material)
86 {
87 int indx = (int)material;
88 if (indx < m_materialdata.Length)
89 return (m_materialdata[indx].bounce);
90 else
91 return 0;
92 }
93
94 }
95} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/SOPVehicle.cs b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs
new file mode 100644
index 0000000..58f4641
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs
@@ -0,0 +1,792 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Region.PhysicsModules.SharedBase;
33using System.Text;
34using System.IO;
35using System.Xml;
36using OpenSim.Framework.Serialization;
37using OpenSim.Framework.Serialization.External;
38using OpenSim.Region.Framework.Scenes.Serialization;
39
40namespace OpenSim.Region.Framework.Scenes
41{
42 public class SOPVehicle
43 {
44 public VehicleData vd;
45
46 public Vehicle Type
47 {
48 get { return vd.m_type; }
49 }
50
51 public SOPVehicle()
52 {
53 vd = new VehicleData();
54 ProcessTypeChange(Vehicle.TYPE_NONE); // is needed?
55 }
56
57 public void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
58 {
59 float len;
60 float timestep = 0.01f;
61 switch (pParam)
62 {
63 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
64 if (pValue < 0f) pValue = 0f;
65 if (pValue > 1f) pValue = 1f;
66 vd.m_angularDeflectionEfficiency = pValue;
67 break;
68 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
69 if (pValue < timestep) pValue = timestep;
70 vd.m_angularDeflectionTimescale = pValue;
71 break;
72 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
73 if (pValue < timestep) pValue = timestep;
74 else if (pValue > 120) pValue = 120;
75 vd.m_angularMotorDecayTimescale = pValue;
76 break;
77 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
78 if (pValue < timestep) pValue = timestep;
79 vd.m_angularMotorTimescale = pValue;
80 break;
81 case Vehicle.BANKING_EFFICIENCY:
82 if (pValue < -1f) pValue = -1f;
83 if (pValue > 1f) pValue = 1f;
84 vd.m_bankingEfficiency = pValue;
85 break;
86 case Vehicle.BANKING_MIX:
87 if (pValue < 0f) pValue = 0f;
88 if (pValue > 1f) pValue = 1f;
89 vd.m_bankingMix = pValue;
90 break;
91 case Vehicle.BANKING_TIMESCALE:
92 if (pValue < timestep) pValue = timestep;
93 vd.m_bankingTimescale = pValue;
94 break;
95 case Vehicle.BUOYANCY:
96 if (pValue < -1f) pValue = -1f;
97 if (pValue > 1f) pValue = 1f;
98 vd.m_VehicleBuoyancy = pValue;
99 break;
100 case Vehicle.HOVER_EFFICIENCY:
101 if (pValue < 0f) pValue = 0f;
102 if (pValue > 1f) pValue = 1f;
103 vd.m_VhoverEfficiency = pValue;
104 break;
105 case Vehicle.HOVER_HEIGHT:
106 vd.m_VhoverHeight = pValue;
107 break;
108 case Vehicle.HOVER_TIMESCALE:
109 if (pValue < timestep) pValue = timestep;
110 vd.m_VhoverTimescale = pValue;
111 break;
112 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
113 if (pValue < 0f) pValue = 0f;
114 if (pValue > 1f) pValue = 1f;
115 vd.m_linearDeflectionEfficiency = pValue;
116 break;
117 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
118 if (pValue < timestep) pValue = timestep;
119 vd.m_linearDeflectionTimescale = pValue;
120 break;
121 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
122 if (pValue < timestep) pValue = timestep;
123 else if (pValue > 120) pValue = 120;
124 vd.m_linearMotorDecayTimescale = pValue;
125 break;
126 case Vehicle.LINEAR_MOTOR_TIMESCALE:
127 if (pValue < timestep) pValue = timestep;
128 vd.m_linearMotorTimescale = pValue;
129 break;
130 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
131 if (pValue < 0f) pValue = 0f;
132 if (pValue > 1f) pValue = 1f;
133 vd.m_verticalAttractionEfficiency = pValue;
134 break;
135 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
136 if (pValue < timestep) pValue = timestep;
137 vd.m_verticalAttractionTimescale = pValue;
138 break;
139
140 // These are vector properties but the engine lets you use a single float value to
141 // set all of the components to the same value
142 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
143 if (pValue < timestep) pValue = timestep;
144 vd.m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
145 break;
146 case Vehicle.ANGULAR_MOTOR_DIRECTION:
147 vd.m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
148 len = vd.m_angularMotorDirection.Length();
149 if (len > 12.566f)
150 vd.m_angularMotorDirection *= (12.566f / len);
151 break;
152 case Vehicle.LINEAR_FRICTION_TIMESCALE:
153 if (pValue < timestep) pValue = timestep;
154 vd.m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
155 break;
156 case Vehicle.LINEAR_MOTOR_DIRECTION:
157 vd.m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
158 len = vd.m_linearMotorDirection.Length();
159 if (len > 30.0f)
160 vd.m_linearMotorDirection *= (30.0f / len);
161 break;
162 case Vehicle.LINEAR_MOTOR_OFFSET:
163 vd.m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
164 len = vd.m_linearMotorOffset.Length();
165 if (len > 100.0f)
166 vd.m_linearMotorOffset *= (100.0f / len);
167 break;
168 }
169 }//end ProcessFloatVehicleParam
170
171 public void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
172 {
173 float len;
174 float timestep = 0.01f;
175 switch (pParam)
176 {
177 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
178 if (pValue.X < timestep) pValue.X = timestep;
179 if (pValue.Y < timestep) pValue.Y = timestep;
180 if (pValue.Z < timestep) pValue.Z = timestep;
181
182 vd.m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
183 break;
184 case Vehicle.ANGULAR_MOTOR_DIRECTION:
185 vd.m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
186 // Limit requested angular speed to 2 rps= 4 pi rads/sec
187 len = vd.m_angularMotorDirection.Length();
188 if (len > 12.566f)
189 vd.m_angularMotorDirection *= (12.566f / len);
190 break;
191 case Vehicle.LINEAR_FRICTION_TIMESCALE:
192 if (pValue.X < timestep) pValue.X = timestep;
193 if (pValue.Y < timestep) pValue.Y = timestep;
194 if (pValue.Z < timestep) pValue.Z = timestep;
195 vd.m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
196 break;
197 case Vehicle.LINEAR_MOTOR_DIRECTION:
198 vd.m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
199 len = vd.m_linearMotorDirection.Length();
200 if (len > 30.0f)
201 vd.m_linearMotorDirection *= (30.0f / len);
202 break;
203 case Vehicle.LINEAR_MOTOR_OFFSET:
204 vd.m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
205 len = vd.m_linearMotorOffset.Length();
206 if (len > 100.0f)
207 vd.m_linearMotorOffset *= (100.0f / len);
208 break;
209 }
210 }//end ProcessVectorVehicleParam
211
212 public void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
213 {
214 switch (pParam)
215 {
216 case Vehicle.REFERENCE_FRAME:
217 vd.m_referenceFrame = pValue;
218 break;
219 }
220 }//end ProcessRotationVehicleParam
221
222 public void ProcessVehicleFlags(int pParam, bool remove)
223 {
224 if (remove)
225 {
226 vd.m_flags &= ~((VehicleFlag)pParam);
227 }
228 else
229 {
230 vd.m_flags |= (VehicleFlag)pParam;
231 }
232 }//end ProcessVehicleFlags
233
234 public void ProcessTypeChange(Vehicle pType)
235 {
236 vd.m_linearMotorDirection = Vector3.Zero;
237 vd.m_angularMotorDirection = Vector3.Zero;
238 vd.m_linearMotorOffset = Vector3.Zero;
239 vd.m_referenceFrame = Quaternion.Identity;
240
241 // Set Defaults For Type
242 vd.m_type = pType;
243 switch (pType)
244 {
245 case Vehicle.TYPE_NONE:
246 vd.m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
247 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
248 vd.m_linearMotorTimescale = 1000;
249 vd.m_linearMotorDecayTimescale = 120;
250 vd.m_angularMotorTimescale = 1000;
251 vd.m_angularMotorDecayTimescale = 1000;
252 vd.m_VhoverHeight = 0;
253 vd.m_VhoverEfficiency = 1;
254 vd.m_VhoverTimescale = 1000;
255 vd.m_VehicleBuoyancy = 0;
256 vd.m_linearDeflectionEfficiency = 0;
257 vd.m_linearDeflectionTimescale = 1000;
258 vd.m_angularDeflectionEfficiency = 0;
259 vd.m_angularDeflectionTimescale = 1000;
260 vd.m_bankingEfficiency = 0;
261 vd.m_bankingMix = 1;
262 vd.m_bankingTimescale = 1000;
263 vd.m_verticalAttractionEfficiency = 0;
264 vd.m_verticalAttractionTimescale = 1000;
265
266 vd.m_flags = (VehicleFlag)0;
267 break;
268
269 case Vehicle.TYPE_SLED:
270 vd.m_linearFrictionTimescale = new Vector3(30, 1, 1000);
271 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
272 vd.m_linearMotorTimescale = 1000;
273 vd.m_linearMotorDecayTimescale = 120;
274 vd.m_angularMotorTimescale = 1000;
275 vd.m_angularMotorDecayTimescale = 120;
276 vd.m_VhoverHeight = 0;
277 vd.m_VhoverEfficiency = 1;
278 vd.m_VhoverTimescale = 10;
279 vd.m_VehicleBuoyancy = 0;
280 vd.m_linearDeflectionEfficiency = 1;
281 vd.m_linearDeflectionTimescale = 1;
282 vd.m_angularDeflectionEfficiency = 0;
283 vd.m_angularDeflectionTimescale = 1000;
284 vd.m_bankingEfficiency = 0;
285 vd.m_bankingMix = 1;
286 vd.m_bankingTimescale = 10;
287 vd.m_flags &=
288 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
289 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
290 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
291 break;
292 case Vehicle.TYPE_CAR:
293 vd.m_linearFrictionTimescale = new Vector3(100, 2, 1000);
294 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
295 vd.m_linearMotorTimescale = 1;
296 vd.m_linearMotorDecayTimescale = 60;
297 vd.m_angularMotorTimescale = 1;
298 vd.m_angularMotorDecayTimescale = 0.8f;
299 vd.m_VhoverHeight = 0;
300 vd.m_VhoverEfficiency = 0;
301 vd.m_VhoverTimescale = 1000;
302 vd.m_VehicleBuoyancy = 0;
303 vd.m_linearDeflectionEfficiency = 1;
304 vd.m_linearDeflectionTimescale = 2;
305 vd.m_angularDeflectionEfficiency = 0;
306 vd.m_angularDeflectionTimescale = 10;
307 vd.m_verticalAttractionEfficiency = 1f;
308 vd.m_verticalAttractionTimescale = 10f;
309 vd.m_bankingEfficiency = -0.2f;
310 vd.m_bankingMix = 1;
311 vd.m_bankingTimescale = 1;
312 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
313 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
314 VehicleFlag.LIMIT_MOTOR_UP | VehicleFlag.HOVER_UP_ONLY);
315 break;
316 case Vehicle.TYPE_BOAT:
317 vd.m_linearFrictionTimescale = new Vector3(10, 3, 2);
318 vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
319 vd.m_linearMotorTimescale = 5;
320 vd.m_linearMotorDecayTimescale = 60;
321 vd.m_angularMotorTimescale = 4;
322 vd.m_angularMotorDecayTimescale = 4;
323 vd.m_VhoverHeight = 0;
324 vd.m_VhoverEfficiency = 0.5f;
325 vd.m_VhoverTimescale = 2;
326 vd.m_VehicleBuoyancy = 1;
327 vd.m_linearDeflectionEfficiency = 0.5f;
328 vd.m_linearDeflectionTimescale = 3;
329 vd.m_angularDeflectionEfficiency = 0.5f;
330 vd.m_angularDeflectionTimescale = 5;
331 vd.m_verticalAttractionEfficiency = 0.5f;
332 vd.m_verticalAttractionTimescale = 5f;
333 vd.m_bankingEfficiency = -0.3f;
334 vd.m_bankingMix = 0.8f;
335 vd.m_bankingTimescale = 1;
336 vd.m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
337 VehicleFlag.HOVER_GLOBAL_HEIGHT |
338 VehicleFlag.HOVER_UP_ONLY |
339 VehicleFlag.LIMIT_ROLL_ONLY);
340 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
341 VehicleFlag.LIMIT_MOTOR_UP |
342 VehicleFlag.HOVER_WATER_ONLY);
343 break;
344 case Vehicle.TYPE_AIRPLANE:
345 vd.m_linearFrictionTimescale = new Vector3(200, 10, 5);
346 vd.m_angularFrictionTimescale = new Vector3(20, 20, 20);
347 vd.m_linearMotorTimescale = 2;
348 vd.m_linearMotorDecayTimescale = 60;
349 vd.m_angularMotorTimescale = 4;
350 vd.m_angularMotorDecayTimescale = 8;
351 vd.m_VhoverHeight = 0;
352 vd.m_VhoverEfficiency = 0.5f;
353 vd.m_VhoverTimescale = 1000;
354 vd.m_VehicleBuoyancy = 0;
355 vd.m_linearDeflectionEfficiency = 0.5f;
356 vd.m_linearDeflectionTimescale = 0.5f;
357 vd.m_angularDeflectionEfficiency = 1;
358 vd.m_angularDeflectionTimescale = 2;
359 vd.m_verticalAttractionEfficiency = 0.9f;
360 vd.m_verticalAttractionTimescale = 2f;
361 vd.m_bankingEfficiency = 1;
362 vd.m_bankingMix = 0.7f;
363 vd.m_bankingTimescale = 2;
364 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
365 VehicleFlag.HOVER_TERRAIN_ONLY |
366 VehicleFlag.HOVER_GLOBAL_HEIGHT |
367 VehicleFlag.HOVER_UP_ONLY |
368 VehicleFlag.NO_DEFLECTION_UP |
369 VehicleFlag.LIMIT_MOTOR_UP);
370 vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
371 break;
372 case Vehicle.TYPE_BALLOON:
373 vd.m_linearFrictionTimescale = new Vector3(5, 5, 5);
374 vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
375 vd.m_linearMotorTimescale = 5;
376 vd.m_linearMotorDecayTimescale = 60;
377 vd.m_angularMotorTimescale = 6;
378 vd.m_angularMotorDecayTimescale = 10;
379 vd.m_VhoverHeight = 5;
380 vd.m_VhoverEfficiency = 0.8f;
381 vd.m_VhoverTimescale = 10;
382 vd.m_VehicleBuoyancy = 1;
383 vd.m_linearDeflectionEfficiency = 0;
384 vd.m_linearDeflectionTimescale = 5;
385 vd.m_angularDeflectionEfficiency = 0;
386 vd.m_angularDeflectionTimescale = 5;
387 vd.m_verticalAttractionEfficiency = 0f;
388 vd.m_verticalAttractionTimescale = 1000f;
389 vd.m_bankingEfficiency = 0;
390 vd.m_bankingMix = 0.7f;
391 vd.m_bankingTimescale = 5;
392 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
393 VehicleFlag.HOVER_TERRAIN_ONLY |
394 VehicleFlag.HOVER_UP_ONLY |
395 VehicleFlag.NO_DEFLECTION_UP |
396 VehicleFlag.LIMIT_MOTOR_UP);
397 vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY |
398 VehicleFlag.HOVER_GLOBAL_HEIGHT);
399 break;
400 }
401 }
402 public void SetVehicle(PhysicsActor ph)
403 {
404 if (ph == null)
405 return;
406 ph.SetVehicle(vd);
407 }
408
409 private XmlTextWriter writer;
410
411 private void XWint(string name, int i)
412 {
413 writer.WriteElementString(name, i.ToString());
414 }
415
416 private void XWfloat(string name, float f)
417 {
418 writer.WriteElementString(name, f.ToString(Utils.EnUsCulture));
419 }
420
421 private void XWVector(string name, Vector3 vec)
422 {
423 writer.WriteStartElement(name);
424 writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture));
425 writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture));
426 writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture));
427 writer.WriteEndElement();
428 }
429
430 private void XWQuat(string name, Quaternion quat)
431 {
432 writer.WriteStartElement(name);
433 writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture));
434 writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture));
435 writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture));
436 writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture));
437 writer.WriteEndElement();
438 }
439
440 public void ToXml2(XmlTextWriter twriter)
441 {
442 writer = twriter;
443 writer.WriteStartElement("Vehicle");
444
445 XWint("TYPE", (int)vd.m_type);
446 XWint("FLAGS", (int)vd.m_flags);
447
448 // Linear properties
449 XWVector("LMDIR", vd.m_linearMotorDirection);
450 XWVector("LMFTIME", vd.m_linearFrictionTimescale);
451 XWfloat("LMDTIME", vd.m_linearMotorDecayTimescale);
452 XWfloat("LMTIME", vd.m_linearMotorTimescale);
453 XWVector("LMOFF", vd.m_linearMotorOffset);
454
455 //Angular properties
456 XWVector("AMDIR", vd.m_angularMotorDirection);
457 XWfloat("AMTIME", vd.m_angularMotorTimescale);
458 XWfloat("AMDTIME", vd.m_angularMotorDecayTimescale);
459 XWVector("AMFTIME", vd.m_angularFrictionTimescale);
460
461 //Deflection properties
462 XWfloat("ADEFF", vd.m_angularDeflectionEfficiency);
463 XWfloat("ADTIME", vd.m_angularDeflectionTimescale);
464 XWfloat("LDEFF", vd.m_linearDeflectionEfficiency);
465 XWfloat("LDTIME", vd.m_linearDeflectionTimescale);
466
467 //Banking properties
468 XWfloat("BEFF", vd.m_bankingEfficiency);
469 XWfloat("BMIX", vd.m_bankingMix);
470 XWfloat("BTIME", vd.m_bankingTimescale);
471
472 //Hover and Buoyancy properties
473 XWfloat("HHEI", vd.m_VhoverHeight);
474 XWfloat("HEFF", vd.m_VhoverEfficiency);
475 XWfloat("HTIME", vd.m_VhoverTimescale);
476 XWfloat("VBUO", vd.m_VehicleBuoyancy);
477
478 //Attractor properties
479 XWfloat("VAEFF", vd.m_verticalAttractionEfficiency);
480 XWfloat("VATIME", vd.m_verticalAttractionTimescale);
481
482 XWQuat("REF_FRAME", vd.m_referenceFrame);
483
484 writer.WriteEndElement();
485 writer = null;
486 }
487
488
489
490 XmlReader reader;
491
492 private int XRint()
493 {
494 return reader.ReadElementContentAsInt();
495 }
496
497 private float XRfloat()
498 {
499 return reader.ReadElementContentAsFloat();
500 }
501
502 public Vector3 XRvector()
503 {
504 Vector3 vec;
505 reader.ReadStartElement();
506 vec.X = reader.ReadElementContentAsFloat();
507 vec.Y = reader.ReadElementContentAsFloat();
508 vec.Z = reader.ReadElementContentAsFloat();
509 reader.ReadEndElement();
510 return vec;
511 }
512
513 public Quaternion XRquat()
514 {
515 Quaternion q;
516 reader.ReadStartElement();
517 q.X = reader.ReadElementContentAsFloat();
518 q.Y = reader.ReadElementContentAsFloat();
519 q.Z = reader.ReadElementContentAsFloat();
520 q.W = reader.ReadElementContentAsFloat();
521 reader.ReadEndElement();
522 return q;
523 }
524
525 public static bool EReadProcessors(
526 Dictionary<string, Action> processors,
527 XmlReader xtr)
528 {
529 bool errors = false;
530
531 string nodeName = string.Empty;
532 while (xtr.NodeType != XmlNodeType.EndElement)
533 {
534 nodeName = xtr.Name;
535
536 // m_log.DebugFormat("[ExternalRepresentationUtils]: Processing: {0}", nodeName);
537
538 Action p = null;
539 if (processors.TryGetValue(xtr.Name, out p))
540 {
541 // m_log.DebugFormat("[ExternalRepresentationUtils]: Found {0} processor, nodeName);
542
543 try
544 {
545 p();
546 }
547 catch (Exception e)
548 {
549 errors = true;
550 if (xtr.NodeType == XmlNodeType.EndElement)
551 xtr.Read();
552 }
553 }
554 else
555 {
556 // m_log.DebugFormat("[LandDataSerializer]: caught unknown element {0}", nodeName);
557 xtr.ReadOuterXml(); // ignore
558 }
559 }
560
561 return errors;
562 }
563
564
565 public string ToXml2()
566 {
567 using (StringWriter sw = new StringWriter())
568 {
569 using (XmlTextWriter xwriter = new XmlTextWriter(sw))
570 {
571 ToXml2(xwriter);
572 }
573
574 return sw.ToString();
575 }
576 }
577
578 public static SOPVehicle FromXml2(string text)
579 {
580 if (text == String.Empty)
581 return null;
582
583 UTF8Encoding enc = new UTF8Encoding();
584 MemoryStream ms = new MemoryStream(enc.GetBytes(text));
585 XmlTextReader xreader = new XmlTextReader(ms);
586
587 SOPVehicle v = new SOPVehicle();
588 bool error;
589
590 v.FromXml2(xreader, out error);
591
592 xreader.Close();
593
594 if (error)
595 {
596 v = null;
597 return null;
598 }
599 return v;
600 }
601
602 public static SOPVehicle FromXml2(XmlReader reader)
603 {
604 SOPVehicle vehicle = new SOPVehicle();
605
606 bool errors = false;
607
608 vehicle.FromXml2(reader, out errors);
609 if (errors)
610 return null;
611
612 return vehicle;
613 }
614
615 private void FromXml2(XmlReader _reader, out bool errors)
616 {
617 errors = false;
618 reader = _reader;
619
620 Dictionary<string, Action> m_VehicleXmlProcessors
621 = new Dictionary<string, Action>();
622
623 m_VehicleXmlProcessors.Add("TYPE", ProcessXR_type);
624 m_VehicleXmlProcessors.Add("FLAGS", ProcessXR_flags);
625
626 // Linear properties
627 m_VehicleXmlProcessors.Add("LMDIR", ProcessXR_linearMotorDirection);
628 m_VehicleXmlProcessors.Add("LMFTIME", ProcessXR_linearFrictionTimescale);
629 m_VehicleXmlProcessors.Add("LMDTIME", ProcessXR_linearMotorDecayTimescale);
630 m_VehicleXmlProcessors.Add("LMTIME", ProcessXR_linearMotorTimescale);
631 m_VehicleXmlProcessors.Add("LMOFF", ProcessXR_linearMotorOffset);
632
633 //Angular properties
634 m_VehicleXmlProcessors.Add("AMDIR", ProcessXR_angularMotorDirection);
635 m_VehicleXmlProcessors.Add("AMTIME", ProcessXR_angularMotorTimescale);
636 m_VehicleXmlProcessors.Add("AMDTIME", ProcessXR_angularMotorDecayTimescale);
637 m_VehicleXmlProcessors.Add("AMFTIME", ProcessXR_angularFrictionTimescale);
638
639 //Deflection properties
640 m_VehicleXmlProcessors.Add("ADEFF", ProcessXR_angularDeflectionEfficiency);
641 m_VehicleXmlProcessors.Add("ADTIME", ProcessXR_angularDeflectionTimescale);
642 m_VehicleXmlProcessors.Add("LDEFF", ProcessXR_linearDeflectionEfficiency);
643 m_VehicleXmlProcessors.Add("LDTIME", ProcessXR_linearDeflectionTimescale);
644
645 //Banking properties
646 m_VehicleXmlProcessors.Add("BEFF", ProcessXR_bankingEfficiency);
647 m_VehicleXmlProcessors.Add("BMIX", ProcessXR_bankingMix);
648 m_VehicleXmlProcessors.Add("BTIME", ProcessXR_bankingTimescale);
649
650 //Hover and Buoyancy properties
651 m_VehicleXmlProcessors.Add("HHEI", ProcessXR_VhoverHeight);
652 m_VehicleXmlProcessors.Add("HEFF", ProcessXR_VhoverEfficiency);
653 m_VehicleXmlProcessors.Add("HTIME", ProcessXR_VhoverTimescale);
654
655 m_VehicleXmlProcessors.Add("VBUO", ProcessXR_VehicleBuoyancy);
656
657 //Attractor properties
658 m_VehicleXmlProcessors.Add("VAEFF", ProcessXR_verticalAttractionEfficiency);
659 m_VehicleXmlProcessors.Add("VATIME", ProcessXR_verticalAttractionTimescale);
660
661 m_VehicleXmlProcessors.Add("REF_FRAME", ProcessXR_referenceFrame);
662
663 vd = new VehicleData();
664
665 reader.ReadStartElement("Vehicle", String.Empty);
666
667 errors = EReadProcessors(
668 m_VehicleXmlProcessors,
669 reader);
670
671 reader.ReadEndElement();
672 reader = null;
673 }
674
675 private void ProcessXR_type()
676 {
677 vd.m_type = (Vehicle)XRint();
678 }
679 private void ProcessXR_flags()
680 {
681 vd.m_flags = (VehicleFlag)XRint();
682 }
683 // Linear properties
684 private void ProcessXR_linearMotorDirection()
685 {
686 vd.m_linearMotorDirection = XRvector();
687 }
688
689 private void ProcessXR_linearFrictionTimescale()
690 {
691 vd.m_linearFrictionTimescale = XRvector();
692 }
693
694 private void ProcessXR_linearMotorDecayTimescale()
695 {
696 vd.m_linearMotorDecayTimescale = XRfloat();
697 }
698 private void ProcessXR_linearMotorTimescale()
699 {
700 vd.m_linearMotorTimescale = XRfloat();
701 }
702 private void ProcessXR_linearMotorOffset()
703 {
704 vd.m_linearMotorOffset = XRvector();
705 }
706
707
708 //Angular properties
709 private void ProcessXR_angularMotorDirection()
710 {
711 vd.m_angularMotorDirection = XRvector();
712 }
713 private void ProcessXR_angularMotorTimescale()
714 {
715 vd.m_angularMotorTimescale = XRfloat();
716 }
717 private void ProcessXR_angularMotorDecayTimescale()
718 {
719 vd.m_angularMotorDecayTimescale = XRfloat();
720 }
721 private void ProcessXR_angularFrictionTimescale()
722 {
723 vd.m_angularFrictionTimescale = XRvector();
724 }
725
726 //Deflection properties
727 private void ProcessXR_angularDeflectionEfficiency()
728 {
729 vd.m_angularDeflectionEfficiency = XRfloat();
730 }
731 private void ProcessXR_angularDeflectionTimescale()
732 {
733 vd.m_angularDeflectionTimescale = XRfloat();
734 }
735 private void ProcessXR_linearDeflectionEfficiency()
736 {
737 vd.m_linearDeflectionEfficiency = XRfloat();
738 }
739 private void ProcessXR_linearDeflectionTimescale()
740 {
741 vd.m_linearDeflectionTimescale = XRfloat();
742 }
743
744 //Banking properties
745 private void ProcessXR_bankingEfficiency()
746 {
747 vd.m_bankingEfficiency = XRfloat();
748 }
749 private void ProcessXR_bankingMix()
750 {
751 vd.m_bankingMix = XRfloat();
752 }
753 private void ProcessXR_bankingTimescale()
754 {
755 vd.m_bankingTimescale = XRfloat();
756 }
757
758 //Hover and Buoyancy properties
759 private void ProcessXR_VhoverHeight()
760 {
761 vd.m_VhoverHeight = XRfloat();
762 }
763 private void ProcessXR_VhoverEfficiency()
764 {
765 vd.m_VhoverEfficiency = XRfloat();
766 }
767 private void ProcessXR_VhoverTimescale()
768 {
769 vd.m_VhoverTimescale = XRfloat();
770 }
771
772 private void ProcessXR_VehicleBuoyancy()
773 {
774 vd.m_VehicleBuoyancy = XRfloat();
775 }
776
777 //Attractor properties
778 private void ProcessXR_verticalAttractionEfficiency()
779 {
780 vd.m_verticalAttractionEfficiency = XRfloat();
781 }
782 private void ProcessXR_verticalAttractionTimescale()
783 {
784 vd.m_verticalAttractionTimescale = XRfloat();
785 }
786
787 private void ProcessXR_referenceFrame()
788 {
789 vd.m_referenceFrame = XRquat();
790 }
791 }
792}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index b838177..edb881f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -106,12 +106,12 @@ namespace OpenSim.Region.Framework.Scenes
106 engine.StartProcessing(); 106 engine.StartProcessing();
107 } 107 }
108 108
109 public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item) 109 public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item, uint cost)
110 { 110 {
111 IMoneyModule money = RequestModuleInterface<IMoneyModule>(); 111 IMoneyModule money = RequestModuleInterface<IMoneyModule>();
112 if (money != null) 112 if (money != null)
113 { 113 {
114 money.ApplyUploadCharge(agentID, money.UploadCharge, "Asset upload"); 114 money.ApplyUploadCharge(agentID, (int)cost, "Asset upload");
115 } 115 }
116 116
117 AddInventoryItem(item); 117 AddInventoryItem(item);
@@ -182,7 +182,7 @@ namespace OpenSim.Region.Framework.Scenes
182 return false; 182 return false;
183 } 183 }
184 } 184 }
185 185
186 if (InventoryService.AddItem(item)) 186 if (InventoryService.AddItem(item))
187 { 187 {
188 int userlevel = 0; 188 int userlevel = 0;
@@ -338,8 +338,7 @@ namespace OpenSim.Region.Framework.Scenes
338 338
339 // Update item with new asset 339 // Update item with new asset
340 item.AssetID = asset.FullID; 340 item.AssetID = asset.FullID;
341 if (group.UpdateInventoryItem(item)) 341 group.UpdateInventoryItem(item);
342 remoteClient.SendAlertMessage("Script saved");
343 342
344 part.SendPropertiesToClient(remoteClient); 343 part.SendPropertiesToClient(remoteClient);
345 344
@@ -350,12 +349,7 @@ namespace OpenSim.Region.Framework.Scenes
350 { 349 {
351 // Needs to determine which engine was running it and use that 350 // Needs to determine which engine was running it and use that
352 // 351 //
353 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 352 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 1);
354 errors = part.Inventory.GetScriptErrors(item.ItemID);
355 }
356 else
357 {
358 remoteClient.SendAlertMessage("Script saved");
359 } 353 }
360 354
361 // Tell anyone managing scripts that a script has been reloaded/changed 355 // Tell anyone managing scripts that a script has been reloaded/changed
@@ -421,6 +415,7 @@ namespace OpenSim.Region.Framework.Scenes
421 if (item.Owner != remoteClient.AgentId) 415 if (item.Owner != remoteClient.AgentId)
422 return; 416 return;
423 417
418 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
424 item.Name = itemUpd.Name; 419 item.Name = itemUpd.Name;
425 item.Description = itemUpd.Description; 420 item.Description = itemUpd.Description;
426 421
@@ -889,6 +884,20 @@ namespace OpenSim.Region.Framework.Scenes
889 if (newName == String.Empty) 884 if (newName == String.Empty)
890 newName = item.Name; 885 newName = item.Name;
891 886
887 AssetBase asset = AssetService.Get(item.AssetID.ToString());
888
889 if (asset != null)
890 {
891 if (newName != String.Empty)
892 {
893 asset.Name = newName;
894 }
895 else
896 {
897 newName = item.Name;
898 }
899
900
892 if (remoteClient.AgentId == oldAgentID 901 if (remoteClient.AgentId == oldAgentID
893 || (LibraryService != null 902 || (LibraryService != null
894 && LibraryService.LibraryRootFolder != null 903 && LibraryService.LibraryRootFolder != null
@@ -915,6 +924,13 @@ namespace OpenSim.Region.Framework.Scenes
915 } 924 }
916 } 925 }
917 } 926 }
927 else
928 {
929 m_log.ErrorFormat(
930 "[AGENT INVENTORY]: Could not copy item {0} since asset {1} could not be found",
931 item.Name, item.AssetID);
932 }
933 }
918 934
919 /// <summary> 935 /// <summary>
920 /// Create a new asset data structure. 936 /// Create a new asset data structure.
@@ -929,6 +945,24 @@ namespace OpenSim.Region.Framework.Scenes
929 } 945 }
930 946
931 /// <summary> 947 /// <summary>
948 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
949 /// </summary>
950 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
951 {
952 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
953 foreach (InventoryItemBase b in items)
954 {
955 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
956 InventoryItemBase n = InventoryService.GetItem(b);
957 n.Folder = destfolder;
958 moveitems.Add(n);
959 remoteClient.SendInventoryItemCreateUpdate(n, 0);
960 }
961
962 MoveInventoryItem(remoteClient, moveitems);
963 }
964
965 /// <summary>
932 /// Move an item within the agent's inventory. 966 /// Move an item within the agent's inventory.
933 /// </summary> 967 /// </summary>
934 /// <param name="remoteClient"></param> 968 /// <param name="remoteClient"></param>
@@ -1015,7 +1049,11 @@ namespace OpenSim.Region.Framework.Scenes
1015 item.BasePermissions = baseMask; 1049 item.BasePermissions = baseMask;
1016 item.CreationDate = creationDate; 1050 item.CreationDate = creationDate;
1017 1051
1018 if (AddInventoryItem(item, assetUpload)) 1052 // special AnimationSet case
1053 if (item.InvType == (int)CustomInventoryType.AnimationSet)
1054 AnimationSet.enforceItemPermitions(item,true);
1055
1056 if (AddInventoryItem(item))
1019 { 1057 {
1020 remoteClient.SendInventoryItemCreateUpdate(item, callbackID); 1058 remoteClient.SendInventoryItemCreateUpdate(item, callbackID);
1021 } 1059 }
@@ -1327,6 +1365,10 @@ namespace OpenSim.Region.Framework.Scenes
1327 { 1365 {
1328 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1366 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1329 1367
1368 // Can't move a null item
1369 if (itemId == UUID.Zero)
1370 return;
1371
1330 if (null == part) 1372 if (null == part)
1331 { 1373 {
1332 m_log.WarnFormat( 1374 m_log.WarnFormat(
@@ -1437,21 +1479,28 @@ namespace OpenSim.Region.Framework.Scenes
1437 return; 1479 return;
1438 } 1480 }
1439 1481
1440 if (part.OwnerID != destPart.OwnerID) 1482 // Can't transfer this
1483 //
1484 if (part.OwnerID != destPart.OwnerID && (srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1485 return;
1486
1487 bool overrideNoMod = false;
1488 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1489 overrideNoMod = true;
1490
1491 if (part.OwnerID != destPart.OwnerID && (destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1441 { 1492 {
1442 // Source must have transfer permissions 1493 // object cannot copy items to an object owned by a different owner
1443 if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) 1494 // unless llAllowInventoryDrop has been called
1444 return;
1445 1495
1446 // Object cannot copy items to an object owned by a different owner 1496 return;
1447 // unless llAllowInventoryDrop has been called on the destination
1448 if ((destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1449 return;
1450 } 1497 }
1451 1498
1452 // must have both move and modify permission to put an item in an object 1499 // must have both move and modify permission to put an item in an object
1453 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1500 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1501 {
1454 return; 1502 return;
1503 }
1455 1504
1456 TaskInventoryItem destTaskItem = new TaskInventoryItem(); 1505 TaskInventoryItem destTaskItem = new TaskInventoryItem();
1457 1506
@@ -1507,10 +1556,20 @@ namespace OpenSim.Region.Framework.Scenes
1507 1556
1508 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1557 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1509 { 1558 {
1559
1510 ScenePresence avatar; 1560 ScenePresence avatar;
1511 IClientAPI remoteClient = null; 1561 IClientAPI remoteClient = null;
1512 if (TryGetScenePresence(destID, out avatar)) 1562 if (TryGetScenePresence(destID, out avatar))
1513 remoteClient = avatar.ControllingClient; 1563 remoteClient = avatar.ControllingClient;
1564// ????
1565 SceneObjectPart destPart = GetSceneObjectPart(destID);
1566 if (destPart != null) // Move into a prim
1567 {
1568 foreach(UUID itemID in items)
1569 MoveTaskInventoryItem(destID, host, itemID);
1570 return destID; // Prim folder ID == prim ID
1571 }
1572// /????
1514 1573
1515 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1574 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1516 1575
@@ -1696,12 +1755,12 @@ namespace OpenSim.Region.Framework.Scenes
1696 AgentTransactionsModule.HandleTaskItemUpdateFromTransaction( 1755 AgentTransactionsModule.HandleTaskItemUpdateFromTransaction(
1697 remoteClient, part, transactionID, currentItem); 1756 remoteClient, part, transactionID, currentItem);
1698 1757
1699 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1758// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1700 remoteClient.SendAlertMessage("Notecard saved"); 1759// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1701 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1760// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1702 remoteClient.SendAlertMessage("Script saved"); 1761// remoteClient.SendAgentAlertMessage("Script saved", false);
1703 else 1762// else
1704 remoteClient.SendAlertMessage("Item saved"); 1763// remoteClient.SendAgentAlertMessage("Item saved", false);
1705 } 1764 }
1706 1765
1707 // Base ALWAYS has move 1766 // Base ALWAYS has move
@@ -2075,7 +2134,8 @@ namespace OpenSim.Region.Framework.Scenes
2075 // build a list of eligible objects 2134 // build a list of eligible objects
2076 List<uint> deleteIDs = new List<uint>(); 2135 List<uint> deleteIDs = new List<uint>();
2077 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 2136 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
2078 2137 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
2138
2079 // Start with true for both, then remove the flags if objects 2139 // Start with true for both, then remove the flags if objects
2080 // that we can't derez are part of the selection 2140 // that we can't derez are part of the selection
2081 bool permissionToTake = true; 2141 bool permissionToTake = true;
@@ -2084,14 +2144,24 @@ namespace OpenSim.Region.Framework.Scenes
2084 2144
2085 foreach (uint localID in localIDs) 2145 foreach (uint localID in localIDs)
2086 { 2146 {
2147
2148
2087 // Invalid id 2149 // Invalid id
2088 SceneObjectPart part = GetSceneObjectPart(localID); 2150 SceneObjectPart part = GetSceneObjectPart(localID);
2089 if (part == null) 2151 if (part == null)
2152 {
2153 //Client still thinks the object exists, kill it
2154 deleteIDs.Add(localID);
2090 continue; 2155 continue;
2156 }
2091 2157
2092 // Already deleted by someone else 2158 // Already deleted by someone else
2093 if (part.ParentGroup.IsDeleted) 2159 if (part.ParentGroup.IsDeleted)
2160 {
2161 //Client still thinks the object exists, kill it
2162 deleteIDs.Add(localID);
2094 continue; 2163 continue;
2164 }
2095 2165
2096 // Can't delete child prims 2166 // Can't delete child prims
2097 if (part != part.ParentGroup.RootPart) 2167 if (part != part.ParentGroup.RootPart)
@@ -2099,9 +2169,6 @@ namespace OpenSim.Region.Framework.Scenes
2099 2169
2100 SceneObjectGroup grp = part.ParentGroup; 2170 SceneObjectGroup grp = part.ParentGroup;
2101 2171
2102 deleteIDs.Add(localID);
2103 deleteGroups.Add(grp);
2104
2105 // If child prims have invalid perms, fix them 2172 // If child prims have invalid perms, fix them
2106 grp.AdjustChildPrimPermissions(false); 2173 grp.AdjustChildPrimPermissions(false);
2107 2174
@@ -2121,87 +2188,191 @@ namespace OpenSim.Region.Framework.Scenes
2121 } 2188 }
2122 else 2189 else
2123 { 2190 {
2124 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 2191 if (action == DeRezAction.TakeCopy)
2192 {
2193 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
2194 permissionToTakeCopy = false;
2195 }
2196 else
2197 {
2125 permissionToTakeCopy = false; 2198 permissionToTakeCopy = false;
2126 2199 }
2127 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 2200 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
2128 permissionToTake = false; 2201 permissionToTake = false;
2129 2202
2130 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 2203 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
2131 permissionToDelete = false; 2204 permissionToDelete = false;
2132 } 2205 }
2133 }
2134 2206
2135 // Handle god perms 2207 // Handle god perms
2136 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 2208 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
2137 {
2138 permissionToTake = true;
2139 permissionToTakeCopy = true;
2140 permissionToDelete = true;
2141 }
2142
2143 // If we're re-saving, we don't even want to delete
2144 if (action == DeRezAction.SaveToExistingUserInventoryItem)
2145 permissionToDelete = false;
2146
2147 // if we want to take a copy, we also don't want to delete
2148 // Note: after this point, the permissionToTakeCopy flag
2149 // becomes irrelevant. It already includes the permissionToTake
2150 // permission and after excluding no copy items here, we can
2151 // just use that.
2152 if (action == DeRezAction.TakeCopy)
2153 {
2154 // If we don't have permission, stop right here
2155 if (!permissionToTakeCopy)
2156 { 2209 {
2157 remoteClient.SendAlertMessage("You don't have permission to take the object"); 2210 permissionToTake = true;
2158 return; 2211 permissionToTakeCopy = true;
2212 permissionToDelete = true;
2159 } 2213 }
2160 2214
2161 permissionToTake = true; 2215 // If we're re-saving, we don't even want to delete
2162 // Don't delete 2216 if (action == DeRezAction.SaveToExistingUserInventoryItem)
2163 permissionToDelete = false; 2217 permissionToDelete = false;
2164 }
2165 2218
2166 if (action == DeRezAction.Return) 2219 // if we want to take a copy, we also don't want to delete
2167 { 2220 // Note: after this point, the permissionToTakeCopy flag
2168 if (remoteClient != null) 2221 // becomes irrelevant. It already includes the permissionToTake
2222 // permission and after excluding no copy items here, we can
2223 // just use that.
2224 if (action == DeRezAction.TakeCopy)
2169 { 2225 {
2170 if (Permissions.CanReturnObjects( 2226 // If we don't have permission, stop right here
2171 null, 2227 if (!permissionToTakeCopy)
2172 remoteClient.AgentId,
2173 deleteGroups))
2174 { 2228 {
2175 permissionToTake = true; 2229 remoteClient.SendAlertMessage("You don't have permission to take the object");
2176 permissionToDelete = true; 2230 return;
2231 }
2177 2232
2178 foreach (SceneObjectGroup g in deleteGroups) 2233 permissionToTake = true;
2234 // Don't delete
2235 permissionToDelete = false;
2236 }
2237
2238 if (action == DeRezAction.Return)
2239 {
2240 if (remoteClient != null)
2241 {
2242 if (Permissions.CanReturnObjects(
2243 null,
2244 remoteClient.AgentId,
2245 new List<SceneObjectGroup>() {grp}))
2179 { 2246 {
2180 AddReturn(g.OwnerID == g.GroupID ? g.LastOwnerID : g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 2247 permissionToTake = true;
2248 permissionToDelete = true;
2249
2250 AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
2181 } 2251 }
2182 } 2252 }
2253 else // Auto return passes through here with null agent
2254 {
2255 permissionToTake = true;
2256 permissionToDelete = true;
2257 }
2183 } 2258 }
2184 else // Auto return passes through here with null agent 2259
2260 if (permissionToTake && (!permissionToDelete))
2261 takeGroups.Add(grp);
2262
2263 if (permissionToDelete)
2185 { 2264 {
2186 permissionToTake = true; 2265 if (permissionToTake)
2187 permissionToDelete = true; 2266 deleteGroups.Add(grp);
2267 deleteIDs.Add(grp.LocalId);
2188 } 2268 }
2189 } 2269 }
2190 2270
2191 // OK, we're done with permissions. Let's check if any part of the code prevents the objects from being deleted 2271 SendKillObject(deleteIDs);
2192 bool canDelete = EventManager.TriggerDeRezRequested(remoteClient, deleteGroups, action);
2193 2272
2194 if (permissionToTake && (action != DeRezAction.Delete || this.m_useTrashOnDelete)) 2273 if (deleteGroups.Count > 0)
2195 { 2274 {
2275 foreach (SceneObjectGroup g in deleteGroups)
2276 deleteIDs.Remove(g.LocalId);
2277
2196 m_asyncSceneObjectDeleter.DeleteToInventory( 2278 m_asyncSceneObjectDeleter.DeleteToInventory(
2197 action, destinationID, deleteGroups, remoteClient, 2279 action, destinationID, deleteGroups, remoteClient,
2198 permissionToDelete && canDelete); 2280 true);
2199 } 2281 }
2200 else if (permissionToDelete && canDelete) 2282 if (takeGroups.Count > 0)
2283 {
2284 m_asyncSceneObjectDeleter.DeleteToInventory(
2285 action, destinationID, takeGroups, remoteClient,
2286 false);
2287 }
2288 if (deleteIDs.Count > 0)
2201 { 2289 {
2202 foreach (SceneObjectGroup g in deleteGroups) 2290 foreach (SceneObjectGroup g in deleteGroups)
2203 DeleteSceneObject(g, false); 2291 DeleteSceneObject(g, true);
2292 }
2293 }
2294
2295 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
2296 {
2297 itemID = UUID.Zero;
2298 if (grp != null)
2299 {
2300 Vector3 inventoryStoredPosition = new Vector3(
2301 Math.Min(grp.AbsolutePosition.X, RegionInfo.RegionSizeX - 6),
2302 Math.Min(grp.AbsolutePosition.Y, RegionInfo.RegionSizeY - 6),
2303 grp.AbsolutePosition.Z);
2304
2305 Vector3 originalPosition = grp.AbsolutePosition;
2306
2307 grp.AbsolutePosition = inventoryStoredPosition;
2308
2309 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
2310
2311 grp.AbsolutePosition = originalPosition;
2312
2313 AssetBase asset = CreateAsset(
2314 grp.GetPartName(grp.LocalId),
2315 grp.GetPartDescription(grp.LocalId),
2316 (sbyte)AssetType.Object,
2317 Utils.StringToBytes(sceneObjectXml),
2318 remoteClient.AgentId);
2319 AssetService.Store(asset);
2320
2321 InventoryItemBase item = new InventoryItemBase();
2322 item.CreatorId = grp.RootPart.CreatorID.ToString();
2323 item.CreatorData = grp.RootPart.CreatorData;
2324 item.Owner = remoteClient.AgentId;
2325 item.ID = UUID.Random();
2326 item.AssetID = asset.FullID;
2327 item.Description = asset.Description;
2328 item.Name = asset.Name;
2329 item.AssetType = asset.Type;
2330 item.InvType = (int)InventoryType.Object;
2331
2332 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, FolderType.Object);
2333 if (folder != null)
2334 item.Folder = folder.ID;
2335 else // oopsies
2336 item.Folder = UUID.Zero;
2337
2338 // Set up base perms properly
2339 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
2340 permsBase &= grp.RootPart.BaseMask;
2341 permsBase |= (uint)PermissionMask.Move;
2342
2343 // Make sure we don't lock it
2344 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
2345
2346 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2347 {
2348 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2349 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2350 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2351 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2352 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2353 }
2354 else
2355 {
2356 item.BasePermissions = permsBase;
2357 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2358 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2359 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2360 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2361 }
2362 item.CreationDate = Util.UnixTimeSinceEpoch();
2363
2364 // sets itemID so client can show item as 'attached' in inventory
2365 grp.FromItemID = item.ID;
2366
2367 if (AddInventoryItem(item))
2368 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2369 else
2370 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2371
2372 itemID = item.ID;
2373 return item.AssetID;
2204 } 2374 }
2375 return UUID.Zero;
2205 } 2376 }
2206 2377
2207 /// <summary> 2378 /// <summary>
@@ -2254,7 +2425,7 @@ namespace OpenSim.Region.Framework.Scenes
2254 Util.LogFailedXML("[AGENT INVENTORY]:", xmlData); 2425 Util.LogFailedXML("[AGENT INVENTORY]:", xmlData);
2255 g = null; 2426 g = null;
2256 } 2427 }
2257 2428
2258 if (g != null) 2429 if (g != null)
2259 { 2430 {
2260 objlist.Add(g); 2431 objlist.Add(g);
@@ -2265,7 +2436,7 @@ namespace OpenSim.Region.Framework.Scenes
2265 return true; 2436 return true;
2266 } 2437 }
2267 else 2438 else
2268 { 2439 {
2269 XmlDocument doc = new XmlDocument(); 2440 XmlDocument doc = new XmlDocument();
2270 doc.LoadXml(xmlData); 2441 doc.LoadXml(xmlData);
2271 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject"); 2442 XmlElement e = (XmlElement)doc.SelectSingleNode("/CoalescedObject");
@@ -2371,7 +2542,7 @@ namespace OpenSim.Region.Framework.Scenes
2371 RayStart, RayEnd, RayTargetID, Quaternion.Identity, 2542 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
2372 BypassRayCast, bRayEndIsIntersection, true, scale, false); 2543 BypassRayCast, bRayEndIsIntersection, true, scale, false);
2373 2544
2374 RezObject(part, item, pos, null, Vector3.Zero, 0); 2545 RezObject(part, item, pos, null, Vector3.Zero, 0, false);
2375 } 2546 }
2376 } 2547 }
2377 2548
@@ -2387,15 +2558,18 @@ namespace OpenSim.Region.Framework.Scenes
2387 /// <param name="param"></param> 2558 /// <param name="param"></param>
2388 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns> 2559 /// <returns>The SceneObjectGroup(s) rezzed, or null if rez was unsuccessful</returns>
2389 public virtual List<SceneObjectGroup> RezObject( 2560 public virtual List<SceneObjectGroup> RezObject(
2390 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param) 2561 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param, bool atRoot)
2391 { 2562 {
2392 if (null == item) 2563 if (null == item)
2393 return null; 2564 return null;
2394 2565
2395 List<SceneObjectGroup> objlist; 2566 List<SceneObjectGroup> objlist;
2396 List<Vector3> veclist; 2567 List<Vector3> veclist;
2397 2568 Vector3 bbox;
2398 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist); 2569 float offsetHeight;
2570
2571 bool success = sourcePart.Inventory.GetRezReadySceneObjects(item, out objlist, out veclist,out bbox, out offsetHeight);
2572
2399 if (!success) 2573 if (!success)
2400 return null; 2574 return null;
2401 2575
@@ -2412,10 +2586,69 @@ namespace OpenSim.Region.Framework.Scenes
2412 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2586 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2413 } 2587 }
2414 2588
2589 SceneObjectGroup sog;
2590
2591 bool fixrot = false;
2592 Quaternion netRot = Quaternion.Identity;
2593
2594 // position adjust
2595 if (totalPrims > 1) // nothing to do on a single prim
2596 {
2597 if (objlist.Count == 1)
2598 {
2599 // current object position is root position
2600 if(!atRoot)
2601 {
2602 sog = objlist[0];
2603 Quaternion orot;
2604 if (rot == null)
2605 orot = sog.RootPart.GetWorldRotation();
2606 else
2607 orot = rot.Value;
2608 // possible should be bbox, but geometric center looks better
2609 Vector3 off = sog.GetGeometricCenter();
2610// Vector3 off = bbox * 0.5f;
2611 off *= orot;
2612 pos -= off;
2613 }
2614 }
2615 else
2616 {
2617 //veclist[] are relative to bbox corner with min X,Y and Z
2618 // rez at root, and rot will be referenced to first object in list
2619 if (rot == null)
2620 {
2621 // use original rotations
2622 if (atRoot)
2623 pos -= veclist[0];
2624 else
2625 pos -= bbox / 2;
2626 }
2627 else
2628 {
2629 fixrot = true;
2630 sog = objlist[0];
2631 netRot = Quaternion.Conjugate(sog.RootPart.GetWorldRotation());
2632 netRot = netRot * rot.Value;
2633 Vector3 off;
2634 if (atRoot)
2635 off = veclist[0];
2636 else
2637 off = bbox / 2;
2638 off *= netRot;
2639 pos -= off;
2640 }
2641 }
2642 }
2643
2415 for (int i = 0; i < objlist.Count; i++) 2644 for (int i = 0; i < objlist.Count; i++)
2416 { 2645 {
2417 SceneObjectGroup group = objlist[i]; 2646 SceneObjectGroup group = objlist[i];
2418 Vector3 curpos = pos + veclist[i]; 2647 Vector3 curpos;
2648 if(fixrot)
2649 curpos = pos + veclist[i] * netRot;
2650 else
2651 curpos = pos + veclist[i];
2419 2652
2420 if (group.IsAttachment == false && group.RootPart.Shape.State != 0) 2653 if (group.IsAttachment == false && group.RootPart.Shape.State != 0)
2421 { 2654 {
@@ -2424,7 +2657,17 @@ namespace OpenSim.Region.Framework.Scenes
2424 } 2657 }
2425 2658
2426 group.FromPartID = sourcePart.UUID; 2659 group.FromPartID = sourcePart.UUID;
2427 AddNewSceneObject(group, true, curpos, rot, vel); 2660 if( i == 0)
2661 AddNewSceneObject(group, true, curpos, rot, vel);
2662 else
2663 {
2664 Quaternion crot = objlist[i].RootPart.GetWorldRotation();
2665 if (fixrot)
2666 {
2667 crot *= netRot;
2668 }
2669 AddNewSceneObject(group, true, curpos, crot, vel);
2670 }
2428 2671
2429 // We can only call this after adding the scene object, since the scene object references the scene 2672 // We can only call this after adding the scene object, since the scene object references the scene
2430 // to find out if scripts should be activated at all. 2673 // to find out if scripts should be activated at all.
@@ -2455,6 +2698,9 @@ namespace OpenSim.Region.Framework.Scenes
2455 2698
2456 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2699 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2457 { 2700 {
2701 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2702 return;
2703
2458 SceneObjectPart part = GetSceneObjectPart(objectID); 2704 SceneObjectPart part = GetSceneObjectPart(objectID);
2459 if (part == null) 2705 if (part == null)
2460 return; 2706 return;
@@ -2511,7 +2757,10 @@ namespace OpenSim.Region.Framework.Scenes
2511 } 2757 }
2512 else 2758 else
2513 { 2759 {
2514 if (!Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)) 2760 if (!Permissions.IsGod(remoteClient.AgentId) && sog.OwnerID != remoteClient.AgentId)
2761 continue;
2762
2763 if (!Permissions.CanTransferObject(sog.UUID, groupID))
2515 continue; 2764 continue;
2516 2765
2517 if (sog.GroupID != groupID) 2766 if (sog.GroupID != groupID)
@@ -2622,7 +2871,18 @@ namespace OpenSim.Region.Framework.Scenes
2622 return; 2871 return;
2623 } 2872 }
2624 2873
2874 bool oldUsePhysics = (root.Flags & PrimFlags.Physics) != 0;
2625 m_sceneGraph.LinkObjects(root, children); 2875 m_sceneGraph.LinkObjects(root, children);
2876
2877 ScenePresence sp;
2878 if (TryGetScenePresence(agentId, out sp))
2879 {
2880 root.SendPropertiesToClient(sp.ControllingClient);
2881 if (oldUsePhysics && (root.Flags & PrimFlags.Physics) == 0)
2882 {
2883 sp.ControllingClient.SendAlertMessage("Object physics canceled");
2884 }
2885 }
2626 } 2886 }
2627 2887
2628 private string PermissionString(uint permissions) 2888 private string PermissionString(uint permissions)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 8ebcd92..34b9c5f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.Framework.Scenes
49 /// <param name='targetID'></param> 49 /// <param name='targetID'></param>
50 /// <param name='fromAgent'></param> 50 /// <param name='fromAgent'></param>
51 /// <param name='broadcast'></param> 51 /// <param name='broadcast'></param>
52 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, 52 public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
53 UUID fromID, UUID targetID, bool fromAgent, bool broadcast) 53 UUID fromID, UUID targetID, bool fromAgent, bool broadcast)
54 { 54 {
55 OSChatMessage args = new OSChatMessage(); 55 OSChatMessage args = new OSChatMessage();
@@ -60,6 +60,7 @@ namespace OpenSim.Region.Framework.Scenes
60 args.Position = fromPos; 60 args.Position = fromPos;
61 args.SenderUUID = fromID; 61 args.SenderUUID = fromID;
62 args.Scene = this; 62 args.Scene = this;
63 args.Destination = targetID;
63 64
64 if (fromAgent) 65 if (fromAgent)
65 { 66 {
@@ -74,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes
74 } 75 }
75 76
76 args.From = fromName; 77 args.From = fromName;
77 args.TargetUUID = targetID; 78 //args.
78 79
79// m_log.DebugFormat( 80// m_log.DebugFormat(
80// "[SCENE]: Sending message {0} on channel {1}, type {2} from {3}, broadcast {4}", 81// "[SCENE]: Sending message {0} on channel {1}, type {2} from {3}, broadcast {4}",
@@ -85,7 +86,7 @@ namespace OpenSim.Region.Framework.Scenes
85 else 86 else
86 EventManager.TriggerOnChatFromWorld(this, args); 87 EventManager.TriggerOnChatFromWorld(this, args);
87 } 88 }
88 89
89 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, 90 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
90 UUID fromID, bool fromAgent, bool broadcast) 91 UUID fromID, bool fromAgent, bool broadcast)
91 { 92 {
@@ -129,19 +130,6 @@ namespace OpenSim.Region.Framework.Scenes
129 { 130 {
130 SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, true); 131 SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, true);
131 } 132 }
132 /// <summary>
133 ///
134 /// </summary>
135 /// <param name="message"></param>
136 /// <param name="type"></param>
137 /// <param name="fromPos"></param>
138 /// <param name="fromName"></param>
139 /// <param name="fromAgentID"></param>
140 /// <param name="targetID"></param>
141 public void SimChatToAgent(UUID targetID, byte[] message, Vector3 fromPos, string fromName, UUID fromID, bool fromAgent)
142 {
143 SimChat(message, ChatTypeEnum.Say, 0, fromPos, fromName, fromID, targetID, fromAgent, false);
144 }
145 133
146 /// <summary> 134 /// <summary>
147 /// 135 ///
@@ -178,27 +166,52 @@ namespace OpenSim.Region.Framework.Scenes
178 /// <param name="remoteClient"></param> 166 /// <param name="remoteClient"></param>
179 public void SelectPrim(uint primLocalID, IClientAPI remoteClient) 167 public void SelectPrim(uint primLocalID, IClientAPI remoteClient)
180 { 168 {
169 /*
170 SceneObjectPart part = GetSceneObjectPart(primLocalID);
171
172 if (null == part)
173 return;
174
175 if (part.IsRoot)
176 {
177 SceneObjectGroup sog = part.ParentGroup;
178 sog.SendPropertiesToClient(remoteClient);
179
180 // A prim is only tainted if it's allowed to be edited by the person clicking it.
181 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
182 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
183 {
184 sog.IsSelected = true;
185 EventManager.TriggerParcelPrimCountTainted();
186 }
187 }
188 else
189 {
190 part.SendPropertiesToClient(remoteClient);
191 }
192 */
181 SceneObjectPart part = GetSceneObjectPart(primLocalID); 193 SceneObjectPart part = GetSceneObjectPart(primLocalID);
182 194
183 if (null == part) 195 if (null == part)
184 return; 196 return;
185 197
186 if (part.IsRoot) 198 SceneObjectGroup sog = part.ParentGroup;
187 { 199 if (sog == null)
188 SceneObjectGroup sog = part.ParentGroup; 200 return;
189 sog.SendPropertiesToClient(remoteClient);
190 sog.IsSelected = true;
191 201
192 // A prim is only tainted if it's allowed to be edited by the person clicking it. 202 part.SendPropertiesToClient(remoteClient);
193 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId) 203
194 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId)) 204 // waste of time because properties do not send prim flags as they should
195 { 205 // if a friend got or lost edit rights after login, a full update is needed
196 EventManager.TriggerParcelPrimCountTainted(); 206 if(sog.OwnerID != remoteClient.AgentId)
197 } 207 part.SendFullUpdate(remoteClient);
198 } 208
199 else 209 // A prim is only tainted if it's allowed to be edited by the person clicking it.
210 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
211 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
200 { 212 {
201 part.SendPropertiesToClient(remoteClient); 213 part.IsSelected = true;
214 EventManager.TriggerParcelPrimCountTainted();
202 } 215 }
203 } 216 }
204 217
@@ -251,7 +264,7 @@ namespace OpenSim.Region.Framework.Scenes
251 SceneObjectPart part = GetSceneObjectPart(primLocalID); 264 SceneObjectPart part = GetSceneObjectPart(primLocalID);
252 if (part == null) 265 if (part == null)
253 return; 266 return;
254 267 /*
255 // A deselect packet contains all the local prims being deselected. However, since selection is still 268 // A deselect packet contains all the local prims being deselected. However, since selection is still
256 // group based we only want the root prim to trigger a full update - otherwise on objects with many prims 269 // group based we only want the root prim to trigger a full update - otherwise on objects with many prims
257 // we end up sending many duplicate ObjectUpdates 270 // we end up sending many duplicate ObjectUpdates
@@ -262,7 +275,9 @@ namespace OpenSim.Region.Framework.Scenes
262 // handled by group, but by prim. Legacy cruft. 275 // handled by group, but by prim. Legacy cruft.
263 // TODO: Make selection flagging per prim! 276 // TODO: Make selection flagging per prim!
264 // 277 //
265 part.ParentGroup.IsSelected = false; 278 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
279 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
280 part.ParentGroup.IsSelected = false;
266 281
267 part.ParentGroup.ScheduleGroupForFullUpdate(); 282 part.ParentGroup.ScheduleGroupForFullUpdate();
268 283
@@ -279,6 +294,25 @@ namespace OpenSim.Region.Framework.Scenes
279 part.UUID, remoteClient.AgentId)) 294 part.UUID, remoteClient.AgentId))
280 EventManager.TriggerParcelPrimCountTainted(); 295 EventManager.TriggerParcelPrimCountTainted();
281 } 296 }
297 */
298
299 bool oldgprSelect = part.ParentGroup.IsSelected;
300
301 // This is wrong, wrong, wrong. Selection should not be
302 // handled by group, but by prim. Legacy cruft.
303 // TODO: Make selection flagging per prim!
304 //
305 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
306 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
307 {
308 part.IsSelected = false;
309 if (!part.ParentGroup.IsAttachment && oldgprSelect != part.ParentGroup.IsSelected)
310 EventManager.TriggerParcelPrimCountTainted();
311
312 // restore targetOmega
313 if (part.AngularVelocity != Vector3.Zero)
314 part.ScheduleTerseUpdate();
315 }
282 } 316 }
283 317
284 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount, 318 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount,
@@ -433,12 +467,26 @@ namespace OpenSim.Region.Framework.Scenes
433 } 467 }
434 }); 468 });
435 } 469 }
436 470
437 private bool ShouldSendDiscardableEffect(IClientAPI thisClient, ScenePresence other) 471 private bool ShouldSendDiscardableEffect(IClientAPI thisClient, ScenePresence other)
438 { 472 {
439 return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10; 473 return Vector3.Distance(other.CameraPosition, thisClient.SceneAgent.AbsolutePosition) < 10;
440 } 474 }
441 475
476 private class DescendentsRequestData
477 {
478 public IClientAPI RemoteClient;
479 public UUID FolderID;
480 public UUID OwnerID;
481 public bool FetchFolders;
482 public bool FetchItems;
483 public int SortOrder;
484 }
485
486 private Queue<DescendentsRequestData> m_descendentsRequestQueue = new Queue<DescendentsRequestData>();
487 private Object m_descendentsRequestLock = new Object();
488 private bool m_descendentsRequestProcessing = false;
489
442 /// <summary> 490 /// <summary>
443 /// Tell the client about the various child items and folders contained in the requested folder. 491 /// Tell the client about the various child items and folders contained in the requested folder.
444 /// </summary> 492 /// </summary>
@@ -475,11 +523,31 @@ namespace OpenSim.Region.Framework.Scenes
475 } 523 }
476 } 524 }
477 525
478 // We're going to send the reply async, because there may be 526 lock (m_descendentsRequestLock)
479 // an enormous quantity of packets -- basically the entire inventory! 527 {
480 // We don't want to block the client thread while all that is happening. 528 if (!m_descendentsRequestProcessing)
481 SendInventoryDelegate d = SendInventoryAsync; 529 {
482 d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d); 530 m_descendentsRequestProcessing = true;
531
532 // We're going to send the reply async, because there may be
533 // an enormous quantity of packets -- basically the entire inventory!
534 // We don't want to block the client thread while all that is happening.
535 SendInventoryDelegate d = SendInventoryAsync;
536 d.BeginInvoke(remoteClient, folderID, ownerID, fetchFolders, fetchItems, sortOrder, SendInventoryComplete, d);
537
538 return;
539 }
540
541 DescendentsRequestData req = new DescendentsRequestData();
542 req.RemoteClient = remoteClient;
543 req.FolderID = folderID;
544 req.OwnerID = ownerID;
545 req.FetchFolders = fetchFolders;
546 req.FetchItems = fetchItems;
547 req.SortOrder = sortOrder;
548
549 m_descendentsRequestQueue.Enqueue(req);
550 }
483 } 551 }
484 552
485 delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder); 553 delegate void SendInventoryDelegate(IClientAPI remoteClient, UUID folderID, UUID ownerID, bool fetchFolders, bool fetchItems, int sortOrder);
@@ -496,12 +564,28 @@ namespace OpenSim.Region.Framework.Scenes
496 string.Format( 564 string.Format(
497 "[AGENT INVENTORY]: Error in SendInventoryAsync() for {0} with folder ID {1}. Exception ", e)); 565 "[AGENT INVENTORY]: Error in SendInventoryAsync() for {0} with folder ID {1}. Exception ", e));
498 } 566 }
567 Thread.Sleep(20);
499 } 568 }
500 569
501 void SendInventoryComplete(IAsyncResult iar) 570 void SendInventoryComplete(IAsyncResult iar)
502 { 571 {
503 SendInventoryDelegate d = (SendInventoryDelegate)iar.AsyncState; 572 SendInventoryDelegate d = (SendInventoryDelegate)iar.AsyncState;
504 d.EndInvoke(iar); 573 d.EndInvoke(iar);
574
575 lock (m_descendentsRequestLock)
576 {
577 if (m_descendentsRequestQueue.Count > 0)
578 {
579 DescendentsRequestData req = m_descendentsRequestQueue.Dequeue();
580
581 d = SendInventoryAsync;
582 d.BeginInvoke(req.RemoteClient, req.FolderID, req.OwnerID, req.FetchFolders, req.FetchItems, req.SortOrder, SendInventoryComplete, d);
583
584 return;
585 }
586
587 m_descendentsRequestProcessing = false;
588 }
505 } 589 }
506 590
507 /// <summary> 591 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index 535d87a..4d90726 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -70,7 +70,7 @@ namespace OpenSim.Region.Framework.Scenes
70 public delegate bool IsGridGodHandler(UUID user, Scene requestFromScene); 70 public delegate bool IsGridGodHandler(UUID user, Scene requestFromScene);
71 public delegate bool IsAdministratorHandler(UUID user); 71 public delegate bool IsAdministratorHandler(UUID user);
72 public delegate bool EditParcelHandler(UUID user, ILandObject parcel, Scene scene); 72 public delegate bool EditParcelHandler(UUID user, ILandObject parcel, Scene scene);
73 public delegate bool EditParcelPropertiesHandler(UUID user, ILandObject parcel, GroupPowers p, Scene scene); 73 public delegate bool EditParcelPropertiesHandler(UUID user, ILandObject parcel, GroupPowers p, Scene scene, bool allowManager);
74 public delegate bool SellParcelHandler(UUID user, ILandObject parcel, Scene scene); 74 public delegate bool SellParcelHandler(UUID user, ILandObject parcel, Scene scene);
75 public delegate bool AbandonParcelHandler(UUID user, ILandObject parcel, Scene scene); 75 public delegate bool AbandonParcelHandler(UUID user, ILandObject parcel, Scene scene);
76 public delegate bool ReclaimParcelHandler(UUID user, ILandObject parcel, Scene scene); 76 public delegate bool ReclaimParcelHandler(UUID user, ILandObject parcel, Scene scene);
@@ -763,7 +763,7 @@ namespace OpenSim.Region.Framework.Scenes
763 763
764 #region EDIT PARCEL 764 #region EDIT PARCEL
765 765
766 public bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p) 766 public bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p, bool allowManager)
767 { 767 {
768 EditParcelPropertiesHandler handler = OnEditParcelProperties; 768 EditParcelPropertiesHandler handler = OnEditParcelProperties;
769 if (handler != null) 769 if (handler != null)
@@ -771,7 +771,7 @@ namespace OpenSim.Region.Framework.Scenes
771 Delegate[] list = handler.GetInvocationList(); 771 Delegate[] list = handler.GetInvocationList();
772 foreach (EditParcelPropertiesHandler h in list) 772 foreach (EditParcelPropertiesHandler h in list)
773 { 773 {
774 if (h(user, parcel, p, m_scene) == false) 774 if (h(user, parcel, p, m_scene, allowManager) == false)
775 return false; 775 return false;
776 } 776 }
777 } 777 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 2fe6e22..2fcb78d 100755
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -61,8 +61,7 @@ namespace OpenSim.Region.Framework.Scenes
61 { 61 {
62 private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L; 62 private const long DEFAULT_MIN_TIME_FOR_PERSISTENCE = 60L;
63 private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L; 63 private const long DEFAULT_MAX_TIME_FOR_PERSISTENCE = 600L;
64 64
65 public const int m_defaultNumberFramesStored = 10;
66 65
67 public delegate void SynchronizeSceneHandler(Scene scene); 66 public delegate void SynchronizeSceneHandler(Scene scene);
68 67
@@ -105,9 +104,10 @@ namespace OpenSim.Region.Framework.Scenes
105 /// <summary> 104 /// <summary>
106 /// If false then physical objects are disabled, though collisions will continue as normal. 105 /// If false then physical objects are disabled, though collisions will continue as normal.
107 /// </summary> 106 /// </summary>
108 public bool PhysicsEnabled 107
109 { 108 public bool PhysicsEnabled
110 get 109 {
110 get
111 { 111 {
112 return m_physicsEnabled; 112 return m_physicsEnabled;
113 } 113 }
@@ -216,7 +216,7 @@ namespace OpenSim.Region.Framework.Scenes
216 /// <summary> 216 /// <summary>
217 /// Maximum value of the size of a physical prim in each axis 217 /// Maximum value of the size of a physical prim in each axis
218 /// </summary> 218 /// </summary>
219 public float m_maxPhys = 64; 219 public float m_maxPhys = 10;
220 220
221 /// <summary> 221 /// <summary>
222 /// Max prims an object will hold 222 /// Max prims an object will hold
@@ -228,10 +228,16 @@ namespace OpenSim.Region.Framework.Scenes
228 public bool m_allowScriptCrossings = true; 228 public bool m_allowScriptCrossings = true;
229 229
230 /// <summary> 230 /// <summary>
231
231 /// Can avatars cross from and to this region? 232 /// Can avatars cross from and to this region?
232 /// </summary> 233 /// </summary>
233 public bool AllowAvatarCrossing { get; set; } 234 public bool AllowAvatarCrossing { get; set; }
234 235
236 /// Max prims an Physical object will hold
237 /// </summary>
238 ///
239 public int m_linksetPhysCapacity = 0;
240
235 public bool m_useFlySlow; 241 public bool m_useFlySlow;
236 public bool m_useTrashOnDelete = true; 242 public bool m_useTrashOnDelete = true;
237 243
@@ -265,20 +271,17 @@ namespace OpenSim.Region.Framework.Scenes
265 /// </summary> 271 /// </summary>
266 public int ChildTerseUpdatePeriod { get; set; } 272 public int ChildTerseUpdatePeriod { get; set; }
267 273
268 protected float m_defaultDrawDistance = 255.0f; 274 protected float m_defaultDrawDistance = 255f;
269 public float DefaultDrawDistance 275 public float DefaultDrawDistance
270 { 276 {
271 // get { return m_defaultDrawDistance; } 277 get { return m_defaultDrawDistance; }
272 get 278 }
273 {
274 if (RegionInfo != null)
275 {
276 float largestDimension = Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY);
277 m_defaultDrawDistance = Math.Max(m_defaultDrawDistance, largestDimension);
278 279
279 } 280 protected float m_maxDrawDistance = 512.0f;
280 return m_defaultDrawDistance; 281// protected float m_maxDrawDistance = 256.0f;
281 } 282 public float MaxDrawDistance
283 {
284 get { return m_maxDrawDistance; }
282 } 285 }
283 286
284 private List<string> m_AllowedViewers = new List<string>(); 287 private List<string> m_AllowedViewers = new List<string>();
@@ -287,8 +290,8 @@ namespace OpenSim.Region.Framework.Scenes
287 // TODO: need to figure out how allow client agents but deny 290 // TODO: need to figure out how allow client agents but deny
288 // root agents when ACL denies access to root agent 291 // root agents when ACL denies access to root agent
289 public bool m_strictAccessControl = true; 292 public bool m_strictAccessControl = true;
290 293 public bool m_seeIntoBannedRegion = false;
291 public int MaxUndoCount { get; set; } 294 public int MaxUndoCount = 5;
292 295
293 public bool SeeIntoRegion { get; set; } 296 public bool SeeIntoRegion { get; set; }
294 297
@@ -306,11 +309,13 @@ namespace OpenSim.Region.Framework.Scenes
306 309
307 protected int m_splitRegionID; 310 protected int m_splitRegionID;
308 protected Timer m_restartWaitTimer = new Timer(); 311 protected Timer m_restartWaitTimer = new Timer();
312 protected Timer m_timerWatchdog = new Timer();
309 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 313 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
310 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 314 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
311 protected string m_simulatorVersion = "OpenSimulator Server"; 315 protected string m_simulatorVersion = "OpenSimulator Server";
312 protected AgentCircuitManager m_authenticateHandler; 316 protected AgentCircuitManager m_authenticateHandler;
313 protected SceneCommunicationService m_sceneGridService; 317 protected SceneCommunicationService m_sceneGridService;
318 protected ISnmpModule m_snmpService = null;
314 319
315 protected ISimulationDataService m_SimulationDataService; 320 protected ISimulationDataService m_SimulationDataService;
316 protected IEstateDataService m_EstateDataService; 321 protected IEstateDataService m_EstateDataService;
@@ -339,17 +344,6 @@ namespace OpenSim.Region.Framework.Scenes
339 private Dictionary<string, string> m_extraSettings; 344 private Dictionary<string, string> m_extraSettings;
340 345
341 /// <summary> 346 /// <summary>
342 /// If true then the next time the scene loop is activated, updates will be performed by firing of a timer
343 /// rather than on a single thread that sleeps.
344 /// </summary>
345 public bool UpdateOnTimer { get; set; }
346
347 /// <summary>
348 /// Only used if we are updating scene on a timer rather than sleeping a thread.
349 /// </summary>
350 private Timer m_sceneUpdateTimer;
351
352 /// <summary>
353 /// Current scene frame number 347 /// Current scene frame number
354 /// </summary> 348 /// </summary>
355 public uint Frame 349 public uint Frame
@@ -364,24 +358,9 @@ namespace OpenSim.Region.Framework.Scenes
364 public uint MaintenanceRun { get; private set; } 358 public uint MaintenanceRun { get; private set; }
365 359
366 /// <summary> 360 /// <summary>
367 /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we 361 /// Frame time
368 /// will sleep for the remaining period.
369 /// </summary>
370 /// <remarks>
371 /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations
372 /// occur too quickly (viewer 1) or with even more slide (viewer 2).
373 /// </remarks> 362 /// </remarks>
374 public int MinFrameTicks 363 public float FrameTime { get; private set; }
375 {
376 get { return m_minFrameTicks; }
377 private set
378 {
379 m_minFrameTicks = value;
380 MinFrameSeconds = (float)m_minFrameTicks / 1000;
381 }
382 }
383 private int m_minFrameTicks;
384
385 public int FrameTimeWarnPercent { get; private set; } 364 public int FrameTimeWarnPercent { get; private set; }
386 public int FrameTimeCritPercent { get; private set; } 365 public int FrameTimeCritPercent { get; private set; }
387 366
@@ -395,17 +374,7 @@ namespace OpenSim.Region.Framework.Scenes
395 /// <remarks> 374 /// <remarks>
396 /// Always derived from MinFrameTicks. 375 /// Always derived from MinFrameTicks.
397 /// </remarks> 376 /// </remarks>
398 public float MinFrameSeconds { get; private set; } 377 public float MinMaintenanceTime { get; private set; }
399
400 /// <summary>
401 /// The minimum length of time in milliseconds that will be taken for a scene frame. If the frame takes less time then we
402 /// will sleep for the remaining period.
403 /// </summary>
404 /// <remarks>
405 /// One can tweak this number to experiment. One current effect of reducing it is to make avatar animations
406 /// occur too quickly (viewer 1) or with even more slide (viewer 2).
407 /// </remarks>
408 public int MinMaintenanceTicks { get; set; }
409 378
410 private int m_update_physics = 1; 379 private int m_update_physics = 1;
411 private int m_update_entitymovement = 1; 380 private int m_update_entitymovement = 1;
@@ -413,22 +382,23 @@ namespace OpenSim.Region.Framework.Scenes
413 private int m_update_presences = 1; // Update scene presence movements 382 private int m_update_presences = 1; // Update scene presence movements
414 private int m_update_events = 1; 383 private int m_update_events = 1;
415 private int m_update_backup = 200; 384 private int m_update_backup = 200;
416 private int m_update_terrain = 50; 385
417 // private int m_update_land = 1; 386 private int m_update_terrain = 1000;
387 private int m_update_land = 10;
388
418 private int m_update_coarse_locations = 50; 389 private int m_update_coarse_locations = 50;
419 private int m_update_temp_cleaning = 180; 390 private int m_update_temp_cleaning = 180;
420 391
421 private int agentMS; 392 private float agentMS;
422 private int frameMS; 393 private float frameMS;
423 private int physicsMS2; 394 private float physicsMS2;
424 private int physicsMS; 395 private float physicsMS;
425 private int otherMS; 396 private float otherMS;
426 private int tempOnRezMS; 397 private float tempOnRezMS;
427 private int eventMS; 398 private float eventMS;
428 private int backupMS; 399 private float backupMS;
429 private int terrainMS; 400 private float terrainMS;
430 private int landMS; 401 private float landMS;
431 private int spareMS;
432 402
433 // A temporary configuration flag to enable using FireAndForget to process 403 // A temporary configuration flag to enable using FireAndForget to process
434 // collisions from the physics engine. There is a problem with collisions 404 // collisions from the physics engine. There is a problem with collisions
@@ -446,6 +416,7 @@ namespace OpenSim.Region.Framework.Scenes
446 /// </summary> 416 /// </summary>
447 private int m_lastFrameTick; 417 private int m_lastFrameTick;
448 418
419 public bool CombineRegions = false;
449 /// <summary> 420 /// <summary>
450 /// Tick at which the last maintenance run occurred. 421 /// Tick at which the last maintenance run occurred.
451 /// </summary> 422 /// </summary>
@@ -477,7 +448,7 @@ namespace OpenSim.Region.Framework.Scenes
477 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing 448 private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing
478 private volatile bool m_backingup; 449 private volatile bool m_backingup;
479 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>(); 450 private Dictionary<UUID, ReturnInfo> m_returns = new Dictionary<UUID, ReturnInfo>();
480 private Dictionary<UUID, SceneObjectGroup> m_groupsWithTargets = new Dictionary<UUID, SceneObjectGroup>(); 451 private Dictionary<UUID, int> m_groupsWithTargets = new Dictionary<UUID, int>();
481 452
482 private string m_defaultScriptEngine; 453 private string m_defaultScriptEngine;
483 454
@@ -492,6 +463,11 @@ namespace OpenSim.Region.Framework.Scenes
492 /// </summary> 463 /// </summary>
493 private int m_LastLogin; 464 private int m_LastLogin;
494 465
466 private int m_lastIncoming;
467 private int m_lastOutgoing;
468 private int m_hbRestarts = 0;
469
470
495 /// <summary> 471 /// <summary>
496 /// Thread that runs the scene loop. 472 /// Thread that runs the scene loop.
497 /// </summary> 473 /// </summary>
@@ -540,6 +516,16 @@ namespace OpenSim.Region.Framework.Scenes
540 public bool IsRunning { get { return m_isRunning; } } 516 public bool IsRunning { get { return m_isRunning; } }
541 private volatile bool m_isRunning; 517 private volatile bool m_isRunning;
542 518
519// private int m_lastUpdate;
520 private bool m_firstHeartbeat = true;
521
522 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time;
523 private bool m_reprioritizationEnabled = true;
524 private double m_reprioritizationInterval = 5000.0;
525 private double m_rootReprioritizationDistance = 10.0;
526 private double m_childReprioritizationDistance = 20.0;
527
528
543 private Timer m_mapGenerationTimer = new Timer(); 529 private Timer m_mapGenerationTimer = new Timer();
544 private bool m_generateMaptiles; 530 private bool m_generateMaptiles;
545 531
@@ -571,6 +557,19 @@ namespace OpenSim.Region.Framework.Scenes
571 get { return m_sceneGridService; } 557 get { return m_sceneGridService; }
572 } 558 }
573 559
560 public ISnmpModule SnmpService
561 {
562 get
563 {
564 if (m_snmpService == null)
565 {
566 m_snmpService = RequestModuleInterface<ISnmpModule>();
567 }
568
569 return m_snmpService;
570 }
571 }
572
574 public ISimulationDataService SimulationDataService 573 public ISimulationDataService SimulationDataService
575 { 574 {
576 get 575 get
@@ -777,15 +776,15 @@ namespace OpenSim.Region.Framework.Scenes
777 get { return m_capsModule; } 776 get { return m_capsModule; }
778 } 777 }
779 778
780 public int MonitorFrameTime { get { return frameMS; } } 779 public int MonitorFrameTime { get { return (int)frameMS; } }
781 public int MonitorPhysicsUpdateTime { get { return physicsMS; } } 780 public int MonitorPhysicsUpdateTime { get { return (int)physicsMS; } }
782 public int MonitorPhysicsSyncTime { get { return physicsMS2; } } 781 public int MonitorPhysicsSyncTime { get { return (int)physicsMS2; } }
783 public int MonitorOtherTime { get { return otherMS; } } 782 public int MonitorOtherTime { get { return (int)otherMS; } }
784 public int MonitorTempOnRezTime { get { return tempOnRezMS; } } 783 public int MonitorTempOnRezTime { get { return (int)tempOnRezMS; } }
785 public int MonitorEventTime { get { return eventMS; } } // This may need to be divided into each event? 784 public int MonitorEventTime { get { return (int)eventMS; } } // This may need to be divided into each event?
786 public int MonitorBackupTime { get { return backupMS; } } 785 public int MonitorBackupTime { get { return (int)backupMS; } }
787 public int MonitorTerrainTime { get { return terrainMS; } } 786 public int MonitorTerrainTime { get { return (int)terrainMS; } }
788 public int MonitorLandTime { get { return landMS; } } 787 public int MonitorLandTime { get { return (int)landMS; } }
789 public int MonitorLastFrameTick { get { return m_lastFrameTick; } } 788 public int MonitorLastFrameTick { get { return m_lastFrameTick; } }
790 789
791 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; } 790 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; }
@@ -863,11 +862,11 @@ namespace OpenSim.Region.Framework.Scenes
863 : this(regInfo) 862 : this(regInfo)
864 { 863 {
865 m_config = config; 864 m_config = config;
866 MinFrameTicks = 89; 865 FrameTime = 0.0908f;
867 FrameTimeWarnPercent = 60; 866 FrameTimeWarnPercent = 60;
868 FrameTimeCritPercent = 40; 867 FrameTimeCritPercent = 40;
869 Normalized55FPS = true; 868 Normalized55FPS = true;
870 MinMaintenanceTicks = 1000; 869 MinMaintenanceTime = 1;
871 SeeIntoRegion = true; 870 SeeIntoRegion = true;
872 871
873 Random random = new Random(); 872 Random random = new Random();
@@ -878,6 +877,9 @@ namespace OpenSim.Region.Framework.Scenes
878 m_SimulationDataService = simDataService; 877 m_SimulationDataService = simDataService;
879 m_EstateDataService = estateDataService; 878 m_EstateDataService = estateDataService;
880 879
880 m_lastIncoming = 0;
881 m_lastOutgoing = 0;
882
881 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 883 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
882 m_asyncSceneObjectDeleter.Enabled = true; 884 m_asyncSceneObjectDeleter.Enabled = true;
883 885
@@ -935,7 +937,7 @@ namespace OpenSim.Region.Framework.Scenes
935 EventManager.OnLandObjectRemoved += 937 EventManager.OnLandObjectRemoved +=
936 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); 938 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject);
937 939
938 RegisterDefaultSceneEvents(); 940 RegisterDefaultSceneEvents();
939 941
940 // XXX: Don't set the public property since we don't want to activate here. This needs to be handled 942 // XXX: Don't set the public property since we don't want to activate here. This needs to be handled
941 // better in the future. 943 // better in the future.
@@ -956,6 +958,11 @@ namespace OpenSim.Region.Framework.Scenes
956 StartDisabled = startupConfig.GetBoolean("StartDisabled", false); 958 StartDisabled = startupConfig.GetBoolean("StartDisabled", false);
957 959
958 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance); 960 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance);
961 m_maxDrawDistance = startupConfig.GetFloat("MaxDrawDistance", m_maxDrawDistance);
962
963 if (m_defaultDrawDistance > m_maxDrawDistance)
964 m_defaultDrawDistance = m_maxDrawDistance;
965
959 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup); 966 UseBackup = startupConfig.GetBoolean("UseSceneBackup", UseBackup);
960 if (!UseBackup) 967 if (!UseBackup)
961 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); 968 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
@@ -967,9 +974,8 @@ namespace OpenSim.Region.Framework.Scenes
967 974
968 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20); 975 MaxUndoCount = startupConfig.GetInt("MaxPrimUndos", 20);
969 976
970 PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims); 977 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
971 CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims); 978 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
972
973 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); 979 m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys);
974 if (RegionInfo.NonphysPrimMin > 0) 980 if (RegionInfo.NonphysPrimMin > 0)
975 { 981 {
@@ -989,11 +995,24 @@ namespace OpenSim.Region.Framework.Scenes
989 } 995 }
990 996
991 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 997 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
998
992 if (RegionInfo.PhysPrimMax > 0) 999 if (RegionInfo.PhysPrimMax > 0)
993 { 1000 {
994 m_maxPhys = RegionInfo.PhysPrimMax; 1001 m_maxPhys = RegionInfo.PhysPrimMax;
995 } 1002 }
996 1003
1004 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity);
1005 if (RegionInfo.LinksetCapacity > 0)
1006 {
1007 m_linksetCapacity = RegionInfo.LinksetCapacity;
1008 }
1009
1010 m_linksetPhysCapacity = startupConfig.GetInt("LinksetPhysPrims", m_linksetPhysCapacity);
1011
1012
1013 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
1014 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
1015
997 // Here, if clamping is requested in either global or 1016 // Here, if clamping is requested in either global or
998 // local config, it will be used 1017 // local config, it will be used
999 // 1018 //
@@ -1003,13 +1022,7 @@ namespace OpenSim.Region.Framework.Scenes
1003 m_clampPrimSize = true; 1022 m_clampPrimSize = true;
1004 } 1023 }
1005 1024
1006 m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); 1025 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete);
1007 if (RegionInfo.LinksetCapacity > 0)
1008 {
1009 m_linksetCapacity = RegionInfo.LinksetCapacity;
1010 }
1011
1012 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete);
1013 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 1026 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
1014 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); 1027 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
1015 m_dontPersistBefore = 1028 m_dontPersistBefore =
@@ -1020,11 +1033,11 @@ namespace OpenSim.Region.Framework.Scenes
1020 m_persistAfter *= 10000000; 1033 m_persistAfter *= 10000000;
1021 1034
1022 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 1035 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
1023 1036 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
1024 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
1025 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
1026 1037
1027 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 1038 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
1039 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
1040 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
1028 1041
1029 string[] possibleMapConfigSections = new string[] { "Map", "Startup" }; 1042 string[] possibleMapConfigSections = new string[] { "Map", "Startup" };
1030 1043
@@ -1070,7 +1083,7 @@ namespace OpenSim.Region.Framework.Scenes
1070 1083
1071 if (grant.Length > 0) 1084 if (grant.Length > 0)
1072 { 1085 {
1073 foreach (string viewer in grant.Split('|')) 1086 foreach (string viewer in grant.Split(','))
1074 { 1087 {
1075 m_AllowedViewers.Add(viewer.Trim().ToLower()); 1088 m_AllowedViewers.Add(viewer.Trim().ToLower());
1076 } 1089 }
@@ -1086,17 +1099,16 @@ namespace OpenSim.Region.Framework.Scenes
1086 1099
1087 if (grant.Length > 0) 1100 if (grant.Length > 0)
1088 { 1101 {
1089 foreach (string viewer in grant.Split('|')) 1102 foreach (string viewer in grant.Split(','))
1090 { 1103 {
1091 m_BannedViewers.Add(viewer.Trim().ToLower()); 1104 m_BannedViewers.Add(viewer.Trim().ToLower());
1092 } 1105 }
1093 } 1106 }
1094 1107
1095 if (startupConfig.Contains("MinFrameTime")) 1108 FrameTime = startupConfig.GetFloat( "FrameTime", FrameTime);
1096 MinFrameTicks = (int)(startupConfig.GetFloat("MinFrameTime") * 1000);
1097 FrameTimeWarnPercent = startupConfig.GetInt( "FrameTimeWarnPercent", FrameTimeWarnPercent); 1109 FrameTimeWarnPercent = startupConfig.GetInt( "FrameTimeWarnPercent", FrameTimeWarnPercent);
1098 FrameTimeCritPercent = startupConfig.GetInt( "FrameTimeCritPercent", FrameTimeCritPercent); 1110 FrameTimeCritPercent = startupConfig.GetInt( "FrameTimeCritPercent", FrameTimeCritPercent);
1099 Normalized55FPS = startupConfig.GetBoolean( "Normalized55FPS", Normalized55FPS); 1111 Normalized55FPS = startupConfig.GetBoolean( "Normalized55FPS", Normalized55FPS);
1100 1112
1101 m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup); 1113 m_update_backup = startupConfig.GetInt("UpdateStorageEveryNFrames", m_update_backup);
1102 m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 1114 m_update_coarse_locations = startupConfig.GetInt("UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
@@ -1174,39 +1186,12 @@ namespace OpenSim.Region.Framework.Scenes
1174 1186
1175 #endregion Interest Management 1187 #endregion Interest Management
1176 1188
1177 // The timer used by the Stopwatch class depends on the system hardware and operating system; inform
1178 // if the timer is based on a high-resolution performance counter or based on the system timer;
1179 // the performance counter will provide a more precise time than the system timer
1180 if (Stopwatch.IsHighResolution)
1181 m_log.InfoFormat("[SCENE]: Using high-resolution performance counter for statistics.");
1182 else
1183 m_log.InfoFormat("[SCENE]: Using system timer for statistics.");
1184 1189
1185 // Acquire the statistics section of the OpenSim.ini file located 1190 StatsReporter = new SimStatsReporter(this);
1186 // in the bin directory
1187 IConfig statisticsConfig = m_config.Configs["Statistics"];
1188
1189 // Confirm that the statistics section existed in the configuration
1190 // file
1191 if (statisticsConfig != null)
1192 {
1193 // Create the StatsReporter using the number of frames to store
1194 // for the frame time statistics, or 10 frames if the config
1195 // file doesn't contain a value
1196 StatsReporter = new SimStatsReporter(this,
1197 statisticsConfig.GetInt("NumberOfFrames",
1198 m_defaultNumberFramesStored));
1199 }
1200 else
1201 {
1202 // Create a StatsReporter with the current scene and a default
1203 // 10 frames stored for the frame time statistics
1204 StatsReporter = new SimStatsReporter(this);
1205 }
1206 1191
1207 StatsReporter.OnSendStatsResult += SendSimStatsPackets; 1192 StatsReporter.OnSendStatsResult += SendSimStatsPackets;
1208 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; 1193 StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats;
1209 1194
1210 } 1195 }
1211 1196
1212 public Scene(RegionInfo regInfo) 1197 public Scene(RegionInfo regInfo)
@@ -1249,6 +1234,7 @@ namespace OpenSim.Region.Framework.Scenes
1249 m_eventManager = new EventManager(); 1234 m_eventManager = new EventManager();
1250 1235
1251 m_permissions = new ScenePermissions(this); 1236 m_permissions = new ScenePermissions(this);
1237
1252 } 1238 }
1253 1239
1254 #endregion 1240 #endregion
@@ -1285,7 +1271,6 @@ namespace OpenSim.Region.Framework.Scenes
1285 if (!fm.TryGetFeature("OpenSimExtras", out openSimExtras)) 1271 if (!fm.TryGetFeature("OpenSimExtras", out openSimExtras))
1286 openSimExtras = new OSDMap(); 1272 openSimExtras = new OSDMap();
1287 1273
1288 float FrameTime = MinFrameTicks / 1000.0f;
1289 float statisticsFPSfactor = 1.0f; 1274 float statisticsFPSfactor = 1.0f;
1290 if(Normalized55FPS) 1275 if(Normalized55FPS)
1291 statisticsFPSfactor = 55.0f * FrameTime; 1276 statisticsFPSfactor = 55.0f * FrameTime;
@@ -1325,20 +1310,8 @@ namespace OpenSim.Region.Framework.Scenes
1325 { 1310 {
1326 if (RegionInfo.RegionHandle != otherRegion.RegionHandle) 1311 if (RegionInfo.RegionHandle != otherRegion.RegionHandle)
1327 { 1312 {
1328 //// If these are cast to INT because long + negative values + abs returns invalid data
1329 //int resultX = Math.Abs((int)xcell - (int)RegionInfo.RegionLocX);
1330 //int resultY = Math.Abs((int)ycell - (int)RegionInfo.RegionLocY);
1331 //if (resultX <= 1 && resultY <= 1)
1332 float dist = (float)Math.Max(DefaultDrawDistance,
1333 (float)Math.Max(RegionInfo.RegionSizeX, RegionInfo.RegionSizeY));
1334 uint newRegionX, newRegionY, thisRegionX, thisRegionY;
1335 Util.RegionHandleToRegionLoc(otherRegion.RegionHandle, out newRegionX, out newRegionY);
1336 Util.RegionHandleToRegionLoc(RegionInfo.RegionHandle, out thisRegionX, out thisRegionY);
1337 1313
1338 //m_log.InfoFormat("[SCENE]: (on region {0}): Region {1} up in coords {2}-{3}", 1314 if (isNeighborRegion(otherRegion))
1339 // RegionInfo.RegionName, otherRegion.RegionName, newRegionX, newRegionY);
1340
1341 if (!Util.IsOutsideView(dist, thisRegionX, newRegionX, thisRegionY, newRegionY))
1342 { 1315 {
1343 // Let the grid service module know, so this can be cached 1316 // Let the grid service module know, so this can be cached
1344 m_eventManager.TriggerOnRegionUp(otherRegion); 1317 m_eventManager.TriggerOnRegionUp(otherRegion);
@@ -1373,6 +1346,21 @@ namespace OpenSim.Region.Framework.Scenes
1373 } 1346 }
1374 } 1347 }
1375 1348
1349 public bool isNeighborRegion(GridRegion otherRegion)
1350 {
1351 int tmp = otherRegion.RegionLocX - (int)RegionInfo.WorldLocX; ;
1352
1353 if (tmp < -otherRegion.RegionSizeX && tmp > RegionInfo.RegionSizeX)
1354 return false;
1355
1356 tmp = otherRegion.RegionLocY - (int)RegionInfo.WorldLocY;
1357
1358 if (tmp < -otherRegion.RegionSizeY && tmp > RegionInfo.RegionSizeY)
1359 return false;
1360
1361 return true;
1362 }
1363
1376 public void AddNeighborRegion(RegionInfo region) 1364 public void AddNeighborRegion(RegionInfo region)
1377 { 1365 {
1378 lock (m_neighbours) 1366 lock (m_neighbours)
@@ -1504,8 +1492,11 @@ namespace OpenSim.Region.Framework.Scenes
1504 // Stop all client threads. 1492 // Stop all client threads.
1505 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); }); 1493 ForEachScenePresence(delegate(ScenePresence avatar) { CloseAgent(avatar.UUID, false); });
1506 1494
1507 m_log.Debug("[SCENE]: Persisting changed objects"); 1495 m_log.Debug("[SCENE]: TriggerSceneShuttingDown");
1508 EventManager.TriggerSceneShuttingDown(this); 1496 EventManager.TriggerSceneShuttingDown(this);
1497
1498 m_log.Debug("[SCENE]: Persisting changed objects");
1499
1509 Backup(false); 1500 Backup(false);
1510 m_sceneGraph.Close(); 1501 m_sceneGraph.Close();
1511 1502
@@ -1519,6 +1510,7 @@ namespace OpenSim.Region.Framework.Scenes
1519 // attempt to reference a null or disposed physics scene. 1510 // attempt to reference a null or disposed physics scene.
1520 if (PhysicsScene != null) 1511 if (PhysicsScene != null)
1521 { 1512 {
1513 m_log.Debug("[SCENE]: Dispose Physics");
1522 PhysicsScene phys = PhysicsScene; 1514 PhysicsScene phys = PhysicsScene;
1523 // remove the physics engine from both Scene and SceneGraph 1515 // remove the physics engine from both Scene and SceneGraph
1524 PhysicsScene = null; 1516 PhysicsScene = null;
@@ -1550,10 +1542,28 @@ namespace OpenSim.Region.Framework.Scenes
1550// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); 1542// m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName);
1551 if (m_heartbeatThread != null) 1543 if (m_heartbeatThread != null)
1552 { 1544 {
1545 m_hbRestarts++;
1546 if(m_hbRestarts > 10)
1547 Environment.Exit(1);
1548 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1549
1550//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1551//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1552//proc.EnableRaisingEvents=false;
1553//proc.StartInfo.FileName = "/bin/kill";
1554//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1555//proc.Start();
1556//proc.WaitForExit();
1557//Thread.Sleep(1000);
1558//Environment.Exit(1);
1553 m_heartbeatThread.Abort(); 1559 m_heartbeatThread.Abort();
1560 Watchdog.AbortThread(m_heartbeatThread.ManagedThreadId);
1554 m_heartbeatThread = null; 1561 m_heartbeatThread = null;
1555 } 1562 }
1556 1563
1564 // tell physics to finish building actor
1565 m_sceneGraph.ProcessPhysicsPreSimulation();
1566
1557 m_heartbeatThread 1567 m_heartbeatThread
1558 = WorkManager.StartThread( 1568 = WorkManager.StartThread(
1559 Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false); 1569 Heartbeat, string.Format("Heartbeat-({0})", RegionInfo.RegionName.Replace(" ", "_")), ThreadPriority.Normal, false, false);
@@ -1601,45 +1611,8 @@ namespace OpenSim.Region.Framework.Scenes
1601 1611
1602 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; 1612 Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true;
1603 m_lastFrameTick = Util.EnvironmentTickCount(); 1613 m_lastFrameTick = Util.EnvironmentTickCount();
1604 1614 Update(-1);
1605 if (UpdateOnTimer) 1615 }
1606 {
1607 m_sceneUpdateTimer = new Timer(MinFrameTicks);
1608 m_sceneUpdateTimer.AutoReset = true;
1609 m_sceneUpdateTimer.Elapsed += Update;
1610 m_sceneUpdateTimer.Start();
1611 }
1612 else
1613 {
1614 Thread.CurrentThread.Priority = ThreadPriority.Highest;
1615 Update(-1);
1616 Watchdog.RemoveThread();
1617 m_isRunning = false;
1618 }
1619 }
1620
1621 private volatile bool m_isTimerUpdateRunning;
1622
1623 private void Update(object sender, ElapsedEventArgs e)
1624 {
1625 if (m_isTimerUpdateRunning)
1626 return;
1627
1628 m_isTimerUpdateRunning = true;
1629
1630 // If the last frame did not complete on time, then immediately start the next update on the same thread
1631 // and ignore further timed updates until we have a frame that had spare time.
1632 while (!Update(1) && Active) { }
1633
1634 if (!Active || m_shuttingDown)
1635 {
1636 m_sceneUpdateTimer.Stop();
1637 m_sceneUpdateTimer = null;
1638 m_isRunning = false;
1639 }
1640
1641 m_isTimerUpdateRunning = false;
1642 }
1643 1616
1644 private void Maintenance() 1617 private void Maintenance()
1645 { 1618 {
@@ -1708,24 +1681,24 @@ namespace OpenSim.Region.Framework.Scenes
1708 previousMaintenanceTick = m_lastMaintenanceTick; 1681 previousMaintenanceTick = m_lastMaintenanceTick;
1709 m_lastMaintenanceTick = Util.EnvironmentTickCount(); 1682 m_lastMaintenanceTick = Util.EnvironmentTickCount();
1710 runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc); 1683 runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc);
1711 runtc = MinMaintenanceTicks - runtc; 1684 runtc = (int)(MinMaintenanceTime * 1000) - runtc;
1712 1685
1713 if (runtc > 0) 1686 if (runtc > 0)
1714 m_maintenanceWaitEvent.WaitOne(runtc); 1687 m_maintenanceWaitEvent.WaitOne(runtc);
1715 1688
1716 // Optionally warn if a frame takes double the amount of time that it should. 1689 // Optionally warn if a frame takes double the amount of time that it should.
1717 if (DebugUpdates 1690 if (DebugUpdates
1718 && Util.EnvironmentTickCountSubtract( 1691 && Util.EnvironmentTickCountSubtract(
1719 m_lastMaintenanceTick, previousMaintenanceTick) > MinMaintenanceTicks * 2) 1692 m_lastMaintenanceTick, previousMaintenanceTick) > (int)(MinMaintenanceTime * 1000 * 2))
1720 m_log.WarnFormat( 1693 m_log.WarnFormat(
1721 "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}", 1694 "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}",
1722 Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick), 1695 Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick),
1723 MinMaintenanceTicks, 1696 MinMaintenanceTime * 1000,
1724 RegionInfo.RegionName); 1697 RegionInfo.RegionName);
1725 } 1698 }
1726 } 1699 }
1727 1700
1728 public override bool Update(int frames) 1701 public override void Update(int frames)
1729 { 1702 {
1730 long? endFrame = null; 1703 long? endFrame = null;
1731 1704
@@ -1733,119 +1706,78 @@ namespace OpenSim.Region.Framework.Scenes
1733 endFrame = Frame + frames; 1706 endFrame = Frame + frames;
1734 1707
1735 float physicsFPS = 0f; 1708 float physicsFPS = 0f;
1736 int previousFrameTick, tmpMS; 1709 float frameTimeMS = FrameTime * 1000.0f;
1737 1710
1738 // These variables will be used to save the precise frame time using the 1711 int previousFrameTick;
1739 // Stopwatch class of Microsoft SDK; the times are recorded at the start 1712
1740 // and end of a particular section of code, and then used to calculate 1713 double tmpMS;
1741 // the frame times, which are the sums of the sections for each given name 1714 double tmpMS2;
1742 double preciseTotalFrameTime = 0.0; 1715 double framestart;
1743 double preciseSimFrameTime = 0.0; 1716 float sleepMS;
1744 double precisePhysicsFrameTime = 0.0; 1717 float sleepError = 0;
1745 Stopwatch totalFrameStopwatch = new Stopwatch();
1746 Stopwatch simFrameStopwatch = new Stopwatch();
1747 Stopwatch physicsFrameStopwatch = new Stopwatch();
1748
1749 // Begin the stopwatch to keep track of the time that the frame
1750 // started running to determine how long the frame took to complete
1751 totalFrameStopwatch.Start();
1752 1718
1753 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) 1719 while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame))
1754 { 1720 {
1721 framestart = Util.GetTimeStampMS();
1755 ++Frame; 1722 ++Frame;
1756 1723
1757 // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); 1724 // m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName);
1758 1725
1759 agentMS = eventMS = backupMS = terrainMS = landMS = spareMS = 0; 1726 agentMS = tempOnRezMS = eventMS = backupMS = terrainMS = landMS = 0f;
1760 1727
1761 try 1728 try
1762 { 1729 {
1763 EventManager.TriggerRegionHeartbeatStart(this); 1730 EventManager.TriggerRegionHeartbeatStart(this);
1764 1731
1765 // Apply taints in terrain module to terrain in physics scene 1732 // Apply taints in terrain module to terrain in physics scene
1733
1734 tmpMS = Util.GetTimeStampMS();
1735
1736 if (Frame % 4 == 0)
1737 {
1738 CheckTerrainUpdates();
1739 }
1740
1766 if (Frame % m_update_terrain == 0) 1741 if (Frame % m_update_terrain == 0)
1767 { 1742 {
1768 // At several points inside the code there was a need to
1769 // create a more precise measurement of time elapsed.
1770 // This led to the addition of variables that have a
1771 // similar function and thus remain tightly connected to
1772 // their original counterparts. However, the original
1773 // code is not receiving comments from our group because
1774 // we don't feel right modifying the code to that degree
1775 // at this point in time, the precise values all begin
1776 // with the keyword precise
1777 tmpMS = Util.EnvironmentTickCount();
1778 simFrameStopwatch.Start();
1779 UpdateTerrain(); 1743 UpdateTerrain();
1780
1781 // Get the simulation frame time that the avatar force
1782 // input took
1783 simFrameStopwatch.Stop();
1784 preciseSimFrameTime =
1785 simFrameStopwatch.Elapsed.TotalMilliseconds;
1786 terrainMS = Util.EnvironmentTickCountSubtract(tmpMS);
1787 } 1744 }
1788 1745
1789 // At several points inside the code there was a need to 1746 tmpMS2 = Util.GetTimeStampMS();
1790 // create a more precise measurement of time elapsed. This 1747 terrainMS = (float)(tmpMS2 - tmpMS);
1791 // led to the addition of variables that have a similar 1748 tmpMS = tmpMS2;
1792 // function and thus remain tightly connected to their
1793 // original counterparts. However, the original code is
1794 // not receiving comments from our group because we don't
1795 // feel right modifying the code to that degree at this
1796 // point in time, the precise values all begin with the
1797 // keyword precise
1798 1749
1799 tmpMS = Util.EnvironmentTickCount();
1800
1801 // Begin the stopwatch to track the time to prepare physics
1802 physicsFrameStopwatch.Start();
1803 if (PhysicsEnabled && Frame % m_update_physics == 0) 1750 if (PhysicsEnabled && Frame % m_update_physics == 0)
1804 m_sceneGraph.UpdatePreparePhysics(); 1751 m_sceneGraph.UpdatePreparePhysics();
1805 1752
1806 // Get the time it took to prepare the physics, this 1753 tmpMS2 = Util.GetTimeStampMS();
1807 // would report the most precise time that physics was 1754 physicsMS2 = (float)(tmpMS2 - tmpMS);
1808 // running on the machine and should the physics not be 1755 tmpMS = tmpMS2;
1809 // enabled will report the time it took to check if physics
1810 // was enabled
1811 physicsFrameStopwatch.Stop();
1812 precisePhysicsFrameTime = physicsFrameStopwatch.Elapsed.TotalMilliseconds;
1813 physicsMS2 = Util.EnvironmentTickCountSubtract(tmpMS);
1814 1756
1815 // Apply any pending avatar force input to the avatar's velocity 1757 // Apply any pending avatar force input to the avatar's velocity
1816 tmpMS = Util.EnvironmentTickCount();
1817 simFrameStopwatch.Restart();
1818 if (Frame % m_update_entitymovement == 0) 1758 if (Frame % m_update_entitymovement == 0)
1819 m_sceneGraph.UpdateScenePresenceMovement(); 1759 m_sceneGraph.UpdateScenePresenceMovement();
1820 1760
1821 // Get the simulation frame time that the avatar force input 1761 // Get the simulation frame time that the avatar force input
1822 // took 1762 // took
1823 simFrameStopwatch.Stop(); 1763 tmpMS2 = Util.GetTimeStampMS();
1824 preciseSimFrameTime += 1764 agentMS = (float)(tmpMS2 - tmpMS);
1825 simFrameStopwatch.Elapsed.TotalMilliseconds; 1765 tmpMS = tmpMS2;
1826 agentMS = Util.EnvironmentTickCountSubtract(tmpMS);
1827 1766
1828 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their 1767 // Perform the main physics update. This will do the actual work of moving objects and avatars according to their
1829 // velocity 1768 // velocity
1830 tmpMS = Util.EnvironmentTickCount();
1831 physicsFrameStopwatch.Restart();
1832 if (Frame % m_update_physics == 0) 1769 if (Frame % m_update_physics == 0)
1833 { 1770 {
1834 if (PhysicsEnabled) 1771 if (PhysicsEnabled)
1835 physicsFPS = m_sceneGraph.UpdatePhysics(MinFrameSeconds); 1772 physicsFPS = m_sceneGraph.UpdatePhysics(FrameTime);
1836 1773
1837 if (SynchronizeScene != null) 1774 if (SynchronizeScene != null)
1838 SynchronizeScene(this); 1775 SynchronizeScene(this);
1839 } 1776 }
1840 1777
1841 // Add the main physics update time to the prepare physics time 1778 tmpMS2 = Util.GetTimeStampMS();
1842 physicsFrameStopwatch.Stop(); 1779 physicsMS = (float)(tmpMS2 - tmpMS);
1843 precisePhysicsFrameTime += physicsFrameStopwatch.Elapsed.TotalMilliseconds; 1780 tmpMS = tmpMS2;
1844 physicsMS = Util.EnvironmentTickCountSubtract(tmpMS);
1845
1846 // Start the stopwatch for the remainder of the simulation
1847 simFrameStopwatch.Restart();
1848 tmpMS = Util.EnvironmentTickCount();
1849 1781
1850 // Check if any objects have reached their targets 1782 // Check if any objects have reached their targets
1851 CheckAtTargets(); 1783 CheckAtTargets();
@@ -1860,20 +1792,36 @@ namespace OpenSim.Region.Framework.Scenes
1860 if (Frame % m_update_presences == 0) 1792 if (Frame % m_update_presences == 0)
1861 m_sceneGraph.UpdatePresences(); 1793 m_sceneGraph.UpdatePresences();
1862 1794
1863 agentMS += Util.EnvironmentTickCountSubtract(tmpMS); 1795 tmpMS2 = Util.GetTimeStampMS();
1864 1796 agentMS += (float)(tmpMS2 - tmpMS);
1797 tmpMS = tmpMS2;
1798
1799 // Delete temp-on-rez stuff
1800 if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps)
1801 {
1802 m_cleaningTemps = true;
1803 Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; });
1804 tmpMS2 = Util.GetTimeStampMS();
1805 tempOnRezMS = (float)(tmpMS2 - tmpMS); // bad.. counts the FireAndForget, not CleanTempObjects
1806 tmpMS = tmpMS2;
1807 }
1808
1865 if (Frame % m_update_events == 0) 1809 if (Frame % m_update_events == 0)
1866 { 1810 {
1867 tmpMS = Util.EnvironmentTickCount();
1868 UpdateEvents(); 1811 UpdateEvents();
1869 eventMS = Util.EnvironmentTickCountSubtract(tmpMS); 1812
1813 tmpMS2 = Util.GetTimeStampMS();
1814 eventMS = (float)(tmpMS2 - tmpMS);
1815 tmpMS = tmpMS2;
1870 } 1816 }
1871 1817
1872 if (PeriodicBackup && Frame % m_update_backup == 0) 1818 if (PeriodicBackup && Frame % m_update_backup == 0)
1873 { 1819 {
1874 tmpMS = Util.EnvironmentTickCount();
1875 UpdateStorageBackup(); 1820 UpdateStorageBackup();
1876 backupMS = Util.EnvironmentTickCountSubtract(tmpMS); 1821
1822 tmpMS2 = Util.GetTimeStampMS();
1823 backupMS = (float)(tmpMS2 - tmpMS);
1824 tmpMS = tmpMS2;
1877 } 1825 }
1878 1826
1879 //if (Frame % m_update_land == 0) 1827 //if (Frame % m_update_land == 0)
@@ -1930,79 +1878,64 @@ namespace OpenSim.Region.Framework.Scenes
1930 } 1878 }
1931 1879
1932 EventManager.TriggerRegionHeartbeatEnd(this); 1880 EventManager.TriggerRegionHeartbeatEnd(this);
1933 otherMS = eventMS + backupMS + terrainMS + landMS; 1881 m_firstHeartbeat = false;
1882 Watchdog.UpdateThread();
1934 1883
1935 // Get the elapsed time for the simulation frame 1884 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
1936 simFrameStopwatch.Stop();
1937 preciseSimFrameTime +=
1938 simFrameStopwatch.Elapsed.TotalMilliseconds;
1939 1885
1940 if (!UpdateOnTimer) 1886 tmpMS = Util.GetTimeStampMS();
1941 {
1942 Watchdog.UpdateThread();
1943 1887
1944 spareMS = MinFrameTicks - Util.EnvironmentTickCountSubtract(m_lastFrameTick); 1888 previousFrameTick = m_lastFrameTick;
1889 m_lastFrameTick = (int)(tmpMS + 0.5);
1945 1890
1946 if (spareMS > 0) 1891 // estimate sleep time
1947 m_updateWaitEvent.WaitOne(spareMS); 1892 tmpMS2 = tmpMS - framestart;
1948 else 1893 tmpMS2 = (double)frameTimeMS - tmpMS2 - sleepError;
1949 spareMS = 0;
1950 }
1951 else
1952 {
1953 spareMS = Math.Max(0, MinFrameTicks - physicsMS2 - agentMS - physicsMS - otherMS);
1954 }
1955 1894
1956 // Get the total frame time 1895 // reuse frameMS as temporary
1957 totalFrameStopwatch.Stop(); 1896 frameMS = (float)tmpMS2;
1958 preciseTotalFrameTime = 1897
1959 totalFrameStopwatch.Elapsed.TotalMilliseconds; 1898 // sleep if we can
1899 if (tmpMS2 > 0)
1900 {
1901 Thread.Sleep((int)(tmpMS2 + 0.5));
1960 1902
1961 // Restart the stopwatch for the total time of the next frame 1903 tmpMS2 = Util.GetTimeStampMS();
1962 totalFrameStopwatch.Restart(); 1904 sleepMS = (float)(tmpMS2 - tmpMS);
1905 sleepError = sleepMS - frameMS;
1906 Util.Clamp(sleepError, 0.0f, 20f);
1907 frameMS = (float)(tmpMS2 - framestart);
1908 }
1909 else
1910 {
1911 tmpMS2 = Util.GetTimeStampMS();
1912 frameMS = (float)(tmpMS2 - framestart);
1913 sleepMS = 0.0f;
1914 sleepError = 0.0f;
1915 }
1963 1916
1964 previousFrameTick = m_lastFrameTick; 1917 // script time is not scene frame time, but is displayed per frame
1965 frameMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick); 1918 float scriptTimeMS = GetAndResetScriptExecutionTime();
1966 m_lastFrameTick = Util.EnvironmentTickCount(); 1919 StatsReporter.AddFrameStats(TimeDilation, physicsFPS, agentMS,
1920 physicsMS + physicsMS2, otherMS , sleepMS, frameMS, scriptTimeMS);
1921
1922
1967 1923
1968 // if (Frame%m_update_avatars == 0) 1924 // if (Frame%m_update_avatars == 0)
1969 // UpdateInWorldTime(); 1925 // UpdateInWorldTime();
1970 StatsReporter.AddPhysicsFPS(physicsFPS);
1971 StatsReporter.AddTimeDilation(TimeDilation);
1972 StatsReporter.AddFPS(1);
1973
1974 StatsReporter.addFrameMS(frameMS);
1975 StatsReporter.addAgentMS(agentMS);
1976 StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
1977 StatsReporter.addOtherMS(otherMS);
1978 StatsReporter.AddSpareMS(spareMS);
1979 StatsReporter.addScriptLines(m_sceneGraph.GetScriptLPS());
1980 StatsReporter.AddScriptMS((int) GetAndResetScriptExecutionTime());
1981
1982 // Send the correct time values to the stats reporter for the
1983 // frame times
1984 StatsReporter.addFrameTimeMilliseconds(preciseTotalFrameTime,
1985 preciseSimFrameTime, precisePhysicsFrameTime, 0.0);
1986
1987 // Send the correct number of frames that the physics library
1988 // has processed to the stats reporter
1989 StatsReporter.addPhysicsFrame(1);
1990 1926
1991 // Optionally warn if a frame takes double the amount of time that it should. 1927 // Optionally warn if a frame takes double the amount of time that it should.
1992 if (DebugUpdates 1928 if (DebugUpdates
1993 && Util.EnvironmentTickCountSubtract( 1929 && Util.EnvironmentTickCountSubtract(
1994 m_lastFrameTick, previousFrameTick) > MinFrameTicks * 2) 1930 m_lastFrameTick, previousFrameTick) > (int)(FrameTime * 1000 * 2))
1931
1995 m_log.WarnFormat( 1932 m_log.WarnFormat(
1996 "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}", 1933 "[SCENE]: Frame took {0} ms (desired max {1} ms) in {2}",
1997 Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick), 1934 Util.EnvironmentTickCountSubtract(m_lastFrameTick, previousFrameTick),
1998 MinFrameTicks, 1935 FrameTime * 1000,
1936
1999 RegionInfo.RegionName); 1937 RegionInfo.RegionName);
2000 } 1938 }
2001
2002 // Finished updating scene frame, so stop the total frame's Stopwatch
2003 totalFrameStopwatch.Stop();
2004
2005 return spareMS >= 0;
2006 } 1939 }
2007 1940
2008 /// <summary> 1941 /// <summary>
@@ -2011,24 +1944,28 @@ namespace OpenSim.Region.Framework.Scenes
2011 /// <param name="ticks">Elapsed Stopwatch ticks</param> 1944 /// <param name="ticks">Elapsed Stopwatch ticks</param>
2012 public void AddScriptExecutionTime(long ticks) 1945 public void AddScriptExecutionTime(long ticks)
2013 { 1946 {
1947 StatsReporter.addScriptEvents(1);
2014 Interlocked.Add(ref m_scriptExecutionTime, ticks); 1948 Interlocked.Add(ref m_scriptExecutionTime, ticks);
2015 } 1949 }
2016 1950
2017 /// <summary> 1951 /// <summary>
2018 /// Returns the total execution time of all the scripts in the region since the last frame 1952 /// Returns the total execution time of all the scripts in the region since the last call
2019 /// (in milliseconds), and clears the value in preparation for the next frame. 1953 /// (in milliseconds), and clears the value in preparation for the next call.
2020 /// </summary> 1954 /// </summary>
2021 /// <returns>Time in milliseconds</returns> 1955 /// <returns>Time in milliseconds</returns>
2022 private long GetAndResetScriptExecutionTime() 1956
1957 // Warning: this is now called from StatsReporter, and can't be shared
1958
1959 public long GetAndResetScriptExecutionTime()
2023 { 1960 {
2024 long ticks = Interlocked.Exchange(ref m_scriptExecutionTime, 0); 1961 long ticks = Interlocked.Exchange(ref m_scriptExecutionTime, 0);
2025 return (ticks * 1000) / Stopwatch.Frequency; 1962 return (ticks * 1000L) / Stopwatch.Frequency;
2026 } 1963 }
2027 1964
2028 public void AddGroupTarget(SceneObjectGroup grp) 1965 public void AddGroupTarget(SceneObjectGroup grp)
2029 { 1966 {
2030 lock (m_groupsWithTargets) 1967 lock (m_groupsWithTargets)
2031 m_groupsWithTargets[grp.UUID] = grp; 1968 m_groupsWithTargets[grp.UUID] = 0;
2032 } 1969 }
2033 1970
2034 public void RemoveGroupTarget(SceneObjectGroup grp) 1971 public void RemoveGroupTarget(SceneObjectGroup grp)
@@ -2039,18 +1976,24 @@ namespace OpenSim.Region.Framework.Scenes
2039 1976
2040 private void CheckAtTargets() 1977 private void CheckAtTargets()
2041 { 1978 {
2042 List<SceneObjectGroup> objs = null; 1979 List<UUID> objs = null;
2043 1980
2044 lock (m_groupsWithTargets) 1981 lock (m_groupsWithTargets)
2045 { 1982 {
2046 if (m_groupsWithTargets.Count != 0) 1983 if (m_groupsWithTargets.Count != 0)
2047 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values); 1984 objs = new List<UUID>(m_groupsWithTargets.Keys);
2048 } 1985 }
2049 1986
2050 if (objs != null) 1987 if (objs != null)
2051 { 1988 {
2052 foreach (SceneObjectGroup entry in objs) 1989 foreach (UUID entry in objs)
2053 entry.checkAtTargets(); 1990 {
1991 SceneObjectGroup grp = GetSceneObjectGroup(entry);
1992 if (grp == null)
1993 m_groupsWithTargets.Remove(entry);
1994 else
1995 grp.checkAtTargets();
1996 }
2054 } 1997 }
2055 } 1998 }
2056 1999
@@ -2074,6 +2017,11 @@ namespace OpenSim.Region.Framework.Scenes
2074 EventManager.TriggerTerrainTick(); 2017 EventManager.TriggerTerrainTick();
2075 } 2018 }
2076 2019
2020 private void CheckTerrainUpdates()
2021 {
2022 EventManager.TriggerTerrainCheckUpdates();
2023 }
2024
2077 /// <summary> 2025 /// <summary>
2078 /// Back up queued up changes 2026 /// Back up queued up changes
2079 /// </summary> 2027 /// </summary>
@@ -2125,7 +2073,7 @@ namespace OpenSim.Region.Framework.Scenes
2125 msg.fromAgentName = "Server"; 2073 msg.fromAgentName = "Server";
2126 msg.dialog = (byte)19; // Object msg 2074 msg.dialog = (byte)19; // Object msg
2127 msg.fromGroup = false; 2075 msg.fromGroup = false;
2128 msg.offline = (byte)0; 2076 msg.offline = (byte)1;
2129 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 2077 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
2130 msg.Position = Vector3.Zero; 2078 msg.Position = Vector3.Zero;
2131 msg.RegionID = RegionInfo.RegionID.Guid; 2079 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -2277,7 +2225,7 @@ namespace OpenSim.Region.Framework.Scenes
2277 //// stored in the GridService, because that's what the world map module uses 2225 //// stored in the GridService, because that's what the world map module uses
2278 //// to send the map image UUIDs (of other regions) to the viewer... 2226 //// to send the map image UUIDs (of other regions) to the viewer...
2279 if (m_generateMaptiles) 2227 if (m_generateMaptiles)
2280 RegenerateMaptile(); 2228 RegenerateMaptile();
2281 2229
2282 GridRegion region = new GridRegion(RegionInfo); 2230 GridRegion region = new GridRegion(RegionInfo);
2283 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region); 2231 string error = GridService.RegisterRegion(RegionInfo.ScopeID, region);
@@ -2361,7 +2309,7 @@ namespace OpenSim.Region.Framework.Scenes
2361 return PhysicsScene.SupportsRaycastWorldFiltered(); 2309 return PhysicsScene.SupportsRaycastWorldFiltered();
2362 } 2310 }
2363 2311
2364 public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter) 2312 public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter)
2365 { 2313 {
2366 if (PhysicsScene == null) 2314 if (PhysicsScene == null)
2367 return null; 2315 return null;
@@ -2383,93 +2331,166 @@ namespace OpenSim.Region.Framework.Scenes
2383 /// <returns></returns> 2331 /// <returns></returns>
2384 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 2332 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
2385 { 2333 {
2386 Vector3 pos = Vector3.Zero;
2387 if (RayEndIsIntersection == (byte)1)
2388 {
2389 pos = RayEnd;
2390 return pos;
2391 }
2392 2334
2393 if (RayTargetID != UUID.Zero) 2335 Vector3 dir = RayEnd - RayStart;
2336
2337 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
2338 Vector3 wpos = Vector3.Zero;
2339 // Check for water surface intersection from above
2340 if ((RayStart.Z > wheight) && (RayEnd.Z < wheight))
2394 { 2341 {
2395 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 2342 float ratio = (wheight - RayStart.Z) / dir.Z;
2343 wpos.X = RayStart.X + (ratio * dir.X);
2344 wpos.Y = RayStart.Y + (ratio * dir.Y);
2345 wpos.Z = wheight;
2346 }
2396 2347
2397 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 2348 Vector3 pos = Vector3.Zero;
2398 Vector3 AXOrigin = RayStart;
2399 Vector3 AXdirection = direction;
2400 2349
2401 if (target != null) 2350 if (RayEndIsIntersection != (byte)1)
2351 {
2352 float dist = dir.Length();
2353 if (dist != 0)
2402 { 2354 {
2403 pos = target.AbsolutePosition; 2355 Vector3 direction = dir * (1 / dist);
2404 //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString());
2405 2356
2406 // TODO: Raytrace better here 2357 dist += 1.0f;
2407 2358
2408 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); 2359 if (SupportsRayCastFiltered())
2409 Ray NewRay = new Ray(AXOrigin, AXdirection); 2360 {
2361 RayFilterFlags rayfilter = RayFilterFlags.BackFaceCull;
2362 rayfilter |= RayFilterFlags.land;
2363 rayfilter |= RayFilterFlags.physical;
2364 rayfilter |= RayFilterFlags.nonphysical;
2365 rayfilter |= RayFilterFlags.LSLPhantom; // ubODE will only see volume detectors
2366
2367 // get some more contacts ???
2368 int physcount = 4;
2369
2370 List<ContactResult> physresults =
2371 (List<ContactResult>)RayCastFiltered(RayStart, direction, dist, physcount, rayfilter);
2372 if (physresults != null && physresults.Count > 0)
2373 {
2374 // look for terrain ?
2375 if(RayTargetID == UUID.Zero)
2376 {
2377 foreach (ContactResult r in physresults)
2378 {
2379 if (r.ConsumerID == 0)
2380 {
2381 pos = r.Normal * scale;
2382 pos *= 0.5f;
2383 pos = r.Pos + pos;
2384
2385 if (wpos.Z > pos.Z) pos = wpos;
2386 return pos;
2387 }
2388 }
2389 }
2390 else
2391 {
2392 foreach (ContactResult r in physresults)
2393 {
2394 SceneObjectPart part = GetSceneObjectPart(r.ConsumerID);
2395 if (part == null)
2396 continue;
2397 if (part.UUID == RayTargetID)
2398 {
2399 pos = r.Normal * scale;
2400 pos *= 0.5f;
2401 pos = r.Pos + pos;
2402
2403 if (wpos.Z > pos.Z) pos = wpos;
2404 return pos;
2405 }
2406 }
2407 }
2408 // else the first we got
2409 pos = physresults[0].Normal * scale;
2410 pos *= 0.5f;
2411 pos = physresults[0].Pos + pos;
2412
2413 if (wpos.Z > pos.Z)
2414 pos = wpos;
2415 return pos;
2416 }
2410 2417
2411 // Ray Trace against target here 2418 }
2412 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 2419 if (RayTargetID != UUID.Zero)
2420 {
2421 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
2413 2422
2414 // Un-comment out the following line to Get Raytrace results printed to the console. 2423 Ray NewRay = new Ray(RayStart, direction);
2415 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2416 float ScaleOffset = 0.5f;
2417 2424
2418 // If we hit something 2425 if (target != null)
2419 if (ei.HitTF) 2426 {
2420 { 2427 pos = target.AbsolutePosition;
2421 Vector3 scaleComponent = ei.AAfaceNormal;
2422 if (scaleComponent.X != 0) ScaleOffset = scale.X;
2423 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
2424 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
2425 ScaleOffset = Math.Abs(ScaleOffset);
2426 Vector3 intersectionpoint = ei.ipoint;
2427 Vector3 normal = ei.normal;
2428 // Set the position to the intersection point
2429 Vector3 offset = (normal * (ScaleOffset / 2f));
2430 pos = (intersectionpoint + offset);
2431
2432 //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f
2433 //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
2434 // Un-offset the prim (it gets offset later by the consumer method)
2435 //pos.Z -= 0.25F;
2436 2428
2437 } 2429 // Ray Trace against target here
2430 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
2438 2431
2439 return pos; 2432 // Un-comment out the following line to Get Raytrace results printed to the console.
2440 } 2433 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2441 else 2434 float ScaleOffset = 0.5f;
2442 {
2443 // We don't have a target here, so we're going to raytrace all the objects in the scene.
2444 2435
2445 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 2436 // If we hit something
2437 if (ei.HitTF)
2438 {
2439 Vector3 scaleComponent = ei.AAfaceNormal;
2440 if (scaleComponent.X != 0) ScaleOffset = scale.X;
2441 if (scaleComponent.Y != 0) ScaleOffset = scale.Y;
2442 if (scaleComponent.Z != 0) ScaleOffset = scale.Z;
2443 ScaleOffset = Math.Abs(ScaleOffset);
2444 Vector3 intersectionpoint = ei.ipoint;
2445 Vector3 normal = ei.normal;
2446 // Set the position to the intersection point
2447 Vector3 offset = (normal * (ScaleOffset / 2f));
2448 pos = (intersectionpoint + offset);
2449
2450 //Seems to make no sense to do this as this call is used for rezzing from inventory as well, and with inventory items their size is not always 0.5f
2451 //And in cases when we weren't rezzing from inventory we were re-adding the 0.25 straight after calling this method
2452 // Un-offset the prim (it gets offset later by the consumer method)
2453 //pos.Z -= 0.25F;
2454
2455 if (wpos.Z > pos.Z) pos = wpos;
2456 return pos;
2457 }
2458 }
2459 else
2460 {
2461 // We don't have a target here, so we're going to raytrace all the objects in the scene.
2462 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(NewRay, true, false);
2446 2463
2447 // Un-comment the following line to print the raytrace results to the console. 2464 // Un-comment the following line to print the raytrace results to the console.
2448 //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 2465 //m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
2449 2466
2450 if (ei.HitTF) 2467 if (ei.HitTF)
2451 { 2468 {
2452 pos = ei.ipoint; 2469 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
2453 } 2470 }
2454 else 2471 else
2455 { 2472 {
2456 // fall back to our stupid functionality 2473 // fall back to our stupid functionality
2457 pos = RayEnd; 2474 pos = RayEnd;
2458 } 2475 }
2459 2476
2460 return pos; 2477 if (wpos.Z > pos.Z) pos = wpos;
2478 return pos;
2479 }
2480 }
2461 } 2481 }
2462 } 2482 }
2463 else
2464 {
2465 // fall back to our stupid functionality
2466 pos = RayEnd;
2467 2483
2468 //increase height so its above the ground. 2484 // fall back to our stupid functionality
2469 //should be getting the normal of the ground at the rez point and using that? 2485 pos = RayEnd;
2470 pos.Z += scale.Z / 2f; 2486
2471 return pos; 2487 //increase height so its above the ground.
2472 } 2488 //should be getting the normal of the ground at the rez point and using that?
2489 pos.Z += scale.Z / 2f;
2490 // return pos;
2491 // check against posible water intercept
2492 if (wpos.Z > pos.Z) pos = wpos;
2493 return pos;
2473 } 2494 }
2474 2495
2475 2496
@@ -2560,12 +2581,12 @@ namespace OpenSim.Region.Framework.Scenes
2560 { 2581 {
2561 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) 2582 if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates))
2562 { 2583 {
2584 sceneObject.IsDeleted = false;
2563 EventManager.TriggerObjectAddedToScene(sceneObject); 2585 EventManager.TriggerObjectAddedToScene(sceneObject);
2564 return true; 2586 return true;
2565 } 2587 }
2566 2588
2567 return false; 2589 return false;
2568
2569 } 2590 }
2570 2591
2571 /// <summary> 2592 /// <summary>
@@ -2657,6 +2678,15 @@ namespace OpenSim.Region.Framework.Scenes
2657 /// </summary> 2678 /// </summary>
2658 public void DeleteAllSceneObjects() 2679 public void DeleteAllSceneObjects()
2659 { 2680 {
2681 DeleteAllSceneObjects(false);
2682 }
2683
2684 /// <summary>
2685 /// Delete every object from the scene. This does not include attachments worn by avatars.
2686 /// </summary>
2687 public void DeleteAllSceneObjects(bool exceptNoCopy)
2688 {
2689 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2660 lock (Entities) 2690 lock (Entities)
2661 { 2691 {
2662 EntityBase[] entities = Entities.GetEntities(); 2692 EntityBase[] entities = Entities.GetEntities();
@@ -2665,11 +2695,24 @@ namespace OpenSim.Region.Framework.Scenes
2665 if (e is SceneObjectGroup) 2695 if (e is SceneObjectGroup)
2666 { 2696 {
2667 SceneObjectGroup sog = (SceneObjectGroup)e; 2697 SceneObjectGroup sog = (SceneObjectGroup)e;
2668 if (!sog.IsAttachment) 2698 if (sog != null && !sog.IsAttachment)
2669 DeleteSceneObject((SceneObjectGroup)e, false); 2699 {
2700 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2701 {
2702 DeleteSceneObject((SceneObjectGroup)e, false);
2703 }
2704 else
2705 {
2706 toReturn.Add((SceneObjectGroup)e);
2707 }
2708 }
2670 } 2709 }
2671 } 2710 }
2672 } 2711 }
2712 if (toReturn.Count > 0)
2713 {
2714 returnObjects(toReturn.ToArray(), UUID.Zero);
2715 }
2673 } 2716 }
2674 2717
2675 /// <summary> 2718 /// <summary>
@@ -2700,6 +2743,13 @@ namespace OpenSim.Region.Framework.Scenes
2700 else 2743 else
2701 group.StopScriptInstances(); 2744 group.StopScriptInstances();
2702 2745
2746 List<ScenePresence> avatars = group.GetSittingAvatars();
2747 foreach (ScenePresence av in avatars)
2748 {
2749 if(av.ParentUUID == UUID.Zero)
2750 av.StandUp();
2751 }
2752
2703 SceneObjectPart[] partList = group.Parts; 2753 SceneObjectPart[] partList = group.Parts;
2704 2754
2705 foreach (SceneObjectPart part in partList) 2755 foreach (SceneObjectPart part in partList)
@@ -2727,6 +2777,8 @@ namespace OpenSim.Region.Framework.Scenes
2727 } 2777 }
2728 2778
2729 group.DeleteGroupFromScene(silent); 2779 group.DeleteGroupFromScene(silent);
2780 if (!silent)
2781 SendKillObject(new List<uint>() { group.LocalId });
2730 2782
2731 // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2783 // m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2732 } 2784 }
@@ -2763,6 +2815,13 @@ namespace OpenSim.Region.Framework.Scenes
2763 return false; 2815 return false;
2764 } 2816 }
2765 2817
2818
2819 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
2820 {
2821 m_sceneGraph.updateScenePartGroup(part, grp);
2822 }
2823
2824/* not in use, outdate by async method
2766 /// <summary> 2825 /// <summary>
2767 /// Move the given scene object into a new region depending on which region its absolute position has moved 2826 /// Move the given scene object into a new region depending on which region its absolute position has moved
2768 /// into. 2827 /// into.
@@ -2811,6 +2870,7 @@ namespace OpenSim.Region.Framework.Scenes
2811 if (EntityTransferModule != null) 2870 if (EntityTransferModule != null)
2812 EntityTransferModule.Cross(grp, attemptedPosition, silent); 2871 EntityTransferModule.Cross(grp, attemptedPosition, silent);
2813 } 2872 }
2873*/
2814 2874
2815 // Simple test to see if a position is in the current region. 2875 // Simple test to see if a position is in the current region.
2816 // This test is mostly used to see if a region crossing is necessary. 2876 // This test is mostly used to see if a region crossing is necessary.
@@ -2828,7 +2888,7 @@ namespace OpenSim.Region.Framework.Scenes
2828 if (regionCombinerModule == null) 2888 if (regionCombinerModule == null)
2829 { 2889 {
2830 // Regular region. Just check for region size 2890 // Regular region. Just check for region size
2831 if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY) 2891 if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY )
2832 ret = true; 2892 ret = true;
2833 } 2893 }
2834 else 2894 else
@@ -2836,9 +2896,7 @@ namespace OpenSim.Region.Framework.Scenes
2836 // We're in a mega-region so see if we are still in that larger region 2896 // We're in a mega-region so see if we are still in that larger region
2837 ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy); 2897 ret = regionCombinerModule.PositionIsInMegaregion(this.RegionInfo.RegionID, xx, yy);
2838 } 2898 }
2839
2840 return ret; 2899 return ret;
2841
2842 } 2900 }
2843 2901
2844 /// <summary> 2902 /// <summary>
@@ -2862,8 +2920,52 @@ namespace OpenSim.Region.Framework.Scenes
2862 return false; 2920 return false;
2863 } 2921 }
2864 2922
2865 if (!EntityTransferModule.HandleIncomingSceneObject(newObject, newPosition)) 2923 // If the user is banned, we won't let any of their objects
2924 // enter. Period.
2925 //
2926 if (RegionInfo.EstateSettings.IsBanned(newObject.OwnerID, 36))
2927 {
2928 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", newObject.OwnerID);
2866 return false; 2929 return false;
2930 }
2931
2932 if (newPosition != Vector3.Zero)
2933 newObject.RootPart.GroupPosition = newPosition;
2934
2935 if (!AddSceneObject(newObject))
2936 {
2937 m_log.DebugFormat(
2938 "[INTERREGION]: Problem adding scene object {0} in {1} ", newObject.UUID, RegionInfo.RegionName);
2939 return false;
2940 }
2941
2942 if (!newObject.IsAttachment)
2943 {
2944 // FIXME: It would be better to never add the scene object at all rather than add it and then delete
2945 // it
2946 if (!Permissions.CanObjectEntry(newObject.UUID, true, newObject.AbsolutePosition))
2947 {
2948 // Deny non attachments based on parcel settings
2949 //
2950 m_log.Info("[INTERREGION]: Denied prim crossing because of parcel settings");
2951
2952 DeleteSceneObject(newObject, false);
2953
2954 return false;
2955 }
2956
2957 // For attachments, we need to wait until the agent is root
2958 // before we restart the scripts, or else some functions won't work.
2959 newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject));
2960 newObject.ResumeScripts();
2961
2962 // AddSceneObject already does this and doing it again messes
2963 // up region crossings, so don't.
2964 //if (newObject.RootPart.KeyframeMotion != null)
2965 // newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
2966 }
2967
2968
2867 2969
2868 // Do this as late as possible so that listeners have full access to the incoming object 2970 // Do this as late as possible so that listeners have full access to the incoming object
2869 EventManager.TriggerOnIncomingSceneObject(newObject); 2971 EventManager.TriggerOnIncomingSceneObject(newObject);
@@ -2880,6 +2982,23 @@ namespace OpenSim.Region.Framework.Scenes
2880 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2982 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2881 public bool AddSceneObject(SceneObjectGroup sceneObject) 2983 public bool AddSceneObject(SceneObjectGroup sceneObject)
2882 { 2984 {
2985 if (sceneObject.OwnerID == UUID.Zero)
2986 {
2987 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2988 return false;
2989 }
2990
2991 // If the user is banned, we won't let any of their objects
2992 // enter. Period.
2993 //
2994 int flags = GetUserFlags(sceneObject.OwnerID);
2995 if (RegionInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2996 {
2997 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2998
2999 return false;
3000 }
3001
2883 // Force allocation of new LocalId 3002 // Force allocation of new LocalId
2884 // 3003 //
2885 SceneObjectPart[] parts = sceneObject.Parts; 3004 SceneObjectPart[] parts = sceneObject.Parts;
@@ -2916,22 +3035,62 @@ namespace OpenSim.Region.Framework.Scenes
2916 // information that this is due to a teleport/border cross rather than an ordinary attachment. 3035 // information that this is due to a teleport/border cross rather than an ordinary attachment.
2917 // We currently do this in Scene.MakeRootAgent() instead. 3036 // We currently do this in Scene.MakeRootAgent() instead.
2918 if (AttachmentsModule != null) 3037 if (AttachmentsModule != null)
2919 AttachmentsModule.AttachObject(sp, grp, 0, false, false, true); 3038 AttachmentsModule.AttachObject(sp, grp, 0, false, false, false, true);
2920 } 3039 }
2921 else 3040 else
2922 { 3041 {
3042 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2923 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 3043 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2924 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 3044 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2925 } 3045 }
3046 if (sceneObject.OwnerID == UUID.Zero)
3047 {
3048 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
3049 return false;
3050 }
2926 } 3051 }
2927 else 3052 else
2928 { 3053 {
3054 if (sceneObject.OwnerID == UUID.Zero)
3055 {
3056 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
3057 return false;
3058 }
2929 AddRestoredSceneObject(sceneObject, true, false); 3059 AddRestoredSceneObject(sceneObject, true, false);
2930 } 3060 }
2931 3061
2932 return true; 3062 return true;
2933 } 3063 }
2934 3064
3065 private int GetStateSource(SceneObjectGroup sog)
3066 {
3067 ScenePresence sp = GetScenePresence(sog.OwnerID);
3068
3069 if (sp != null)
3070 return sp.GetStateSource();
3071
3072 return 2; // StateSource.PrimCrossing
3073 }
3074
3075 public int GetUserFlags(UUID user)
3076 {
3077 //Unfortunately the SP approach means that the value is cached until region is restarted
3078 /*
3079 ScenePresence sp;
3080 if (TryGetScenePresence(user, out sp))
3081 {
3082 return sp.UserFlags;
3083 }
3084 else
3085 {
3086 */
3087 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
3088 if (uac == null)
3089 return 0;
3090 return uac.UserFlags;
3091 //}
3092 }
3093
2935 #endregion 3094 #endregion
2936 3095
2937 #region Add/Remove Avatar Methods 3096 #region Add/Remove Avatar Methods
@@ -2967,8 +3126,9 @@ namespace OpenSim.Region.Framework.Scenes
2967 vialogin 3126 vialogin
2968 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 3127 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2969 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 3128 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2970 3129
2971 // CheckHeartbeat(); 3130 CheckHeartbeat();
3131
2972 3132
2973 sp = GetScenePresence(client.AgentId); 3133 sp = GetScenePresence(client.AgentId);
2974 3134
@@ -2979,27 +3139,27 @@ namespace OpenSim.Region.Framework.Scenes
2979 if (sp == null) 3139 if (sp == null)
2980 { 3140 {
2981 m_log.DebugFormat( 3141 m_log.DebugFormat(
2982 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", 3142 "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}, tpflags: {4}",
2983 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); 3143 client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos,
2984 3144 ((TPFlags)aCircuit.teleportFlags).ToString());
2985 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); 3145
2986
2987 // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the
2988 // client is for a root or child agent.
2989 // We must also set this before adding the client to the client manager so that an exception later on
2990 // does not leave a client manager entry without the scene agent set, which will cause other code
2991 // to fail since any entry in the client manager should have a ScenePresence
2992 //
2993 // XXX: This may be better set for a new client before that client is added to the client manager.
2994 // But need to know what happens in the case where a ScenePresence is already present (and if this
2995 // actually occurs).
2996 client.SceneAgent = sp;
2997
2998 m_clientManager.Add(client); 3146 m_clientManager.Add(client);
2999 SubscribeToClientEvents(client); 3147 SubscribeToClientEvents(client);
3000 m_eventManager.TriggerOnNewPresence(sp); 3148
3149 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
3001 3150
3002 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; 3151 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
3152
3153/* done in completMovement
3154 InventoryFolderBase cof = InventoryService.GetFolderForType(client.AgentId, (AssetType)46);
3155 if (cof == null)
3156 sp.COF = UUID.Zero;
3157 else
3158 sp.COF = cof.ID;
3159
3160 m_log.DebugFormat("[SCENE]: COF for {0} is {1}", client.AgentId, sp.COF);
3161 */
3162 m_eventManager.TriggerOnNewPresence(sp);
3003 } 3163 }
3004 else 3164 else
3005 { 3165 {
@@ -3008,7 +3168,7 @@ namespace OpenSim.Region.Framework.Scenes
3008 // XXX: This may be better set for a new client before that client is added to the client manager. 3168 // XXX: This may be better set for a new client before that client is added to the client manager.
3009 // But need to know what happens in the case where a ScenePresence is already present (and if this 3169 // But need to know what happens in the case where a ScenePresence is already present (and if this
3010 // actually occurs). 3170 // actually occurs).
3011 client.SceneAgent = sp; 3171
3012 3172
3013 m_log.WarnFormat( 3173 m_log.WarnFormat(
3014 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", 3174 "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence",
@@ -3016,6 +3176,7 @@ namespace OpenSim.Region.Framework.Scenes
3016 3176
3017 reallyNew = false; 3177 reallyNew = false;
3018 } 3178 }
3179 client.SceneAgent = sp;
3019 3180
3020 // This is currently also being done earlier in NewUserConnection for real users to see if this 3181 // This is currently also being done earlier in NewUserConnection for real users to see if this
3021 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other 3182 // resolves problems where HG agents are occasionally seen by others as "Unknown user" in chat and other
@@ -3134,19 +3295,15 @@ namespace OpenSim.Region.Framework.Scenes
3134 // and the scene presence and the client, if they exist 3295 // and the scene presence and the client, if they exist
3135 try 3296 try
3136 { 3297 {
3137 // We need to wait for the client to make UDP contact first.
3138 // It's the UDP contact that creates the scene presence
3139 ScenePresence sp = WaitGetScenePresence(agentID); 3298 ScenePresence sp = WaitGetScenePresence(agentID);
3299
3140 if (sp != null) 3300 if (sp != null)
3141 { 3301 {
3142 PresenceService.LogoutAgent(sp.ControllingClient.SessionId); 3302 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
3143 3303
3144 CloseAgent(sp.UUID, false); 3304 CloseAgent(sp.UUID, false);
3145 } 3305 }
3146 else 3306
3147 {
3148 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
3149 }
3150 // BANG! SLASH! 3307 // BANG! SLASH!
3151 m_authenticateHandler.RemoveCircuit(agentID); 3308 m_authenticateHandler.RemoveCircuit(agentID);
3152 3309
@@ -3183,7 +3340,7 @@ namespace OpenSim.Region.Framework.Scenes
3183 3340
3184 public virtual void SubscribeToClientTerrainEvents(IClientAPI client) 3341 public virtual void SubscribeToClientTerrainEvents(IClientAPI client)
3185 { 3342 {
3186 client.OnRegionHandShakeReply += SendLayerData; 3343// client.OnRegionHandShakeReply += SendLayerData;
3187 } 3344 }
3188 3345
3189 public virtual void SubscribeToClientPrimEvents(IClientAPI client) 3346 public virtual void SubscribeToClientPrimEvents(IClientAPI client)
@@ -3191,6 +3348,8 @@ namespace OpenSim.Region.Framework.Scenes
3191 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; 3348 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition;
3192 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; 3349 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
3193 3350
3351 client.onClientChangeObject += m_sceneGraph.ClientChangeObject;
3352
3194 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; 3353 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation;
3195 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; 3354 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation;
3196 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; 3355 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
@@ -3247,6 +3406,7 @@ namespace OpenSim.Region.Framework.Scenes
3247 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 3406 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
3248 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 3407 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
3249 client.OnCopyInventoryItem += CopyInventoryItem; 3408 client.OnCopyInventoryItem += CopyInventoryItem;
3409 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
3250 client.OnMoveInventoryItem += MoveInventoryItem; 3410 client.OnMoveInventoryItem += MoveInventoryItem;
3251 client.OnRemoveInventoryItem += RemoveInventoryItem; 3411 client.OnRemoveInventoryItem += RemoveInventoryItem;
3252 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 3412 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -3308,7 +3468,7 @@ namespace OpenSim.Region.Framework.Scenes
3308 3468
3309 public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client) 3469 public virtual void UnSubscribeToClientTerrainEvents(IClientAPI client)
3310 { 3470 {
3311 client.OnRegionHandShakeReply -= SendLayerData; 3471// client.OnRegionHandShakeReply -= SendLayerData;
3312 } 3472 }
3313 3473
3314 public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) 3474 public virtual void UnSubscribeToClientPrimEvents(IClientAPI client)
@@ -3316,6 +3476,8 @@ namespace OpenSim.Region.Framework.Scenes
3316 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; 3476 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition;
3317 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; 3477 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition;
3318 3478
3479 client.onClientChangeObject -= m_sceneGraph.ClientChangeObject;
3480
3319 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3481 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation;
3320 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3482 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation;
3321 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; 3483 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation;
@@ -3473,16 +3635,14 @@ namespace OpenSim.Region.Framework.Scenes
3473 if (target != null && target2 != null) 3635 if (target != null && target2 != null)
3474 { 3636 {
3475 Vector3 direction = Vector3.Normalize(RayEnd - RayStart); 3637 Vector3 direction = Vector3.Normalize(RayEnd - RayStart);
3476 Vector3 AXOrigin = RayStart; 3638
3477 Vector3 AXdirection = direction;
3478
3479 pos = target2.AbsolutePosition; 3639 pos = target2.AbsolutePosition;
3480 //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString()); 3640 //m_log.Info("[OBJECT_REZ]: TargetPos: " + pos.ToString() + ", RayStart: " + RayStart.ToString() + ", RayEnd: " + RayEnd.ToString() + ", Volume: " + Util.GetDistanceTo(RayStart,RayEnd).ToString() + ", mag1: " + Util.GetMagnitude(RayStart).ToString() + ", mag2: " + Util.GetMagnitude(RayEnd).ToString());
3481 3641
3482 // TODO: Raytrace better here 3642 // TODO: Raytrace better here
3483 3643
3484 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection)); 3644 //EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection));
3485 Ray NewRay = new Ray(AXOrigin, AXdirection); 3645 Ray NewRay = new Ray(RayStart,direction);
3486 3646
3487 // Ray Trace against target here 3647 // Ray Trace against target here
3488 EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters); 3648 EntityIntersection ei = target2.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, CopyCenters);
@@ -3564,6 +3724,10 @@ namespace OpenSim.Region.Framework.Scenes
3564 /// <param name='closeChildAgents'> 3724 /// <param name='closeChildAgents'>
3565 /// Close the neighbour child agents associated with this client. 3725 /// Close the neighbour child agents associated with this client.
3566 /// </param> 3726 /// </param>
3727 ///
3728
3729 private object m_removeClientPrivLock = new Object();
3730
3567 public void RemoveClient(UUID agentID, bool closeChildAgents) 3731 public void RemoveClient(UUID agentID, bool closeChildAgents)
3568 { 3732 {
3569 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID); 3733 AgentCircuitData acd = m_authenticateHandler.GetAgentCircuitData(agentID);
@@ -3580,8 +3744,8 @@ namespace OpenSim.Region.Framework.Scenes
3580 } 3744 }
3581 3745
3582 // TODO: Can we now remove this lock? 3746 // TODO: Can we now remove this lock?
3583 lock (acd) 3747 lock (m_removeClientPrivLock)
3584 { 3748 {
3585 bool isChildAgent = false; 3749 bool isChildAgent = false;
3586 3750
3587 ScenePresence avatar = GetScenePresence(agentID); 3751 ScenePresence avatar = GetScenePresence(agentID);
@@ -3625,8 +3789,8 @@ namespace OpenSim.Region.Framework.Scenes
3625 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3789 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
3626 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI 3790 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3627 if (closeChildAgents && CapsModule != null) 3791 if (closeChildAgents && CapsModule != null)
3628 CapsModule.RemoveCaps(agentID); 3792 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
3629 3793
3630 if (closeChildAgents && !isChildAgent) 3794 if (closeChildAgents && !isChildAgent)
3631 { 3795 {
3632 List<ulong> regions = avatar.KnownRegionHandles; 3796 List<ulong> regions = avatar.KnownRegionHandles;
@@ -3637,13 +3801,17 @@ namespace OpenSim.Region.Framework.Scenes
3637 } 3801 }
3638 3802
3639 m_eventManager.TriggerClientClosed(agentID, this); 3803 m_eventManager.TriggerClientClosed(agentID, this);
3804// m_log.Debug("[Scene]TriggerClientClosed done");
3640 m_eventManager.TriggerOnRemovePresence(agentID); 3805 m_eventManager.TriggerOnRemovePresence(agentID);
3641 3806// m_log.Debug("[Scene]TriggerOnRemovePresence done");
3807
3642 if (!isChildAgent) 3808 if (!isChildAgent)
3643 { 3809 {
3644 if (AttachmentsModule != null) 3810 if (AttachmentsModule != null)
3645 { 3811 {
3812// m_log.Debug("[Scene]DeRezAttachments");
3646 AttachmentsModule.DeRezAttachments(avatar); 3813 AttachmentsModule.DeRezAttachments(avatar);
3814// m_log.Debug("[Scene]DeRezAttachments done");
3647 } 3815 }
3648 3816
3649 ForEachClient( 3817 ForEachClient(
@@ -3657,7 +3825,11 @@ namespace OpenSim.Region.Framework.Scenes
3657 3825
3658 // It's possible for child agents to have transactions if changes are being made cross-border. 3826 // It's possible for child agents to have transactions if changes are being made cross-border.
3659 if (AgentTransactionsModule != null) 3827 if (AgentTransactionsModule != null)
3828 {
3829// m_log.Debug("[Scene]RemoveAgentAssetTransactions");
3660 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); 3830 AgentTransactionsModule.RemoveAgentAssetTransactions(agentID);
3831 }
3832 m_log.Debug("[Scene] The avatar has left the building");
3661 } 3833 }
3662 catch (Exception e) 3834 catch (Exception e)
3663 { 3835 {
@@ -3776,6 +3948,9 @@ namespace OpenSim.Region.Framework.Scenes
3776 /// or other applications where a full grid/Hypergrid presence may not be required.</param> 3948 /// or other applications where a full grid/Hypergrid presence may not be required.</param>
3777 /// <returns>True if the region accepts this agent. False if it does not. False will 3949 /// <returns>True if the region accepts this agent. False if it does not. False will
3778 /// also return a reason.</returns> 3950 /// also return a reason.</returns>
3951 ///
3952 private object m_newUserConnLock = new object();
3953
3779 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup) 3954 public bool NewUserConnection(AgentCircuitData acd, uint teleportFlags, GridRegion source, out string reason, bool requirePresenceLookup)
3780 { 3955 {
3781 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 || 3956 bool vialogin = ((teleportFlags & (uint)TPFlags.ViaLogin) != 0 ||
@@ -3809,6 +3984,8 @@ namespace OpenSim.Region.Framework.Scenes
3809 (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI) 3984 (source == null) ? "" : string.Format("From region {0} ({1}){2}", source.RegionName, source.RegionID, (source.RawServerURI == null) ? "" : " @ " + source.ServerURI)
3810 ); 3985 );
3811 3986
3987// m_log.DebugFormat("NewUserConnection stack {0}", Environment.StackTrace);
3988
3812 if (!LoginsEnabled) 3989 if (!LoginsEnabled)
3813 { 3990 {
3814 reason = "Logins Disabled"; 3991 reason = "Logins Disabled";
@@ -3936,7 +4113,7 @@ namespace OpenSim.Region.Framework.Scenes
3936 } 4113 }
3937 4114
3938 // TODO: can we remove this lock? 4115 // TODO: can we remove this lock?
3939 lock (acd) 4116 lock (m_newUserConnLock)
3940 { 4117 {
3941 if (sp != null && !sp.IsChildAgent) 4118 if (sp != null && !sp.IsChildAgent)
3942 { 4119 {
@@ -3963,6 +4140,12 @@ namespace OpenSim.Region.Framework.Scenes
3963 // We need the circuit data here for some of the subsequent checks. (groups, for example) 4140 // We need the circuit data here for some of the subsequent checks. (groups, for example)
3964 // If the checks fail, we remove the circuit. 4141 // If the checks fail, we remove the circuit.
3965 acd.teleportFlags = teleportFlags; 4142 acd.teleportFlags = teleportFlags;
4143
4144 // Remove any preexisting circuit - we don't want duplicates
4145 // This is a stab at preventing avatar "ghosting"
4146 if (vialogin)
4147 m_authenticateHandler.RemoveCircuit(acd.AgentID);
4148
3966 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd); 4149 m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd);
3967 4150
3968 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y); 4151 land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y);
@@ -3970,6 +4153,9 @@ namespace OpenSim.Region.Framework.Scenes
3970 // On login test land permisions 4153 // On login test land permisions
3971 if (vialogin) 4154 if (vialogin)
3972 { 4155 {
4156 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
4157 if (cache != null)
4158 cache.Remove(acd.firstname + " " + acd.lastname);
3973 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y)) 4159 if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y))
3974 { 4160 {
3975 m_authenticateHandler.RemoveCircuit(acd.circuitcode); 4161 m_authenticateHandler.RemoveCircuit(acd.circuitcode);
@@ -4024,7 +4210,7 @@ namespace OpenSim.Region.Framework.Scenes
4024 if (CapsModule != null) 4210 if (CapsModule != null)
4025 { 4211 {
4026 CapsModule.SetAgentCapsSeeds(acd); 4212 CapsModule.SetAgentCapsSeeds(acd);
4027 CapsModule.CreateCaps(acd.AgentID); 4213 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4028 } 4214 }
4029 } 4215 }
4030 else 4216 else
@@ -4037,15 +4223,15 @@ namespace OpenSim.Region.Framework.Scenes
4037 { 4223 {
4038 m_log.DebugFormat( 4224 m_log.DebugFormat(
4039 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", 4225 "[SCENE]: Adjusting known seeds for existing agent {0} in {1}",
4040 acd.AgentID, RegionInfo.RegionName); 4226 acd.AgentID, RegionInfo.RegionName);
4041
4042 sp.AdjustKnownSeeds();
4043 4227
4044 if (CapsModule != null) 4228 if (CapsModule != null)
4045 { 4229 {
4046 CapsModule.SetAgentCapsSeeds(acd); 4230 CapsModule.SetAgentCapsSeeds(acd);
4047 CapsModule.CreateCaps(acd.AgentID); 4231 CapsModule.CreateCaps(acd.AgentID, acd.circuitcode);
4048 } 4232 }
4233
4234 sp.AdjustKnownSeeds();
4049 } 4235 }
4050 } 4236 }
4051 4237
@@ -4055,6 +4241,11 @@ namespace OpenSim.Region.Framework.Scenes
4055 CacheUserName(null, acd); 4241 CacheUserName(null, acd);
4056 } 4242 }
4057 4243
4244 if (CapsModule != null)
4245 {
4246 CapsModule.ActivateCaps(acd.circuitcode);
4247 }
4248
4058 if (vialogin) 4249 if (vialogin)
4059 { 4250 {
4060// CleanDroppedAttachments(); 4251// CleanDroppedAttachments();
@@ -4124,6 +4315,8 @@ namespace OpenSim.Region.Framework.Scenes
4124 } 4315 }
4125 4316
4126 // Honor parcel landing type and position. 4317 // Honor parcel landing type and position.
4318 /*
4319 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
4127 if (land != null) 4320 if (land != null)
4128 { 4321 {
4129 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 4322 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -4138,6 +4331,7 @@ namespace OpenSim.Region.Framework.Scenes
4138 } 4331 }
4139 } 4332 }
4140 } 4333 }
4334 */// This is now handled properly in ScenePresence.MakeRootAgent
4141 } 4335 }
4142 4336
4143 return true; 4337 return true;
@@ -4162,12 +4356,13 @@ namespace OpenSim.Region.Framework.Scenes
4162 { 4356 {
4163 if (posX < 0) 4357 if (posX < 0)
4164 posX = 0; 4358 posX = 0;
4165 else if (posX >= (float)RegionInfo.RegionSizeX) 4359
4166 posX = (float)RegionInfo.RegionSizeX - 0.001f; 4360 else if (posX >= RegionInfo.RegionSizeX)
4361 posX = RegionInfo.RegionSizeX - 0.5f;
4167 if (posY < 0) 4362 if (posY < 0)
4168 posY = 0; 4363 posY = 0;
4169 else if (posY >= (float)RegionInfo.RegionSizeY) 4364 else if (posY >= RegionInfo.RegionSizeY)
4170 posY = (float)RegionInfo.RegionSizeY - 0.001f; 4365 posY = RegionInfo.RegionSizeY - 0.5f;
4171 4366
4172 reason = String.Empty; 4367 reason = String.Empty;
4173 if (Permissions.IsGod(agentID)) 4368 if (Permissions.IsGod(agentID))
@@ -4271,7 +4466,8 @@ namespace OpenSim.Region.Framework.Scenes
4271 { 4466 {
4272 if (RegionInfo.EstateSettings != null) 4467 if (RegionInfo.EstateSettings != null)
4273 { 4468 {
4274 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID)) 4469 int flags = GetUserFlags(agent.AgentID);
4470 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags))
4275 { 4471 {
4276 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 4472 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
4277 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 4473 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -4460,6 +4656,22 @@ namespace OpenSim.Region.Framework.Scenes
4460 m_log.DebugFormat( 4656 m_log.DebugFormat(
4461 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); 4657 "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName);
4462 4658
4659 if (!LoginsEnabled)
4660 {
4661// reason = "Logins Disabled";
4662 m_log.DebugFormat(
4663 "[SCENE]: update for {0} in {1} refused: Logins Disabled", cAgentData.AgentID, RegionInfo.RegionName);
4664 return false;
4665 }
4666 // We have to wait until the viewer contacts this region after receiving EAC.
4667 // That calls AddNewClient, which finally creates the ScenePresence
4668 int flags = GetUserFlags(cAgentData.AgentID);
4669 if (RegionInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
4670 {
4671 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
4672 return false;
4673 }
4674
4463 // TODO: This check should probably be in QueryAccess(). 4675 // TODO: This check should probably be in QueryAccess().
4464 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2); 4676 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, RegionInfo.RegionSizeX / 2, RegionInfo.RegionSizeY / 2);
4465 if (nearestParcel == null) 4677 if (nearestParcel == null)
@@ -4477,8 +4689,14 @@ namespace OpenSim.Region.Framework.Scenes
4477 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence. 4689 // a UseCircuitCode packet which in turn calls AddNewAgent which finally creates the ScenePresence.
4478 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID); 4690 ScenePresence sp = WaitGetScenePresence(cAgentData.AgentID);
4479 4691
4480 if (sp != null) 4692 if (sp != null)
4481 { 4693 {
4694 if (!sp.IsChildAgent)
4695 {
4696 m_log.WarnFormat("[SCENE]: Ignoring a child update on a root agent {0} {1} in {2}",
4697 sp.Name, sp.UUID, Name);
4698 return false;
4699 }
4482 if (cAgentData.SessionID != sp.ControllingClient.SessionId) 4700 if (cAgentData.SessionID != sp.ControllingClient.SessionId)
4483 { 4701 {
4484 m_log.WarnFormat( 4702 m_log.WarnFormat(
@@ -4563,7 +4781,7 @@ namespace OpenSim.Region.Framework.Scenes
4563 /// <param name='agentID'></param> 4781 /// <param name='agentID'></param>
4564 protected virtual ScenePresence WaitGetScenePresence(UUID agentID) 4782 protected virtual ScenePresence WaitGetScenePresence(UUID agentID)
4565 { 4783 {
4566 int ntimes = 20; 4784 int ntimes = 30;
4567 ScenePresence sp = null; 4785 ScenePresence sp = null;
4568 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0)) 4786 while ((sp = GetScenePresence(agentID)) == null && (ntimes-- > 0))
4569 Thread.Sleep(1000); 4787 Thread.Sleep(1000);
@@ -4613,6 +4831,16 @@ namespace OpenSim.Region.Framework.Scenes
4613 return false; 4831 return false;
4614 } 4832 }
4615 4833
4834// public bool IncomingCloseAgent(UUID agentID)
4835// {
4836// return IncomingCloseAgent(agentID, false);
4837// }
4838
4839// public bool IncomingCloseChildAgent(UUID agentID)
4840// {
4841// return IncomingCloseAgent(agentID, true);
4842// }
4843
4616 /// <summary> 4844 /// <summary>
4617 /// Tell a single client to prepare to close. 4845 /// Tell a single client to prepare to close.
4618 /// </summary> 4846 /// </summary>
@@ -4675,6 +4903,20 @@ namespace OpenSim.Region.Framework.Scenes
4675 4903
4676 if (sp == null) 4904 if (sp == null)
4677 { 4905 {
4906 // If there is no scene presence, we may be handling a dead
4907 // client. These can keep an avatar from reentering a region
4908 // and since they don't get cleaned up they will stick
4909 // around until region restart. So, if there is no SP,
4910 // remove the client as well.
4911 IClientAPI client = null;
4912 if (m_clientManager.TryGetValue(agentID, out client))
4913 {
4914 m_clientManager.Remove(agentID);
4915 if (CapsModule != null)
4916 CapsModule.RemoveCaps(agentID, 0);
4917 m_log.DebugFormat( "[SCENE]: Dead client for agent ID {0} was cleaned up in {1}", agentID, Name);
4918 return true;
4919 }
4678 m_log.DebugFormat( 4920 m_log.DebugFormat(
4679 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}", 4921 "[SCENE]: Called CloseClient() with agent ID {0} but no such presence is in {1}",
4680 agentID, Name); 4922 agentID, Name);
@@ -4709,7 +4951,11 @@ namespace OpenSim.Region.Framework.Scenes
4709 sp.LifecycleState = ScenePresenceState.Removing; 4951 sp.LifecycleState = ScenePresenceState.Removing;
4710 } 4952 }
4711 4953
4712 sp.ControllingClient.Close(force); 4954 if (sp != null)
4955 {
4956 sp.ControllingClient.Close(force, force);
4957 return true;
4958 }
4713 4959
4714 return true; 4960 return true;
4715 } 4961 }
@@ -4871,7 +5117,10 @@ namespace OpenSim.Region.Framework.Scenes
4871 5117
4872 public LandData GetLandData(float x, float y) 5118 public LandData GetLandData(float x, float y)
4873 { 5119 {
4874 return LandChannel.GetLandObject(x, y).LandData; 5120 ILandObject parcel = LandChannel.GetLandObject(x, y);
5121 if (parcel == null)
5122 return null;
5123 return parcel.LandData;
4875 } 5124 }
4876 5125
4877 /// <summary> 5126 /// <summary>
@@ -4887,7 +5136,10 @@ namespace OpenSim.Region.Framework.Scenes
4887 public LandData GetLandData(uint x, uint y) 5136 public LandData GetLandData(uint x, uint y)
4888 { 5137 {
4889 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); 5138 m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y);
4890 return LandChannel.GetLandObject((int)x, (int)y).LandData; 5139 ILandObject parcel = LandChannel.GetLandObject((int)x, (int)y);
5140 if (parcel == null)
5141 return null;
5142 return parcel.LandData;
4891 } 5143 }
4892 5144
4893 #endregion 5145 #endregion
@@ -5275,7 +5527,7 @@ namespace OpenSim.Region.Framework.Scenes
5275 { 5527 {
5276 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 5528 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
5277 { 5529 {
5278 if (grp.RootPart.Expires <= DateTime.Now) 5530 if (grp.GetSittingAvatarsCount() == 0 && grp.RootPart.Expires <= DateTime.Now)
5279 DeleteSceneObject(grp, false); 5531 DeleteSceneObject(grp, false);
5280 } 5532 }
5281 } 5533 }
@@ -5289,35 +5541,80 @@ namespace OpenSim.Region.Framework.Scenes
5289 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID); 5541 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID);
5290 } 5542 }
5291 5543
5292 public int GetHealth() 5544 public int GetHealth(out int flags, out string message)
5293 { 5545 {
5294 // Returns: 5546 // Returns:
5295 // 1 = sim is up and accepting http requests. The heartbeat has 5547 // 1 = sim is up and accepting http requests. The heartbeat has
5296 // stopped and the sim is probably locked up, but a remote 5548 // stopped and the sim is probably locked up, but a remote
5297 // admin restart may succeed 5549 // admin restart may succeed
5298 // 5550 //
5299 // 2 = Sim is up and the heartbeat is running. The sim is likely 5551 // 2 = Sim is up and the heartbeat is running. The sim is likely
5300 // usable for people within and logins _may_ work 5552 // usable for people within
5553 //
5554 // 3 = Sim is up and one packet thread is running. Sim is
5555 // unstable and will not accept new logins
5301 // 5556 //
5302 // 3 = We have seen a new user enter within the past 4 minutes 5557 // 4 = Sim is up and both packet threads are running. Sim is
5558 // likely usable
5559 //
5560 // 5 = We have seen a new user enter within the past 4 minutes
5303 // which can be seen as positive confirmation of sim health 5561 // which can be seen as positive confirmation of sim health
5304 // 5562 //
5305 int health = 1; // Start at 1, means we're up 5563 int health = 1; // Start at 1, means we're up
5306 5564
5565 flags = 0;
5566 message = String.Empty;
5567
5568 CheckHeartbeat();
5569
5570 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
5571 {
5572 // We're still starting
5573 // 0 means "in startup", it can't happen another way, since
5574 // to get here, we must be able to accept http connections
5575 return 0;
5576 }
5577
5307 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) 5578 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000)
5308 health += 1; 5579 {
5580 health+=1;
5581 flags |= 1;
5582 }
5583
5584 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
5585 {
5586 health+=1;
5587 flags |= 2;
5588 }
5589
5590 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
5591 {
5592 health+=1;
5593 flags |= 4;
5594 }
5309 else 5595 else
5596 {
5597int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
5598System.Diagnostics.Process proc = new System.Diagnostics.Process();
5599proc.EnableRaisingEvents=false;
5600proc.StartInfo.FileName = "/bin/kill";
5601proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
5602proc.Start();
5603proc.WaitForExit();
5604Thread.Sleep(1000);
5605Environment.Exit(1);
5606 }
5607
5608 if (flags != 7)
5310 return health; 5609 return health;
5311 5610
5312 // A login in the last 4 mins? We can't be doing too badly 5611 // A login in the last 4 mins? We can't be doing too badly
5313 // 5612 //
5314 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 5613 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
5315 health++; 5614 health++;
5316 else 5615 else
5317 return health; 5616 return health;
5318 5617
5319// CheckHeartbeat();
5320
5321 return health; 5618 return health;
5322 } 5619 }
5323 5620
@@ -5405,7 +5702,7 @@ namespace OpenSim.Region.Framework.Scenes
5405 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); 5702 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
5406 if (wasUsingPhysics) 5703 if (wasUsingPhysics)
5407 { 5704 {
5408 jointProxyObject.UpdatePrimFlags(false, false, true, false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock 5705 jointProxyObject.UpdatePrimFlags(false, false, true, false,false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock
5409 } 5706 }
5410 } 5707 }
5411 5708
@@ -5508,14 +5805,14 @@ namespace OpenSim.Region.Framework.Scenes
5508 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; 5805 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z;
5509 } 5806 }
5510 5807
5511// private void CheckHeartbeat() 5808 private void CheckHeartbeat()
5512// { 5809 {
5513// if (m_firstHeartbeat) 5810 if (m_firstHeartbeat)
5514// return; 5811 return;
5515// 5812
5516// if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) 5813 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) > 5000)
5517// StartTimer(); 5814 Start();
5518// } 5815 }
5519 5816
5520 public override ISceneObject DeserializeObject(string representation) 5817 public override ISceneObject DeserializeObject(string representation)
5521 { 5818 {
@@ -5572,8 +5869,7 @@ namespace OpenSim.Region.Framework.Scenes
5572 //Go to the edge, this happens in teleporting to a region with no available parcels 5869 //Go to the edge, this happens in teleporting to a region with no available parcels
5573 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar); 5870 Vector3 nearestRegionEdgePoint = GetNearestRegionEdgePosition(avatar);
5574 5871
5575 //m_log.Debug("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString()); 5872 //Debug.WriteLine("They are really in a place they don't belong, sending them to: " + nearestRegionEdgePoint.ToString());
5576
5577 return nearestRegionEdgePoint; 5873 return nearestRegionEdgePoint;
5578 } 5874 }
5579 5875
@@ -5829,7 +6125,55 @@ namespace OpenSim.Region.Framework.Scenes
5829 mapModule.GenerateMaptile(); 6125 mapModule.GenerateMaptile();
5830 } 6126 }
5831 6127
5832 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 6128// public void CleanDroppedAttachments()
6129// {
6130// List<SceneObjectGroup> objectsToDelete =
6131// new List<SceneObjectGroup>();
6132//
6133// lock (m_cleaningAttachments)
6134// {
6135// ForEachSOG(delegate (SceneObjectGroup grp)
6136// {
6137// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
6138// {
6139// UUID agentID = grp.OwnerID;
6140// if (agentID == UUID.Zero)
6141// {
6142// objectsToDelete.Add(grp);
6143// return;
6144// }
6145//
6146// ScenePresence sp = GetScenePresence(agentID);
6147// if (sp == null)
6148// {
6149// objectsToDelete.Add(grp);
6150// return;
6151// }
6152// }
6153// });
6154// }
6155//
6156// foreach (SceneObjectGroup grp in objectsToDelete)
6157// {
6158// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
6159// DeleteSceneObject(grp, true);
6160// }
6161// }
6162
6163 public void ThreadAlive(int threadCode)
6164 {
6165 switch(threadCode)
6166 {
6167 case 1: // Incoming
6168 m_lastIncoming = Util.EnvironmentTickCount();
6169 break;
6170 case 2: // Incoming
6171 m_lastOutgoing = Util.EnvironmentTickCount();
6172 break;
6173 }
6174 }
6175
6176 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5833 { 6177 {
5834 RegenerateMaptile(); 6178 RegenerateMaptile();
5835 6179
@@ -5995,7 +6339,19 @@ namespace OpenSim.Region.Framework.Scenes
5995 return true; 6339 return true;
5996 } 6340 }
5997 6341
5998 /// <summary> 6342 public void StartTimerWatchdog()
6343 {
6344 m_timerWatchdog.Interval = 1000;
6345 m_timerWatchdog.Elapsed += TimerWatchdog;
6346 m_timerWatchdog.AutoReset = true;
6347 m_timerWatchdog.Start();
6348 }
6349
6350 public void TimerWatchdog(object sender, ElapsedEventArgs e)
6351 {
6352 CheckHeartbeat();
6353 }
6354
5999 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 6355 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
6000 /// autopilot that moves an avatar to a sit target!. 6356 /// autopilot that moves an avatar to a sit target!.
6001 /// </summary> 6357 /// </summary>
@@ -6074,6 +6430,11 @@ namespace OpenSim.Region.Framework.Scenes
6074 return m_SpawnPoint - 1; 6430 return m_SpawnPoint - 1;
6075 } 6431 }
6076 6432
6433 private void HandleGcCollect(string module, string[] args)
6434 {
6435 GC.Collect();
6436 }
6437
6077 /// <summary> 6438 /// <summary>
6078 /// Wrappers to get physics modules retrieve assets. 6439 /// Wrappers to get physics modules retrieve assets.
6079 /// </summary> 6440 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 7ff3d40..f420f69 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -200,7 +200,7 @@ namespace OpenSim.Region.Framework.Scenes
200 /// If -1 then updates until shutdown. 200 /// If -1 then updates until shutdown.
201 /// </param> 201 /// </param>
202 /// <returns>true if update completed within minimum frame time, false otherwise.</returns> 202 /// <returns>true if update completed within minimum frame time, false otherwise.</returns>
203 public abstract bool Update(int frames); 203 public abstract void Update(int frames);
204 204
205 #endregion 205 #endregion
206 206
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index b9526da..3eefd3c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -66,7 +66,7 @@ namespace OpenSim.Region.Framework.Scenes
66 66
67 private void InformNeighborsThatRegionisUpCompleted(IAsyncResult iar) 67 private void InformNeighborsThatRegionisUpCompleted(IAsyncResult iar)
68 { 68 {
69 InformNeighbourThatRegionUpDelegate icon = (InformNeighbourThatRegionUpDelegate) iar.AsyncState; 69 InformNeighbourThatRegionUpDelegate icon = (InformNeighbourThatRegionUpDelegate)iar.AsyncState;
70 icon.EndInvoke(iar); 70 icon.EndInvoke(iar);
71 } 71 }
72 72
@@ -84,11 +84,11 @@ namespace OpenSim.Region.Framework.Scenes
84 if (neighbourService != null) 84 if (neighbourService != null)
85 neighbour = neighbourService.HelloNeighbour(regionhandle, region); 85 neighbour = neighbourService.HelloNeighbour(regionhandle, region);
86 else 86 else
87 m_log.DebugFormat( "{0} neighbour service provided for region {0} to inform neigbhours of status", LogHeader, m_scene.Name); 87 m_log.DebugFormat("{0} neighbour service provided for region {0} to inform neigbhours of status", LogHeader, m_scene.Name);
88 88
89 if (neighbour != null) 89 if (neighbour != null)
90 { 90 {
91 m_log.DebugFormat( "{0} Region {1} successfully informed neighbour {2} at {3}-{4} that it is up", 91 m_log.DebugFormat("{0} Region {1} successfully informed neighbour {2} at {3}-{4} that it is up",
92 LogHeader, m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y)); 92 LogHeader, m_scene.Name, neighbour.RegionName, Util.WorldToRegionLoc(x), Util.WorldToRegionLoc(y));
93 93
94 m_scene.EventManager.TriggerOnRegionUp(neighbour); 94 m_scene.EventManager.TriggerOnRegionUp(neighbour);
@@ -114,9 +114,9 @@ namespace OpenSim.Region.Framework.Scenes
114 { 114 {
115 OpenSim.Framework.RegionFlags? regionFlags = n.RegionFlags; 115 OpenSim.Framework.RegionFlags? regionFlags = n.RegionFlags;
116 116
117// m_log.DebugFormat( 117 // m_log.DebugFormat(
118// "{0}: Region flags for {1} as seen by {2} are {3}", 118 // "{0}: Region flags for {1} as seen by {2} are {3}",
119// LogHeader, n.RegionName, m_scene.Name, regionFlags != null ? regionFlags.ToString() : "not present"); 119 // LogHeader, n.RegionName, m_scene.Name, regionFlags != null ? regionFlags.ToString() : "not present");
120 120
121 // Robust services before 2015-01-14 do not return the regionFlags information. In this case, we could 121 // Robust services before 2015-01-14 do not return the regionFlags information. In this case, we could
122 // make a separate RegionFlags call but this would involve a network call for each neighbour. 122 // make a separate RegionFlags call but this would involve a network call for each neighbour.
@@ -132,7 +132,7 @@ namespace OpenSim.Region.Framework.Scenes
132 } 132 }
133 133
134 m_log.DebugFormat( 134 m_log.DebugFormat(
135 "{0} Informing {1} neighbours that region {2} is up", 135 "{0} Informing {1} neighbours that region {2} is up",
136 LogHeader, onlineNeighbours.Count, m_scene.Name); 136 LogHeader, onlineNeighbours.Count, m_scene.Name);
137 137
138 foreach (GridRegion n in onlineNeighbours) 138 foreach (GridRegion n in onlineNeighbours)
@@ -168,15 +168,15 @@ namespace OpenSim.Region.Framework.Scenes
168 168
169 private void SendChildAgentDataUpdateCompleted(IAsyncResult iar) 169 private void SendChildAgentDataUpdateCompleted(IAsyncResult iar)
170 { 170 {
171 SendChildAgentDataUpdateDelegate icon = (SendChildAgentDataUpdateDelegate) iar.AsyncState; 171 SendChildAgentDataUpdateDelegate icon = (SendChildAgentDataUpdateDelegate)iar.AsyncState;
172 icon.EndInvoke(iar); 172 icon.EndInvoke(iar);
173 } 173 }
174 174
175 public void SendChildAgentDataUpdate(AgentPosition cAgentData, ScenePresence presence) 175 public void SendChildAgentDataUpdate(AgentPosition cAgentData, ScenePresence presence)
176 { 176 {
177// m_log.DebugFormat( 177 // m_log.DebugFormat(
178// "[SCENE COMMUNICATION SERVICE]: Sending child agent position updates for {0} in {1}", 178 // "[SCENE COMMUNICATION SERVICE]: Sending child agent position updates for {0} in {1}",
179// presence.Name, m_scene.Name); 179 // presence.Name, m_scene.Name);
180 180
181 // This assumes that we know what our neighbors are. 181 // This assumes that we know what our neighbors are.
182 try 182 try
@@ -218,8 +218,11 @@ namespace OpenSim.Region.Framework.Scenes
218 } 218 }
219 } 219 }
220 220
221 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
222
221 /// <summary> 223 /// <summary>
222 /// Closes a child agent on a given region 224 /// This Closes child agents on neighboring regions
225 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
223 /// </summary> 226 /// </summary>
224 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle, string auth_token) 227 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle, string auth_token)
225 { 228 {
@@ -231,6 +234,13 @@ namespace OpenSim.Region.Framework.Scenes
231 234
232 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 235 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
233 236
237 if (destination == null)
238 {
239 m_log.DebugFormat(
240 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} FAIL, region with handle {1} not found", agentID, regionHandle);
241 return;
242 }
243
234 m_log.DebugFormat( 244 m_log.DebugFormat(
235 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName); 245 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName);
236 246
@@ -245,21 +255,22 @@ namespace OpenSim.Region.Framework.Scenes
245 /// <param name="regionslst"></param> 255 /// <param name="regionslst"></param>
246 public void SendCloseChildAgentConnections(UUID agentID, string auth_code, List<ulong> regionslst) 256 public void SendCloseChildAgentConnections(UUID agentID, string auth_code, List<ulong> regionslst)
247 { 257 {
248 foreach (ulong handle in regionslst) 258 if (regionslst.Count == 0)
259 return;
260
261 // use a single thread job for all
262 Util.FireAndForget(o =>
249 { 263 {
250 // We must take a copy here since handle is acts like a reference when used in an iterator. 264 foreach (ulong handle in regionslst)
251 // This leads to race conditions if directly passed to SendCloseChildAgent with more than one neighbour region. 265 {
252 ulong handleCopy = handle; 266 SendCloseChildAgent(agentID, handle, auth_code);
253 Util.FireAndForget( 267 }
254 o => SendCloseChildAgent(agentID, handleCopy, auth_code), 268 }, null, "SceneCommunicationService.SendCloseChildAgentConnections");
255 null,
256 "SceneCommunicationService.SendCloseChildAgentConnections");
257 }
258 } 269 }
259 270
260 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 271 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
261 { 272 {
262 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 273 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
263 } 274 }
264 } 275 }
265} \ No newline at end of file 276}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e0080f2..0879cce 100755
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -41,6 +41,12 @@ namespace OpenSim.Region.Framework.Scenes
41{ 41{
42 public delegate void PhysicsCrash(); 42 public delegate void PhysicsCrash();
43 43
44 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
45
46 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
49
44 /// <summary> 50 /// <summary>
45 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components 51 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
46 /// should be migrated out over time. 52 /// should be migrated out over time.
@@ -54,11 +60,15 @@ namespace OpenSim.Region.Framework.Scenes
54 protected internal event PhysicsCrash UnRecoverableError; 60 protected internal event PhysicsCrash UnRecoverableError;
55 private PhysicsCrash handlerPhysicsCrash = null; 61 private PhysicsCrash handlerPhysicsCrash = null;
56 62
63 public event AttachToBackupDelegate OnAttachToBackup;
64 public event DetachFromBackupDelegate OnDetachFromBackup;
65 public event ChangedBackupDelegate OnChangeBackup;
66
57 #endregion 67 #endregion
58 68
59 #region Fields 69 #region Fields
60 70
61 protected object m_presenceLock = new object(); 71 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
62 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
63 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
64 74
@@ -134,13 +144,18 @@ namespace OpenSim.Region.Framework.Scenes
134 144
135 protected internal void Close() 145 protected internal void Close()
136 { 146 {
137 lock (m_presenceLock) 147 m_scenePresencesLock.EnterWriteLock();
148 try
138 { 149 {
139 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 150 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
140 List<ScenePresence> newlist = new List<ScenePresence>(); 151 List<ScenePresence> newlist = new List<ScenePresence>();
141 m_scenePresenceMap = newmap; 152 m_scenePresenceMap = newmap;
142 m_scenePresenceArray = newlist; 153 m_scenePresenceArray = newlist;
143 } 154 }
155 finally
156 {
157 m_scenePresencesLock.ExitWriteLock();
158 }
144 159
145 lock (SceneObjectGroupsByFullID) 160 lock (SceneObjectGroupsByFullID)
146 SceneObjectGroupsByFullID.Clear(); 161 SceneObjectGroupsByFullID.Clear();
@@ -207,6 +222,12 @@ namespace OpenSim.Region.Framework.Scenes
207 return PhysicsScene.Simulate((float)elapsed); 222 return PhysicsScene.Simulate((float)elapsed);
208 } 223 }
209 224
225 protected internal void ProcessPhysicsPreSimulation()
226 {
227 if(PhysicsScene != null)
228 PhysicsScene.ProcessPreSimulation();
229 }
230
210 protected internal void UpdateScenePresenceMovement() 231 protected internal void UpdateScenePresenceMovement()
211 { 232 {
212 ForEachScenePresence(delegate(ScenePresence presence) 233 ForEachScenePresence(delegate(ScenePresence presence)
@@ -261,13 +282,54 @@ namespace OpenSim.Region.Framework.Scenes
261 protected internal bool AddRestoredSceneObject( 282 protected internal bool AddRestoredSceneObject(
262 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 283 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
263 { 284 {
285 if (!m_parentScene.CombineRegions)
286 {
287 // temporary checks to remove after varsize suport
288 float regionSizeX = m_parentScene.RegionInfo.RegionSizeX;
289 if (regionSizeX == 0)
290 regionSizeX = Constants.RegionSize;
291 float regionSizeY = m_parentScene.RegionInfo.RegionSizeY;
292 if (regionSizeY == 0)
293 regionSizeY = Constants.RegionSize;
294
295 // KF: Check for out-of-region, move inside and make static.
296 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
297 sceneObject.RootPart.GroupPosition.Y,
298 sceneObject.RootPart.GroupPosition.Z);
299 if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 ||
300 npos.X > regionSizeX ||
301 npos.Y > regionSizeY))
302 {
303 if (npos.X < 0.0) npos.X = 1.0f;
304 if (npos.Y < 0.0) npos.Y = 1.0f;
305 if (npos.Z < 0.0) npos.Z = 0.0f;
306 if (npos.X > regionSizeX) npos.X = regionSizeX - 1.0f;
307 if (npos.Y > regionSizeY) npos.Y = regionSizeY - 1.0f;
308
309 SceneObjectPart rootpart = sceneObject.RootPart;
310 rootpart.GroupPosition = npos;
311
312 foreach (SceneObjectPart part in sceneObject.Parts)
313 {
314 if (part == rootpart)
315 continue;
316 part.GroupPosition = npos;
317 }
318 rootpart.Velocity = Vector3.Zero;
319 rootpart.AngularVelocity = Vector3.Zero;
320 rootpart.Acceleration = Vector3.Zero;
321 }
322 }
323
324 bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
325
264 if (attachToBackup && (!alreadyPersisted)) 326 if (attachToBackup && (!alreadyPersisted))
265 { 327 {
266 sceneObject.ForceInventoryPersistence(); 328 sceneObject.ForceInventoryPersistence();
267 sceneObject.HasGroupChanged = true; 329 sceneObject.HasGroupChanged = true;
268 } 330 }
269 331
270 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 332 return ret;
271 } 333 }
272 334
273 /// <summary> 335 /// <summary>
@@ -284,12 +346,16 @@ namespace OpenSim.Region.Framework.Scenes
284 /// </returns> 346 /// </returns>
285 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 347 protected internal bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
286 { 348 {
287 // Ensure that we persist this new scene object if it's not an 349
350 bool ret = AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
351
352 // Ensure that we persist this new scene object if it's not an
288 // attachment 353 // attachment
354
289 if (attachToBackup) 355 if (attachToBackup)
290 sceneObject.HasGroupChanged = true; 356 sceneObject.HasGroupChanged = true;
291 357
292 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 358 return ret;
293 } 359 }
294 360
295 /// <summary> 361 /// <summary>
@@ -324,9 +390,8 @@ namespace OpenSim.Region.Framework.Scenes
324 if (pa != null && pa.IsPhysical && vel != Vector3.Zero) 390 if (pa != null && pa.IsPhysical && vel != Vector3.Zero)
325 { 391 {
326 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); 392 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false);
327 sceneObject.Velocity = vel;
328 } 393 }
329 394
330 return true; 395 return true;
331 } 396 }
332 397
@@ -351,6 +416,11 @@ namespace OpenSim.Region.Framework.Scenes
351 /// </returns> 416 /// </returns>
352 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 417 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
353 { 418 {
419 if (sceneObject == null)
420 {
421 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
422 return false;
423 }
354 if (sceneObject.UUID == UUID.Zero) 424 if (sceneObject.UUID == UUID.Zero)
355 { 425 {
356 m_log.ErrorFormat( 426 m_log.ErrorFormat(
@@ -383,9 +453,9 @@ namespace OpenSim.Region.Framework.Scenes
383 { 453 {
384 Vector3 scale = part.Shape.Scale; 454 Vector3 scale = part.Shape.Scale;
385 455
386 scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); 456 scale.X = Util.Clamp(scale.X, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
387 scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); 457 scale.Y = Util.Clamp(scale.Y, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
388 scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); 458 scale.Z = Util.Clamp(scale.Z, m_parentScene.m_minNonphys, m_parentScene.m_maxNonphys);
389 459
390 part.Shape.Scale = scale; 460 part.Shape.Scale = scale;
391 } 461 }
@@ -406,36 +476,39 @@ namespace OpenSim.Region.Framework.Scenes
406 476
407 sceneObject.AttachToScene(m_parentScene); 477 sceneObject.AttachToScene(m_parentScene);
408 478
409 if (sendClientUpdates)
410 sceneObject.ScheduleGroupForFullUpdate();
411
412 Entities.Add(sceneObject); 479 Entities.Add(sceneObject);
413 480
414 if (attachToBackup)
415 sceneObject.AttachToBackup();
416
417 lock (SceneObjectGroupsByFullID) 481 lock (SceneObjectGroupsByFullID)
418 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; 482 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
419 483
420 lock (SceneObjectGroupsByFullPartID) 484 foreach (SceneObjectPart part in parts)
421 { 485 {
422 foreach (SceneObjectPart part in parts) 486 lock (SceneObjectGroupsByFullPartID)
423 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; 487 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
424 }
425
426 lock (SceneObjectGroupsByLocalPartID)
427 {
428// m_log.DebugFormat(
429// "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}",
430// sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName);
431 488
432 foreach (SceneObjectPart part in parts) 489 lock (SceneObjectGroupsByLocalPartID)
433 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; 490 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
434 } 491 }
435 492
493 if (sendClientUpdates)
494 sceneObject.ScheduleGroupForFullUpdate();
495
496 if (attachToBackup)
497 sceneObject.AttachToBackup();
498
436 return true; 499 return true;
437 } 500 }
438 501
502 public void updateScenePartGroup(SceneObjectPart part, SceneObjectGroup grp)
503 {
504 // no tests, caller has responsability...
505 lock (SceneObjectGroupsByFullPartID)
506 SceneObjectGroupsByFullPartID[part.UUID] = grp;
507
508 lock (SceneObjectGroupsByLocalPartID)
509 SceneObjectGroupsByLocalPartID[part.LocalId] = grp;
510 }
511
439 /// <summary> 512 /// <summary>
440 /// Delete an object from the scene 513 /// Delete an object from the scene
441 /// </summary> 514 /// </summary>
@@ -476,25 +549,23 @@ namespace OpenSim.Region.Framework.Scenes
476 if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) 549 if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
477 RemovePhysicalPrim(grp.PrimCount); 550 RemovePhysicalPrim(grp.PrimCount);
478 } 551 }
479 552
553 bool ret = Entities.Remove(uuid);
554
480 lock (SceneObjectGroupsByFullID) 555 lock (SceneObjectGroupsByFullID)
481 SceneObjectGroupsByFullID.Remove(grp.UUID); 556 SceneObjectGroupsByFullID.Remove(grp.UUID);
482 557
483 lock (SceneObjectGroupsByFullPartID) 558 SceneObjectPart[] parts = grp.Parts;
559 for (int i = 0; i < parts.Length; i++)
484 { 560 {
485 SceneObjectPart[] parts = grp.Parts; 561 lock (SceneObjectGroupsByFullPartID)
486 for (int i = 0; i < parts.Length; i++)
487 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); 562 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID);
488 }
489 563
490 lock (SceneObjectGroupsByLocalPartID) 564 lock (SceneObjectGroupsByLocalPartID)
491 {
492 SceneObjectPart[] parts = grp.Parts;
493 for (int i = 0; i < parts.Length; i++)
494 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); 565 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId);
495 } 566 }
496 567
497 return Entities.Remove(uuid); 568 return ret;
498 } 569 }
499 570
500 /// <summary> 571 /// <summary>
@@ -509,6 +580,30 @@ namespace OpenSim.Region.Framework.Scenes
509 m_updateList[obj.UUID] = obj; 580 m_updateList[obj.UUID] = obj;
510 } 581 }
511 582
583 public void FireAttachToBackup(SceneObjectGroup obj)
584 {
585 if (OnAttachToBackup != null)
586 {
587 OnAttachToBackup(obj);
588 }
589 }
590
591 public void FireDetachFromBackup(SceneObjectGroup obj)
592 {
593 if (OnDetachFromBackup != null)
594 {
595 OnDetachFromBackup(obj);
596 }
597 }
598
599 public void FireChangeBackup(SceneObjectGroup obj)
600 {
601 if (OnChangeBackup != null)
602 {
603 OnChangeBackup(obj);
604 }
605 }
606
512 /// <summary> 607 /// <summary>
513 /// Process all pending updates 608 /// Process all pending updates
514 /// </summary> 609 /// </summary>
@@ -600,7 +695,8 @@ namespace OpenSim.Region.Framework.Scenes
600 695
601 Entities[presence.UUID] = presence; 696 Entities[presence.UUID] = presence;
602 697
603 lock (m_presenceLock) 698 m_scenePresencesLock.EnterWriteLock();
699 try
604 { 700 {
605 m_numChildAgents++; 701 m_numChildAgents++;
606 702
@@ -626,6 +722,10 @@ namespace OpenSim.Region.Framework.Scenes
626 m_scenePresenceMap = newmap; 722 m_scenePresenceMap = newmap;
627 m_scenePresenceArray = newlist; 723 m_scenePresenceArray = newlist;
628 } 724 }
725 finally
726 {
727 m_scenePresencesLock.ExitWriteLock();
728 }
629 729
630 return presence; 730 return presence;
631 } 731 }
@@ -642,7 +742,8 @@ namespace OpenSim.Region.Framework.Scenes
642 agentID); 742 agentID);
643 } 743 }
644 744
645 lock (m_presenceLock) 745 m_scenePresencesLock.EnterWriteLock();
746 try
646 { 747 {
647 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 748 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
648 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 749 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -664,6 +765,10 @@ namespace OpenSim.Region.Framework.Scenes
664 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 765 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
665 } 766 }
666 } 767 }
768 finally
769 {
770 m_scenePresencesLock.ExitWriteLock();
771 }
667 } 772 }
668 773
669 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 774 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -892,7 +997,7 @@ namespace OpenSim.Region.Framework.Scenes
892 m_log.WarnFormat( 997 m_log.WarnFormat(
893 "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.", 998 "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.",
894 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName); 999 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
895 1000 m_log.WarnFormat("stack: {0}", Environment.StackTrace);
896 SceneObjectGroupsByLocalPartID.Remove(localID); 1001 SceneObjectGroupsByLocalPartID.Remove(localID);
897 } 1002 }
898 } 1003 }
@@ -1228,6 +1333,52 @@ namespace OpenSim.Region.Framework.Scenes
1228 1333
1229 #region Client Event handlers 1334 #region Client Event handlers
1230 1335
1336 protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
1337 {
1338 SceneObjectPart part = GetSceneObjectPart(localID);
1339 ObjectChangeData data = (ObjectChangeData)odata;
1340
1341 if (part != null)
1342 {
1343 SceneObjectGroup grp = part.ParentGroup;
1344 if (grp != null)
1345 {
1346 if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId))
1347 {
1348 // These two are exceptions SL makes in the interpretation
1349 // of the change flags. Must check them here because otherwise
1350 // the group flag (see below) would be lost
1351 if (data.change == ObjectChangeType.groupS)
1352 data.change = ObjectChangeType.primS;
1353 if (data.change == ObjectChangeType.groupPS)
1354 data.change = ObjectChangeType.primPS;
1355 part.StoreUndoState(data.change); // lets test only saving what we changed
1356 grp.doChangeObject(part, (ObjectChangeData)data);
1357 }
1358 else
1359 {
1360 // Is this any kind of group operation?
1361 if ((data.change & ObjectChangeType.Group) != 0)
1362 {
1363 // Is a move and/or rotation requested?
1364 if ((data.change & (ObjectChangeType.Position | ObjectChangeType.Rotation)) != 0)
1365 {
1366 // Are we allowed to move it?
1367 if (m_parentScene.Permissions.CanMoveObject(grp.UUID, remoteClient.AgentId))
1368 {
1369 // Strip all but move and rotation from request
1370 data.change &= (ObjectChangeType.Group | ObjectChangeType.Position | ObjectChangeType.Rotation);
1371
1372 part.StoreUndoState(data.change);
1373 grp.doChangeObject(part, (ObjectChangeData)data);
1374 }
1375 }
1376 }
1377 }
1378 }
1379 }
1380 }
1381
1231 /// <summary> 1382 /// <summary>
1232 /// Update the scale of an individual prim. 1383 /// Update the scale of an individual prim.
1233 /// </summary> 1384 /// </summary>
@@ -1242,7 +1393,17 @@ namespace OpenSim.Region.Framework.Scenes
1242 { 1393 {
1243 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) 1394 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId))
1244 { 1395 {
1396 bool physbuild = false;
1397 if (part.ParentGroup.RootPart.PhysActor != null)
1398 {
1399 part.ParentGroup.RootPart.PhysActor.Building = true;
1400 physbuild = true;
1401 }
1402
1245 part.Resize(scale); 1403 part.Resize(scale);
1404
1405 if (physbuild)
1406 part.ParentGroup.RootPart.PhysActor.Building = false;
1246 } 1407 }
1247 } 1408 }
1248 } 1409 }
@@ -1254,7 +1415,17 @@ namespace OpenSim.Region.Framework.Scenes
1254 { 1415 {
1255 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1416 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1256 { 1417 {
1418 bool physbuild = false;
1419 if (group.RootPart.PhysActor != null)
1420 {
1421 group.RootPart.PhysActor.Building = true;
1422 physbuild = true;
1423 }
1424
1257 group.GroupResize(scale); 1425 group.GroupResize(scale);
1426
1427 if (physbuild)
1428 group.RootPart.PhysActor.Building = false;
1258 } 1429 }
1259 } 1430 }
1260 } 1431 }
@@ -1393,8 +1564,13 @@ namespace OpenSim.Region.Framework.Scenes
1393 { 1564 {
1394 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1565 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1395 { 1566 {
1396 if (m_parentScene.AttachmentsModule != null) 1567 // Set the new attachment point data in the object
1397 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1568 byte attachmentPoint = group.GetAttachmentPoint();
1569 group.UpdateGroupPosition(pos);
1570 group.IsAttachment = false;
1571 group.AbsolutePosition = group.RootPart.AttachedPos;
1572 group.AttachmentPoint = attachmentPoint;
1573 group.HasGroupChanged = true;
1398 } 1574 }
1399 else 1575 else
1400 { 1576 {
@@ -1452,6 +1628,7 @@ namespace OpenSim.Region.Framework.Scenes
1452 // VolumeDetect can't be set via UI and will always be off when a change is made there 1628 // VolumeDetect can't be set via UI and will always be off when a change is made there
1453 // now only change volume dtc if phantom off 1629 // now only change volume dtc if phantom off
1454 1630
1631 bool wantedPhys = UsePhysics;
1455 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data 1632 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data
1456 { 1633 {
1457 bool vdtc; 1634 bool vdtc;
@@ -1468,10 +1645,17 @@ namespace OpenSim.Region.Framework.Scenes
1468 if (part != null) 1645 if (part != null)
1469 { 1646 {
1470 part.UpdateExtraPhysics(PhysData); 1647 part.UpdateExtraPhysics(PhysData);
1471 if (part.UpdatePhysRequired) 1648 if (part.UpdatePhysRequired && remoteClient != null)
1472 remoteClient.SendPartPhysicsProprieties(part); 1649 remoteClient.SendPartPhysicsProprieties(part);
1473 } 1650 }
1474 } 1651 }
1652
1653 if (wantedPhys != group.UsesPhysics && remoteClient != null)
1654 {
1655 remoteClient.SendAlertMessage("Object physics canceled because exceeds the limit of " +
1656 m_parentScene.m_linksetPhysCapacity + " physical prims with shape type not set to None");
1657 group.RootPart.ScheduleFullUpdate();
1658 }
1475 } 1659 }
1476 } 1660 }
1477 } 1661 }
@@ -1616,6 +1800,7 @@ namespace OpenSim.Region.Framework.Scenes
1616 { 1800 {
1617 part.Material = Convert.ToByte(material); 1801 part.Material = Convert.ToByte(material);
1618 group.HasGroupChanged = true; 1802 group.HasGroupChanged = true;
1803 remoteClient.SendPartPhysicsProprieties(part);
1619 } 1804 }
1620 } 1805 }
1621 } 1806 }
@@ -1694,12 +1879,14 @@ namespace OpenSim.Region.Framework.Scenes
1694 return; 1879 return;
1695 1880
1696 Monitor.Enter(m_updateLock); 1881 Monitor.Enter(m_updateLock);
1882
1697 try 1883 try
1698 { 1884 {
1885
1699 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1886 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1700 1887
1701 // We do this in reverse to get the link order of the prims correct 1888 // We do this in reverse to get the link order of the prims correct
1702 for (int i = 0 ; i < children.Count ; i++) 1889 for (int i = 0; i < children.Count; i++)
1703 { 1890 {
1704 SceneObjectGroup child = children[i].ParentGroup; 1891 SceneObjectGroup child = children[i].ParentGroup;
1705 1892
@@ -1710,9 +1897,13 @@ namespace OpenSim.Region.Framework.Scenes
1710 // Make sure no child prim is set for sale 1897 // Make sure no child prim is set for sale
1711 // So that, on delink, no prims are unwittingly 1898 // So that, on delink, no prims are unwittingly
1712 // left for sale and sold off 1899 // left for sale and sold off
1713 child.RootPart.ObjectSaleType = 0; 1900
1714 child.RootPart.SalePrice = 10; 1901 if (child != null)
1715 childGroups.Add(child); 1902 {
1903 child.RootPart.ObjectSaleType = 0;
1904 child.RootPart.SalePrice = 10;
1905 childGroups.Add(child);
1906 }
1716 } 1907 }
1717 1908
1718 foreach (SceneObjectGroup child in childGroups) 1909 foreach (SceneObjectGroup child in childGroups)
@@ -1741,6 +1932,17 @@ namespace OpenSim.Region.Framework.Scenes
1741 } 1932 }
1742 finally 1933 finally
1743 { 1934 {
1935/*
1936 lock (SceneObjectGroupsByLocalPartID)
1937 {
1938 foreach (SceneObjectPart part in parentGroup.Parts)
1939 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1940 }
1941*/
1942 parentGroup.AdjustChildPrimPermissions(false);
1943 parentGroup.HasGroupChanged = true;
1944 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1945 parentGroup.ScheduleGroupForFullUpdate();
1744 Monitor.Exit(m_updateLock); 1946 Monitor.Exit(m_updateLock);
1745 } 1947 }
1746 } 1948 }
@@ -1782,21 +1984,23 @@ namespace OpenSim.Region.Framework.Scenes
1782 1984
1783 SceneObjectGroup group = part.ParentGroup; 1985 SceneObjectGroup group = part.ParentGroup;
1784 if (!affectedGroups.Contains(group)) 1986 if (!affectedGroups.Contains(group))
1987 {
1785 affectedGroups.Add(group); 1988 affectedGroups.Add(group);
1989 }
1786 } 1990 }
1787 } 1991 }
1788 } 1992 }
1789 1993
1790 foreach (SceneObjectPart child in childParts) 1994 if (childParts.Count > 0)
1791 { 1995 {
1792 // Unlink all child parts from their groups 1996 foreach (SceneObjectPart child in childParts)
1793 // 1997 {
1794 child.ParentGroup.DelinkFromGroup(child, true); 1998 // Unlink all child parts from their groups
1795 1999 //
1796 // These are not in affected groups and will not be 2000 child.ParentGroup.DelinkFromGroup(child, true);
1797 // handled further. Do the honors here. 2001 child.ParentGroup.HasGroupChanged = true;
1798 child.ParentGroup.HasGroupChanged = true; 2002 child.ParentGroup.ScheduleGroupForFullUpdate();
1799 child.ParentGroup.ScheduleGroupForFullUpdate(); 2003 }
1800 } 2004 }
1801 2005
1802 foreach (SceneObjectPart root in rootParts) 2006 foreach (SceneObjectPart root in rootParts)
@@ -1810,52 +2014,58 @@ namespace OpenSim.Region.Framework.Scenes
1810 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 2014 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1811 int numChildren = newSet.Count; 2015 int numChildren = newSet.Count;
1812 2016
2017 if (numChildren == 1)
2018 break;
2019
1813 // If there are prims left in a link set, but the root is 2020 // If there are prims left in a link set, but the root is
1814 // slated for unlink, we need to do this 2021 // slated for unlink, we need to do this
2022 // Unlink the remaining set
1815 // 2023 //
1816 if (numChildren != 1) 2024 bool sendEventsToRemainder = false;
1817 { 2025 if (numChildren == 2) // only one child prim no re-link needed
1818 // Unlink the remaining set 2026 sendEventsToRemainder = true;
1819 //
1820 bool sendEventsToRemainder = true;
1821 if (numChildren > 1)
1822 sendEventsToRemainder = false;
1823 2027
1824 foreach (SceneObjectPart p in newSet) 2028 foreach (SceneObjectPart p in newSet)
2029 {
2030 if (p != group.RootPart)
1825 { 2031 {
1826 if (p != group.RootPart) 2032 group.DelinkFromGroup(p, sendEventsToRemainder);
1827 group.DelinkFromGroup(p, sendEventsToRemainder); 2033 if (sendEventsToRemainder) // finish single child prim now
2034 {
2035 p.ParentGroup.HasGroupChanged = true;
2036 p.ParentGroup.ScheduleGroupForFullUpdate();
2037 }
1828 } 2038 }
2039 }
2040
2041 // If there is more than one prim remaining, we
2042 // need to re-link
2043 //
2044 if (numChildren > 2)
2045 {
2046 // Remove old root
2047 //
2048 if (newSet.Contains(root))
2049 newSet.Remove(root);
1829 2050
1830 // If there is more than one prim remaining, we 2051 // Preserve link ordering
1831 // need to re-link
1832 // 2052 //
1833 if (numChildren > 2) 2053 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1834 { 2054 {
1835 // Remove old root 2055 return a.LinkNum.CompareTo(b.LinkNum);
1836 // 2056 });
1837 if (newSet.Contains(root))
1838 newSet.Remove(root);
1839
1840 // Preserve link ordering
1841 //
1842 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1843 {
1844 return a.LinkNum.CompareTo(b.LinkNum);
1845 });
1846 2057
1847 // Determine new root 2058 // Determine new root
1848 // 2059 //
1849 SceneObjectPart newRoot = newSet[0]; 2060 SceneObjectPart newRoot = newSet[0];
1850 newSet.RemoveAt(0); 2061 newSet.RemoveAt(0);
1851 2062
1852 foreach (SceneObjectPart newChild in newSet) 2063 foreach (SceneObjectPart newChild in newSet)
1853 newChild.ClearUpdateSchedule(); 2064 newChild.ClearUpdateSchedule();
1854 2065
1855 LinkObjects(newRoot, newSet); 2066 LinkObjects(newRoot, newSet);
1856 if (!affectedGroups.Contains(newRoot.ParentGroup)) 2067// if (!affectedGroups.Contains(newRoot.ParentGroup))
1857 affectedGroups.Add(newRoot.ParentGroup); 2068// affectedGroups.Add(newRoot.ParentGroup);
1858 }
1859 } 2069 }
1860 } 2070 }
1861 2071
@@ -1863,6 +2073,12 @@ namespace OpenSim.Region.Framework.Scenes
1863 // 2073 //
1864 foreach (SceneObjectGroup g in affectedGroups) 2074 foreach (SceneObjectGroup g in affectedGroups)
1865 { 2075 {
2076 // Child prims that have been unlinked and deleted will
2077 // return unless the root is deleted. This will remove them
2078 // from the database. They will be rewritten immediately,
2079 // minus the rows for the unlinked child prims.
2080 g.AdjustChildPrimPermissions(false);
2081 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1866 g.TriggerScriptChangedEvent(Changed.LINK); 2082 g.TriggerScriptChangedEvent(Changed.LINK);
1867 g.HasGroupChanged = true; // Persist 2083 g.HasGroupChanged = true; // Persist
1868 g.ScheduleGroupForFullUpdate(); 2084 g.ScheduleGroupForFullUpdate();
@@ -1936,120 +2152,90 @@ namespace OpenSim.Region.Framework.Scenes
1936 /// <param name="GroupID"></param> 2152 /// <param name="GroupID"></param>
1937 /// <param name="rot"></param> 2153 /// <param name="rot"></param>
1938 /// <returns>null if duplication fails, otherwise the duplicated object</returns> 2154 /// <returns>null if duplication fails, otherwise the duplicated object</returns>
1939 public SceneObjectGroup DuplicateObject( 2155 /// <summary>
1940 uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) 2156 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
1941 { 2157 {
1942 Monitor.Enter(m_updateLock); 2158// m_log.DebugFormat(
2159// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
2160// originalPrimID, offset, AgentID);
1943 2161
1944 try 2162 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
2163 if (original != null)
1945 { 2164 {
1946 // m_log.DebugFormat( 2165 if (m_parentScene.Permissions.CanDuplicateObject(
1947 // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
1948 // originalPrimID, offset, AgentID);
1949
1950 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1951 if (original == null)
1952 {
1953 m_log.WarnFormat(
1954 "[SCENEGRAPH]: Attempt to duplicate nonexistent prim id {0} by {1}", originalPrimID, AgentID);
1955
1956 return null;
1957 }
1958
1959 if (!m_parentScene.Permissions.CanDuplicateObject(
1960 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition)) 2166 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1961 return null;
1962
1963 SceneObjectGroup copy = original.Copy(true);
1964 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1965
1966 if (original.OwnerID != AgentID)
1967 { 2167 {
1968 copy.SetOwnerId(AgentID); 2168 SceneObjectGroup copy = original.Copy(true);
1969 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); 2169 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1970
1971 SceneObjectPart[] partList = copy.Parts;
1972 2170
1973 if (m_parentScene.Permissions.PropagatePermissions()) 2171 if (original.OwnerID != AgentID)
1974 { 2172 {
1975 foreach (SceneObjectPart child in partList) 2173 copy.SetOwnerId(AgentID);
2174 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
2175
2176 SceneObjectPart[] partList = copy.Parts;
2177
2178 if (m_parentScene.Permissions.PropagatePermissions())
1976 { 2179 {
1977 child.Inventory.ChangeInventoryOwner(AgentID); 2180 foreach (SceneObjectPart child in partList)
1978 child.TriggerScriptChangedEvent(Changed.OWNER); 2181 {
1979 child.ApplyNextOwnerPermissions(); 2182 child.Inventory.ChangeInventoryOwner(AgentID);
2183 child.TriggerScriptChangedEvent(Changed.OWNER);
2184 child.ApplyNextOwnerPermissions();
2185 }
1980 } 2186 }
1981 } 2187 }
1982 2188
1983 copy.RootPart.ObjectSaleType = 0; 2189 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
1984 copy.RootPart.SalePrice = 10; 2190 Entities.Add(copy);
1985 }
1986 2191
1987 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2192 lock (SceneObjectGroupsByFullID)
1988 Entities.Add(copy); 2193 SceneObjectGroupsByFullID[copy.UUID] = copy;
1989
1990 lock (SceneObjectGroupsByFullID)
1991 SceneObjectGroupsByFullID[copy.UUID] = copy;
1992
1993 SceneObjectPart[] children = copy.Parts;
1994
1995 lock (SceneObjectGroupsByFullPartID)
1996 {
1997 SceneObjectGroupsByFullPartID[copy.UUID] = copy;
1998 foreach (SceneObjectPart part in children)
1999 SceneObjectGroupsByFullPartID[part.UUID] = copy;
2000 }
2001
2002 lock (SceneObjectGroupsByLocalPartID)
2003 {
2004 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
2005 foreach (SceneObjectPart part in children)
2006 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
2007 }
2008 // PROBABLE END OF FIXME
2009 2194
2010 // Since we copy from a source group that is in selected 2195 SceneObjectPart[] parts = copy.Parts;
2011 // state, but the copy is shown deselected in the viewer, 2196 foreach (SceneObjectPart part in parts)
2012 // We need to clear the selection flag here, else that 2197 {
2013 // prim never gets persisted at all. The client doesn't 2198 lock (SceneObjectGroupsByFullPartID)
2014 // think it's selected, so it will never send a deselect... 2199 SceneObjectGroupsByFullPartID[part.UUID] = copy;
2015 copy.IsSelected = false; 2200 lock (SceneObjectGroupsByLocalPartID)
2201 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
2202 }
2016 2203
2017 m_numTotalPrim += copy.Parts.Length; 2204 // PROBABLE END OF FIXME
2018 2205
2019 // Go through all parts (primitives and meshes) of this Scene Object 2206 // Since we copy from a source group that is in selected
2020 foreach (SceneObjectPart part in copy.Parts) 2207 // state, but the copy is shown deselected in the viewer,
2021 { 2208 // We need to clear the selection flag here, else that
2022 // Keep track of the total number of meshes or geometric primitives now in the scene; 2209 // prim never gets persisted at all. The client doesn't
2023 // determine which object this is based on its primitive type: sculpted (sculpt) prim refers to 2210 // think it's selected, so it will never send a deselect...
2024 // a mesh and all other prims (i.e. box, sphere, etc) are geometric primitives 2211 copy.IsSelected = false;
2025 if (part.GetPrimType() == PrimType.SCULPT)
2026 m_numMesh++;
2027 else
2028 m_numPrim++;
2029 }
2030 2212
2031 if (rot != Quaternion.Identity) 2213 m_numPrim += copy.Parts.Length;
2032 {
2033 copy.UpdateGroupRotationR(rot);
2034 }
2035 2214
2036 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); 2215 if (rot != Quaternion.Identity)
2037 copy.HasGroupChanged = true; 2216 {
2038 copy.ScheduleGroupForFullUpdate(); 2217 copy.UpdateGroupRotationR(rot);
2039 copy.ResumeScripts(); 2218 }
2219
2220 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
2221 copy.HasGroupChanged = true;
2222 copy.ScheduleGroupForFullUpdate();
2223 copy.ResumeScripts();
2040 2224
2041 // required for physics to update it's position 2225 // required for physics to update it's position
2042 copy.AbsolutePosition = copy.AbsolutePosition; 2226 copy.AbsolutePosition = copy.AbsolutePosition;
2043 2227
2044 return copy; 2228 return copy;
2229 }
2045 } 2230 }
2046 finally 2231 else
2047 { 2232 {
2048 Monitor.Exit(m_updateLock); 2233 m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID);
2049 } 2234 }
2235
2236 return null;
2050 } 2237 }
2051 2238
2052 /// <summary>
2053 /// Calculates the distance between two Vector3s 2239 /// Calculates the distance between two Vector3s
2054 /// </summary> 2240 /// </summary>
2055 /// <param name="v1"></param> 2241 /// <param name="v1"></param>
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index 28f7896..c5c083a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -99,11 +99,11 @@ namespace OpenSim.Region.Framework.Scenes
99 } 99 }
100 } 100 }
101 101
102 private readonly List<Scene> m_localScenes = new List<Scene>(); 102 private readonly DoubleDictionary<UUID, string, Scene> m_localScenes = new DoubleDictionary<UUID, string, Scene>();
103 103
104 public List<Scene> Scenes 104 public List<Scene> Scenes
105 { 105 {
106 get { return new List<Scene>(m_localScenes); } 106 get { return new List<Scene>(m_localScenes.FindAll(delegate(Scene s) { return true; })); }
107 } 107 }
108 108
109 /// <summary> 109 /// <summary>
@@ -120,13 +120,10 @@ namespace OpenSim.Region.Framework.Scenes
120 { 120 {
121 if (CurrentScene == null) 121 if (CurrentScene == null)
122 { 122 {
123 lock (m_localScenes) 123 List<Scene> sceneList = Scenes;
124 { 124 if (sceneList.Count == 0)
125 if (m_localScenes.Count > 0) 125 return null;
126 return m_localScenes[0]; 126 return sceneList[0];
127 else
128 return null;
129 }
130 } 127 }
131 else 128 else
132 { 129 {
@@ -138,41 +135,35 @@ namespace OpenSim.Region.Framework.Scenes
138 public SceneManager() 135 public SceneManager()
139 { 136 {
140 m_instance = this; 137 m_instance = this;
141 m_localScenes = new List<Scene>(); 138 m_localScenes = new DoubleDictionary<UUID, string, Scene>();
142 } 139 }
143 140
144 public void Close() 141 public void Close()
145 { 142 {
143 List<Scene> localScenes = null;
144
146 lock (m_localScenes) 145 lock (m_localScenes)
147 { 146 {
148 for (int i = 0; i < m_localScenes.Count; i++) 147 localScenes = Scenes;
149 { 148 }
150 m_localScenes[i].Close(); 149
151 } 150 for (int i = 0; i < localScenes.Count; i++)
151 {
152 localScenes[i].Close();
152 } 153 }
153 } 154 }
154 155
155 public void Close(Scene cscene) 156 public void Close(Scene cscene)
156 { 157 {
157 lock (m_localScenes) 158 if (!m_localScenes.ContainsKey(cscene.RegionInfo.RegionID))
158 { 159 return;
159 if (m_localScenes.Contains(cscene)) 160 cscene.Close();
160 {
161 for (int i = 0; i < m_localScenes.Count; i++)
162 {
163 if (m_localScenes[i].Equals(cscene))
164 {
165 m_localScenes[i].Close();
166 }
167 }
168 }
169 }
170 } 161 }
171 162
172 public void Add(Scene scene) 163 public void Add(Scene scene)
173 { 164 {
174 lock (m_localScenes) 165 lock (m_localScenes)
175 m_localScenes.Add(scene); 166 m_localScenes.Add(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, scene);
176 167
177 scene.OnRestart += HandleRestart; 168 scene.OnRestart += HandleRestart;
178 scene.EventManager.OnRegionReadyStatusChange += HandleRegionReadyStatusChange; 169 scene.EventManager.OnRegionReadyStatusChange += HandleRegionReadyStatusChange;
@@ -184,15 +175,8 @@ namespace OpenSim.Region.Framework.Scenes
184 175
185 lock (m_localScenes) 176 lock (m_localScenes)
186 { 177 {
187 for (int i = 0; i < m_localScenes.Count; i++) 178 m_localScenes.TryGetValue(rdata.RegionID, out restartedScene);
188 { 179 m_localScenes.Remove(rdata.RegionID);
189 if (rdata.RegionName == m_localScenes[i].RegionInfo.RegionName)
190 {
191 restartedScene = m_localScenes[i];
192 m_localScenes.RemoveAt(i);
193 break;
194 }
195 }
196 } 180 }
197 181
198 // If the currently selected scene has been restarted, then we can't reselect here since we the scene 182 // If the currently selected scene has been restarted, then we can't reselect here since we the scene
@@ -207,39 +191,36 @@ namespace OpenSim.Region.Framework.Scenes
207 private void HandleRegionReadyStatusChange(IScene scene) 191 private void HandleRegionReadyStatusChange(IScene scene)
208 { 192 {
209 lock (m_localScenes) 193 lock (m_localScenes)
210 AllRegionsReady = m_localScenes.TrueForAll(s => s.Ready); 194 AllRegionsReady = m_localScenes.FindAll(s => !s.Ready).Count == 0;
211 } 195 }
212 196
213 public void SendSimOnlineNotification(ulong regionHandle) 197 public void SendSimOnlineNotification(ulong regionHandle)
214 { 198 {
215 RegionInfo Result = null; 199 RegionInfo Result = null;
216 200
217 lock (m_localScenes) 201 Scene s = m_localScenes.FindValue(delegate(Scene x)
218 {
219 for (int i = 0; i < m_localScenes.Count; i++)
220 {
221 if (m_localScenes[i].RegionInfo.RegionHandle == regionHandle)
222 { 202 {
223 // Inform other regions to tell their avatar about me 203 if (x.RegionInfo.RegionHandle == regionHandle)
224 Result = m_localScenes[i].RegionInfo; 204 return true;
225 } 205 return false;
226 } 206 });
207
208 if (s != null)
209 {
210 List<Scene> sceneList = Scenes;
227 211
228 if (Result != null) 212 for (int i = 0; i < sceneList.Count; i++)
229 { 213 {
230 for (int i = 0; i < m_localScenes.Count; i++) 214 if (sceneList[i]!= s)
231 { 215 {
232 if (m_localScenes[i].RegionInfo.RegionHandle != regionHandle) 216 // Inform other regions to tell their avatar about me
233 { 217 //sceneList[i].OtherRegionUp(Result);
234 // Inform other regions to tell their avatar about me
235 //m_localScenes[i].OtherRegionUp(Result);
236 }
237 } 218 }
238 } 219 }
239 else 220 }
240 { 221 else
241 m_log.Error("[REGION]: Unable to notify Other regions of this Region coming up"); 222 {
242 } 223 m_log.Error("[REGION]: Unable to notify Other regions of this Region coming up");
243 } 224 }
244 } 225 }
245 226
@@ -368,16 +349,12 @@ namespace OpenSim.Region.Framework.Scenes
368 } 349 }
369 else 350 else
370 { 351 {
371 lock (m_localScenes) 352 Scene s;
353
354 if (m_localScenes.TryGetValue(regionName, out s))
372 { 355 {
373 foreach (Scene scene in m_localScenes) 356 CurrentScene = s;
374 { 357 return true;
375 if (String.Compare(scene.RegionInfo.RegionName, regionName, true) == 0)
376 {
377 CurrentScene = scene;
378 return true;
379 }
380 }
381 } 358 }
382 359
383 return false; 360 return false;
@@ -386,18 +363,14 @@ namespace OpenSim.Region.Framework.Scenes
386 363
387 public bool TrySetCurrentScene(UUID regionID) 364 public bool TrySetCurrentScene(UUID regionID)
388 { 365 {
389 m_log.Debug("Searching for Region: '" + regionID + "'"); 366// m_log.Debug("Searching for Region: '" + regionID + "'");
390 367
391 lock (m_localScenes) 368 Scene s;
369
370 if (m_localScenes.TryGetValue(regionID, out s))
392 { 371 {
393 foreach (Scene scene in m_localScenes) 372 CurrentScene = s;
394 { 373 return true;
395 if (scene.RegionInfo.RegionID == regionID)
396 {
397 CurrentScene = scene;
398 return true;
399 }
400 }
401 } 374 }
402 375
403 return false; 376 return false;
@@ -405,52 +378,24 @@ namespace OpenSim.Region.Framework.Scenes
405 378
406 public bool TryGetScene(string regionName, out Scene scene) 379 public bool TryGetScene(string regionName, out Scene scene)
407 { 380 {
408 lock (m_localScenes) 381 return m_localScenes.TryGetValue(regionName, out scene);
409 {
410 foreach (Scene mscene in m_localScenes)
411 {
412 if (String.Compare(mscene.RegionInfo.RegionName, regionName, true) == 0)
413 {
414 scene = mscene;
415 return true;
416 }
417 }
418 }
419
420 scene = null;
421 return false;
422 } 382 }
423 383
424 public bool TryGetScene(UUID regionID, out Scene scene) 384 public bool TryGetScene(UUID regionID, out Scene scene)
425 { 385 {
426 lock (m_localScenes) 386 return m_localScenes.TryGetValue(regionID, out scene);
427 {
428 foreach (Scene mscene in m_localScenes)
429 {
430 if (mscene.RegionInfo.RegionID == regionID)
431 {
432 scene = mscene;
433 return true;
434 }
435 }
436 }
437
438 scene = null;
439 return false;
440 } 387 }
441 388
442 public bool TryGetScene(uint locX, uint locY, out Scene scene) 389 public bool TryGetScene(uint locX, uint locY, out Scene scene)
443 { 390 {
444 lock (m_localScenes) 391 List<Scene> sceneList = Scenes;
392 foreach (Scene mscene in sceneList)
445 { 393 {
446 foreach (Scene mscene in m_localScenes) 394 if (mscene.RegionInfo.RegionLocX == locX &&
395 mscene.RegionInfo.RegionLocY == locY)
447 { 396 {
448 if (mscene.RegionInfo.RegionLocX == locX && 397 scene = mscene;
449 mscene.RegionInfo.RegionLocY == locY) 398 return true;
450 {
451 scene = mscene;
452 return true;
453 }
454 } 399 }
455 } 400 }
456 401
@@ -460,16 +405,14 @@ namespace OpenSim.Region.Framework.Scenes
460 405
461 public bool TryGetScene(IPEndPoint ipEndPoint, out Scene scene) 406 public bool TryGetScene(IPEndPoint ipEndPoint, out Scene scene)
462 { 407 {
463 lock (m_localScenes) 408 List<Scene> sceneList = Scenes;
409 foreach (Scene mscene in sceneList)
464 { 410 {
465 foreach (Scene mscene in m_localScenes) 411 if ((mscene.RegionInfo.InternalEndPoint.Equals(ipEndPoint.Address)) &&
412 (mscene.RegionInfo.InternalEndPoint.Port == ipEndPoint.Port))
466 { 413 {
467 if ((mscene.RegionInfo.InternalEndPoint.Equals(ipEndPoint.Address)) && 414 scene = mscene;
468 (mscene.RegionInfo.InternalEndPoint.Port == ipEndPoint.Port)) 415 return true;
469 {
470 scene = mscene;
471 return true;
472 }
473 } 416 }
474 } 417 }
475 418
@@ -511,15 +454,10 @@ namespace OpenSim.Region.Framework.Scenes
511 454
512 public RegionInfo GetRegionInfo(UUID regionID) 455 public RegionInfo GetRegionInfo(UUID regionID)
513 { 456 {
514 lock (m_localScenes) 457 Scene s;
458 if (m_localScenes.TryGetValue(regionID, out s))
515 { 459 {
516 foreach (Scene scene in m_localScenes) 460 return s.RegionInfo;
517 {
518 if (scene.RegionInfo.RegionID == regionID)
519 {
520 return scene.RegionInfo;
521 }
522 }
523 } 461 }
524 462
525 return null; 463 return null;
@@ -537,14 +475,12 @@ namespace OpenSim.Region.Framework.Scenes
537 475
538 public bool TryGetScenePresence(UUID avatarId, out ScenePresence avatar) 476 public bool TryGetScenePresence(UUID avatarId, out ScenePresence avatar)
539 { 477 {
540 lock (m_localScenes) 478 List<Scene> sceneList = Scenes;
479 foreach (Scene scene in sceneList)
541 { 480 {
542 foreach (Scene scene in m_localScenes) 481 if (scene.TryGetScenePresence(avatarId, out avatar))
543 { 482 {
544 if (scene.TryGetScenePresence(avatarId, out avatar)) 483 return true;
545 {
546 return true;
547 }
548 } 484 }
549 } 485 }
550 486
@@ -554,15 +490,13 @@ namespace OpenSim.Region.Framework.Scenes
554 490
555 public bool TryGetRootScenePresence(UUID avatarId, out ScenePresence avatar) 491 public bool TryGetRootScenePresence(UUID avatarId, out ScenePresence avatar)
556 { 492 {
557 lock (m_localScenes) 493 List<Scene> sceneList = Scenes;
494 foreach (Scene scene in sceneList)
558 { 495 {
559 foreach (Scene scene in m_localScenes) 496 avatar = scene.GetScenePresence(avatarId);
560 {
561 avatar = scene.GetScenePresence(avatarId);
562 497
563 if (avatar != null && !avatar.IsChildAgent) 498 if (avatar != null && !avatar.IsChildAgent)
564 return true; 499 return true;
565 }
566 } 500 }
567 501
568 avatar = null; 502 avatar = null;
@@ -572,21 +506,19 @@ namespace OpenSim.Region.Framework.Scenes
572 public void CloseScene(Scene scene) 506 public void CloseScene(Scene scene)
573 { 507 {
574 lock (m_localScenes) 508 lock (m_localScenes)
575 m_localScenes.Remove(scene); 509 m_localScenes.Remove(scene.RegionInfo.RegionID);
576 510
577 scene.Close(); 511 scene.Close();
578 } 512 }
579 513
580 public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) 514 public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar)
581 { 515 {
582 lock (m_localScenes) 516 List<Scene> sceneList = Scenes;
517 foreach (Scene scene in sceneList)
583 { 518 {
584 foreach (Scene scene in m_localScenes) 519 if (scene.TryGetAvatarByName(avatarName, out avatar))
585 { 520 {
586 if (scene.TryGetAvatarByName(avatarName, out avatar)) 521 return true;
587 {
588 return true;
589 }
590 } 522 }
591 } 523 }
592 524
@@ -596,14 +528,12 @@ namespace OpenSim.Region.Framework.Scenes
596 528
597 public bool TryGetRootScenePresenceByName(string firstName, string lastName, out ScenePresence sp) 529 public bool TryGetRootScenePresenceByName(string firstName, string lastName, out ScenePresence sp)
598 { 530 {
599 lock (m_localScenes) 531 List<Scene> sceneList = Scenes;
532 foreach (Scene scene in sceneList)
600 { 533 {
601 foreach (Scene scene in m_localScenes) 534 sp = scene.GetScenePresence(firstName, lastName);
602 { 535 if (sp != null && !sp.IsChildAgent)
603 sp = scene.GetScenePresence(firstName, lastName); 536 return true;
604 if (sp != null && !sp.IsChildAgent)
605 return true;
606 }
607 } 537 }
608 538
609 sp = null; 539 sp = null;
@@ -612,8 +542,8 @@ namespace OpenSim.Region.Framework.Scenes
612 542
613 public void ForEachScene(Action<Scene> action) 543 public void ForEachScene(Action<Scene> action)
614 { 544 {
615 lock (m_localScenes) 545 List<Scene> sceneList = Scenes;
616 m_localScenes.ForEach(action); 546 sceneList.ForEach(action);
617 } 547 }
618 } 548 }
619} 549}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 81cef5b..98617d1 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -88,10 +88,6 @@ namespace OpenSim.Region.Framework.Scenes
88 /// <summary> 88 /// <summary>
89 /// Stop and remove the scripts contained in all the prims in this group 89 /// Stop and remove the scripts contained in all the prims in this group
90 /// </summary> 90 /// </summary>
91 /// <param name="sceneObjectBeingDeleted">
92 /// Should be true if these scripts are being removed because the scene
93 /// object is being deleted. This will prevent spurious updates to the client.
94 /// </param>
95 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 91 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
96 { 92 {
97 SceneObjectPart[] parts = m_parts.GetArray(); 93 SceneObjectPart[] parts = m_parts.GetArray();
@@ -254,6 +250,11 @@ namespace OpenSim.Region.Framework.Scenes
254 250
255 public uint GetEffectivePermissions() 251 public uint GetEffectivePermissions()
256 { 252 {
253 return GetEffectivePermissions(false);
254 }
255
256 public uint GetEffectivePermissions(bool useBase)
257 {
257 uint perms=(uint)(PermissionMask.Modify | 258 uint perms=(uint)(PermissionMask.Modify |
258 PermissionMask.Copy | 259 PermissionMask.Copy |
259 PermissionMask.Move | 260 PermissionMask.Move |
@@ -265,8 +266,12 @@ namespace OpenSim.Region.Framework.Scenes
265 for (int i = 0; i < parts.Length; i++) 266 for (int i = 0; i < parts.Length; i++)
266 { 267 {
267 SceneObjectPart part = parts[i]; 268 SceneObjectPart part = parts[i];
268// m_log.DebugFormat("[SCENE OBJECT GROUP INVENTORY]: Effective perms of {0} are {1}", part.Name, (OpenMetaverse.PermissionMask)part.OwnerMask); 269
269 ownerMask &= part.OwnerMask; 270 if (useBase)
271 ownerMask &= part.BaseMask;
272 else
273 ownerMask &= part.OwnerMask;
274
270 perms &= part.Inventory.MaskEffectivePermissions(); 275 perms &= part.Inventory.MaskEffectivePermissions();
271 } 276 }
272 277
@@ -408,6 +413,9 @@ namespace OpenSim.Region.Framework.Scenes
408 413
409 public void ResumeScripts() 414 public void ResumeScripts()
410 { 415 {
416 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
417 return;
418
411 SceneObjectPart[] parts = m_parts.GetArray(); 419 SceneObjectPart[] parts = m_parts.GetArray();
412 for (int i = 0; i < parts.Length; i++) 420 for (int i = 0; i < parts.Length; i++)
413 parts[i].Inventory.ResumeScripts(); 421 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index d08237e..e780f86 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -24,12 +24,13 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.ComponentModel; 29using System.ComponentModel;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Drawing; 31using System.Drawing;
32using System.IO; 32using System.IO;
33using System.Diagnostics;
33using System.Linq; 34using System.Linq;
34using System.Threading; 35using System.Threading;
35using System.Xml; 36using System.Xml;
@@ -45,6 +46,7 @@ using OpenSim.Services.Interfaces;
45 46
46namespace OpenSim.Region.Framework.Scenes 47namespace OpenSim.Region.Framework.Scenes
47{ 48{
49
48 [Flags] 50 [Flags]
49 public enum scriptEvents 51 public enum scriptEvents
50 { 52 {
@@ -80,14 +82,14 @@ namespace OpenSim.Region.Framework.Scenes
80 object_rez = 4194304 82 object_rez = 4194304
81 } 83 }
82 84
83 struct scriptPosTarget 85 public struct scriptPosTarget
84 { 86 {
85 public Vector3 targetPos; 87 public Vector3 targetPos;
86 public float tolerance; 88 public float tolerance;
87 public uint handle; 89 public uint handle;
88 } 90 }
89 91
90 struct scriptRotTarget 92 public struct scriptRotTarget
91 { 93 {
92 public Quaternion targetRot; 94 public Quaternion targetRot;
93 public float tolerance; 95 public float tolerance;
@@ -109,6 +111,9 @@ namespace OpenSim.Region.Framework.Scenes
109 STATUS_ROTATE_X = 0x002, 111 STATUS_ROTATE_X = 0x002,
110 STATUS_ROTATE_Y = 0x004, 112 STATUS_ROTATE_Y = 0x004,
111 STATUS_ROTATE_Z = 0x008, 113 STATUS_ROTATE_Z = 0x008,
114 NOT_STATUS_ROTATE_X = 0xFD,
115 NOT_STATUS_ROTATE_Y = 0xFB,
116 NOT_STATUS_ROTATE_Z = 0xF7
112 } 117 }
113 118
114 // This flag has the same purpose as InventoryItemFlags.ObjectSlamPerm 119 // This flag has the same purpose as InventoryItemFlags.ObjectSlamPerm
@@ -121,8 +126,11 @@ namespace OpenSim.Region.Framework.Scenes
121 /// since the group's last persistent backup 126 /// since the group's last persistent backup
122 /// </summary> 127 /// </summary>
123 private bool m_hasGroupChanged = false; 128 private bool m_hasGroupChanged = false;
124 private long timeFirstChanged; 129 private long timeFirstChanged = 0;
125 private long timeLastChanged; 130 private long timeLastChanged = 0;
131 private long m_maxPersistTime = 0;
132 private long m_minPersistTime = 0;
133// private Random m_rand;
126 134
127 /// <summary> 135 /// <summary>
128 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage 136 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage
@@ -139,9 +147,44 @@ namespace OpenSim.Region.Framework.Scenes
139 { 147 {
140 if (value) 148 if (value)
141 { 149 {
150
151 if (m_isBackedUp)
152 {
153 m_scene.SceneGraph.FireChangeBackup(this);
154 }
142 timeLastChanged = DateTime.Now.Ticks; 155 timeLastChanged = DateTime.Now.Ticks;
143 if (!m_hasGroupChanged) 156 if (!m_hasGroupChanged)
144 timeFirstChanged = DateTime.Now.Ticks; 157 timeFirstChanged = DateTime.Now.Ticks;
158 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
159 {
160/*
161 if (m_rand == null)
162 {
163 byte[] val = new byte[16];
164 m_rootPart.UUID.ToBytes(val, 0);
165 m_rand = new Random(BitConverter.ToInt32(val, 0));
166 }
167 */
168 if (m_scene.GetRootAgentCount() == 0)
169 {
170 //If the region is empty, this change has been made by an automated process
171 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
172
173// float factor = 1.5f + (float)(m_rand.NextDouble());
174 float factor = 2.0f;
175 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
176 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
177 }
178 else
179 {
180 //If the region is not empty, we want to obey the minimum and maximum persist times
181 //but add a random factor so we stagger the object persistance a little
182// m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
183// m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
184 m_maxPersistTime = m_scene.m_persistAfter;
185 m_minPersistTime = m_scene.m_dontPersistBefore;
186 }
187 }
145 } 188 }
146 m_hasGroupChanged = value; 189 m_hasGroupChanged = value;
147 190
@@ -172,6 +215,7 @@ namespace OpenSim.Region.Framework.Scenes
172 get { return m_groupContainsForeignPrims; } 215 get { return m_groupContainsForeignPrims; }
173 } 216 }
174 217
218 public bool HasGroupChangedDueToDelink { get; set; }
175 219
176 private bool isTimeToPersist() 220 private bool isTimeToPersist()
177 { 221 {
@@ -181,8 +225,19 @@ namespace OpenSim.Region.Framework.Scenes
181 return false; 225 return false;
182 if (m_scene.ShuttingDown) 226 if (m_scene.ShuttingDown)
183 return true; 227 return true;
228
229 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
230 {
231 m_maxPersistTime = m_scene.m_persistAfter;
232 m_minPersistTime = m_scene.m_dontPersistBefore;
233 }
234
184 long currentTime = DateTime.Now.Ticks; 235 long currentTime = DateTime.Now.Ticks;
185 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 236
237 if (timeLastChanged == 0) timeLastChanged = currentTime;
238 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
239
240 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
186 return true; 241 return true;
187 return false; 242 return false;
188 } 243 }
@@ -240,6 +295,11 @@ namespace OpenSim.Region.Framework.Scenes
240 { 295 {
241 AttachmentPoint = 0; 296 AttachmentPoint = 0;
242 297
298 // Don't zap trees
299 if (RootPart.Shape.PCode == (byte)PCode.Tree ||
300 RootPart.Shape.PCode == (byte)PCode.NewTree)
301 return;
302
243 // Even though we don't use child part state parameters for attachments any more, we still need to set 303 // Even though we don't use child part state parameters for attachments any more, we still need to set
244 // these to zero since having them non-zero in rezzed scene objects will crash some clients. Even if 304 // these to zero since having them non-zero in rezzed scene objects will crash some clients. Even if
245 // we store them correctly, scene objects that we receive from elsewhere might not. 305 // we store them correctly, scene objects that we receive from elsewhere might not.
@@ -293,21 +353,38 @@ namespace OpenSim.Region.Framework.Scenes
293 /// </summary> 353 /// </summary>
294 public bool Backup { get; private set; } 354 public bool Backup { get; private set; }
295 355
356 private bool m_isBackedUp;
357
358 public bool IsBackedUp
359 {
360 get { return m_isBackedUp; }
361 }
362
296 protected MapAndArray<UUID, SceneObjectPart> m_parts = new MapAndArray<UUID, SceneObjectPart>(); 363 protected MapAndArray<UUID, SceneObjectPart> m_parts = new MapAndArray<UUID, SceneObjectPart>();
297 364
298 protected ulong m_regionHandle; 365 protected ulong m_regionHandle;
299 protected SceneObjectPart m_rootPart; 366 protected SceneObjectPart m_rootPart;
300 // private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>(); 367 // private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>();
301 368
302 private Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>(); 369 private SortedDictionary<uint, scriptPosTarget> m_targets = new SortedDictionary<uint, scriptPosTarget>();
303 private Dictionary<uint, scriptRotTarget> m_rotTargets = new Dictionary<uint, scriptRotTarget>(); 370 private SortedDictionary<uint, scriptRotTarget> m_rotTargets = new SortedDictionary<uint, scriptRotTarget>();
371
372 public SortedDictionary<uint, scriptPosTarget> AtTargets
373 {
374 get { return m_targets; }
375 }
376
377 public SortedDictionary<uint, scriptRotTarget> RotTargets
378 {
379 get { return m_rotTargets; }
380 }
304 381
305 private bool m_scriptListens_atTarget; 382 private bool m_scriptListens_atTarget;
306 private bool m_scriptListens_notAtTarget; 383 private bool m_scriptListens_notAtTarget;
307
308 private bool m_scriptListens_atRotTarget; 384 private bool m_scriptListens_atRotTarget;
309 private bool m_scriptListens_notAtRotTarget; 385 private bool m_scriptListens_notAtRotTarget;
310 386
387 public bool m_dupeInProgress = false;
311 internal Dictionary<UUID, string> m_savedScriptState; 388 internal Dictionary<UUID, string> m_savedScriptState;
312 389
313 #region Properties 390 #region Properties
@@ -344,6 +421,16 @@ namespace OpenSim.Region.Framework.Scenes
344 get { return m_parts.Count; } 421 get { return m_parts.Count; }
345 } 422 }
346 423
424// protected Quaternion m_rotation = Quaternion.Identity;
425//
426// public virtual Quaternion Rotation
427// {
428// get { return m_rotation; }
429// set {
430// m_rotation = value;
431// }
432// }
433
347 public Quaternion GroupRotation 434 public Quaternion GroupRotation
348 { 435 {
349 get { return m_rootPart.RotationOffset; } 436 get { return m_rootPart.RotationOffset; }
@@ -458,6 +545,10 @@ namespace OpenSim.Region.Framework.Scenes
458 public uint ParentID; 545 public uint ParentID;
459 } 546 }
460 547
548
549 public bool inTransit = false;
550 public delegate SceneObjectGroup SOGCrossDelegate(SceneObjectGroup sog,Vector3 pos);
551
461 /// <summary> 552 /// <summary>
462 /// The absolute position of this scene object in the scene 553 /// The absolute position of this scene object in the scene
463 /// </summary> 554 /// </summary>
@@ -467,183 +558,269 @@ namespace OpenSim.Region.Framework.Scenes
467 set 558 set
468 { 559 {
469 Vector3 val = value; 560 Vector3 val = value;
561 if (Scene != null
562 && !Scene.PositionIsInCurrentRegion(val)
563 && !IsAttachmentCheckFull()
564 && !Scene.LoadingPrims
565 )
566 {
567 if (!inTransit)
568 {
569 inTransit = true;
570 SOGCrossDelegate d = CrossAsync;
571 d.BeginInvoke(this, val, CrossAsyncCompleted, d);
572 }
573 return;
574 }
470 575
471 if (Scene != null) 576 if (RootPart.GetStatusSandbox())
472 { 577 {
473 if ( 578 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
474 !Scene.PositionIsInCurrentRegion(val)
475 && !IsAttachmentCheckFull()
476 && (!Scene.LoadingPrims)
477 )
478 { 579 {
479 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 580 RootPart.ScriptSetPhysicsStatus(false);
480 EntityTransferContext ctx = new EntityTransferContext();
481 Vector3 newpos = Vector3.Zero;
482 string failureReason = String.Empty;
483 OpenSim.Services.Interfaces.GridRegion destination = null;
484 581
485 if (m_rootPart.KeyframeMotion != null) 582 if (Scene != null)
486 m_rootPart.KeyframeMotion.StartCrossingCheck(); 583 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
584 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
487 585
488 bool canCross = true; 586 return;
489 foreach (ScenePresence av in GetSittingAvatars()) 587 }
490 { 588 }
491 // We need to cross these agents. First, let's find
492 // out if any of them can't cross for some reason.
493 // We have to deny the crossing entirely if any
494 // of them are banned. Alternatively, we could
495 // unsit banned agents....
496 589
590 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
591 if (m_dupeInProgress || IsDeleted)
592 triggerScriptEvent = false;
497 593
498 // We set the avatar position as being the object 594 m_rootPart.GroupPosition = val;
499 // position to get the region to send to
500 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, ctx, out newpos, out failureReason)) == null)
501 {
502 canCross = false;
503 break;
504 }
505 595
506 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); 596 // Restuff the new GroupPosition into each child SOP of the linkset.
507 } 597 // this is needed because physics may not have linksets but just loose SOPs in world
508 598
509 if (canCross) 599 SceneObjectPart[] parts = m_parts.GetArray();
510 {
511 // We unparent the SP quietly so that it won't
512 // be made to stand up
513 600
514 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>(); 601 foreach (SceneObjectPart part in parts)
602 {
603 if (part != m_rootPart)
604 part.GroupPosition = val;
605 }
515 606
516 foreach (ScenePresence av in GetSittingAvatars()) 607 foreach (ScenePresence av in m_sittingAvatars)
517 { 608 {
518 avtocrossInfo avinfo = new avtocrossInfo(); 609 av.sitSOGmoved();
519 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID); 610 }
520 if (parentPart != null)
521 av.ParentUUID = parentPart.UUID;
522 611
523 avinfo.av = av;
524 avinfo.ParentID = av.ParentID;
525 avsToCross.Add(avinfo);
526 612
527 av.PrevSitOffset = av.OffsetPosition; 613 // now that position is changed tell it to scripts
528 av.ParentID = 0; 614 if (triggerScriptEvent)
529 } 615 {
616 foreach (SceneObjectPart part in parts)
617 {
618 part.TriggerScriptChangedEvent(Changed.POSITION);
619 }
620 }
530 621
531 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 622 if (Scene != null)
623 Scene.EventManager.TriggerParcelPrimCountTainted();
532 624
533 // Normalize 625 }
534 if (val.X >= m_scene.RegionInfo.RegionSizeX) 626 }
535 val.X -= m_scene.RegionInfo.RegionSizeX;
536 if (val.Y >= m_scene.RegionInfo.RegionSizeY)
537 val.Y -= m_scene.RegionInfo.RegionSizeY;
538 if (val.X < 0)
539 val.X += m_scene.RegionInfo.RegionSizeX;
540 if (val.Y < 0)
541 val.Y += m_scene.RegionInfo.RegionSizeY;
542 627
543 // If it's deleted, crossing was successful 628 public SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val)
544 if (IsDeleted) 629 {
545 { 630 Scene sogScene = sog.m_scene;
546 foreach (avtocrossInfo avinfo in avsToCross) 631 IEntityTransferModule entityTransfer = sogScene.RequestModuleInterface<IEntityTransferModule>();
547 {
548 ScenePresence av = avinfo.av;
549 if (!av.IsInTransit) // just in case...
550 {
551 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
552
553 av.IsInTransit = true;
554
555 // A temporary measure to allow regression tests to work.
556 // Quite possibly, all BeginInvoke() calls should be replaced by Util.FireAndForget
557 // or similar since BeginInvoke() always uses the system threadpool to launch
558 // threads rather than any replace threadpool that we might be using.
559 if (Util.FireAndForgetMethod == FireAndForgetMethod.RegressionTest)
560 {
561 entityTransfer.CrossAgentToNewRegionAsync(av, val, destination, av.Flying, ctx);
562 CrossAgentToNewRegionCompleted(av);
563 }
564 else
565 {
566 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
567 d.BeginInvoke(
568 av, val, destination, av.Flying, ctx,
569 ar => CrossAgentToNewRegionCompleted(d.EndInvoke(ar)), null);
570 }
571 }
572 else
573 {
574 m_log.DebugFormat("[SCENE OBJECT]: Not crossing avatar {0} to {1} because it's already in transit", av.Name, val);
575 }
576 }
577 632
578 return; 633 Vector3 newpos = Vector3.Zero;
579 } 634 OpenSim.Services.Interfaces.GridRegion destination = null;
580 else // cross failed, put avas back ?? 635
636 if (sog.RootPart.DIE_AT_EDGE)
637 {
638 try
639 {
640 sogScene.DeleteSceneObject(sog, false);
641 }
642 catch (Exception)
643 {
644 m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border.");
645 }
646 return sog;
647 }
648
649 if (sog.RootPart.RETURN_AT_EDGE)
650 {
651 // We remove the object here
652 try
653 {
654 List<uint> localIDs = new List<uint>();
655 localIDs.Add(sog.RootPart.LocalId);
656 sogScene.AddReturn(sog.OwnerID, sog.Name, sog.AbsolutePosition,
657 "Returned at region cross");
658 sogScene.DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, UUID.Zero);
659 }
660 catch (Exception)
661 {
662 m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border.");
663 }
664 return sog;
665 }
666
667 if (sog.m_rootPart.KeyframeMotion != null)
668 sog.m_rootPart.KeyframeMotion.StartCrossingCheck();
669
670 if (entityTransfer == null)
671 return sog;
672
673 destination = entityTransfer.GetObjectDestination(sog, val, out newpos);
674 if (destination == null)
675 return sog;
676
677 if (sog.m_sittingAvatars.Count == 0)
678 {
679 entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true, true);
680 return sog;
681 }
682
683 string reason = String.Empty;
684 EntityTransferContext ctx = new EntityTransferContext();
685
686 foreach (ScenePresence av in sog.m_sittingAvatars)
687 {
688 // We need to cross these agents. First, let's find
689 // out if any of them can't cross for some reason.
690 // We have to deny the crossing entirely if any
691 // of them are banned. Alternatively, we could
692 // unsit banned agents....
693
694 // We set the avatar position as being the object
695 // position to get the region to send to
696 if(!entityTransfer.checkAgentAccessToRegion(av, destination, newpos, ctx, out reason))
697 {
698 return sog;
699 }
700 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
701 }
702
703 // We unparent the SP quietly so that it won't
704 // be made to stand up
705
706 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
707
708 foreach (ScenePresence av in sog.m_sittingAvatars)
709 {
710 avtocrossInfo avinfo = new avtocrossInfo();
711 SceneObjectPart parentPart = sogScene.GetSceneObjectPart(av.ParentID);
712 if (parentPart != null)
713 av.ParentUUID = parentPart.UUID;
714
715 avinfo.av = av;
716 avinfo.ParentID = av.ParentID;
717 avsToCross.Add(avinfo);
718
719 av.PrevSitOffset = av.OffsetPosition;
720 av.ParentID = 0;
721 }
722
723 if (entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true, false))
724 {
725 foreach (avtocrossInfo avinfo in avsToCross)
726 {
727 ScenePresence av = avinfo.av;
728 if (!av.IsInTransit) // just in case...
729 {
730 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
731
732 av.IsInTransit = true;
733
734// CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
735// d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
736 entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, av.Flying, ctx);
737 if (av.IsChildAgent)
738 {
739 // avatar crossed do some extra cleanup
740 if (av.ParentUUID != UUID.Zero)
581 { 741 {
582 foreach (avtocrossInfo avinfo in avsToCross) 742 av.ClearControls();
583 { 743 av.ParentPart = null;
584 ScenePresence av = avinfo.av;
585 av.ParentUUID = UUID.Zero;
586 av.ParentID = avinfo.ParentID;
587 }
588 } 744 }
589 } 745 }
590 else 746 else
591 { 747 {
592 if (m_rootPart.KeyframeMotion != null) 748 // avatar cross failed we need do dedicated standUp
593 m_rootPart.KeyframeMotion.CrossingFailure(); 749 // part of it was done at CrossAgentToNewRegionAsync
594 750 // so for now just remove the sog controls
595 if (RootPart.PhysActor != null) 751 // this may need extra care
596 { 752 av.UnRegisterSeatControls(sog.UUID);
597 RootPart.PhysActor.CrossingFailure();
598 }
599 } 753 }
600 754
601 Vector3 oldp = AbsolutePosition; 755 av.ParentUUID = UUID.Zero;
602 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)m_scene.RegionInfo.RegionSizeX - 0.5f); 756 // In any case
603 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)m_scene.RegionInfo.RegionSizeY - 0.5f); 757 av.IsInTransit = false;
604 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, Constants.RegionHeight); 758
759 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname);
605 } 760 }
761 else
762 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar already in transit {0} to {1}", av.Name, val);
606 } 763 }
607 764 avsToCross.Clear();
608 if (RootPart.GetStatusSandbox()) 765 sog.RemoveScriptInstances(true);
766 return sog;
767 }
768 else // cross failed, put avas back ??
769 {
770 foreach (avtocrossInfo avinfo in avsToCross)
609 { 771 {
610 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 772 ScenePresence av = avinfo.av;
611 { 773 av.ParentUUID = UUID.Zero;
612 RootPart.ScriptSetPhysicsStatus(false); 774 av.ParentID = avinfo.ParentID;
613
614 if (Scene != null)
615 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
616 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
617
618 return;
619 }
620 } 775 }
621
622 // Restuff the new GroupPosition into each SOP of the linkset.
623 // This has the affect of resetting and tainting the physics actors.
624 SceneObjectPart[] parts = m_parts.GetArray();
625 for (int i = 0; i < parts.Length; i++)
626 parts[i].GroupPosition = val;
627
628 //if (m_rootPart.PhysActor != null)
629 //{
630 //m_rootPart.PhysActor.Position =
631 //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y,
632 //m_rootPart.GroupPosition.Z);
633 //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
634 //}
635
636 if (Scene != null)
637 Scene.EventManager.TriggerParcelPrimCountTainted();
638 } 776 }
777 avsToCross.Clear();
778
779 return sog;
639 } 780 }
640 781
641 public override Vector3 Velocity 782 public void CrossAsyncCompleted(IAsyncResult iar)
642 { 783 {
643 get { return RootPart.Velocity; } 784 SOGCrossDelegate icon = (SOGCrossDelegate)iar.AsyncState;
644 set { RootPart.Velocity = value; } 785 SceneObjectGroup sog = icon.EndInvoke(iar);
786
787 if (!sog.IsDeleted)
788 {
789 SceneObjectPart rootp = sog.m_rootPart;
790 Vector3 oldp = rootp.GroupPosition;
791 oldp.X = Util.Clamp<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f);
792 oldp.Y = Util.Clamp<float>(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f);
793 rootp.GroupPosition = oldp;
794
795 SceneObjectPart[] parts = sog.m_parts.GetArray();
796
797 foreach (SceneObjectPart part in parts)
798 {
799 if (part != rootp)
800 part.GroupPosition = oldp;
801 }
802
803 foreach (ScenePresence av in sog.m_sittingAvatars)
804 {
805 av.sitSOGmoved();
806 }
807
808 sog.Velocity = Vector3.Zero;
809
810 if (sog.m_rootPart.KeyframeMotion != null)
811 sog.m_rootPart.KeyframeMotion.CrossingFailure();
812
813 if (sog.RootPart.PhysActor != null)
814 {
815 sog.RootPart.PhysActor.CrossingFailure();
816 }
817
818 sog.inTransit = false;
819 sog.ScheduleGroupForFullUpdate();
820 }
645 } 821 }
646 822
823/* outdated
647 private void CrossAgentToNewRegionCompleted(ScenePresence agent) 824 private void CrossAgentToNewRegionCompleted(ScenePresence agent)
648 { 825 {
649 //// If the cross was successful, this agent is a child agent 826 //// If the cross was successful, this agent is a child agent
@@ -651,6 +828,7 @@ namespace OpenSim.Region.Framework.Scenes
651 { 828 {
652 if (agent.ParentUUID != UUID.Zero) 829 if (agent.ParentUUID != UUID.Zero)
653 { 830 {
831 agent.HandleForceReleaseControls(agent.ControllingClient,agent.UUID);
654 agent.ParentPart = null; 832 agent.ParentPart = null;
655// agent.ParentPosition = Vector3.Zero; 833// agent.ParentPosition = Vector3.Zero;
656// agent.ParentUUID = UUID.Zero; 834// agent.ParentUUID = UUID.Zero;
@@ -667,6 +845,12 @@ namespace OpenSim.Region.Framework.Scenes
667 845
668 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); 846 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
669 } 847 }
848*/
849 public override Vector3 Velocity
850 {
851 get { return RootPart.Velocity; }
852 set { RootPart.Velocity = value; }
853 }
670 854
671 public override uint LocalId 855 public override uint LocalId
672 { 856 {
@@ -742,6 +926,11 @@ namespace OpenSim.Region.Framework.Scenes
742 m_isSelected = value; 926 m_isSelected = value;
743 // Tell physics engine that group is selected 927 // Tell physics engine that group is selected
744 928
929 // this is not right
930 // but ode engines should only really need to know about root part
931 // so they can put entire object simulation on hold and not colliding
932 // keep as was for now
933
745 PhysicsActor pa = m_rootPart.PhysActor; 934 PhysicsActor pa = m_rootPart.PhysActor;
746 if (pa != null) 935 if (pa != null)
747 { 936 {
@@ -763,13 +952,47 @@ namespace OpenSim.Region.Framework.Scenes
763 } 952 }
764 } 953 }
765 954
955 public void PartSelectChanged(bool partSelect)
956 {
957 // any part selected makes group selected
958 if (m_isSelected == partSelect)
959 return;
960
961 if (partSelect)
962 {
963 IsSelected = partSelect;
964// if (!IsAttachment)
965// ScheduleGroupForFullUpdate();
966 }
967 else
968 {
969 // bad bad bad 2 heavy for large linksets
970 // since viewer does send lot of (un)selects
971 // this needs to be replaced by a specific list or count ?
972 // but that will require extra code in several places
973
974 SceneObjectPart[] parts = m_parts.GetArray();
975 for (int i = 0; i < parts.Length; i++)
976 {
977 SceneObjectPart part = parts[i];
978 if (part.IsSelected)
979 return;
980 }
981 IsSelected = partSelect;
982// if (!IsAttachment)
983// {
984// ScheduleGroupForFullUpdate();
985// }
986 }
987 }
988 // PlaySoundMasterPrim no longer in use to remove
766 private SceneObjectPart m_PlaySoundMasterPrim = null; 989 private SceneObjectPart m_PlaySoundMasterPrim = null;
767 public SceneObjectPart PlaySoundMasterPrim 990 public SceneObjectPart PlaySoundMasterPrim
768 { 991 {
769 get { return m_PlaySoundMasterPrim; } 992 get { return m_PlaySoundMasterPrim; }
770 set { m_PlaySoundMasterPrim = value; } 993 set { m_PlaySoundMasterPrim = value; }
771 } 994 }
772 995 // PlaySoundSlavePrims no longer in use to remove
773 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>(); 996 private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>();
774 public List<SceneObjectPart> PlaySoundSlavePrims 997 public List<SceneObjectPart> PlaySoundSlavePrims
775 { 998 {
@@ -777,6 +1000,7 @@ namespace OpenSim.Region.Framework.Scenes
777 set { m_PlaySoundSlavePrims = value; } 1000 set { m_PlaySoundSlavePrims = value; }
778 } 1001 }
779 1002
1003 // LoopSoundMasterPrim no longer in use to remove
780 private SceneObjectPart m_LoopSoundMasterPrim = null; 1004 private SceneObjectPart m_LoopSoundMasterPrim = null;
781 public SceneObjectPart LoopSoundMasterPrim 1005 public SceneObjectPart LoopSoundMasterPrim
782 { 1006 {
@@ -784,6 +1008,7 @@ namespace OpenSim.Region.Framework.Scenes
784 set { m_LoopSoundMasterPrim = value; } 1008 set { m_LoopSoundMasterPrim = value; }
785 } 1009 }
786 1010
1011 // m_LoopSoundSlavePrims no longer in use to remove
787 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>(); 1012 private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>();
788 public List<SceneObjectPart> LoopSoundSlavePrims 1013 public List<SceneObjectPart> LoopSoundSlavePrims
789 { 1014 {
@@ -863,6 +1088,7 @@ namespace OpenSim.Region.Framework.Scenes
863 /// </summary> 1088 /// </summary>
864 public SceneObjectGroup() 1089 public SceneObjectGroup()
865 { 1090 {
1091
866 } 1092 }
867 1093
868 /// <summary> 1094 /// <summary>
@@ -880,8 +1106,8 @@ namespace OpenSim.Region.Framework.Scenes
880 /// Constructor. This object is added to the scene later via AttachToScene() 1106 /// Constructor. This object is added to the scene later via AttachToScene()
881 /// </summary> 1107 /// </summary>
882 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 1108 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
883 :this(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)) 1109 {
884 { 1110 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
885 } 1111 }
886 1112
887 /// <summary> 1113 /// <summary>
@@ -956,7 +1182,10 @@ namespace OpenSim.Region.Framework.Scenes
956 /// </summary> 1182 /// </summary>
957 public virtual void AttachToBackup() 1183 public virtual void AttachToBackup()
958 { 1184 {
959 if (CanBeBackedUp) 1185 if (IsAttachment) return;
1186 m_scene.SceneGraph.FireAttachToBackup(this);
1187
1188// if (InSceneBackup)
960 { 1189 {
961// m_log.DebugFormat( 1190// m_log.DebugFormat(
962// "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID); 1191// "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID);
@@ -1003,6 +1232,13 @@ namespace OpenSim.Region.Framework.Scenes
1003 1232
1004 ApplyPhysics(); 1233 ApplyPhysics();
1005 1234
1235 if (RootPart.PhysActor != null)
1236 RootPart.Force = RootPart.Force;
1237 if (RootPart.PhysActor != null)
1238 RootPart.Torque = RootPart.Torque;
1239 if (RootPart.PhysActor != null)
1240 RootPart.Buoyancy = RootPart.Buoyancy;
1241
1006 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 1242 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
1007 // for the same object with very different properties. The caller must schedule the update. 1243 // for the same object with very different properties. The caller must schedule the update.
1008 //ScheduleGroupForFullUpdate(); 1244 //ScheduleGroupForFullUpdate();
@@ -1018,6 +1254,10 @@ namespace OpenSim.Region.Framework.Scenes
1018 EntityIntersection result = new EntityIntersection(); 1254 EntityIntersection result = new EntityIntersection();
1019 1255
1020 SceneObjectPart[] parts = m_parts.GetArray(); 1256 SceneObjectPart[] parts = m_parts.GetArray();
1257
1258 // Find closest hit here
1259 float idist = float.MaxValue;
1260
1021 for (int i = 0; i < parts.Length; i++) 1261 for (int i = 0; i < parts.Length; i++)
1022 { 1262 {
1023 SceneObjectPart part = parts[i]; 1263 SceneObjectPart part = parts[i];
@@ -1032,11 +1272,6 @@ namespace OpenSim.Region.Framework.Scenes
1032 1272
1033 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 1273 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
1034 1274
1035 // This may need to be updated to the maximum draw distance possible..
1036 // We might (and probably will) be checking for prim creation from other sims
1037 // when the camera crosses the border.
1038 float idist = Constants.RegionSize;
1039
1040 if (inter.HitTF) 1275 if (inter.HitTF)
1041 { 1276 {
1042 // We need to find the closest prim to return to the testcaller along the ray 1277 // We need to find the closest prim to return to the testcaller along the ray
@@ -1047,10 +1282,11 @@ namespace OpenSim.Region.Framework.Scenes
1047 result.obj = part; 1282 result.obj = part;
1048 result.normal = inter.normal; 1283 result.normal = inter.normal;
1049 result.distance = inter.distance; 1284 result.distance = inter.distance;
1285
1286 idist = inter.distance;
1050 } 1287 }
1051 } 1288 }
1052 } 1289 }
1053
1054 return result; 1290 return result;
1055 } 1291 }
1056 1292
@@ -1062,25 +1298,27 @@ namespace OpenSim.Region.Framework.Scenes
1062 /// <returns></returns> 1298 /// <returns></returns>
1063 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 1299 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
1064 { 1300 {
1065 maxX = -256f; 1301 maxX = float.MinValue;
1066 maxY = -256f; 1302 maxY = float.MinValue;
1067 maxZ = -256f; 1303 maxZ = float.MinValue;
1068 minX = 10000f; 1304 minX = float.MaxValue;
1069 minY = 10000f; 1305 minY = float.MaxValue;
1070 minZ = 10000f; 1306 minZ = float.MaxValue;
1071 1307
1072 SceneObjectPart[] parts = m_parts.GetArray(); 1308 SceneObjectPart[] parts = m_parts.GetArray();
1073 for (int i = 0; i < parts.Length; i++) 1309 foreach (SceneObjectPart part in parts)
1074 { 1310 {
1075 SceneObjectPart part = parts[i];
1076
1077 Vector3 worldPos = part.GetWorldPosition(); 1311 Vector3 worldPos = part.GetWorldPosition();
1078 Vector3 offset = worldPos - AbsolutePosition; 1312 Vector3 offset = worldPos - AbsolutePosition;
1079 Quaternion worldRot; 1313 Quaternion worldRot;
1080 if (part.ParentID == 0) 1314 if (part.ParentID == 0)
1315 {
1081 worldRot = part.RotationOffset; 1316 worldRot = part.RotationOffset;
1317 }
1082 else 1318 else
1319 {
1083 worldRot = part.GetWorldRotation(); 1320 worldRot = part.GetWorldRotation();
1321 }
1084 1322
1085 Vector3 frontTopLeft; 1323 Vector3 frontTopLeft;
1086 Vector3 frontTopRight; 1324 Vector3 frontTopRight;
@@ -1092,6 +1330,8 @@ namespace OpenSim.Region.Framework.Scenes
1092 Vector3 backBottomLeft; 1330 Vector3 backBottomLeft;
1093 Vector3 backBottomRight; 1331 Vector3 backBottomRight;
1094 1332
1333 // Vector3[] corners = new Vector3[8];
1334
1095 Vector3 orig = Vector3.Zero; 1335 Vector3 orig = Vector3.Zero;
1096 1336
1097 frontTopLeft.X = orig.X - (part.Scale.X / 2); 1337 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -1126,6 +1366,38 @@ namespace OpenSim.Region.Framework.Scenes
1126 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1366 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
1127 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1367 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
1128 1368
1369
1370
1371 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1372 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1373 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1374 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1375 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1376 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1377 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1378 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1379
1380 //for (int i = 0; i < 8; i++)
1381 //{
1382 // corners[i] = corners[i] * worldRot;
1383 // corners[i] += offset;
1384
1385 // if (corners[i].X > maxX)
1386 // maxX = corners[i].X;
1387 // if (corners[i].X < minX)
1388 // minX = corners[i].X;
1389
1390 // if (corners[i].Y > maxY)
1391 // maxY = corners[i].Y;
1392 // if (corners[i].Y < minY)
1393 // minY = corners[i].Y;
1394
1395 // if (corners[i].Z > maxZ)
1396 // maxZ = corners[i].Y;
1397 // if (corners[i].Z < minZ)
1398 // minZ = corners[i].Z;
1399 //}
1400
1129 frontTopLeft = frontTopLeft * worldRot; 1401 frontTopLeft = frontTopLeft * worldRot;
1130 frontTopRight = frontTopRight * worldRot; 1402 frontTopRight = frontTopRight * worldRot;
1131 frontBottomLeft = frontBottomLeft * worldRot; 1403 frontBottomLeft = frontBottomLeft * worldRot;
@@ -1147,6 +1419,15 @@ namespace OpenSim.Region.Framework.Scenes
1147 backTopLeft += offset; 1419 backTopLeft += offset;
1148 backTopRight += offset; 1420 backTopRight += offset;
1149 1421
1422 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1423 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1424 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1425 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1426 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1427 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1428 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1429 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1430
1150 if (frontTopRight.X > maxX) 1431 if (frontTopRight.X > maxX)
1151 maxX = frontTopRight.X; 1432 maxX = frontTopRight.X;
1152 if (frontTopLeft.X > maxX) 1433 if (frontTopLeft.X > maxX)
@@ -1290,17 +1571,118 @@ namespace OpenSim.Region.Framework.Scenes
1290 1571
1291 #endregion 1572 #endregion
1292 1573
1574 public void GetResourcesCosts(SceneObjectPart apart,
1575 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost)
1576 {
1577 // this information may need to be cached
1578
1579 float cost;
1580 float tmpcost;
1581
1582 bool ComplexCost = false;
1583
1584 SceneObjectPart p;
1585 SceneObjectPart[] parts;
1586
1587 lock (m_parts)
1588 {
1589 parts = m_parts.GetArray();
1590 }
1591
1592 int nparts = parts.Length;
1593
1594
1595 for (int i = 0; i < nparts; i++)
1596 {
1597 p = parts[i];
1598
1599 if (p.UsesComplexCost)
1600 {
1601 ComplexCost = true;
1602 break;
1603 }
1604 }
1605
1606 if (ComplexCost)
1607 {
1608 linksetResCost = 0;
1609 linksetPhysCost = 0;
1610 partCost = 0;
1611 partPhysCost = 0;
1612
1613 for (int i = 0; i < nparts; i++)
1614 {
1615 p = parts[i];
1616
1617 cost = p.StreamingCost;
1618 tmpcost = p.SimulationCost;
1619 if (tmpcost > cost)
1620 cost = tmpcost;
1621 tmpcost = p.PhysicsCost;
1622 if (tmpcost > cost)
1623 cost = tmpcost;
1624
1625 linksetPhysCost += tmpcost;
1626 linksetResCost += cost;
1627
1628 if (p == apart)
1629 {
1630 partCost = cost;
1631 partPhysCost = tmpcost;
1632 }
1633 }
1634 }
1635 else
1636 {
1637 partPhysCost = 1.0f;
1638 partCost = 1.0f;
1639 linksetResCost = (float)nparts;
1640 linksetPhysCost = linksetResCost;
1641 }
1642 }
1643
1644 public void GetSelectedCosts(out float PhysCost, out float StreamCost, out float SimulCost)
1645 {
1646 SceneObjectPart p;
1647 SceneObjectPart[] parts;
1648
1649 lock (m_parts)
1650 {
1651 parts = m_parts.GetArray();
1652 }
1653
1654 int nparts = parts.Length;
1655
1656 PhysCost = 0;
1657 StreamCost = 0;
1658 SimulCost = 0;
1659
1660 for (int i = 0; i < nparts; i++)
1661 {
1662 p = parts[i];
1663
1664 StreamCost += p.StreamingCost;
1665 SimulCost += p.SimulationCost;
1666 PhysCost += p.PhysicsCost;
1667 }
1668 }
1669
1293 public void SaveScriptedState(XmlTextWriter writer) 1670 public void SaveScriptedState(XmlTextWriter writer)
1294 { 1671 {
1672 SaveScriptedState(writer, false);
1673 }
1674
1675 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1676 {
1295 XmlDocument doc = new XmlDocument(); 1677 XmlDocument doc = new XmlDocument();
1296 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1678 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
1297 1679
1298 SceneObjectPart[] parts = m_parts.GetArray(); 1680 SceneObjectPart[] parts = m_parts.GetArray();
1299 for (int i = 0; i < parts.Length; i++) 1681 for (int i = 0; i < parts.Length; i++)
1300 { 1682 {
1301 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1683 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
1302 foreach (KeyValuePair<UUID, string> kvp in pstates) 1684 foreach (KeyValuePair<UUID, string> kvp in pstates)
1303 states.Add(kvp.Key, kvp.Value); 1685 states[kvp.Key] = kvp.Value;
1304 } 1686 }
1305 1687
1306 if (states.Count > 0) 1688 if (states.Count > 0)
@@ -1319,6 +1701,130 @@ namespace OpenSim.Region.Framework.Scenes
1319 } 1701 }
1320 } 1702 }
1321 1703
1704 /// <summary>
1705 /// Attach this scene object to the given avatar.
1706 /// </summary>
1707 /// <param name="agentID"></param>
1708 /// <param name="attachmentpoint"></param>
1709 /// <param name="AttachOffset"></param>
1710 private void AttachToAgent(
1711 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1712 {
1713 if (avatar != null)
1714 {
1715 // don't attach attachments to child agents
1716 if (avatar.IsChildAgent) return;
1717
1718 // Remove from database and parcel prim count
1719 m_scene.DeleteFromStorage(so.UUID);
1720 m_scene.EventManager.TriggerParcelPrimCountTainted();
1721
1722 so.AttachedAvatar = avatar.UUID;
1723
1724 if (so.RootPart.PhysActor != null)
1725 {
1726 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1727 so.RootPart.PhysActor = null;
1728 }
1729
1730 so.AbsolutePosition = attachOffset;
1731 so.RootPart.AttachedPos = attachOffset;
1732 so.IsAttachment = true;
1733 so.RootPart.SetParentLocalId(avatar.LocalId);
1734 so.AttachmentPoint = attachmentpoint;
1735
1736 avatar.AddAttachment(this);
1737
1738 if (!silent)
1739 {
1740 // Killing it here will cause the client to deselect it
1741 // It then reappears on the avatar, deselected
1742 // through the full update below
1743 //
1744 if (IsSelected)
1745 {
1746 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1747 }
1748
1749 IsSelected = false; // fudge....
1750 ScheduleGroupForFullUpdate();
1751 }
1752 }
1753 else
1754 {
1755 m_log.WarnFormat(
1756 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1757 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1758 }
1759 }
1760
1761 public byte GetAttachmentPoint()
1762 {
1763 return m_rootPart.Shape.State;
1764 }
1765
1766 public void DetachToGround()
1767 {
1768 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1769 if (avatar == null)
1770 return;
1771 m_rootPart.Shape.LastAttachPoint = m_rootPart.Shape.State;
1772 m_rootPart.AttachedPos = m_rootPart.OffsetPosition;
1773 avatar.RemoveAttachment(this);
1774
1775 Vector3 detachedpos = new Vector3(127f,127f,127f);
1776 if (avatar == null)
1777 return;
1778
1779 detachedpos = avatar.AbsolutePosition;
1780 FromItemID = UUID.Zero;
1781
1782 AbsolutePosition = detachedpos;
1783 AttachedAvatar = UUID.Zero;
1784
1785 //SceneObjectPart[] parts = m_parts.GetArray();
1786 //for (int i = 0; i < parts.Length; i++)
1787 // parts[i].AttachedAvatar = UUID.Zero;
1788
1789 m_rootPart.SetParentLocalId(0);
1790 AttachmentPoint = (byte)0;
1791 // must check if buildind should be true or false here
1792// m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1793 ApplyPhysics();
1794
1795 HasGroupChanged = true;
1796 RootPart.Rezzed = DateTime.Now;
1797 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1798 AttachToBackup();
1799 m_scene.EventManager.TriggerParcelPrimCountTainted();
1800 m_rootPart.ScheduleFullUpdate();
1801 m_rootPart.ClearUndoState();
1802 }
1803
1804 public void DetachToInventoryPrep()
1805 {
1806 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1807 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1808 if (avatar != null)
1809 {
1810 //detachedpos = avatar.AbsolutePosition;
1811 avatar.RemoveAttachment(this);
1812 }
1813
1814 AttachedAvatar = UUID.Zero;
1815
1816 /*SceneObjectPart[] parts = m_parts.GetArray();
1817 for (int i = 0; i < parts.Length; i++)
1818 parts[i].AttachedAvatar = UUID.Zero;*/
1819
1820 m_rootPart.SetParentLocalId(0);
1821 //m_rootPart.SetAttachmentPoint((byte)0);
1822 IsAttachment = false;
1823 AbsolutePosition = m_rootPart.AttachedPos;
1824 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1825 //AttachToBackup();
1826 //m_rootPart.ScheduleFullUpdate();
1827 }
1322 1828
1323 /// <summary> 1829 /// <summary>
1324 /// 1830 ///
@@ -1360,7 +1866,10 @@ namespace OpenSim.Region.Framework.Scenes
1360 public void AddPart(SceneObjectPart part) 1866 public void AddPart(SceneObjectPart part)
1361 { 1867 {
1362 part.SetParent(this); 1868 part.SetParent(this);
1363 part.LinkNum = m_parts.Add(part.UUID, part); 1869 m_parts.Add(part.UUID, part);
1870
1871 part.LinkNum = m_parts.Count;
1872
1364 if (part.LinkNum == 2) 1873 if (part.LinkNum == 2)
1365 RootPart.LinkNum = 1; 1874 RootPart.LinkNum = 1;
1366 } 1875 }
@@ -1386,6 +1895,14 @@ namespace OpenSim.Region.Framework.Scenes
1386 parts[i].UUID = UUID.Random(); 1895 parts[i].UUID = UUID.Random();
1387 } 1896 }
1388 1897
1898 // helper provided for parts.
1899 public int GetSceneMaxUndo()
1900 {
1901 if (m_scene != null)
1902 return m_scene.MaxUndoCount;
1903 return 5;
1904 }
1905
1389 // justincc: I don't believe this hack is needed any longer, especially since the physics 1906 // justincc: I don't believe this hack is needed any longer, especially since the physics
1390 // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false 1907 // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false
1391 // this method was preventing proper reload of scene objects. 1908 // this method was preventing proper reload of scene objects.
@@ -1407,11 +1924,21 @@ namespace OpenSim.Region.Framework.Scenes
1407 // Setting this SOG's absolute position also loops through and sets the positions 1924 // Setting this SOG's absolute position also loops through and sets the positions
1408 // of the SOP's in this SOG's linkset. This has the side affect of making sure 1925 // of the SOP's in this SOG's linkset. This has the side affect of making sure
1409 // the physics world matches the simulated world. 1926 // the physics world matches the simulated world.
1410 AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works? 1927 // AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works?
1411 1928
1412 // teravus: AbsolutePosition is NOT a normal property! 1929 // teravus: AbsolutePosition is NOT a normal property!
1413 // the code in the getter of AbsolutePosition is significantly different then the code in the setter! 1930 // the code in the getter of AbsolutePosition is significantly different then the code in the setter!
1414 // jhurliman: Then why is it a property instead of two methods? 1931 // jhurliman: Then why is it a property instead of two methods?
1932
1933 // do only what is supposed to do
1934 Vector3 groupPosition = m_rootPart.GroupPosition;
1935 SceneObjectPart[] parts = m_parts.GetArray();
1936
1937 foreach (SceneObjectPart part in parts)
1938 {
1939 if (part != m_rootPart)
1940 part.GroupPosition = groupPosition;
1941 }
1415 } 1942 }
1416 1943
1417 public UUID GetPartsFullID(uint localID) 1944 public UUID GetPartsFullID(uint localID)
@@ -1443,7 +1970,7 @@ namespace OpenSim.Region.Framework.Scenes
1443// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 1970// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1444// remoteClient.Name, part.Name, part.LocalId, offsetPos); 1971// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1445 1972
1446 part.StoreUndoState(); 1973// part.StoreUndoState();
1447 part.OnGrab(offsetPos, remoteClient); 1974 part.OnGrab(offsetPos, remoteClient);
1448 } 1975 }
1449 1976
@@ -1463,28 +1990,36 @@ namespace OpenSim.Region.Framework.Scenes
1463 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1990 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1464 public void DeleteGroupFromScene(bool silent) 1991 public void DeleteGroupFromScene(bool silent)
1465 { 1992 {
1993 // We need to keep track of this state in case this group is still queued for backup.
1994 IsDeleted = true;
1995
1996 DetachFromBackup();
1997
1466 SceneObjectPart[] parts = m_parts.GetArray(); 1998 SceneObjectPart[] parts = m_parts.GetArray();
1467 for (int i = 0; i < parts.Length; i++) 1999 for (int i = 0; i < parts.Length; i++)
1468 { 2000 {
1469 SceneObjectPart part = parts[i]; 2001 SceneObjectPart part = parts[i];
1470 2002
1471 Scene.ForEachScenePresence(sp => 2003 if (Scene != null)
1472 { 2004 {
1473 if (!sp.IsChildAgent && sp.ParentID == part.LocalId) 2005 Scene.ForEachRootScenePresence(delegate(ScenePresence avatar)
1474 sp.StandUp();
1475
1476 if (!silent)
1477 { 2006 {
1478 part.ClearUpdateSchedule(); 2007 if (avatar.ParentID == LocalId)
1479 if (part == m_rootPart) 2008 avatar.StandUp();
2009
2010 if (!silent)
1480 { 2011 {
1481 if (!IsAttachment 2012 part.ClearUpdateSchedule();
1482 || AttachedAvatar == sp.UUID 2013 if (part == m_rootPart)
1483 || !HasPrivateAttachmentPoint) 2014 {
1484 sp.ControllingClient.SendKillObject(new List<uint> { part.LocalId }); 2015 if (!IsAttachment
2016 || AttachedAvatar == avatar.ControllingClient.AgentId
2017 || !HasPrivateAttachmentPoint)
2018 avatar.ControllingClient.SendKillObject(new List<uint> { part.LocalId });
2019 }
1485 } 2020 }
1486 } 2021 });
1487 }); 2022 }
1488 } 2023 }
1489 } 2024 }
1490 2025
@@ -1555,28 +2090,43 @@ namespace OpenSim.Region.Framework.Scenes
1555 /// </summary> 2090 /// </summary>
1556 public void ApplyPhysics() 2091 public void ApplyPhysics()
1557 { 2092 {
1558 // Apply physics to the root prim
1559 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1560
1561 // Apply physics to child prims
1562 SceneObjectPart[] parts = m_parts.GetArray(); 2093 SceneObjectPart[] parts = m_parts.GetArray();
1563 if (parts.Length > 1) 2094 if (parts.Length > 1)
1564 { 2095 {
2096 ResetChildPrimPhysicsPositions();
2097
2098 // Apply physics to the root prim
2099 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
2100
2101
1565 for (int i = 0; i < parts.Length; i++) 2102 for (int i = 0; i < parts.Length; i++)
1566 { 2103 {
1567 SceneObjectPart part = parts[i]; 2104 SceneObjectPart part = parts[i];
1568 if (part.LocalId != m_rootPart.LocalId) 2105 if (part.LocalId != m_rootPart.LocalId)
1569 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 2106 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1570 } 2107 }
1571
1572 // Hack to get the physics scene geometries in the right spot 2108 // Hack to get the physics scene geometries in the right spot
1573 ResetChildPrimPhysicsPositions(); 2109// ResetChildPrimPhysicsPositions();
2110 if (m_rootPart.PhysActor != null)
2111 {
2112 m_rootPart.PhysActor.Building = false;
2113 }
2114 }
2115 else
2116 {
2117 // Apply physics to the root prim
2118 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1574 } 2119 }
1575 } 2120 }
1576 2121
1577 public void SetOwnerId(UUID userId) 2122 public void SetOwnerId(UUID userId)
1578 { 2123 {
1579 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 2124 ForEachPart(delegate(SceneObjectPart part)
2125 {
2126
2127 part.OwnerID = userId;
2128
2129 });
1580 } 2130 }
1581 2131
1582 public void ForEachPart(Action<SceneObjectPart> whatToDo) 2132 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1601,18 +2151,24 @@ namespace OpenSim.Region.Framework.Scenes
1601 return; 2151 return;
1602 } 2152 }
1603 2153
1604 if (IsDeleted || UUID == UUID.Zero) 2154 if (IsDeleted || inTransit || UUID == UUID.Zero)
1605 { 2155 {
1606// m_log.DebugFormat( 2156// m_log.DebugFormat(
1607// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID); 2157// "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID);
1608 return; 2158 return;
1609 } 2159 }
1610 2160
2161 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
2162 return;
2163
1611 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 2164 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1612 // any exception propogate upwards. 2165 // any exception propogate upwards.
1613 try 2166 try
1614 { 2167 {
1615 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 2168 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
2169 !m_scene.LoginsEnabled || // We're starting up or doing maintenance, don't mess with things
2170 m_scene.LoadingPrims) // Land may not be valid yet
2171
1616 { 2172 {
1617 ILandObject parcel = m_scene.LandChannel.GetLandObject( 2173 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1618 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 2174 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1639,6 +2195,7 @@ namespace OpenSim.Region.Framework.Scenes
1639 } 2195 }
1640 } 2196 }
1641 } 2197 }
2198
1642 } 2199 }
1643 2200
1644 if (m_scene.UseBackup && HasGroupChanged) 2201 if (m_scene.UseBackup && HasGroupChanged)
@@ -1646,10 +2203,31 @@ namespace OpenSim.Region.Framework.Scenes
1646 // don't backup while it's selected or you're asking for changes mid stream. 2203 // don't backup while it's selected or you're asking for changes mid stream.
1647 if (isTimeToPersist() || forcedBackup) 2204 if (isTimeToPersist() || forcedBackup)
1648 { 2205 {
2206 if (m_rootPart.PhysActor != null &&
2207 (!m_rootPart.PhysActor.IsPhysical))
2208 {
2209 // Possible ghost prim
2210 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
2211 {
2212 foreach (SceneObjectPart part in m_parts.GetArray())
2213 {
2214 // Re-set physics actor positions and
2215 // orientations
2216 part.GroupPosition = m_rootPart.GroupPosition;
2217 }
2218 }
2219 }
1649// m_log.DebugFormat( 2220// m_log.DebugFormat(
1650// "[SCENE]: Storing {0}, {1} in {2}", 2221// "[SCENE]: Storing {0}, {1} in {2}",
1651// Name, UUID, m_scene.RegionInfo.RegionName); 2222// Name, UUID, m_scene.RegionInfo.RegionName);
1652 2223
2224 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
2225 {
2226 RootPart.Shape.LastAttachPoint = RootPart.Shape.State;
2227 RootPart.Shape.State = 0;
2228 ScheduleGroupForFullUpdate();
2229 }
2230
1653 SceneObjectGroup backup_group = Copy(false); 2231 SceneObjectGroup backup_group = Copy(false);
1654 backup_group.RootPart.Velocity = RootPart.Velocity; 2232 backup_group.RootPart.Velocity = RootPart.Velocity;
1655 backup_group.RootPart.Acceleration = RootPart.Acceleration; 2233 backup_group.RootPart.Acceleration = RootPart.Acceleration;
@@ -1659,13 +2237,22 @@ namespace OpenSim.Region.Framework.Scenes
1659 GroupContainsForeignPrims = false; 2237 GroupContainsForeignPrims = false;
1660 2238
1661 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); 2239 m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this);
2240
1662 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); 2241 datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID);
1663 2242
1664 backup_group.ForEachPart(delegate(SceneObjectPart part) 2243 backup_group.ForEachPart(delegate(SceneObjectPart part)
1665 { 2244 {
1666 part.Inventory.ProcessInventoryBackup(datastore); 2245 part.Inventory.ProcessInventoryBackup(datastore);
2246
2247 // take the change to delete things
2248 if(part.KeyframeMotion != null)
2249 {
2250 part.KeyframeMotion.Delete();
2251 part.KeyframeMotion = null;
2252 }
1667 }); 2253 });
1668 2254
2255
1669 backup_group = null; 2256 backup_group = null;
1670 } 2257 }
1671// else 2258// else
@@ -1715,26 +2302,34 @@ namespace OpenSim.Region.Framework.Scenes
1715 /// <returns></returns> 2302 /// <returns></returns>
1716 public SceneObjectGroup Copy(bool userExposed) 2303 public SceneObjectGroup Copy(bool userExposed)
1717 { 2304 {
1718 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up 2305 m_dupeInProgress = true;
1719 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
1720 // but not between regions on different simulators). Really, all copying should be done explicitly.
1721 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 2306 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
2307 dupe.m_isBackedUp = false;
2308 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1722 2309
2310 // a copy isnt backedup
1723 dupe.Backup = false; 2311 dupe.Backup = false;
1724 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 2312 dupe.m_isBackedUp = false;
2313
2314 // a copy is not in transit hopefully
2315 dupe.inTransit = false;
2316
2317 // new group as no sitting avatars
1725 dupe.m_sittingAvatars = new List<ScenePresence>(); 2318 dupe.m_sittingAvatars = new List<ScenePresence>();
2319
1726 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 2320 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1727 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 2321 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
2322
1728 2323
1729 if (userExposed) 2324 if (userExposed)
1730 dupe.m_rootPart.TrimPermissions(); 2325 dupe.m_rootPart.TrimPermissions();
1731 2326
1732 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 2327 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1733 2328
1734 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 2329 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1735 { 2330 {
1736 return p1.LinkNum.CompareTo(p2.LinkNum); 2331 return p1.LinkNum.CompareTo(p2.LinkNum);
1737 } 2332 }
1738 ); 2333 );
1739 2334
1740 foreach (SceneObjectPart part in partList) 2335 foreach (SceneObjectPart part in partList)
@@ -1744,43 +2339,56 @@ namespace OpenSim.Region.Framework.Scenes
1744 { 2339 {
1745 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2340 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1746 newPart.LinkNum = part.LinkNum; 2341 newPart.LinkNum = part.LinkNum;
1747 } 2342// if (userExposed)
2343 newPart.ParentID = dupe.m_rootPart.LocalId;
2344 }
1748 else 2345 else
1749 { 2346 {
1750 newPart = dupe.m_rootPart; 2347 newPart = dupe.m_rootPart;
1751 } 2348 }
2349/*
2350 bool isphys = ((newPart.Flags & PrimFlags.Physics) != 0);
2351 bool isphan = ((newPart.Flags & PrimFlags.Phantom) != 0);
1752 2352
1753 // Need to duplicate the physics actor as well 2353 // Need to duplicate the physics actor as well
1754 PhysicsActor originalPartPa = part.PhysActor; 2354 if (userExposed && (isphys || !isphan || newPart.VolumeDetectActive))
1755 if (originalPartPa != null && userExposed)
1756 { 2355 {
1757 PrimitiveBaseShape pbs = newPart.Shape; 2356 PrimitiveBaseShape pbs = newPart.Shape;
1758
1759 newPart.PhysActor 2357 newPart.PhysActor
1760 = m_scene.PhysicsScene.AddPrimShape( 2358 = m_scene.PhysicsScene.AddPrimShape(
1761 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 2359 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1762 pbs, 2360 pbs,
1763 newPart.AbsolutePosition, 2361 newPart.AbsolutePosition,
1764 newPart.Scale, 2362 newPart.Scale,
1765 newPart.RotationOffset, 2363 newPart.GetWorldRotation(),
1766 originalPartPa.IsPhysical, 2364 isphys,
2365 isphan,
1767 newPart.LocalId); 2366 newPart.LocalId);
1768 2367
1769 newPart.DoPhysicsPropertyUpdate(originalPartPa.IsPhysical, true); 2368 newPart.DoPhysicsPropertyUpdate(isphys, true);
1770 } 2369 */
2370 if (userExposed)
2371 newPart.ApplyPhysics((uint)newPart.Flags,newPart.VolumeDetectActive,true);
2372// }
2373 // copy keyframemotion
1771 if (part.KeyframeMotion != null) 2374 if (part.KeyframeMotion != null)
1772 newPart.KeyframeMotion = part.KeyframeMotion.Copy(dupe); 2375 newPart.KeyframeMotion = part.KeyframeMotion.Copy(dupe);
1773 } 2376 }
1774 2377
1775 if (userExposed) 2378 if (userExposed)
1776 { 2379 {
1777 dupe.UpdateParentIDs(); 2380// done above dupe.UpdateParentIDs();
2381
2382 if (dupe.m_rootPart.PhysActor != null)
2383 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
2384
1778 dupe.HasGroupChanged = true; 2385 dupe.HasGroupChanged = true;
1779 dupe.AttachToBackup(); 2386 dupe.AttachToBackup();
1780 2387
1781 ScheduleGroupForFullUpdate(); 2388 ScheduleGroupForFullUpdate();
1782 } 2389 }
1783 2390
2391 m_dupeInProgress = false;
1784 return dupe; 2392 return dupe;
1785 } 2393 }
1786 2394
@@ -1792,7 +2400,13 @@ namespace OpenSim.Region.Framework.Scenes
1792 /// <param name="cGroupID"></param> 2400 /// <param name="cGroupID"></param>
1793 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2401 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1794 { 2402 {
1795 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2403 SceneObjectPart newpart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed);
2404// SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2405// newpart.LocalId = m_scene.AllocateLocalId();
2406
2407 SetRootPart(newpart);
2408 if (userExposed)
2409 RootPart.Velocity = Vector3.Zero; // In case source is moving
1796 } 2410 }
1797 2411
1798 public void ScriptSetPhysicsStatus(bool usePhysics) 2412 public void ScriptSetPhysicsStatus(bool usePhysics)
@@ -1850,13 +2464,14 @@ namespace OpenSim.Region.Framework.Scenes
1850 2464
1851 if (pa != null) 2465 if (pa != null)
1852 { 2466 {
1853 pa.AddForce(impulse, true); 2467 // false to be applied as a impulse
2468 pa.AddForce(impulse, false);
1854 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2469 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1855 } 2470 }
1856 } 2471 }
1857 } 2472 }
1858 2473
1859 public void applyAngularImpulse(Vector3 impulse) 2474 public void ApplyAngularImpulse(Vector3 impulse)
1860 { 2475 {
1861 PhysicsActor pa = RootPart.PhysActor; 2476 PhysicsActor pa = RootPart.PhysActor;
1862 2477
@@ -1864,21 +2479,8 @@ namespace OpenSim.Region.Framework.Scenes
1864 { 2479 {
1865 if (!IsAttachment) 2480 if (!IsAttachment)
1866 { 2481 {
1867 pa.AddAngularForce(impulse, true); 2482 // false to be applied as a impulse
1868 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2483 pa.AddAngularForce(impulse, false);
1869 }
1870 }
1871 }
1872
1873 public void setAngularImpulse(Vector3 impulse)
1874 {
1875 PhysicsActor pa = RootPart.PhysActor;
1876
1877 if (pa != null)
1878 {
1879 if (!IsAttachment)
1880 {
1881 pa.Torque = impulse;
1882 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2484 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1883 } 2485 }
1884 } 2486 }
@@ -1886,20 +2488,10 @@ namespace OpenSim.Region.Framework.Scenes
1886 2488
1887 public Vector3 GetTorque() 2489 public Vector3 GetTorque()
1888 { 2490 {
1889 PhysicsActor pa = RootPart.PhysActor; 2491 return RootPart.Torque;
1890
1891 if (pa != null)
1892 {
1893 if (!IsAttachment)
1894 {
1895 Vector3 torque = pa.Torque;
1896 return torque;
1897 }
1898 }
1899
1900 return Vector3.Zero;
1901 } 2492 }
1902 2493
2494 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1903 public void MoveToTarget(Vector3 target, float tau) 2495 public void MoveToTarget(Vector3 target, float tau)
1904 { 2496 {
1905 if (IsAttachment) 2497 if (IsAttachment)
@@ -1929,21 +2521,61 @@ namespace OpenSim.Region.Framework.Scenes
1929 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); 2521 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1930 2522
1931 if (avatar != null) 2523 if (avatar != null)
2524 {
1932 avatar.ResetMoveToTarget(); 2525 avatar.ResetMoveToTarget();
2526 }
1933 } 2527 }
1934 else 2528 else
1935 { 2529 {
1936 PhysicsActor pa = RootPart.PhysActor; 2530 PhysicsActor pa = RootPart.PhysActor;
1937 2531
1938 if (pa != null && pa.PIDActive) 2532 if (pa != null)
1939 {
1940 pa.PIDActive = false; 2533 pa.PIDActive = false;
1941 2534
1942 ScheduleGroupForTerseUpdate(); 2535 RootPart.ScheduleTerseUpdate(); // send a stop information
2536 }
2537 }
2538
2539 public void rotLookAt(Quaternion target, float strength, float damping)
2540 {
2541 SceneObjectPart rootpart = m_rootPart;
2542 if (rootpart != null)
2543 {
2544 if (IsAttachment)
2545 {
2546 /*
2547 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2548 if (avatar != null)
2549 {
2550 Rotate the Av?
2551 } */
2552 }
2553 else
2554 {
2555 if (rootpart.PhysActor != null)
2556 { // APID must be implemented in your physics system for this to function.
2557 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2558 rootpart.PhysActor.APIDStrength = strength;
2559 rootpart.PhysActor.APIDDamping = damping;
2560 rootpart.PhysActor.APIDActive = true;
2561 }
1943 } 2562 }
1944 } 2563 }
1945 } 2564 }
2565
2566 public void stopLookAt()
2567 {
2568 SceneObjectPart rootpart = m_rootPart;
2569 if (rootpart != null)
2570 {
2571 if (rootpart.PhysActor != null)
2572 { // APID must be implemented in your physics system for this to function.
2573 rootpart.PhysActor.APIDActive = false;
2574 }
2575 }
1946 2576
2577 }
2578
1947 /// <summary> 2579 /// <summary>
1948 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2580 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1949 /// </summary> 2581 /// </summary>
@@ -1952,7 +2584,15 @@ namespace OpenSim.Region.Framework.Scenes
1952 /// <param name="tau">Number of seconds over which to reach target</param> 2584 /// <param name="tau">Number of seconds over which to reach target</param>
1953 public void SetHoverHeight(float height, PIDHoverType hoverType, float tau) 2585 public void SetHoverHeight(float height, PIDHoverType hoverType, float tau)
1954 { 2586 {
1955 PhysicsActor pa = RootPart.PhysActor; 2587 PhysicsActor pa = null;
2588 if(IsAttachment)
2589 {
2590 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
2591 if (avatar != null)
2592 pa = avatar.PhysicsActor;
2593 }
2594 else
2595 pa = RootPart.PhysActor;
1956 2596
1957 if (pa != null) 2597 if (pa != null)
1958 { 2598 {
@@ -1960,7 +2600,7 @@ namespace OpenSim.Region.Framework.Scenes
1960 { 2600 {
1961 pa.PIDHoverHeight = height; 2601 pa.PIDHoverHeight = height;
1962 pa.PIDHoverType = hoverType; 2602 pa.PIDHoverType = hoverType;
1963 pa.PIDTau = tau; 2603 pa.PIDHoverTau = tau;
1964 pa.PIDHoverActive = true; 2604 pa.PIDHoverActive = true;
1965 } 2605 }
1966 else 2606 else
@@ -2001,6 +2641,9 @@ namespace OpenSim.Region.Framework.Scenes
2001 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2641 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
2002 { 2642 {
2003 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2643 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2644// SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2645// newPart.LocalId = m_scene.AllocateLocalId();
2646
2004 AddPart(newPart); 2647 AddPart(newPart);
2005 2648
2006 SetPartAsNonRoot(newPart); 2649 SetPartAsNonRoot(newPart);
@@ -2050,6 +2693,7 @@ namespace OpenSim.Region.Framework.Scenes
2050 2693
2051 #endregion 2694 #endregion
2052 2695
2696
2053 public override void Update() 2697 public override void Update()
2054 { 2698 {
2055 // Check that the group was not deleted before the scheduled update 2699 // Check that the group was not deleted before the scheduled update
@@ -2057,7 +2701,7 @@ namespace OpenSim.Region.Framework.Scenes
2057 // an object has been deleted from a scene before update was processed. 2701 // an object has been deleted from a scene before update was processed.
2058 // A more fundamental overhaul of the update mechanism is required to eliminate all 2702 // A more fundamental overhaul of the update mechanism is required to eliminate all
2059 // the race conditions. 2703 // the race conditions.
2060 if (IsDeleted) 2704 if (IsDeleted || inTransit)
2061 return; 2705 return;
2062 2706
2063 // Even temporary objects take part in physics (e.g. temp-on-rez bullets) 2707 // Even temporary objects take part in physics (e.g. temp-on-rez bullets)
@@ -2068,18 +2712,17 @@ namespace OpenSim.Region.Framework.Scenes
2068 // check to see if the physical position or rotation warrant an update. 2712 // check to see if the physical position or rotation warrant an update.
2069 if (m_rootPart.UpdateFlag == UpdateRequired.NONE) 2713 if (m_rootPart.UpdateFlag == UpdateRequired.NONE)
2070 { 2714 {
2071 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 2715 // rootpart SendScheduledUpdates will check if a update is needed
2072 2716 m_rootPart.UpdateFlag = UpdateRequired.TERSE;
2073 if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f)) 2717 }
2074 {
2075 m_rootPart.UpdateFlag = UpdateRequired.TERSE;
2076 lastPhysGroupPos = AbsolutePosition;
2077 }
2078 2718
2079 if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f)) 2719 if (IsAttachment)
2720 {
2721 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2722 if (sp != null)
2080 { 2723 {
2081 m_rootPart.UpdateFlag = UpdateRequired.TERSE; 2724 sp.SendAttachmentScheduleUpdate(this);
2082 lastPhysGroupRot = GroupRotation; 2725 return;
2083 } 2726 }
2084 } 2727 }
2085 2728
@@ -2139,20 +2782,30 @@ namespace OpenSim.Region.Framework.Scenes
2139 /// Immediately send a full update for this scene object. 2782 /// Immediately send a full update for this scene object.
2140 /// </summary> 2783 /// </summary>
2141 public void SendGroupFullUpdate() 2784 public void SendGroupFullUpdate()
2142 { 2785 {
2143 if (IsDeleted) 2786 if (IsDeleted)
2144 return; 2787 return;
2145 2788
2146// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2789// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
2147 2790
2148 RootPart.SendFullUpdateToAllClients(); 2791 if (IsAttachment)
2792 {
2793 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2794 if (sp != null)
2795 {
2796 sp.SendAttachmentUpdate(this,UpdateRequired.FULL);
2797 return;
2798 }
2799 }
2800
2801 RootPart.SendFullUpdateToAllClientsInternal();
2149 2802
2150 SceneObjectPart[] parts = m_parts.GetArray(); 2803 SceneObjectPart[] parts = m_parts.GetArray();
2151 for (int i = 0; i < parts.Length; i++) 2804 for (int i = 0; i < parts.Length; i++)
2152 { 2805 {
2153 SceneObjectPart part = parts[i]; 2806 SceneObjectPart part = parts[i];
2154 if (part != RootPart) 2807 if (part != RootPart)
2155 part.SendFullUpdateToAllClients(); 2808 part.SendFullUpdateToAllClientsInternal();
2156 } 2809 }
2157 } 2810 }
2158 2811
@@ -2164,7 +2817,7 @@ namespace OpenSim.Region.Framework.Scenes
2164 /// </summary> 2817 /// </summary>
2165 public void SendGroupRootTerseUpdate() 2818 public void SendGroupRootTerseUpdate()
2166 { 2819 {
2167 if (IsDeleted) 2820 if (IsDeleted || inTransit)
2168 return; 2821 return;
2169 2822
2170 RootPart.SendTerseUpdateToAllClients(); 2823 RootPart.SendTerseUpdateToAllClients();
@@ -2183,12 +2836,22 @@ namespace OpenSim.Region.Framework.Scenes
2183 /// </summary> 2836 /// </summary>
2184 public void SendGroupTerseUpdate() 2837 public void SendGroupTerseUpdate()
2185 { 2838 {
2186 if (IsDeleted) 2839 if (IsDeleted || inTransit)
2187 return; 2840 return;
2188 2841
2842 if (IsAttachment)
2843 {
2844 ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar);
2845 if (sp != null)
2846 {
2847 sp.SendAttachmentUpdate(this, UpdateRequired.TERSE);
2848 return;
2849 }
2850 }
2851
2189 SceneObjectPart[] parts = m_parts.GetArray(); 2852 SceneObjectPart[] parts = m_parts.GetArray();
2190 for (int i = 0; i < parts.Length; i++) 2853 for (int i = 0; i < parts.Length; i++)
2191 parts[i].SendTerseUpdateToAllClients(); 2854 parts[i].SendTerseUpdateToAllClientsInternal();
2192 } 2855 }
2193 2856
2194 /// <summary> 2857 /// <summary>
@@ -2296,9 +2959,41 @@ namespace OpenSim.Region.Framework.Scenes
2296 return; 2959 return;
2297 } 2960 }
2298 2961
2962 // physical prims count limit
2963 // not very eficient :(
2964
2965 if (UsesPhysics && m_scene.m_linksetPhysCapacity > 0 && (PrimCount + objectGroup.PrimCount) >
2966 m_scene.m_linksetPhysCapacity)
2967 {
2968 int cntr = 0;
2969 foreach (SceneObjectPart part in Parts)
2970 {
2971 if (part.PhysicsShapeType != (byte)PhysicsShapeType.None)
2972 cntr++;
2973 }
2974 foreach (SceneObjectPart part in objectGroup.Parts)
2975 {
2976 if (part.PhysicsShapeType != (byte)PhysicsShapeType.None)
2977 cntr++;
2978 }
2979
2980 if (cntr > m_scene.m_linksetPhysCapacity)
2981 {
2982 // cancel physics
2983 RootPart.Flags &= ~PrimFlags.Physics;
2984 ApplyPhysics();
2985 }
2986 }
2987
2988
2299 // 'linkPart' == the root of the group being linked into this group 2989 // 'linkPart' == the root of the group being linked into this group
2300 SceneObjectPart linkPart = objectGroup.m_rootPart; 2990 SceneObjectPart linkPart = objectGroup.m_rootPart;
2301 2991
2992 if (m_rootPart.PhysActor != null)
2993 m_rootPart.PhysActor.Building = true;
2994 if (linkPart.PhysActor != null)
2995 linkPart.PhysActor.Building = true;
2996
2302 // physics flags from group to be applied to linked parts 2997 // physics flags from group to be applied to linked parts
2303 bool grpusephys = UsesPhysics; 2998 bool grpusephys = UsesPhysics;
2304 bool grptemporary = IsTemporary; 2999 bool grptemporary = IsTemporary;
@@ -2315,22 +3010,24 @@ namespace OpenSim.Region.Framework.Scenes
2315 // First move the new group's root SOP's position to be relative to ours 3010 // First move the new group's root SOP's position to be relative to ours
2316 // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not, 3011 // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not,
2317 // this code can be reordered to have a more logical flow.) 3012 // this code can be reordered to have a more logical flow.)
2318 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; 3013 linkPart.setOffsetPosition(linkPart.GroupPosition - AbsolutePosition);
2319 // Assign the new parent to the root of the old group 3014 // Assign the new parent to the root of the old group
2320 linkPart.ParentID = m_rootPart.LocalId; 3015 linkPart.ParentID = m_rootPart.LocalId;
2321 // Now that it's a child, it's group position is our root position 3016 // Now that it's a child, it's group position is our root position
2322 linkPart.GroupPosition = AbsolutePosition; 3017 linkPart.setGroupPosition(AbsolutePosition);
2323 3018
2324 Vector3 axPos = linkPart.OffsetPosition;
2325 // Rotate the linking root SOP's position to be relative to the new root prim 3019 // Rotate the linking root SOP's position to be relative to the new root prim
2326 Quaternion parentRot = m_rootPart.RotationOffset; 3020 Quaternion parentRot = m_rootPart.RotationOffset;
2327 axPos *= Quaternion.Inverse(parentRot);
2328 linkPart.OffsetPosition = axPos;
2329 3021
2330 // Make the linking root SOP's rotation relative to the new root prim 3022 // Make the linking root SOP's rotation relative to the new root prim
2331 Quaternion oldRot = linkPart.RotationOffset; 3023 Quaternion oldRot = linkPart.RotationOffset;
2332 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 3024 Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot;
2333 linkPart.RotationOffset = newRot; 3025 linkPart.setRotationOffset(newRot);
3026
3027 Vector3 axPos = linkPart.OffsetPosition;
3028 axPos *= Quaternion.Conjugate(parentRot);
3029 linkPart.OffsetPosition = axPos;
3030
2334 3031
2335 // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. 3032 // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset.
2336 // Now that we know this SOG has at least two SOPs in it, the new root 3033 // Now that we know this SOG has at least two SOPs in it, the new root
@@ -2360,10 +3057,12 @@ namespace OpenSim.Region.Framework.Scenes
2360 m_parts.Add(linkPart.UUID, linkPart); 3057 m_parts.Add(linkPart.UUID, linkPart);
2361 3058
2362 linkPart.SetParent(this); 3059 linkPart.SetParent(this);
3060 m_scene.updateScenePartGroup(linkPart, this);
3061
2363 linkPart.CreateSelected = true; 3062 linkPart.CreateSelected = true;
2364 3063
2365 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now 3064 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
2366 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive); 3065 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true);
2367 3066
2368 // If the added SOP is physical, also tell the physics engine about the link relationship. 3067 // If the added SOP is physical, also tell the physics engine about the link relationship.
2369 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 3068 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
@@ -2373,6 +3072,7 @@ namespace OpenSim.Region.Framework.Scenes
2373 } 3072 }
2374 3073
2375 linkPart.LinkNum = linkNum++; 3074 linkPart.LinkNum = linkNum++;
3075 linkPart.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2376 3076
2377 // Get a list of the SOP's in the old group in order of their linknum's. 3077 // Get a list of the SOP's in the old group in order of their linknum's.
2378 SceneObjectPart[] ogParts = objectGroup.Parts; 3078 SceneObjectPart[] ogParts = objectGroup.Parts;
@@ -2391,7 +3091,7 @@ namespace OpenSim.Region.Framework.Scenes
2391 3091
2392 // Update the physics flags for the newly added SOP 3092 // Update the physics flags for the newly added SOP
2393 // (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??) 3093 // (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??)
2394 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive); 3094 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true);
2395 3095
2396 // If the added SOP is physical, also tell the physics engine about the link relationship. 3096 // If the added SOP is physical, also tell the physics engine about the link relationship.
2397 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 3097 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
@@ -2409,7 +3109,7 @@ namespace OpenSim.Region.Framework.Scenes
2409 objectGroup.IsDeleted = true; 3109 objectGroup.IsDeleted = true;
2410 3110
2411 objectGroup.m_parts.Clear(); 3111 objectGroup.m_parts.Clear();
2412 3112
2413 // Can't do this yet since backup still makes use of the root part without any synchronization 3113 // Can't do this yet since backup still makes use of the root part without any synchronization
2414// objectGroup.m_rootPart = null; 3114// objectGroup.m_rootPart = null;
2415 3115
@@ -2425,6 +3125,9 @@ namespace OpenSim.Region.Framework.Scenes
2425 // unmoved prims! 3125 // unmoved prims!
2426 ResetChildPrimPhysicsPositions(); 3126 ResetChildPrimPhysicsPositions();
2427 3127
3128 if (m_rootPart.PhysActor != null)
3129 m_rootPart.PhysActor.Building = false;
3130
2428 //HasGroupChanged = true; 3131 //HasGroupChanged = true;
2429 //ScheduleGroupForFullUpdate(); 3132 //ScheduleGroupForFullUpdate();
2430 } 3133 }
@@ -2492,7 +3195,10 @@ namespace OpenSim.Region.Framework.Scenes
2492// m_log.DebugFormat( 3195// m_log.DebugFormat(
2493// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", 3196// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2494// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); 3197// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2495 3198
3199 if (m_rootPart.PhysActor != null)
3200 m_rootPart.PhysActor.Building = true;
3201
2496 linkPart.ClearUndoState(); 3202 linkPart.ClearUndoState();
2497 3203
2498 Vector3 worldPos = linkPart.GetWorldPosition(); 3204 Vector3 worldPos = linkPart.GetWorldPosition();
@@ -2547,30 +3253,31 @@ namespace OpenSim.Region.Framework.Scenes
2547 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; 3253 linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition;
2548 linkPart.OffsetPosition = new Vector3(0, 0, 0); 3254 linkPart.OffsetPosition = new Vector3(0, 0, 0);
2549 */ 3255 */
2550 linkPart.GroupPosition = worldPos; 3256 linkPart.setGroupPosition(worldPos);
2551 linkPart.OffsetPosition = Vector3.Zero; 3257 linkPart.setOffsetPosition(Vector3.Zero);
2552 linkPart.RotationOffset = worldRot; 3258 linkPart.setRotationOffset(worldRot);
2553 3259
2554 // Create a new SOG to go around this unlinked and unattached SOP 3260 // Create a new SOG to go around this unlinked and unattached SOP
2555 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); 3261 SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart);
2556 3262
2557 m_scene.AddNewSceneObject(objectGroup, true); 3263 m_scene.AddNewSceneObject(objectGroup, true);
2558 3264
2559 if (sendEvents)
2560 linkPart.TriggerScriptChangedEvent(Changed.LINK);
2561
2562 linkPart.Rezzed = RootPart.Rezzed; 3265 linkPart.Rezzed = RootPart.Rezzed;
2563 3266
2564 // We must persist the delinked group to the database immediately, for safety. The problem 3267 // When we delete a group, we currently have to force persist to the database if the object id has changed
2565 // is that although in memory the new group has a new SceneGroupID, in the database it 3268 // (since delete works by deleting all rows which have a given object id)
2566 // still has the parent group's SceneGroupID (until the next backup). This means that if the 3269
2567 // parent group is deleted then the delinked group will also be deleted from the database. 3270 // this is as it seems to be in sl now
2568 // This problem will disappear if the region remains alive long enough for another backup, 3271 if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none)
2569 // since at that time the delinked group's new SceneGroupID will be written to the database. 3272 linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now
2570 // But if the region crashes before that then the prims will be permanently gone, and this must 3273
2571 // not happen. (We can't use a just-in-time trick like GroupContainsForeignPrims in this case 3274 if (m_rootPart.PhysActor != null)
2572 // because the delinked group doesn't know when the source group is deleted.) 3275 m_rootPart.PhysActor.Building = false;
2573 m_scene.ForceSceneObjectBackup(objectGroup); 3276
3277 objectGroup.HasGroupChangedDueToDelink = true;
3278
3279 if (sendEvents)
3280 linkPart.TriggerScriptChangedEvent(Changed.LINK);
2574 3281
2575 return objectGroup; 3282 return objectGroup;
2576 } 3283 }
@@ -2581,7 +3288,9 @@ namespace OpenSim.Region.Framework.Scenes
2581 /// <param name="objectGroup"></param> 3288 /// <param name="objectGroup"></param>
2582 public virtual void DetachFromBackup() 3289 public virtual void DetachFromBackup()
2583 { 3290 {
2584 if (Backup && Scene != null) 3291 if (m_scene != null)
3292 m_scene.SceneGraph.FireDetachFromBackup(this);
3293 if (m_isBackedUp && Scene != null)
2585 m_scene.EventManager.OnBackup -= ProcessBackup; 3294 m_scene.EventManager.OnBackup -= ProcessBackup;
2586 3295
2587 Backup = false; 3296 Backup = false;
@@ -2597,14 +3306,14 @@ namespace OpenSim.Region.Framework.Scenes
2597 Quaternion parentRot = oldGroupRotation; 3306 Quaternion parentRot = oldGroupRotation;
2598 Quaternion oldRot = part.RotationOffset; 3307 Quaternion oldRot = part.RotationOffset;
2599 3308
2600 // Move our position to not be relative to the old parent 3309 // Move our position in world
2601 Vector3 axPos = part.OffsetPosition; 3310 Vector3 axPos = part.OffsetPosition;
2602 axPos *= parentRot; 3311 axPos *= parentRot;
2603 part.OffsetPosition = axPos; 3312 Vector3 newPos = oldGroupPosition + axPos;
2604 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 3313 part.setGroupPosition(newPos);
2605 part.OffsetPosition = Vector3.Zero; 3314 part.setOffsetPosition(Vector3.Zero);
2606 3315
2607 // Compution our rotation to be not relative to the old parent 3316 // Compution our rotation in world
2608 Quaternion worldRot = parentRot * oldRot; 3317 Quaternion worldRot = parentRot * oldRot;
2609 part.RotationOffset = worldRot; 3318 part.RotationOffset = worldRot;
2610 3319
@@ -2615,29 +3324,32 @@ namespace OpenSim.Region.Framework.Scenes
2615 3324
2616 part.LinkNum = linkNum; 3325 part.LinkNum = linkNum;
2617 3326
3327 m_scene.updateScenePartGroup(part, this);
3328
2618 // Compute the new position of this SOP relative to the group position 3329 // Compute the new position of this SOP relative to the group position
2619 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 3330 part.setOffsetPosition(newPos - AbsolutePosition);
2620 3331
2621 // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times. 3332 // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times.
2622 // It would have the affect of setting the physics engine position multiple 3333 // It would have the affect of setting the physics engine position multiple
2623 // times. In theory, that is not necessary but I don't have a good linkset 3334 // times. In theory, that is not necessary but I don't have a good linkset
2624 // test to know that cleaning up this code wouldn't break things.) 3335 // test to know that cleaning up this code wouldn't break things.)
2625 3336
2626 // Rotate the relative position by the rotation of the group
2627 Quaternion rootRotation = m_rootPart.RotationOffset;
2628 Vector3 pos = part.OffsetPosition;
2629 pos *= Quaternion.Inverse(rootRotation);
2630 part.OffsetPosition = pos;
2631
2632 // Compute the SOP's rotation relative to the rotation of the group. 3337 // Compute the SOP's rotation relative to the rotation of the group.
2633 parentRot = m_rootPart.RotationOffset; 3338 parentRot = m_rootPart.RotationOffset;
3339
2634 oldRot = part.RotationOffset; 3340 oldRot = part.RotationOffset;
2635 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 3341 Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot;
2636 part.RotationOffset = newRot; 3342 part.setRotationOffset(newRot);
3343
3344 Vector3 pos = part.OffsetPosition;
3345 pos *= Quaternion.Conjugate(parentRot);
3346
3347 part.OffsetPosition = pos; // update position and orientation on physics also
2637 3348
2638 // Since this SOP's state has changed, push those changes into the physics engine 3349 // Since this SOP's state has changed, push those changes into the physics engine
2639 // and the simulator. 3350 // and the simulator.
2640 part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3351 // done on caller
3352// part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2641 } 3353 }
2642 3354
2643 /// <summary> 3355 /// <summary>
@@ -2665,10 +3377,14 @@ namespace OpenSim.Region.Framework.Scenes
2665 { 3377 {
2666 if (!BlockGrabOverride && !part.BlockGrab) 3378 if (!BlockGrabOverride && !part.BlockGrab)
2667 { 3379 {
2668 Vector3 llmoveforce = pos - AbsolutePosition; 3380/* Vector3 llmoveforce = pos - AbsolutePosition;
2669 Vector3 grabforce = llmoveforce; 3381 Vector3 grabforce = llmoveforce;
2670 grabforce = (grabforce / 10) * pa.Mass; 3382 grabforce = (grabforce / 10) * pa.Mass;
2671 pa.AddForce(grabforce, true); 3383 */
3384 // empirically convert distance diference to a impulse
3385 Vector3 grabforce = pos - AbsolutePosition;
3386 grabforce = grabforce * (pa.Mass/ 10.0f);
3387 pa.AddForce(grabforce, false);
2672 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 3388 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
2673 } 3389 }
2674 } 3390 }
@@ -2882,6 +3598,8 @@ namespace OpenSim.Region.Framework.Scenes
2882 /// <param name="SetVolumeDetect"></param> 3598 /// <param name="SetVolumeDetect"></param>
2883 public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect) 3599 public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect)
2884 { 3600 {
3601 HasGroupChanged = true;
3602
2885 SceneObjectPart selectionPart = GetPart(localID); 3603 SceneObjectPart selectionPart = GetPart(localID);
2886 3604
2887 if (Scene != null) 3605 if (Scene != null)
@@ -2907,8 +3625,12 @@ namespace OpenSim.Region.Framework.Scenes
2907 { 3625 {
2908 SceneObjectPart[] parts = m_parts.GetArray(); 3626 SceneObjectPart[] parts = m_parts.GetArray();
2909 3627
2910 if (Scene != null) 3628 if (Scene != null && UsePhysics)
2911 { 3629 {
3630 int maxprims = m_scene.m_linksetPhysCapacity;
3631 bool checkShape = (maxprims > 0 &&
3632 parts.Length > maxprims);
3633
2912 for (int i = 0; i < parts.Length; i++) 3634 for (int i = 0; i < parts.Length; i++)
2913 { 3635 {
2914 SceneObjectPart part = parts[i]; 3636 SceneObjectPart part = parts[i];
@@ -2919,11 +3641,34 @@ namespace OpenSim.Region.Framework.Scenes
2919 UsePhysics = false; // Reset physics 3641 UsePhysics = false; // Reset physics
2920 break; 3642 break;
2921 } 3643 }
3644
3645 if (checkShape && part.PhysicsShapeType != (byte)PhysicsShapeType.None)
3646 {
3647 if (--maxprims < 0)
3648 {
3649 UsePhysics = false;
3650 break;
3651 }
3652 }
2922 } 3653 }
2923 } 3654 }
2924 3655
2925 for (int i = 0; i < parts.Length; i++) 3656 if (parts.Length > 1)
2926 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 3657 {
3658 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3659
3660 for (int i = 0; i < parts.Length; i++)
3661 {
3662
3663 if (parts[i].UUID != m_rootPart.UUID)
3664 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3665 }
3666
3667 if (m_rootPart.PhysActor != null)
3668 m_rootPart.PhysActor.Building = false;
3669 }
3670 else
3671 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
2927 } 3672 }
2928 } 3673 }
2929 3674
@@ -2936,6 +3681,17 @@ namespace OpenSim.Region.Framework.Scenes
2936 } 3681 }
2937 } 3682 }
2938 3683
3684
3685
3686 /// <summary>
3687 /// Gets the number of parts
3688 /// </summary>
3689 /// <returns></returns>
3690 public int GetPartCount()
3691 {
3692 return Parts.Count();
3693 }
3694
2939 /// <summary> 3695 /// <summary>
2940 /// Update the texture entry for this part 3696 /// Update the texture entry for this part
2941 /// </summary> 3697 /// </summary>
@@ -2980,7 +3736,23 @@ namespace OpenSim.Region.Framework.Scenes
2980 { 3736 {
2981 RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF); 3737 RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
2982 3738
2983 AdjustChildPrimPermissions(Scene.Permissions.IsGod(AgentID)); 3739 bool god = Scene.Permissions.IsGod(AgentID);
3740
3741 if (field == 1 && god)
3742 {
3743 ForEachPart(part =>
3744 {
3745 part.BaseMask = RootPart.BaseMask;
3746 });
3747 }
3748
3749 AdjustChildPrimPermissions(false);
3750
3751 if (field == 1 && god) // Base mask was set. Update all child part inventories
3752 {
3753 foreach (SceneObjectPart part in Parts)
3754 part.Inventory.ApplyGodPermissions(RootPart.BaseMask);
3755 }
2984 3756
2985 HasGroupChanged = true; 3757 HasGroupChanged = true;
2986 3758
@@ -3025,163 +3797,101 @@ namespace OpenSim.Region.Framework.Scenes
3025// m_log.DebugFormat( 3797// m_log.DebugFormat(
3026// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 3798// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
3027 3799
3800 if (Scene == null)
3801 return;
3802
3028 PhysicsActor pa = m_rootPart.PhysActor; 3803 PhysicsActor pa = m_rootPart.PhysActor;
3029 3804
3030 RootPart.StoreUndoState(true); 3805 float minsize = Scene.m_minNonphys;
3806 float maxsize = Scene.m_maxNonphys;
3031 3807
3032 if (Scene != null) 3808 if (pa != null && pa.IsPhysical)
3033 { 3809 {
3034 scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); 3810 minsize = Scene.m_minPhys;
3035 scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y)); 3811 maxsize = Scene.m_maxPhys;
3036 scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z));
3037
3038 if (pa != null && pa.IsPhysical)
3039 {
3040 scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X));
3041 scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y));
3042 scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z));
3043 }
3044 } 3812 }
3045 3813
3814 scale.X = Util.Clamp(scale.X, minsize, maxsize);
3815 scale.Y = Util.Clamp(scale.Y, minsize, maxsize);
3816 scale.Z = Util.Clamp(scale.Z, minsize, maxsize);
3817
3818 // requested scaling factors
3046 float x = (scale.X / RootPart.Scale.X); 3819 float x = (scale.X / RootPart.Scale.X);
3047 float y = (scale.Y / RootPart.Scale.Y); 3820 float y = (scale.Y / RootPart.Scale.Y);
3048 float z = (scale.Z / RootPart.Scale.Z); 3821 float z = (scale.Z / RootPart.Scale.Z);
3049 3822
3050 SceneObjectPart[] parts = m_parts.GetArray(); 3823 SceneObjectPart[] parts = m_parts.GetArray();
3051 3824
3052 if (Scene != null & (x > 1.0f || y > 1.0f || z > 1.0f)) 3825 // fix scaling factors so parts don't violate dimensions
3826 for(int i = 0;i < parts.Length;i++)
3053 { 3827 {
3054 for (int i = 0; i < parts.Length; i++) 3828 SceneObjectPart obPart = parts[i];
3829 if(obPart.UUID != m_rootPart.UUID)
3055 { 3830 {
3056 SceneObjectPart obPart = parts[i]; 3831 Vector3 oldSize = new Vector3(obPart.Scale);
3057 if (obPart.UUID != m_rootPart.UUID)
3058 {
3059// obPart.IgnoreUndoUpdate = true;
3060 Vector3 oldSize = new Vector3(obPart.Scale);
3061
3062 float f = 1.0f;
3063 float a = 1.0f;
3064
3065 if (pa != null && pa.IsPhysical)
3066 {
3067 if (oldSize.X * x > Scene.m_maxPhys)
3068 {
3069 f = m_scene.m_maxPhys / oldSize.X;
3070 a = f / x;
3071 x *= a;
3072 y *= a;
3073 z *= a;
3074 }
3075 else if (oldSize.X * x < Scene.m_minPhys)
3076 {
3077 f = m_scene.m_minPhys / oldSize.X;
3078 a = f / x;
3079 x *= a;
3080 y *= a;
3081 z *= a;
3082 }
3083
3084 if (oldSize.Y * y > Scene.m_maxPhys)
3085 {
3086 f = m_scene.m_maxPhys / oldSize.Y;
3087 a = f / y;
3088 x *= a;
3089 y *= a;
3090 z *= a;
3091 }
3092 else if (oldSize.Y * y < Scene.m_minPhys)
3093 {
3094 f = m_scene.m_minPhys / oldSize.Y;
3095 a = f / y;
3096 x *= a;
3097 y *= a;
3098 z *= a;
3099 }
3100 3832
3101 if (oldSize.Z * z > Scene.m_maxPhys) 3833 float f = 1.0f;
3102 { 3834 float a = 1.0f;
3103 f = m_scene.m_maxPhys / oldSize.Z;
3104 a = f / z;
3105 x *= a;
3106 y *= a;
3107 z *= a;
3108 }
3109 else if (oldSize.Z * z < Scene.m_minPhys)
3110 {
3111 f = m_scene.m_minPhys / oldSize.Z;
3112 a = f / z;
3113 x *= a;
3114 y *= a;
3115 z *= a;
3116 }
3117 }
3118 else
3119 {
3120 if (oldSize.X * x > Scene.m_maxNonphys)
3121 {
3122 f = m_scene.m_maxNonphys / oldSize.X;
3123 a = f / x;
3124 x *= a;
3125 y *= a;
3126 z *= a;
3127 }
3128 else if (oldSize.X * x < Scene.m_minNonphys)
3129 {
3130 f = m_scene.m_minNonphys / oldSize.X;
3131 a = f / x;
3132 x *= a;
3133 y *= a;
3134 z *= a;
3135 }
3136 3835
3137 if (oldSize.Y * y > Scene.m_maxNonphys) 3836 if(oldSize.X * x > maxsize)
3138 { 3837 {
3139 f = m_scene.m_maxNonphys / oldSize.Y; 3838 f = maxsize / oldSize.X;
3140 a = f / y; 3839 a = f / x;
3141 x *= a; 3840 x *= a;
3142 y *= a; 3841 y *= a;
3143 z *= a; 3842 z *= a;
3144 } 3843 }
3145 else if (oldSize.Y * y < Scene.m_minNonphys) 3844 else if(oldSize.X * x < minsize)
3146 { 3845 {
3147 f = m_scene.m_minNonphys / oldSize.Y; 3846 f = minsize / oldSize.X;
3148 a = f / y; 3847 a = f / x;
3149 x *= a; 3848 x *= a;
3150 y *= a; 3849 y *= a;
3151 z *= a; 3850 z *= a;
3152 } 3851 }
3153 3852
3154 if (oldSize.Z * z > Scene.m_maxNonphys) 3853 if(oldSize.Y * y > maxsize)
3155 { 3854 {
3156 f = m_scene.m_maxNonphys / oldSize.Z; 3855 f = maxsize / oldSize.Y;
3157 a = f / z; 3856 a = f / y;
3158 x *= a; 3857 x *= a;
3159 y *= a; 3858 y *= a;
3160 z *= a; 3859 z *= a;
3161 } 3860 }
3162 else if (oldSize.Z * z < Scene.m_minNonphys) 3861 else if(oldSize.Y * y < minsize)
3163 { 3862 {
3164 f = m_scene.m_minNonphys / oldSize.Z; 3863 f = minsize / oldSize.Y;
3165 a = f / z; 3864 a = f / y;
3166 x *= a; 3865 x *= a;
3167 y *= a; 3866 y *= a;
3168 z *= a; 3867 z *= a;
3169 } 3868 }
3170 }
3171 3869
3172// obPart.IgnoreUndoUpdate = false; 3870 if(oldSize.Z * z > maxsize)
3871 {
3872 f = maxsize / oldSize.Z;
3873 a = f / z;
3874 x *= a;
3875 y *= a;
3876 z *= a;
3877 }
3878 else if(oldSize.Z * z < minsize)
3879 {
3880 f = minsize / oldSize.Z;
3881 a = f / z;
3882 x *= a;
3883 y *= a;
3884 z *= a;
3173 } 3885 }
3174 } 3886 }
3175 } 3887 }
3176 3888
3177 Vector3 prevScale = RootPart.Scale; 3889 Vector3 rootScale = RootPart.Scale;
3178 prevScale.X *= x; 3890 rootScale.X *= x;
3179 prevScale.Y *= y; 3891 rootScale.Y *= y;
3180 prevScale.Z *= z; 3892 rootScale.Z *= z;
3181 3893
3182// RootPart.IgnoreUndoUpdate = true; 3894 RootPart.Scale = rootScale;
3183 RootPart.Resize(prevScale);
3184// RootPart.IgnoreUndoUpdate = false;
3185 3895
3186 for (int i = 0; i < parts.Length; i++) 3896 for (int i = 0; i < parts.Length; i++)
3187 { 3897 {
@@ -3189,8 +3899,6 @@ namespace OpenSim.Region.Framework.Scenes
3189 3899
3190 if (obPart.UUID != m_rootPart.UUID) 3900 if (obPart.UUID != m_rootPart.UUID)
3191 { 3901 {
3192 obPart.IgnoreUndoUpdate = true;
3193
3194 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3902 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
3195 currentpos.X *= x; 3903 currentpos.X *= x;
3196 currentpos.Y *= y; 3904 currentpos.Y *= y;
@@ -3201,18 +3909,14 @@ namespace OpenSim.Region.Framework.Scenes
3201 newSize.Y *= y; 3909 newSize.Y *= y;
3202 newSize.Z *= z; 3910 newSize.Z *= z;
3203 3911
3204 obPart.Resize(newSize); 3912 obPart.Scale = newSize;
3205 obPart.UpdateOffSet(currentpos); 3913 obPart.UpdateOffSet(currentpos);
3206
3207 obPart.IgnoreUndoUpdate = false;
3208 } 3914 }
3209 3915
3210// obPart.IgnoreUndoUpdate = false; 3916 HasGroupChanged = true;
3211// obPart.StoreUndoState(); 3917 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3918 ScheduleGroupForTerseUpdate();
3212 } 3919 }
3213
3214// m_log.DebugFormat(
3215// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale);
3216 } 3920 }
3217 3921
3218 #endregion 3922 #endregion
@@ -3225,14 +3929,6 @@ namespace OpenSim.Region.Framework.Scenes
3225 /// <param name="pos"></param> 3929 /// <param name="pos"></param>
3226 public void UpdateGroupPosition(Vector3 pos) 3930 public void UpdateGroupPosition(Vector3 pos)
3227 { 3931 {
3228// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
3229
3230 RootPart.StoreUndoState(true);
3231
3232// SceneObjectPart[] parts = m_parts.GetArray();
3233// for (int i = 0; i < parts.Length; i++)
3234// parts[i].StoreUndoState();
3235
3236 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3932 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
3237 { 3933 {
3238 if (IsAttachment) 3934 if (IsAttachment)
@@ -3265,21 +3961,17 @@ namespace OpenSim.Region.Framework.Scenes
3265 /// </summary> 3961 /// </summary>
3266 /// <param name="pos"></param> 3962 /// <param name="pos"></param>
3267 /// <param name="localID"></param> 3963 /// <param name="localID"></param>
3964 ///
3965
3268 public void UpdateSinglePosition(Vector3 pos, uint localID) 3966 public void UpdateSinglePosition(Vector3 pos, uint localID)
3269 { 3967 {
3270 SceneObjectPart part = GetPart(localID); 3968 SceneObjectPart part = GetPart(localID);
3271 3969
3272// SceneObjectPart[] parts = m_parts.GetArray();
3273// for (int i = 0; i < parts.Length; i++)
3274// parts[i].StoreUndoState();
3275
3276 if (part != null) 3970 if (part != null)
3277 { 3971 {
3278// m_log.DebugFormat( 3972// unlock parts position change
3279// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); 3973 if (m_rootPart.PhysActor != null)
3280 3974 m_rootPart.PhysActor.Building = true;
3281 part.StoreUndoState(false);
3282 part.IgnoreUndoUpdate = true;
3283 3975
3284 if (part.UUID == m_rootPart.UUID) 3976 if (part.UUID == m_rootPart.UUID)
3285 { 3977 {
@@ -3290,8 +3982,10 @@ namespace OpenSim.Region.Framework.Scenes
3290 part.UpdateOffSet(pos); 3982 part.UpdateOffSet(pos);
3291 } 3983 }
3292 3984
3985 if (m_rootPart.PhysActor != null)
3986 m_rootPart.PhysActor.Building = false;
3987
3293 HasGroupChanged = true; 3988 HasGroupChanged = true;
3294 part.IgnoreUndoUpdate = false;
3295 } 3989 }
3296 } 3990 }
3297 3991
@@ -3301,13 +3995,7 @@ namespace OpenSim.Region.Framework.Scenes
3301 /// <param name="newPos"></param> 3995 /// <param name="newPos"></param>
3302 public void UpdateRootPosition(Vector3 newPos) 3996 public void UpdateRootPosition(Vector3 newPos)
3303 { 3997 {
3304// m_log.DebugFormat( 3998 // needs to be called with phys building true
3305// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
3306
3307// SceneObjectPart[] parts = m_parts.GetArray();
3308// for (int i = 0; i < parts.Length; i++)
3309// parts[i].StoreUndoState();
3310
3311 Vector3 oldPos; 3999 Vector3 oldPos;
3312 4000
3313 if (IsAttachment) 4001 if (IsAttachment)
@@ -3328,12 +4016,19 @@ namespace OpenSim.Region.Framework.Scenes
3328 } 4016 }
3329 4017
3330 AbsolutePosition = newPos; 4018 AbsolutePosition = newPos;
3331 4019
3332 if (IsAttachment) 4020 if (IsAttachment)
3333 m_rootPart.AttachedPos = newPos; 4021 m_rootPart.AttachedPos = newPos;
3334 4022
3335 HasGroupChanged = true; 4023 HasGroupChanged = true;
3336 ScheduleGroupForTerseUpdate(); 4024 if (m_rootPart.Undoing)
4025 {
4026 ScheduleGroupForFullUpdate();
4027 }
4028 else
4029 {
4030 ScheduleGroupForTerseUpdate();
4031 }
3337 } 4032 }
3338 4033
3339 #endregion 4034 #endregion
@@ -3346,24 +4041,16 @@ namespace OpenSim.Region.Framework.Scenes
3346 /// <param name="rot"></param> 4041 /// <param name="rot"></param>
3347 public void UpdateGroupRotationR(Quaternion rot) 4042 public void UpdateGroupRotationR(Quaternion rot)
3348 { 4043 {
3349// m_log.DebugFormat(
3350// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
3351
3352// SceneObjectPart[] parts = m_parts.GetArray();
3353// for (int i = 0; i < parts.Length; i++)
3354// parts[i].StoreUndoState();
3355
3356 m_rootPart.StoreUndoState(true);
3357
3358 m_rootPart.UpdateRotation(rot); 4044 m_rootPart.UpdateRotation(rot);
3359 4045
4046/* this is done by rootpart RotationOffset set called by UpdateRotation
3360 PhysicsActor actor = m_rootPart.PhysActor; 4047 PhysicsActor actor = m_rootPart.PhysActor;
3361 if (actor != null) 4048 if (actor != null)
3362 { 4049 {
3363 actor.Orientation = m_rootPart.RotationOffset; 4050 actor.Orientation = m_rootPart.RotationOffset;
3364 m_scene.PhysicsScene.AddPhysicsActorTaint(actor); 4051 m_scene.PhysicsScene.AddPhysicsActorTaint(actor);
3365 } 4052 }
3366 4053*/
3367 HasGroupChanged = true; 4054 HasGroupChanged = true;
3368 ScheduleGroupForTerseUpdate(); 4055 ScheduleGroupForTerseUpdate();
3369 } 4056 }
@@ -3375,16 +4062,6 @@ namespace OpenSim.Region.Framework.Scenes
3375 /// <param name="rot"></param> 4062 /// <param name="rot"></param>
3376 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 4063 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
3377 { 4064 {
3378// m_log.DebugFormat(
3379// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
3380
3381// SceneObjectPart[] parts = m_parts.GetArray();
3382// for (int i = 0; i < parts.Length; i++)
3383// parts[i].StoreUndoState();
3384
3385 RootPart.StoreUndoState(true);
3386 RootPart.IgnoreUndoUpdate = true;
3387
3388 m_rootPart.UpdateRotation(rot); 4065 m_rootPart.UpdateRotation(rot);
3389 4066
3390 PhysicsActor actor = m_rootPart.PhysActor; 4067 PhysicsActor actor = m_rootPart.PhysActor;
@@ -3403,8 +4080,6 @@ namespace OpenSim.Region.Framework.Scenes
3403 4080
3404 HasGroupChanged = true; 4081 HasGroupChanged = true;
3405 ScheduleGroupForTerseUpdate(); 4082 ScheduleGroupForTerseUpdate();
3406
3407 RootPart.IgnoreUndoUpdate = false;
3408 } 4083 }
3409 4084
3410 /// <summary> 4085 /// <summary>
@@ -3417,13 +4092,11 @@ namespace OpenSim.Region.Framework.Scenes
3417 SceneObjectPart part = GetPart(localID); 4092 SceneObjectPart part = GetPart(localID);
3418 4093
3419 SceneObjectPart[] parts = m_parts.GetArray(); 4094 SceneObjectPart[] parts = m_parts.GetArray();
3420 for (int i = 0; i < parts.Length; i++)
3421 parts[i].StoreUndoState();
3422 4095
3423 if (part != null) 4096 if (part != null)
3424 { 4097 {
3425// m_log.DebugFormat( 4098 if (m_rootPart.PhysActor != null)
3426// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); 4099 m_rootPart.PhysActor.Building = true;
3427 4100
3428 if (part.UUID == m_rootPart.UUID) 4101 if (part.UUID == m_rootPart.UUID)
3429 { 4102 {
@@ -3433,6 +4106,9 @@ namespace OpenSim.Region.Framework.Scenes
3433 { 4106 {
3434 part.UpdateRotation(rot); 4107 part.UpdateRotation(rot);
3435 } 4108 }
4109
4110 if (m_rootPart.PhysActor != null)
4111 m_rootPart.PhysActor.Building = false;
3436 } 4112 }
3437 } 4113 }
3438 4114
@@ -3446,12 +4122,8 @@ namespace OpenSim.Region.Framework.Scenes
3446 SceneObjectPart part = GetPart(localID); 4122 SceneObjectPart part = GetPart(localID);
3447 if (part != null) 4123 if (part != null)
3448 { 4124 {
3449// m_log.DebugFormat( 4125 if (m_rootPart.PhysActor != null)
3450// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", 4126 m_rootPart.PhysActor.Building = true;
3451// part.Name, part.LocalId, rot);
3452
3453 part.StoreUndoState();
3454 part.IgnoreUndoUpdate = true;
3455 4127
3456 if (part.UUID == m_rootPart.UUID) 4128 if (part.UUID == m_rootPart.UUID)
3457 { 4129 {
@@ -3464,7 +4136,8 @@ namespace OpenSim.Region.Framework.Scenes
3464 part.OffsetPosition = pos; 4136 part.OffsetPosition = pos;
3465 } 4137 }
3466 4138
3467 part.IgnoreUndoUpdate = false; 4139 if (m_rootPart.PhysActor != null)
4140 m_rootPart.PhysActor.Building = false;
3468 } 4141 }
3469 } 4142 }
3470 4143
@@ -3474,15 +4147,12 @@ namespace OpenSim.Region.Framework.Scenes
3474 /// <param name="rot"></param> 4147 /// <param name="rot"></param>
3475 public void UpdateRootRotation(Quaternion rot) 4148 public void UpdateRootRotation(Quaternion rot)
3476 { 4149 {
3477// m_log.DebugFormat( 4150 // needs to be called with phys building true
3478// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
3479// Name, LocalId, rot);
3480
3481 Quaternion axRot = rot; 4151 Quaternion axRot = rot;
3482 Quaternion oldParentRot = m_rootPart.RotationOffset; 4152 Quaternion oldParentRot = m_rootPart.RotationOffset;
3483 4153
3484 m_rootPart.StoreUndoState(); 4154 //Don't use UpdateRotation because it schedules an update prematurely
3485 m_rootPart.UpdateRotation(rot); 4155 m_rootPart.RotationOffset = rot;
3486 4156
3487 PhysicsActor pa = m_rootPart.PhysActor; 4157 PhysicsActor pa = m_rootPart.PhysActor;
3488 4158
@@ -3498,64 +4168,203 @@ namespace OpenSim.Region.Framework.Scenes
3498 SceneObjectPart prim = parts[i]; 4168 SceneObjectPart prim = parts[i];
3499 if (prim.UUID != m_rootPart.UUID) 4169 if (prim.UUID != m_rootPart.UUID)
3500 { 4170 {
3501 prim.IgnoreUndoUpdate = true; 4171 Quaternion NewRot = oldParentRot * prim.RotationOffset;
4172 NewRot = Quaternion.Inverse(axRot) * NewRot;
4173 prim.RotationOffset = NewRot;
4174
3502 Vector3 axPos = prim.OffsetPosition; 4175 Vector3 axPos = prim.OffsetPosition;
4176
3503 axPos *= oldParentRot; 4177 axPos *= oldParentRot;
3504 axPos *= Quaternion.Inverse(axRot); 4178 axPos *= Quaternion.Inverse(axRot);
3505 prim.OffsetPosition = axPos; 4179 prim.OffsetPosition = axPos;
3506 Quaternion primsRot = prim.RotationOffset;
3507 Quaternion newRot = oldParentRot * primsRot;
3508 newRot = Quaternion.Inverse(axRot) * newRot;
3509 prim.RotationOffset = newRot;
3510 prim.ScheduleTerseUpdate();
3511 prim.IgnoreUndoUpdate = false;
3512 } 4180 }
3513 } 4181 }
3514 4182
3515// for (int i = 0; i < parts.Length; i++) 4183 HasGroupChanged = true;
3516// { 4184 ScheduleGroupForFullUpdate();
3517// SceneObjectPart childpart = parts[i]; 4185 }
3518// if (childpart != m_rootPart) 4186
3519// { 4187 private enum updatetype :int
3520//// childpart.IgnoreUndoUpdate = false; 4188 {
3521//// childpart.StoreUndoState(); 4189 none = 0,
3522// } 4190 partterse = 1,
3523// } 4191 partfull = 2,
4192 groupterse = 3,
4193 groupfull = 4
4194 }
3524 4195
3525 m_rootPart.ScheduleTerseUpdate(); 4196 public void doChangeObject(SceneObjectPart part, ObjectChangeData data)
4197 {
4198 // TODO this still as excessive *.Schedule*Update()s
3526 4199
3527// m_log.DebugFormat( 4200 if (part != null && part.ParentGroup != null)
3528// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 4201 {
3529// Name, LocalId, rot); 4202 ObjectChangeType change = data.change;
4203 bool togroup = ((change & ObjectChangeType.Group) != 0);
4204 // bool uniform = ((what & ObjectChangeType.UniformScale) != 0); not in use
4205
4206 SceneObjectGroup group = part.ParentGroup;
4207 PhysicsActor pha = group.RootPart.PhysActor;
4208
4209 updatetype updateType = updatetype.none;
4210
4211 if (togroup)
4212 {
4213 // related to group
4214 if ((change & (ObjectChangeType.Rotation | ObjectChangeType.Position)) != 0)
4215 {
4216 if ((change & ObjectChangeType.Rotation) != 0)
4217 {
4218 group.RootPart.UpdateRotation(data.rotation);
4219 updateType = updatetype.none;
4220 }
4221 if ((change & ObjectChangeType.Position) != 0)
4222 {
4223 if (IsAttachment || m_scene.Permissions.CanObjectEntry(group.UUID, false, data.position))
4224 UpdateGroupPosition(data.position);
4225 updateType = updatetype.groupterse;
4226 }
4227 else
4228 // ugly rotation update of all parts
4229 {
4230 group.ResetChildPrimPhysicsPositions();
4231 }
4232
4233 }
4234 if ((change & ObjectChangeType.Scale) != 0)
4235 {
4236 if (pha != null)
4237 pha.Building = true;
4238
4239 group.GroupResize(data.scale);
4240 updateType = updatetype.none;
4241
4242 if (pha != null)
4243 pha.Building = false;
4244 }
4245 }
4246 else
4247 {
4248 // related to single prim in a link-set ( ie group)
4249 if (pha != null)
4250 pha.Building = true;
4251
4252 // root part is special
4253 // parts offset positions or rotations need to change also
4254
4255 if (part == group.RootPart)
4256 {
4257 if ((change & ObjectChangeType.Rotation) != 0)
4258 group.UpdateRootRotation(data.rotation);
4259 if ((change & ObjectChangeType.Position) != 0)
4260 group.UpdateRootPosition(data.position);
4261 if ((change & ObjectChangeType.Scale) != 0)
4262 part.Resize(data.scale);
4263 }
4264 else
4265 {
4266 if ((change & ObjectChangeType.Position) != 0)
4267 {
4268 part.OffsetPosition = data.position;
4269 updateType = updatetype.partterse;
4270 }
4271 if ((change & ObjectChangeType.Rotation) != 0)
4272 {
4273 part.UpdateRotation(data.rotation);
4274 updateType = updatetype.none;
4275 }
4276 if ((change & ObjectChangeType.Scale) != 0)
4277 {
4278 part.Resize(data.scale);
4279 updateType = updatetype.none;
4280 }
4281 }
4282
4283 if (pha != null)
4284 pha.Building = false;
4285 }
4286
4287 if (updateType != updatetype.none)
4288 {
4289 group.HasGroupChanged = true;
4290
4291 switch (updateType)
4292 {
4293 case updatetype.partterse:
4294 part.ScheduleTerseUpdate();
4295 break;
4296 case updatetype.partfull:
4297 part.ScheduleFullUpdate();
4298 break;
4299 case updatetype.groupterse:
4300 group.ScheduleGroupForTerseUpdate();
4301 break;
4302 case updatetype.groupfull:
4303 group.ScheduleGroupForFullUpdate();
4304 break;
4305 default:
4306 break;
4307 }
4308 }
4309 }
3530 } 4310 }
3531 4311
3532 #endregion 4312 #endregion
3533 4313
3534 internal void SetAxisRotation(int axis, int rotate10) 4314 internal void SetAxisRotation(int axis, int rotate10)
3535 { 4315 {
3536 bool setX = false; 4316 bool setX = ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0);
3537 bool setY = false; 4317 bool setY = ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0);
3538 bool setZ = false; 4318 bool setZ = ((axis & (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0);
3539 4319
3540 int xaxis = 2; 4320 if (setX || setY || setZ)
3541 int yaxis = 4; 4321 {
3542 int zaxis = 8; 4322 bool lockaxis = (rotate10 == 0); // zero means axis locked
3543 4323
3544 setX = ((axis & xaxis) != 0) ? true : false; 4324 byte locks = RootPart.RotationAxisLocks;
3545 setY = ((axis & yaxis) != 0) ? true : false;
3546 setZ = ((axis & zaxis) != 0) ? true : false;
3547 4325
3548 float setval = (rotate10 > 0) ? 1f : 0f; 4326 if (setX)
4327 {
4328 if(lockaxis)
4329 locks |= (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_X;
4330 else
4331 locks &= (byte)SceneObjectGroup.axisSelect.NOT_STATUS_ROTATE_X;
4332 }
4333
4334 if (setY)
4335 {
4336 if(lockaxis)
4337 locks |= (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y;
4338 else
4339 locks &= (byte)SceneObjectGroup.axisSelect.NOT_STATUS_ROTATE_Y;
4340 }
3549 4341
3550 if (setX) 4342 if (setZ)
3551 RootPart.RotationAxis.X = setval; 4343 {
3552 if (setY) 4344 if(lockaxis)
3553 RootPart.RotationAxis.Y = setval; 4345 locks |= (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z;
3554 if (setZ) 4346 else
3555 RootPart.RotationAxis.Z = setval; 4347 locks &= (byte)SceneObjectGroup.axisSelect.NOT_STATUS_ROTATE_Z;
4348 }
3556 4349
3557 if (setX || setY || setZ) 4350 RootPart.RotationAxisLocks = locks;
3558 RootPart.SetPhysicsAxisRotation(); 4351 RootPart.SetPhysicsAxisRotation();
4352 }
4353 }
4354
4355 public int GetAxisRotation(int axis)
4356 {
4357 byte rotAxislocks = RootPart.RotationAxisLocks;
4358
4359 // if multiple return the one with higher id
4360 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z)
4361 return (rotAxislocks & (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) == 0 ? 1:0;
4362 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y)
4363 return (rotAxislocks & (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) == 0 ? 1:0;
4364 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X)
4365 return (rotAxislocks & (byte)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) == 0 ? 1:0;
4366
4367 return 0;
3559 } 4368 }
3560 4369
3561 public int registerRotTargetWaypoint(Quaternion target, float tolerance) 4370 public int registerRotTargetWaypoint(Quaternion target, float tolerance)
@@ -3567,6 +4376,8 @@ namespace OpenSim.Region.Framework.Scenes
3567 waypoint.handle = handle; 4376 waypoint.handle = handle;
3568 lock (m_rotTargets) 4377 lock (m_rotTargets)
3569 { 4378 {
4379 if (m_rotTargets.Count >= 8)
4380 m_rotTargets.Remove(m_rotTargets.ElementAt(0).Key);
3570 m_rotTargets.Add(handle, waypoint); 4381 m_rotTargets.Add(handle, waypoint);
3571 } 4382 }
3572 m_scene.AddGroupTarget(this); 4383 m_scene.AddGroupTarget(this);
@@ -3592,6 +4403,8 @@ namespace OpenSim.Region.Framework.Scenes
3592 waypoint.handle = handle; 4403 waypoint.handle = handle;
3593 lock (m_targets) 4404 lock (m_targets)
3594 { 4405 {
4406 if (m_targets.Count >= 8)
4407 m_targets.Remove(m_targets.ElementAt(0).Key);
3595 m_targets.Add(handle, waypoint); 4408 m_targets.Add(handle, waypoint);
3596 } 4409 }
3597 m_scene.AddGroupTarget(this); 4410 m_scene.AddGroupTarget(this);
@@ -3625,10 +4438,11 @@ namespace OpenSim.Region.Framework.Scenes
3625 scriptPosTarget target = m_targets[idx]; 4438 scriptPosTarget target = m_targets[idx];
3626 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance) 4439 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance)
3627 { 4440 {
4441 at_target = true;
4442
3628 // trigger at_target 4443 // trigger at_target
3629 if (m_scriptListens_atTarget) 4444 if (m_scriptListens_atTarget)
3630 { 4445 {
3631 at_target = true;
3632 scriptPosTarget att = new scriptPosTarget(); 4446 scriptPosTarget att = new scriptPosTarget();
3633 att.targetPos = target.targetPos; 4447 att.targetPos = target.targetPos;
3634 att.tolerance = target.tolerance; 4448 att.tolerance = target.tolerance;
@@ -3746,11 +4560,50 @@ namespace OpenSim.Region.Framework.Scenes
3746 } 4560 }
3747 } 4561 }
3748 } 4562 }
3749 4563
4564 public Vector3 GetGeometricCenter()
4565 {
4566 // this is not real geometric center but a average of positions relative to root prim acording to
4567 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
4568 // ignoring tortured prims details since sl also seems to ignore
4569 // so no real use in doing it on physics
4570
4571 Vector3 gc = Vector3.Zero;
4572
4573 int nparts = m_parts.Count;
4574 if (nparts <= 1)
4575 return gc;
4576
4577 SceneObjectPart[] parts = m_parts.GetArray();
4578 nparts = parts.Length; // just in case it changed
4579 if (nparts <= 1)
4580 return gc;
4581
4582 Quaternion parentRot = RootPart.RotationOffset;
4583 Vector3 pPos;
4584
4585 // average all parts positions
4586 for (int i = 0; i < nparts; i++)
4587 {
4588 // do it directly
4589 // gc += parts[i].GetWorldPosition();
4590 if (parts[i] != RootPart)
4591 {
4592 pPos = parts[i].OffsetPosition;
4593 gc += pPos;
4594 }
4595
4596 }
4597 gc /= nparts;
4598
4599 // relative to root:
4600// gc -= AbsolutePosition;
4601 return gc;
4602 }
4603
3750 public float GetMass() 4604 public float GetMass()
3751 { 4605 {
3752 float retmass = 0f; 4606 float retmass = 0f;
3753
3754 SceneObjectPart[] parts = m_parts.GetArray(); 4607 SceneObjectPart[] parts = m_parts.GetArray();
3755 for (int i = 0; i < parts.Length; i++) 4608 for (int i = 0; i < parts.Length; i++)
3756 retmass += parts[i].GetMass(); 4609 retmass += parts[i].GetMass();
@@ -3758,6 +4611,39 @@ namespace OpenSim.Region.Framework.Scenes
3758 return retmass; 4611 return retmass;
3759 } 4612 }
3760 4613
4614 // center of mass of full object
4615 public Vector3 GetCenterOfMass()
4616 {
4617 PhysicsActor pa = RootPart.PhysActor;
4618
4619 if(((RootPart.Flags & PrimFlags.Physics) !=0) && pa !=null)
4620 {
4621 // physics knows better about center of mass of physical prims
4622 Vector3 tmp = pa.CenterOfMass;
4623 return tmp;
4624 }
4625
4626 Vector3 Ptot = Vector3.Zero;
4627 float totmass = 0f;
4628 float m;
4629
4630 SceneObjectPart[] parts = m_parts.GetArray();
4631 for (int i = 0; i < parts.Length; i++)
4632 {
4633 m = parts[i].GetMass();
4634 Ptot += parts[i].GetPartCenterOfMass() * m;
4635 totmass += m;
4636 }
4637
4638 if (totmass == 0)
4639 totmass = 0;
4640 else
4641 totmass = 1 / totmass;
4642 Ptot *= totmass;
4643
4644 return Ptot;
4645 }
4646
3761 /// <summary> 4647 /// <summary>
3762 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that 4648 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that
3763 /// the physics engine can use it. 4649 /// the physics engine can use it.
@@ -3937,6 +4823,14 @@ namespace OpenSim.Region.Framework.Scenes
3937 FromItemID = uuid; 4823 FromItemID = uuid;
3938 } 4824 }
3939 4825
4826 public void ResetOwnerChangeFlag()
4827 {
4828 ForEachPart(delegate(SceneObjectPart part)
4829 {
4830 part.ResetOwnerChangeFlag();
4831 });
4832 }
4833
3940 #endregion 4834 #endregion
3941 } 4835 }
3942} 4836}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index d1c5f72..52f9b51 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -64,7 +64,8 @@ namespace OpenSim.Region.Framework.Scenes
64 TELEPORT = 512, 64 TELEPORT = 512,
65 REGION_RESTART = 1024, 65 REGION_RESTART = 1024,
66 MEDIA = 2048, 66 MEDIA = 2048,
67 ANIMATION = 16384 67 ANIMATION = 16384,
68 POSITION = 32768
68 } 69 }
69 70
70 // I don't really know where to put this except here. 71 // I don't really know where to put this except here.
@@ -123,7 +124,18 @@ namespace OpenSim.Region.Framework.Scenes
123 /// Denote all sides of the prim 124 /// Denote all sides of the prim
124 /// </value> 125 /// </value>
125 public const int ALL_SIDES = -1; 126 public const int ALL_SIDES = -1;
126 127
128 private const scriptEvents PhysicsNeededSubsEvents = (
129 scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end |
130 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
131 );
132 private const scriptEvents PhyscicsPhantonSubsEvents = (
133 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
134 );
135 private const scriptEvents PhyscicsVolumeDtcSubsEvents = (
136 scriptEvents.collision_start | scriptEvents.collision_end
137 );
138
127 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 139 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
128 140
129 /// <summary> 141 /// <summary>
@@ -160,7 +172,7 @@ namespace OpenSim.Region.Framework.Scenes
160 /// </remarks> 172 /// </remarks>
161 public bool IsRoot 173 public bool IsRoot
162 { 174 {
163 get { return ParentGroup.RootPart == this; } 175 get { return Object.ReferenceEquals(ParentGroup.RootPart, this); }
164 } 176 }
165 177
166 /// <summary> 178 /// <summary>
@@ -233,11 +245,22 @@ namespace OpenSim.Region.Framework.Scenes
233 245
234 public uint TimeStampTerse; 246 public uint TimeStampTerse;
235 247
236 public int STATUS_ROTATE_X; 248 // The following two are to hold the attachment data
249 // while an object is inworld
250 [XmlIgnore]
251 public byte AttachPoint = 0;
252
253 [XmlIgnore]
254 public Quaternion AttachRotation = Quaternion.Identity;
237 255
238 public int STATUS_ROTATE_Y; 256 [XmlIgnore]
257 public int STATUS_ROTATE_X; // this should not be used
258
259 [XmlIgnore]
260 public int STATUS_ROTATE_Y; // this should not be used
239 261
240 public int STATUS_ROTATE_Z; 262 [XmlIgnore]
263 public int STATUS_ROTATE_Z; // this should not be used
241 264
242 private Dictionary<int, string> m_CollisionFilter = new Dictionary<int, string>(); 265 private Dictionary<int, string> m_CollisionFilter = new Dictionary<int, string>();
243 266
@@ -257,10 +280,12 @@ namespace OpenSim.Region.Framework.Scenes
257 280
258 public Vector3 AttachedPos; 281 public Vector3 AttachedPos;
259 282
260 public Vector3 RotationAxis = Vector3.One; 283 // rotation locks on local X,Y and or Z axis bit flags
284 // bits are as in llSetStatus defined in SceneObjectGroup.axisSelect enum
285 // but reversed logic: bit cleared means free to rotate
286 public byte RotationAxisLocks = 0;
261 287
262 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 288 public bool VolumeDetectActive;
263 // Certainly this must be a persistant setting finally
264 289
265 public bool IsWaitingForFirstSpinUpdatePacket; 290 public bool IsWaitingForFirstSpinUpdatePacket;
266 291
@@ -300,10 +325,10 @@ namespace OpenSim.Region.Framework.Scenes
300 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 325 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
301 private Vector3 m_sitTargetPosition; 326 private Vector3 m_sitTargetPosition;
302 private string m_sitAnimation = "SIT"; 327 private string m_sitAnimation = "SIT";
328 private bool m_occupied; // KF if any av is sitting on this prim
303 private string m_text = String.Empty; 329 private string m_text = String.Empty;
304 private string m_touchName = String.Empty; 330 private string m_touchName = String.Empty;
305 private readonly List<UndoState> m_undo = new List<UndoState>(5); 331 private UndoRedoState m_UndoRedo = null;
306 private readonly List<UndoState> m_redo = new List<UndoState>(5);
307 332
308 private bool m_passTouches = false; 333 private bool m_passTouches = false;
309 private bool m_passCollisions = false; 334 private bool m_passCollisions = false;
@@ -331,14 +356,20 @@ namespace OpenSim.Region.Framework.Scenes
331 protected Vector3 m_lastVelocity; 356 protected Vector3 m_lastVelocity;
332 protected Vector3 m_lastAcceleration; 357 protected Vector3 m_lastAcceleration;
333 protected Vector3 m_lastAngularVelocity; 358 protected Vector3 m_lastAngularVelocity;
334 protected int m_lastTerseSent; 359 protected int m_lastUpdateSentTime;
360 protected float m_buoyancy = 0.0f;
361 protected Vector3 m_force;
362 protected Vector3 m_torque;
335 363
336 protected byte m_physicsShapeType = (byte)PhysShapeType.prim; 364 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
337 protected float m_density = 1000.0f; // in kg/m^3 365 protected float m_density = 1000.0f; // in kg/m^3
338 protected float m_gravitymod = 1.0f; 366 protected float m_gravitymod = 1.0f;
339 protected float m_friction = 0.6f; // wood 367 protected float m_friction = 0.6f; // wood
340 protected float m_bounce = 0.5f; // wood 368 protected float m_bounce = 0.5f; // wood
341 369
370
371 protected bool m_isSelected = false;
372
342 /// <summary> 373 /// <summary>
343 /// Stores media texture data 374 /// Stores media texture data
344 /// </summary> 375 /// </summary>
@@ -350,15 +381,23 @@ namespace OpenSim.Region.Framework.Scenes
350 private Vector3 m_cameraAtOffset; 381 private Vector3 m_cameraAtOffset;
351 private bool m_forceMouselook; 382 private bool m_forceMouselook;
352 383
353 // TODO: Collision sound should have default. 384
385 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
386 private sbyte m_collisionSoundType;
354 private UUID m_collisionSound; 387 private UUID m_collisionSound;
355 private float m_collisionSoundVolume; 388 private float m_collisionSoundVolume;
356 389
390 private int LastColSoundSentTime;
391
392
393 private SOPVehicle m_vehicleParams = null;
394
357 public KeyframeMotion KeyframeMotion 395 public KeyframeMotion KeyframeMotion
358 { 396 {
359 get; set; 397 get; set;
360 } 398 }
361 399
400
362 #endregion Fields 401 #endregion Fields
363 402
364// ~SceneObjectPart() 403// ~SceneObjectPart()
@@ -388,6 +427,7 @@ namespace OpenSim.Region.Framework.Scenes
388 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from 427 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
389 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log 428 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
390 m_inventory = new SceneObjectPartInventory(this); 429 m_inventory = new SceneObjectPartInventory(this);
430 LastColSoundSentTime = Util.EnvironmentTickCount();
391 } 431 }
392 432
393 /// <summary> 433 /// <summary>
@@ -402,7 +442,7 @@ namespace OpenSim.Region.Framework.Scenes
402 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 442 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
403 Quaternion rotationOffset, Vector3 offsetPosition) : this() 443 Quaternion rotationOffset, Vector3 offsetPosition) : this()
404 { 444 {
405 m_name = "Primitive"; 445 m_name = "Object";
406 446
407 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 447 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
408 LastOwnerID = CreatorID = OwnerID = ownerID; 448 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -441,7 +481,7 @@ namespace OpenSim.Region.Framework.Scenes
441 private uint _ownerMask = (uint)(PermissionMask.All | PermissionMask.Export); 481 private uint _ownerMask = (uint)(PermissionMask.All | PermissionMask.Export);
442 private uint _groupMask = (uint)PermissionMask.None; 482 private uint _groupMask = (uint)PermissionMask.None;
443 private uint _everyoneMask = (uint)PermissionMask.None; 483 private uint _everyoneMask = (uint)PermissionMask.None;
444 private uint _nextOwnerMask = (uint)PermissionMask.All; 484 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
445 private PrimFlags _flags = PrimFlags.None; 485 private PrimFlags _flags = PrimFlags.None;
446 private DateTime m_expires; 486 private DateTime m_expires;
447 private DateTime m_rezzed; 487 private DateTime m_rezzed;
@@ -539,12 +579,16 @@ namespace OpenSim.Region.Framework.Scenes
539 } 579 }
540 580
541 /// <value> 581 /// <value>
542 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 582 /// Get the inventory list
543 /// </value> 583 /// </value>
544 public TaskInventoryDictionary TaskInventory 584 public TaskInventoryDictionary TaskInventory
545 { 585 {
546 get { return m_inventory.Items; } 586 get {
547 set { m_inventory.Items = value; } 587 return m_inventory.Items;
588 }
589 set {
590 m_inventory.Items = value;
591 }
548 } 592 }
549 593
550 /// <summary> 594 /// <summary>
@@ -594,20 +638,6 @@ namespace OpenSim.Region.Framework.Scenes
594 } 638 }
595 } 639 }
596 640
597 public byte Material
598 {
599 get { return (byte) m_material; }
600 set
601 {
602 m_material = (Material)value;
603
604 PhysicsActor pa = PhysActor;
605
606 if (pa != null)
607 pa.SetMaterial((int)value);
608 }
609 }
610
611 [XmlIgnore] 641 [XmlIgnore]
612 public bool PassTouches 642 public bool PassTouches
613 { 643 {
@@ -633,6 +663,19 @@ namespace OpenSim.Region.Framework.Scenes
633 } 663 }
634 } 664 }
635 665
666 public bool IsSelected
667 {
668 get { return m_isSelected; }
669 set
670 {
671 m_isSelected = value;
672 if (ParentGroup != null)
673 ParentGroup.PartSelectChanged(value);
674
675 }
676 }
677
678
636 public Dictionary<int, string> CollisionFilter 679 public Dictionary<int, string> CollisionFilter
637 { 680 {
638 get { return m_CollisionFilter; } 681 get { return m_CollisionFilter; }
@@ -707,14 +750,12 @@ namespace OpenSim.Region.Framework.Scenes
707 set { m_LoopSoundSlavePrims = value; } 750 set { m_LoopSoundSlavePrims = value; }
708 } 751 }
709 752
710
711 public Byte[] TextureAnimation 753 public Byte[] TextureAnimation
712 { 754 {
713 get { return m_TextureAnimation; } 755 get { return m_TextureAnimation; }
714 set { m_TextureAnimation = value; } 756 set { m_TextureAnimation = value; }
715 } 757 }
716 758
717
718 public Byte[] ParticleSystem 759 public Byte[] ParticleSystem
719 { 760 {
720 get { return m_particleSystem; } 761 get { return m_particleSystem; }
@@ -742,18 +783,28 @@ namespace OpenSim.Region.Framework.Scenes
742 set { m_damage = value; } 783 set { m_damage = value; }
743 } 784 }
744 785
786 public void setGroupPosition(Vector3 pos)
787 {
788 m_groupPosition = pos;
789 }
790
745 /// <summary> 791 /// <summary>
746 /// The position of the entire group that this prim belongs to. 792 /// The position of the entire group that this prim belongs to.
747 /// </summary> 793 /// </summary>
794 ///
795
748 public Vector3 GroupPosition 796 public Vector3 GroupPosition
749 { 797 {
750 get 798 get
751 { 799 {
752 // If this is a linkset, we don't want the physics engine mucking up our group position here. 800 // If this is a linkset, we don't want the physics engine mucking up our group position here.
753 PhysicsActor actor = PhysActor; 801 PhysicsActor actor = PhysActor;
754 // If physical and the root prim of a linkset, the position of the group is what physics thinks. 802 if (ParentID == 0)
755 if (actor != null && ParentID == 0) 803 {
756 m_groupPosition = actor.Position; 804 if (actor != null)
805 m_groupPosition = actor.Position;
806 return m_groupPosition;
807 }
757 808
758 // If I'm an attachment, my position is reported as the position of who I'm attached to 809 // If I'm an attachment, my position is reported as the position of who I'm attached to
759 if (ParentGroup.IsAttachment) 810 if (ParentGroup.IsAttachment)
@@ -763,21 +814,23 @@ namespace OpenSim.Region.Framework.Scenes
763 return sp.AbsolutePosition; 814 return sp.AbsolutePosition;
764 } 815 }
765 816
817 // use root prim's group position. Physics may have updated it
818 if (ParentGroup.RootPart != this)
819 m_groupPosition = ParentGroup.RootPart.GroupPosition;
766 return m_groupPosition; 820 return m_groupPosition;
767 } 821 }
768 set 822 set
769 { 823 {
770 m_groupPosition = value; 824 m_groupPosition = value;
771
772 PhysicsActor actor = PhysActor; 825 PhysicsActor actor = PhysActor;
773 if (actor != null) 826 if (actor != null && ParentGroup.Scene.PhysicsScene != null)
774 { 827 {
775 try 828 try
776 { 829 {
777 // Root prim actually goes at Position 830 // Root prim actually goes at Position
778 if (ParentID == 0) 831 if (ParentID == 0)
779 { 832 {
780 actor.Position = value; 833 actor.Position = value;
781 } 834 }
782 else 835 else
783 { 836 {
@@ -798,12 +851,17 @@ namespace OpenSim.Region.Framework.Scenes
798 } 851 }
799 } 852 }
800 853
854 public void setOffsetPosition(Vector3 pos)
855 {
856 m_offsetPosition = pos;
857 }
858
801 public Vector3 OffsetPosition 859 public Vector3 OffsetPosition
802 { 860 {
803 get { return m_offsetPosition; } 861 get { return m_offsetPosition; }
804 set 862 set
805 { 863 {
806// StoreUndoState(); 864 Vector3 oldpos = m_offsetPosition;
807 m_offsetPosition = value; 865 m_offsetPosition = value;
808 866
809 if (ParentGroup != null && !ParentGroup.IsDeleted) 867 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -815,10 +873,26 @@ namespace OpenSim.Region.Framework.Scenes
815 actor.Orientation = GetWorldRotation(); 873 actor.Orientation = GetWorldRotation();
816 874
817 // Tell the physics engines that this prim changed. 875 // Tell the physics engines that this prim changed.
818 if (ParentGroup.Scene != null) 876 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
819 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 877 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
820 } 878 }
879
880 if (!m_parentGroup.m_dupeInProgress)
881 {
882 List<ScenePresence> avs = ParentGroup.GetSittingAvatars();
883 foreach (ScenePresence av in avs)
884 {
885 if (av.ParentID == m_localId)
886 {
887 Vector3 offset = (m_offsetPosition - oldpos);
888 av.AbsolutePosition += offset;
889// av.SendAvatarDataToAllAgents();
890 av.SendTerseUpdateToAllClients();
891 }
892 }
893 }
821 } 894 }
895 TriggerScriptChangedEvent(Changed.POSITION);
822 } 896 }
823 } 897 }
824 898
@@ -840,6 +914,11 @@ namespace OpenSim.Region.Framework.Scenes
840 } 914 }
841 } 915 }
842 916
917 public void setRotationOffset(Quaternion q)
918 {
919 m_rotationOffset = q;
920 }
921
843 public Quaternion RotationOffset 922 public Quaternion RotationOffset
844 { 923 {
845 get 924 get
@@ -869,7 +948,7 @@ namespace OpenSim.Region.Framework.Scenes
869 948
870 set 949 set
871 { 950 {
872 StoreUndoState(); 951// StoreUndoState();
873 m_rotationOffset = value; 952 m_rotationOffset = value;
874 953
875 PhysicsActor actor = PhysActor; 954 PhysicsActor actor = PhysActor;
@@ -960,7 +1039,7 @@ namespace OpenSim.Region.Framework.Scenes
960 get 1039 get
961 { 1040 {
962 PhysicsActor actor = PhysActor; 1041 PhysicsActor actor = PhysActor;
963 if ((actor != null) && actor.IsPhysical) 1042 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
964 { 1043 {
965 m_angularVelocity = actor.RotationalVelocity; 1044 m_angularVelocity = actor.RotationalVelocity;
966 } 1045 }
@@ -974,15 +1053,26 @@ namespace OpenSim.Region.Framework.Scenes
974 m_angularVelocity = value; 1053 m_angularVelocity = value;
975 1054
976 PhysicsActor actor = PhysActor; 1055 PhysicsActor actor = PhysActor;
977 if ((actor != null) && actor.IsPhysical) 1056 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this && VehicleType == (int)Vehicle.TYPE_NONE)
1057 {
978 actor.RotationalVelocity = m_angularVelocity; 1058 actor.RotationalVelocity = m_angularVelocity;
1059 }
979 } 1060 }
980 } 1061 }
981 1062
982 /// <summary></summary> 1063 /// <summary></summary>
983 public Vector3 Acceleration 1064 public Vector3 Acceleration
984 { 1065 {
985 get { return m_acceleration; } 1066 get
1067 {
1068 PhysicsActor actor = PhysActor;
1069 if (actor != null)
1070 {
1071 m_acceleration = actor.Acceleration;
1072 }
1073 return m_acceleration;
1074 }
1075
986 set 1076 set
987 { 1077 {
988 if (Util.IsNanOrInfinity(value)) 1078 if (Util.IsNanOrInfinity(value))
@@ -1056,7 +1146,10 @@ namespace OpenSim.Region.Framework.Scenes
1056 public PrimitiveBaseShape Shape 1146 public PrimitiveBaseShape Shape
1057 { 1147 {
1058 get { return m_shape; } 1148 get { return m_shape; }
1059 set { m_shape = value;} 1149 set
1150 {
1151 m_shape = value;
1152 }
1060 } 1153 }
1061 1154
1062 /// <summary> 1155 /// <summary>
@@ -1069,7 +1162,6 @@ namespace OpenSim.Region.Framework.Scenes
1069 { 1162 {
1070 if (m_shape != null) 1163 if (m_shape != null)
1071 { 1164 {
1072 StoreUndoState();
1073 1165
1074 m_shape.Scale = value; 1166 m_shape.Scale = value;
1075 1167
@@ -1137,10 +1229,7 @@ namespace OpenSim.Region.Framework.Scenes
1137 { 1229 {
1138 get 1230 get
1139 { 1231 {
1140 if (ParentGroup.IsAttachment) 1232 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1141 return GroupPosition;
1142
1143 return m_offsetPosition + m_groupPosition;
1144 } 1233 }
1145 } 1234 }
1146 1235
@@ -1309,6 +1398,13 @@ namespace OpenSim.Region.Framework.Scenes
1309 _flags = value; 1398 _flags = value;
1310 } 1399 }
1311 } 1400 }
1401
1402 [XmlIgnore]
1403 public bool IsOccupied // KF If an av is sittingon this prim
1404 {
1405 get { return m_occupied; }
1406 set { m_occupied = value; }
1407 }
1312 1408
1313 /// <summary> 1409 /// <summary>
1314 /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero 1410 /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero
@@ -1359,12 +1455,41 @@ namespace OpenSim.Region.Framework.Scenes
1359 set { m_sitAnimation = value; } 1455 set { m_sitAnimation = value; }
1360 } 1456 }
1361 1457
1458 public UUID invalidCollisionSoundUUID = new UUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
1459
1460 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
1461 // runtime thing.. do not persist
1462 [XmlIgnore]
1463 public sbyte CollisionSoundType
1464 {
1465 get
1466 {
1467 return m_collisionSoundType;
1468 }
1469 set
1470 {
1471 m_collisionSoundType = value;
1472 if (value == -1)
1473 m_collisionSound = invalidCollisionSoundUUID;
1474 else if (value == 0)
1475 m_collisionSound = UUID.Zero;
1476 }
1477 }
1478
1362 public UUID CollisionSound 1479 public UUID CollisionSound
1363 { 1480 {
1364 get { return m_collisionSound; } 1481 get { return m_collisionSound; }
1365 set 1482 set
1366 { 1483 {
1367 m_collisionSound = value; 1484 m_collisionSound = value;
1485
1486 if (value == invalidCollisionSoundUUID)
1487 m_collisionSoundType = -1;
1488 else if (value == UUID.Zero)
1489 m_collisionSoundType = 0;
1490 else
1491 m_collisionSoundType = 1;
1492
1368 aggregateScriptEvents(); 1493 aggregateScriptEvents();
1369 } 1494 }
1370 } 1495 }
@@ -1375,6 +1500,125 @@ namespace OpenSim.Region.Framework.Scenes
1375 set { m_collisionSoundVolume = value; } 1500 set { m_collisionSoundVolume = value; }
1376 } 1501 }
1377 1502
1503 public float Buoyancy
1504 {
1505 get
1506 {
1507 if (ParentGroup.RootPart == this)
1508 return m_buoyancy;
1509
1510 return ParentGroup.RootPart.Buoyancy;
1511 }
1512 set
1513 {
1514 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1515 {
1516 ParentGroup.RootPart.Buoyancy = value;
1517 return;
1518 }
1519 m_buoyancy = value;
1520 if (PhysActor != null)
1521 PhysActor.Buoyancy = value;
1522 }
1523 }
1524
1525 public Vector3 Force
1526 {
1527 get
1528 {
1529 if (ParentGroup.RootPart == this)
1530 return m_force;
1531
1532 return ParentGroup.RootPart.Force;
1533 }
1534
1535 set
1536 {
1537 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1538 {
1539 ParentGroup.RootPart.Force = value;
1540 return;
1541 }
1542 m_force = value;
1543 if (PhysActor != null)
1544 PhysActor.Force = value;
1545 }
1546 }
1547
1548 public Vector3 Torque
1549 {
1550 get
1551 {
1552 if (ParentGroup.RootPart == this)
1553 return m_torque;
1554
1555 return ParentGroup.RootPart.Torque;
1556 }
1557
1558 set
1559 {
1560 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1561 {
1562 ParentGroup.RootPart.Torque = value;
1563 return;
1564 }
1565 m_torque = value;
1566 if (PhysActor != null)
1567 PhysActor.Torque = value;
1568 }
1569 }
1570
1571 public byte Material
1572 {
1573 get { return (byte)m_material; }
1574 set
1575 {
1576 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1577 {
1578 bool update = false;
1579
1580 if (m_material != (Material)value)
1581 {
1582 update = true;
1583 m_material = (Material)value;
1584 }
1585
1586 if (m_friction != SOPMaterialData.friction(m_material))
1587 {
1588 update = true;
1589 m_friction = SOPMaterialData.friction(m_material);
1590 }
1591
1592 if (m_bounce != SOPMaterialData.bounce(m_material))
1593 {
1594 update = true;
1595 m_bounce = SOPMaterialData.bounce(m_material);
1596 }
1597
1598 if (update)
1599 {
1600 if (PhysActor != null)
1601 {
1602 PhysActor.SetMaterial((int)value);
1603 }
1604 if(ParentGroup != null)
1605 ParentGroup.HasGroupChanged = true;
1606 ScheduleFullUpdateIfNone();
1607 UpdatePhysRequired = true;
1608 }
1609 }
1610 }
1611 }
1612
1613 // not a propriety to move to methods place later
1614 private bool HasMesh()
1615 {
1616 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1617 return true;
1618 return false;
1619 }
1620
1621 // not a propriety to move to methods place later
1378 public byte DefaultPhysicsShapeType() 1622 public byte DefaultPhysicsShapeType()
1379 { 1623 {
1380 byte type; 1624 byte type;
@@ -1387,6 +1631,65 @@ namespace OpenSim.Region.Framework.Scenes
1387 return type; 1631 return type;
1388 } 1632 }
1389 1633
1634 [XmlIgnore]
1635 public bool UsesComplexCost
1636 {
1637 get
1638 {
1639 byte pst = PhysicsShapeType;
1640 if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh())
1641 return true;
1642 return false;
1643 }
1644 }
1645
1646 [XmlIgnore]
1647 public float PhysicsCost
1648 {
1649 get
1650 {
1651 if(PhysicsShapeType == (byte)PhysShapeType.none)
1652 return 0;
1653
1654 float cost = 0.1f;
1655 if (PhysActor != null)
1656 cost = PhysActor.PhysicsCost;
1657 else
1658 cost = 0.1f;
1659
1660 if ((Flags & PrimFlags.Physics) != 0)
1661 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1662 return cost;
1663 }
1664 }
1665
1666 [XmlIgnore]
1667 public float StreamingCost
1668 {
1669 get
1670 {
1671 float cost;
1672 if (PhysActor != null)
1673 cost = PhysActor.StreamCost;
1674 else
1675 cost = 1.0f;
1676 return 1.0f;
1677 }
1678 }
1679
1680 [XmlIgnore]
1681 public float SimulationCost
1682 {
1683 get
1684 {
1685 // ignoring scripts. Don't like considering them for this
1686 if((Flags & PrimFlags.Physics) != 0)
1687 return 1.0f;
1688
1689 return 0.5f;
1690 }
1691 }
1692
1390 public byte PhysicsShapeType 1693 public byte PhysicsShapeType
1391 { 1694 {
1392 get { return m_physicsShapeType; } 1695 get { return m_physicsShapeType; }
@@ -1420,11 +1723,14 @@ namespace OpenSim.Region.Framework.Scenes
1420 } 1723 }
1421 else if (PhysActor == null) 1724 else if (PhysActor == null)
1422 { 1725 {
1423 ApplyPhysics((uint)Flags, VolumeDetectActive); 1726 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1727 UpdatePhysicsSubscribedEvents();
1424 } 1728 }
1425 else 1729 else
1426 { 1730 {
1427 PhysActor.PhysicsShapeType = m_physicsShapeType; 1731 PhysActor.PhysicsShapeType = m_physicsShapeType;
1732// if (Shape.SculptEntry)
1733// CheckSculptAndLoad();
1428 } 1734 }
1429 1735
1430 if (ParentGroup != null) 1736 if (ParentGroup != null)
@@ -1526,6 +1832,7 @@ namespace OpenSim.Region.Framework.Scenes
1526 } 1832 }
1527 } 1833 }
1528 1834
1835
1529 #endregion Public Properties with only Get 1836 #endregion Public Properties with only Get
1530 1837
1531 private uint ApplyMask(uint val, bool set, uint mask) 1838 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1636,8 +1943,8 @@ namespace OpenSim.Region.Framework.Scenes
1636 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos); 1943 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos);
1637 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4); 1944 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4);
1638 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8); 1945 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8);
1946
1639 } 1947 }
1640
1641 m_TextureAnimation = data; 1948 m_TextureAnimation = data;
1642 } 1949 }
1643 1950
@@ -1680,6 +1987,61 @@ namespace OpenSim.Region.Framework.Scenes
1680 } 1987 }
1681 } 1988 }
1682 1989
1990 // SetVelocity for LSL llSetVelocity.. may need revision if having other uses in future
1991 public void SetVelocity(Vector3 pVel, bool localGlobalTF)
1992 {
1993 if (ParentGroup == null || ParentGroup.IsDeleted)
1994 return;
1995
1996 if (ParentGroup.IsAttachment)
1997 return; // don't work on attachments (for now ??)
1998
1999 SceneObjectPart root = ParentGroup.RootPart;
2000
2001 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
2002 return;
2003
2004 PhysicsActor pa = root.PhysActor;
2005
2006 if (pa == null || !pa.IsPhysical)
2007 return;
2008
2009 if (localGlobalTF)
2010 {
2011 pVel = pVel * GetWorldRotation();
2012 }
2013
2014 ParentGroup.Velocity = pVel;
2015 }
2016
2017 // SetAngularVelocity for LSL llSetAngularVelocity.. may need revision if having other uses in future
2018 public void SetAngularVelocity(Vector3 pAngVel, bool localGlobalTF)
2019 {
2020 if (ParentGroup == null || ParentGroup.IsDeleted)
2021 return;
2022
2023 if (ParentGroup.IsAttachment)
2024 return; // don't work on attachments (for now ??)
2025
2026 SceneObjectPart root = ParentGroup.RootPart;
2027
2028 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
2029 return;
2030
2031 PhysicsActor pa = root.PhysActor;
2032
2033 if (pa == null || !pa.IsPhysical)
2034 return;
2035
2036 if (localGlobalTF)
2037 {
2038 pAngVel = pAngVel * GetWorldRotation();
2039 }
2040
2041 root.AngularVelocity = pAngVel;
2042 }
2043
2044
1683 /// <summary> 2045 /// <summary>
1684 /// hook to the physics scene to apply angular impulse 2046 /// hook to the physics scene to apply angular impulse
1685 /// This is sent up to the group, which then finds the root prim 2047 /// This is sent up to the group, which then finds the root prim
@@ -1700,7 +2062,7 @@ namespace OpenSim.Region.Framework.Scenes
1700 impulse = newimpulse; 2062 impulse = newimpulse;
1701 } 2063 }
1702 2064
1703 ParentGroup.applyAngularImpulse(impulse); 2065 ParentGroup.ApplyAngularImpulse(impulse);
1704 } 2066 }
1705 2067
1706 /// <summary> 2068 /// <summary>
@@ -1710,20 +2072,24 @@ namespace OpenSim.Region.Framework.Scenes
1710 /// </summary> 2072 /// </summary>
1711 /// <param name="impulsei">Vector force</param> 2073 /// <param name="impulsei">Vector force</param>
1712 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 2074 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1713 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 2075
2076 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
2077 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1714 { 2078 {
1715 Vector3 impulse = impulsei; 2079 Vector3 torque = torquei;
1716 2080
1717 if (localGlobalTF) 2081 if (localGlobalTF)
1718 { 2082 {
2083/*
1719 Quaternion grot = GetWorldRotation(); 2084 Quaternion grot = GetWorldRotation();
1720 Quaternion AXgrot = grot; 2085 Quaternion AXgrot = grot;
1721 Vector3 AXimpulsei = impulsei; 2086 Vector3 AXimpulsei = impulsei;
1722 Vector3 newimpulse = AXimpulsei * AXgrot; 2087 Vector3 newimpulse = AXimpulsei * AXgrot;
1723 impulse = newimpulse; 2088 */
2089 torque *= GetWorldRotation();
1724 } 2090 }
1725 2091
1726 ParentGroup.setAngularImpulse(impulse); 2092 Torque = torque;
1727 } 2093 }
1728 2094
1729 /// <summary> 2095 /// <summary>
@@ -1731,7 +2097,9 @@ namespace OpenSim.Region.Framework.Scenes
1731 /// </summary> 2097 /// </summary>
1732 /// <param name="rootObjectFlags"></param> 2098 /// <param name="rootObjectFlags"></param>
1733 /// <param name="VolumeDetectActive"></param> 2099 /// <param name="VolumeDetectActive"></param>
1734 public void ApplyPhysics(uint rootObjectFlags, bool _VolumeDetectActive) 2100 /// <param name="building"></param>
2101
2102 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1735 { 2103 {
1736 VolumeDetectActive = _VolumeDetectActive; 2104 VolumeDetectActive = _VolumeDetectActive;
1737 2105
@@ -1741,8 +2109,8 @@ namespace OpenSim.Region.Framework.Scenes
1741 if (PhysicsShapeType == (byte)PhysShapeType.none) 2109 if (PhysicsShapeType == (byte)PhysShapeType.none)
1742 return; 2110 return;
1743 2111
1744 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 2112 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
1745 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 2113 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
1746 2114
1747 if (_VolumeDetectActive) 2115 if (_VolumeDetectActive)
1748 isPhantom = true; 2116 isPhantom = true;
@@ -1757,7 +2125,8 @@ namespace OpenSim.Region.Framework.Scenes
1757 && !ParentGroup.IsAttachmentCheckFull() 2125 && !ParentGroup.IsAttachmentCheckFull()
1758 && !(Shape.PathCurve == (byte)Extrusion.Flexible)) 2126 && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1759 { 2127 {
1760 AddToPhysics(isPhysical, isPhantom, isPhysical); 2128 AddToPhysics(isPhysical, isPhantom, building, isPhysical);
2129 UpdatePhysicsSubscribedEvents(); // not sure if appliable here
1761 } 2130 }
1762 else 2131 else
1763 PhysActor = null; // just to be sure 2132 PhysActor = null; // just to be sure
@@ -1786,7 +2155,7 @@ namespace OpenSim.Region.Framework.Scenes
1786 /// <param name="linkNum"></param> 2155 /// <param name="linkNum"></param>
1787 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> 2156 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
1788 /// <returns></returns> 2157 /// <returns></returns>
1789 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed) 2158 public SceneObjectPart Copy(uint plocalID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed)
1790 { 2159 {
1791 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up 2160 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up
1792 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator 2161 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
@@ -1816,6 +2185,12 @@ namespace OpenSim.Region.Framework.Scenes
1816 dupe.Category = Category; 2185 dupe.Category = Category;
1817 dupe.m_rezzed = m_rezzed; 2186 dupe.m_rezzed = m_rezzed;
1818 2187
2188 dupe.m_UndoRedo = null;
2189 dupe.m_isSelected = false;
2190
2191 dupe.IgnoreUndoUpdate = false;
2192 dupe.Undoing = false;
2193
1819 dupe.m_inventory = new SceneObjectPartInventory(dupe); 2194 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1820 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 2195 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1821 2196
@@ -1830,7 +2205,8 @@ namespace OpenSim.Region.Framework.Scenes
1830 } 2205 }
1831 2206
1832 // Move afterwards ResetIDs as it clears the localID 2207 // Move afterwards ResetIDs as it clears the localID
1833 dupe.LocalId = localID; 2208 dupe.LocalId = plocalID;
2209
1834 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 2210 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1835 dupe.LastOwnerID = OwnerID; 2211 dupe.LastOwnerID = OwnerID;
1836 2212
@@ -1857,8 +2233,12 @@ namespace OpenSim.Region.Framework.Scenes
1857*/ 2233*/
1858 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 2234 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
1859 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 2235 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
2236// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
1860 } 2237 }
1861 2238
2239 if (dupe.PhysActor != null)
2240 dupe.PhysActor.LocalID = plocalID;
2241
1862 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2242 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1863 2243
1864// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 2244// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1877,10 +2257,10 @@ namespace OpenSim.Region.Framework.Scenes
1877 { 2257 {
1878 if (asset != null) 2258 if (asset != null)
1879 SculptTextureCallback(asset); 2259 SculptTextureCallback(asset);
1880 else 2260// else
1881 m_log.WarnFormat( 2261// m_log.WarnFormat(
1882 "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data", 2262// "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
1883 Name, UUID, id); 2263// Name, UUID, id);
1884 } 2264 }
1885*/ 2265*/
1886 /// <summary> 2266 /// <summary>
@@ -1979,6 +2359,7 @@ namespace OpenSim.Region.Framework.Scenes
1979 2359
1980 /// <summary> 2360 /// <summary>
1981 /// Do a physics propery update for this part. 2361 /// Do a physics propery update for this part.
2362 /// now also updates phantom and volume detector
1982 /// </summary> 2363 /// </summary>
1983 /// <param name="UsePhysics"></param> 2364 /// <param name="UsePhysics"></param>
1984 /// <param name="isNew"></param> 2365 /// <param name="isNew"></param>
@@ -2004,64 +2385,69 @@ namespace OpenSim.Region.Framework.Scenes
2004 { 2385 {
2005 if (pa.IsPhysical) // implies UsePhysics==false for this block 2386 if (pa.IsPhysical) // implies UsePhysics==false for this block
2006 { 2387 {
2007 if (!isNew) 2388 if (!isNew) // implies UsePhysics==false for this block
2389 {
2008 ParentGroup.Scene.RemovePhysicalPrim(1); 2390 ParentGroup.Scene.RemovePhysicalPrim(1);
2009 2391
2010 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2392 Velocity = new Vector3(0, 0, 0);
2011 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2393 Acceleration = new Vector3(0, 0, 0);
2012 pa.delink(); 2394 if (ParentGroup.RootPart == this)
2395 AngularVelocity = new Vector3(0, 0, 0);
2013 2396
2014 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2397 if (pa.Phantom && !VolumeDetectActive)
2015 { 2398 {
2016 // destroy all joints connected to this now deactivated body 2399 RemoveFromPhysics();
2017 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2400 return;
2018 } 2401 }
2019 2402
2020 // stop client-side interpolation of all joint proxy objects that have just been deleted 2403 pa.IsPhysical = UsePhysics;
2021 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2404 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
2022 // which stops client-side interpolation of deactivated joint proxy objects. 2405 pa.OnOutOfBounds -= PhysicsOutOfBounds;
2406 pa.delink();
2407 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2408 {
2409 // destroy all joints connected to this now deactivated body
2410 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
2411 }
2412 }
2023 } 2413 }
2024 2414
2025 if (!UsePhysics && !isNew) 2415 if (pa.IsPhysical != UsePhysics)
2026 { 2416 pa.IsPhysical = UsePhysics;
2027 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
2028 // prim still has velocity and continues to interpolate its position along the old
2029 // velocity-vector.
2030 Velocity = new Vector3(0, 0, 0);
2031 Acceleration = new Vector3(0, 0, 0);
2032 AngularVelocity = new Vector3(0, 0, 0);
2033 //RotationalVelocity = new Vector3(0, 0, 0);
2034 }
2035 2417
2036 pa.IsPhysical = UsePhysics; 2418 if (UsePhysics)
2419 {
2420 if (ParentGroup.RootPart.KeyframeMotion != null)
2421 ParentGroup.RootPart.KeyframeMotion.Stop();
2422 ParentGroup.RootPart.KeyframeMotion = null;
2423 ParentGroup.Scene.AddPhysicalPrim(1);
2037 2424
2038 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2425 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
2039 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2426 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
2040 /// that's not wholesome. Had to make Scene public
2041 //PhysActor = null;
2042 2427
2043 if ((Flags & PrimFlags.Phantom) == 0) 2428 if (ParentID != 0 && ParentID != LocalId)
2044 {
2045 if (UsePhysics)
2046 { 2429 {
2047 if (ParentGroup.RootPart.KeyframeMotion != null) 2430 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
2048 ParentGroup.RootPart.KeyframeMotion.Stop();
2049 ParentGroup.RootPart.KeyframeMotion = null;
2050 ParentGroup.Scene.AddPhysicalPrim(1);
2051
2052 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
2053 pa.OnOutOfBounds += PhysicsOutOfBounds;
2054 if (ParentID != 0 && ParentID != LocalId)
2055 {
2056 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
2057 2431
2058 if (parentPa != null) 2432 if (parentPa != null)
2059 { 2433 {
2060 pa.link(parentPa); 2434 pa.link(parentPa);
2061 }
2062 } 2435 }
2063 } 2436 }
2064 } 2437 }
2438 }
2439
2440 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2441 if (pa.Phantom != phan)
2442 pa.Phantom = phan;
2443
2444// some engines dont' have this check still
2445// if (VolumeDetectActive != pa.IsVolumeDtc)
2446 {
2447 if (VolumeDetectActive)
2448 pa.SetVolumeDetect(1);
2449 else
2450 pa.SetVolumeDetect(0);
2065 } 2451 }
2066 2452
2067 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2453 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
@@ -2132,13 +2518,8 @@ namespace OpenSim.Region.Framework.Scenes
2132 2518
2133 public int GetAxisRotation(int axis) 2519 public int GetAxisRotation(int axis)
2134 { 2520 {
2135 //Cannot use ScriptBaseClass constants as no referance to it currently. 2521 if (!ParentGroup.IsDeleted)
2136 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) 2522 return ParentGroup.GetAxisRotation(axis);
2137 return STATUS_ROTATE_X;
2138 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y)
2139 return STATUS_ROTATE_Y;
2140 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z)
2141 return STATUS_ROTATE_Z;
2142 2523
2143 return 0; 2524 return 0;
2144 } 2525 }
@@ -2164,42 +2545,63 @@ namespace OpenSim.Region.Framework.Scenes
2164 2545
2165 public Vector3 GetGeometricCenter() 2546 public Vector3 GetGeometricCenter()
2166 { 2547 {
2548 // this is not real geometric center but a average of positions relative to root prim acording to
2549 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
2550 // ignoring tortured prims details since sl also seems to ignore
2551 // so no real use in doing it on physics
2552 if (ParentGroup.IsDeleted)
2553 return new Vector3(0, 0, 0);
2554
2555 return ParentGroup.GetGeometricCenter();
2556 }
2557
2558 public float GetMass()
2559 {
2167 PhysicsActor pa = PhysActor; 2560 PhysicsActor pa = PhysActor;
2168 2561
2169 if (pa != null) 2562 if (pa != null)
2170 return pa.GeometricCenter; 2563 return pa.Mass;
2171 else 2564 else
2172 return Vector3.Zero; 2565 return 0;
2173 } 2566 }
2174 2567
2175 public Vector3 GetCenterOfMass() 2568 public Vector3 GetCenterOfMass()
2176 { 2569 {
2570 if (ParentGroup.RootPart == this)
2571 {
2572 if (ParentGroup.IsDeleted)
2573 return AbsolutePosition;
2574 return ParentGroup.GetCenterOfMass();
2575 }
2576
2177 PhysicsActor pa = PhysActor; 2577 PhysicsActor pa = PhysActor;
2178 2578
2179 if (pa != null) 2579 if (pa != null)
2180 return pa.CenterOfMass; 2580 {
2581 Vector3 tmp = pa.CenterOfMass;
2582 return tmp;
2583 }
2181 else 2584 else
2182 return Vector3.Zero; 2585 return AbsolutePosition;
2183 } 2586 }
2184 2587
2185 public float GetMass() 2588 public Vector3 GetPartCenterOfMass()
2186 { 2589 {
2187 PhysicsActor pa = PhysActor; 2590 PhysicsActor pa = PhysActor;
2188 2591
2189 if (pa != null) 2592 if (pa != null)
2190 return pa.Mass; 2593 {
2594 Vector3 tmp = pa.CenterOfMass;
2595 return tmp;
2596 }
2191 else 2597 else
2192 return 0; 2598 return AbsolutePosition;
2193 } 2599 }
2194 2600
2601
2195 public Vector3 GetForce() 2602 public Vector3 GetForce()
2196 { 2603 {
2197 PhysicsActor pa = PhysActor; 2604 return Force;
2198
2199 if (pa != null)
2200 return pa.Force;
2201 else
2202 return Vector3.Zero;
2203 } 2605 }
2204 2606
2205 /// <summary> 2607 /// <summary>
@@ -2314,6 +2716,7 @@ namespace OpenSim.Region.Framework.Scenes
2314 detobj.velVector = obj.Velocity; 2716 detobj.velVector = obj.Velocity;
2315 detobj.colliderType = 0; 2717 detobj.colliderType = 0;
2316 detobj.groupUUID = obj.GroupID; 2718 detobj.groupUUID = obj.GroupID;
2719 detobj.linkNumber = LinkNum; // pass my link number
2317 2720
2318 return detobj; 2721 return detobj;
2319 } 2722 }
@@ -2329,6 +2732,7 @@ namespace OpenSim.Region.Framework.Scenes
2329 detobj.velVector = av.Velocity; 2732 detobj.velVector = av.Velocity;
2330 detobj.colliderType = 0; 2733 detobj.colliderType = 0;
2331 detobj.groupUUID = av.ControllingClient.ActiveGroupId; 2734 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
2735 detobj.linkNumber = LinkNum; // pass my link number
2332 2736
2333 return detobj; 2737 return detobj;
2334 } 2738 }
@@ -2344,6 +2748,7 @@ namespace OpenSim.Region.Framework.Scenes
2344 detobj.velVector = Vector3.Zero; 2748 detobj.velVector = Vector3.Zero;
2345 detobj.colliderType = 0; 2749 detobj.colliderType = 0;
2346 detobj.groupUUID = UUID.Zero; 2750 detobj.groupUUID = UUID.Zero;
2751 detobj.linkNumber = LinkNum; // pass my link number not sure needed.. but no harm
2347 2752
2348 return detobj; 2753 return detobj;
2349 } 2754 }
@@ -2393,7 +2798,7 @@ namespace OpenSim.Region.Framework.Scenes
2393 CollidingMessage = CreateColliderArgs(this, colliders); 2798 CollidingMessage = CreateColliderArgs(this, colliders);
2394 2799
2395 if (CollidingMessage.Colliders.Count > 0) 2800 if (CollidingMessage.Colliders.Count > 0)
2396 DoNotify(notify, LocalId, CollidingMessage); 2801 notify(LocalId, CollidingMessage);
2397 2802
2398 if (PassCollisions) 2803 if (PassCollisions)
2399 sendToRoot = true; 2804 sendToRoot = true;
@@ -2407,48 +2812,32 @@ namespace OpenSim.Region.Framework.Scenes
2407 { 2812 {
2408 CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders); 2813 CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders);
2409 if (CollidingMessage.Colliders.Count > 0) 2814 if (CollidingMessage.Colliders.Count > 0)
2410 DoNotify(notify, ParentGroup.RootPart.LocalId, CollidingMessage); 2815 notify(ParentGroup.RootPart.LocalId, CollidingMessage);
2411 } 2816 }
2412 } 2817 }
2413 } 2818 }
2414 2819
2415 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify) 2820 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify)
2416 { 2821 {
2417 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0) 2822 bool sendToRoot = true;
2418 {
2419 ColliderArgs LandCollidingMessage = new ColliderArgs();
2420 List<DetectedObject> colliding = new List<DetectedObject>();
2421
2422 colliding.Add(CreateDetObjectForGround());
2423 LandCollidingMessage.Colliders = colliding;
2424 2823
2425 DoNotify(notify, LocalId, LandCollidingMessage); 2824 ColliderArgs LandCollidingMessage = new ColliderArgs();
2426 } 2825 List<DetectedObject> colliding = new List<DetectedObject>();
2427 } 2826
2827 colliding.Add(CreateDetObjectForGround());
2828 LandCollidingMessage.Colliders = colliding;
2428 2829
2429 private void DoNotify(ScriptCollidingNotification notify, uint id, ColliderArgs collargs) 2830 if (Inventory.ContainsScripts())
2430 {
2431 if (m_parentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.ShouldUseFireAndForgetForCollisions)
2432 { 2831 {
2433 // For those learning C#, FireAndForget takes a function, an object to pass 2832 if (!PassCollisions)
2434 // to that function and an ID string. The "oo => {}" construct is a lambda expression 2833 sendToRoot = false;
2435 // for a function with one arguement ('oo'). The 'new Object[] {}" construct creates an Object
2436 // that is an object array and initializes it with three items (the parameters
2437 // being passed). The parameters passed are the function to call ('notify') and
2438 // its two arguements. Finally, once in the function (called later by the FireAndForget
2439 // thread scheduler), the passed object is cast to an object array and then each
2440 // of its items (aoo[0] to aoo[2]) are individually cast to what they are and
2441 // then used in a call of the passed ScriptCollidingNotification function.
2442 Util.FireAndForget(oo =>
2443 {
2444 Object[] aoo = (Object[])oo;
2445 ((ScriptCollidingNotification)aoo[0])((uint)aoo[1], (ColliderArgs)aoo[2]);
2446
2447 }, new Object[] { notify, id, collargs }, "SOP.Collision");
2448 } 2834 }
2449 else 2835 if ((ScriptEvents & ev) != 0)
2836 notify(LocalId, LandCollidingMessage);
2837
2838 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0 && sendToRoot)
2450 { 2839 {
2451 notify(id, collargs); 2840 notify(ParentGroup.RootPart.LocalId, LandCollidingMessage);
2452 } 2841 }
2453 } 2842 }
2454 2843
@@ -2464,44 +2853,81 @@ namespace OpenSim.Region.Framework.Scenes
2464 List<uint> endedColliders = new List<uint>(); 2853 List<uint> endedColliders = new List<uint>();
2465 List<uint> startedColliders = new List<uint>(); 2854 List<uint> startedColliders = new List<uint>();
2466 2855
2467 // calculate things that started colliding this time 2856 if (collissionswith.Count == 0)
2468 // and build up list of colliders this time
2469 foreach (uint localid in collissionswith.Keys)
2470 { 2857 {
2471 thisHitColliders.Add(localid); 2858 if (m_lastColliders.Count == 0)
2472 if (!m_lastColliders.Contains(localid)) 2859 return; // nothing to do
2473 startedColliders.Add(localid);
2474 }
2475 2860
2476 // calculate things that ended colliding 2861 foreach (uint localID in m_lastColliders)
2477 foreach (uint localID in m_lastColliders) 2862 {
2478 {
2479 if (!thisHitColliders.Contains(localID))
2480 endedColliders.Add(localID); 2863 endedColliders.Add(localID);
2864 }
2865 m_lastColliders.Clear();
2481 } 2866 }
2482 2867
2483 //add the items that started colliding this time to the last colliders list. 2868 else
2484 foreach (uint localID in startedColliders) 2869 {
2485 m_lastColliders.Add(localID); 2870 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
2486 2871
2487 // remove things that ended colliding from the last colliders list 2872 // calculate things that started colliding this time
2488 foreach (uint localID in endedColliders) 2873 // and build up list of colliders this time
2489 m_lastColliders.Remove(localID); 2874 if (!VolumeDetectActive && CollisionSoundType >= 0)
2875 {
2876 CollisionForSoundInfo soundinfo;
2877 ContactPoint curcontact;
2490 2878
2491 // play the sound. 2879 foreach (uint id in collissionswith.Keys)
2492 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) 2880 {
2493 { 2881 thisHitColliders.Add(id);
2494 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>(); 2882 if (!m_lastColliders.Contains(id))
2495 if (soundModule != null) 2883 {
2884 startedColliders.Add(id);
2885
2886 curcontact = collissionswith[id];
2887 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2888 {
2889 soundinfo = new CollisionForSoundInfo();
2890 soundinfo.colliderID = id;
2891 soundinfo.position = curcontact.Position;
2892 soundinfo.relativeVel = curcontact.RelativeSpeed;
2893 soundinfolist.Add(soundinfo);
2894 }
2895 }
2896 }
2897 }
2898 else
2899 {
2900 foreach (uint id in collissionswith.Keys)
2901 {
2902 thisHitColliders.Add(id);
2903 if (!m_lastColliders.Contains(id))
2904 startedColliders.Add(id);
2905 }
2906 }
2907
2908 // calculate things that ended colliding
2909 foreach (uint localID in m_lastColliders)
2496 { 2910 {
2497 soundModule.SendSound(UUID, CollisionSound, 2911 if (!thisHitColliders.Contains(localID))
2498 CollisionSoundVolume, true, 0, 0, false, 2912 endedColliders.Add(localID);
2499 false);
2500 } 2913 }
2914
2915 //add the items that started colliding this time to the last colliders list.
2916 foreach (uint localID in startedColliders)
2917 m_lastColliders.Add(localID);
2918
2919 // remove things that ended colliding from the last colliders list
2920 foreach (uint localID in endedColliders)
2921 m_lastColliders.Remove(localID);
2922
2923 // play sounds.
2924 if (soundinfolist.Count > 0)
2925 CollisionSounds.PartCollisionSound(this, soundinfolist);
2501 } 2926 }
2502 2927
2503 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); 2928 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart);
2504 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); 2929 if (!VolumeDetectActive)
2930 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
2505 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 2931 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
2506 2932
2507 if (startedColliders.Contains(0)) 2933 if (startedColliders.Contains(0))
@@ -2512,6 +2938,35 @@ namespace OpenSim.Region.Framework.Scenes
2512 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2938 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2513 } 2939 }
2514 2940
2941 // The Collision sounds code calls this
2942 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
2943 {
2944 if (soundID == UUID.Zero)
2945 return;
2946
2947 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
2948 if (soundModule == null)
2949 return;
2950
2951 if (volume > 1)
2952 volume = 1;
2953 if (volume < 0)
2954 volume = 0;
2955
2956 int now = Util.EnvironmentTickCount();
2957 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
2958 return;
2959
2960 LastColSoundSentTime = now;
2961
2962 UUID ownerID = OwnerID;
2963 UUID objectID = ParentGroup.RootPart.UUID;
2964 UUID parentID = ParentGroup.UUID;
2965 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
2966
2967 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
2968 }
2969
2515 public void PhysicsOutOfBounds(Vector3 pos) 2970 public void PhysicsOutOfBounds(Vector3 pos)
2516 { 2971 {
2517 // Note: This is only being called on the root prim at this time. 2972 // Note: This is only being called on the root prim at this time.
@@ -2539,7 +2994,7 @@ namespace OpenSim.Region.Framework.Scenes
2539 } 2994 }
2540 //ParentGroup.RootPart.m_groupPosition = newpos; 2995 //ParentGroup.RootPart.m_groupPosition = newpos;
2541 } 2996 }
2542 2997/* ubit: there are no flexible links
2543 if (pa != null && ParentID != 0 && ParentGroup != null) 2998 if (pa != null && ParentID != 0 && ParentGroup != null)
2544 { 2999 {
2545 // Special case where a child object is requesting property updates. 3000 // Special case where a child object is requesting property updates.
@@ -2559,7 +3014,7 @@ namespace OpenSim.Region.Framework.Scenes
2559 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}", 3014 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}",
2560 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset); 3015 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset);
2561 } 3016 }
2562 3017*/
2563 ScheduleTerseUpdate(); 3018 ScheduleTerseUpdate();
2564 } 3019 }
2565 3020
@@ -2619,18 +3074,17 @@ namespace OpenSim.Region.Framework.Scenes
2619 3074
2620 if (ParentGroup.Scene != null) 3075 if (ParentGroup.Scene != null)
2621 { 3076 {
2622 scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); 3077 float minsize = ParentGroup.Scene.m_minNonphys;
2623 scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); 3078 float maxsize = ParentGroup.Scene.m_maxNonphys;
2624 scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z));
2625
2626 if (pa != null && pa.IsPhysical) 3079 if (pa != null && pa.IsPhysical)
2627 { 3080 {
2628 scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); 3081 minsize = ParentGroup.Scene.m_minPhys;
2629 scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); 3082 maxsize = ParentGroup.Scene.m_maxPhys;
2630 scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); 3083 }
2631 } 3084 scale.X = Util.Clamp(scale.X, minsize, maxsize);
3085 scale.Y = Util.Clamp(scale.Y, minsize, maxsize);
3086 scale.Z = Util.Clamp(scale.Z, minsize, maxsize);
2632 } 3087 }
2633
2634// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); 3088// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
2635 3089
2636 Scale = scale; 3090 Scale = scale;
@@ -2812,7 +3266,19 @@ namespace OpenSim.Region.Framework.Scenes
2812 3266
2813// m_log.DebugFormat( 3267// m_log.DebugFormat(
2814// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); 3268// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId);
2815 3269
3270
3271 if (ParentGroup.IsAttachment)
3272 {
3273 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3274 if (sp != null)
3275 {
3276 sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
3277 }
3278 }
3279
3280/* this does nothing
3281SendFullUpdateToClient(remoteClient, Position) ignores position parameter
2816 if (IsRoot) 3282 if (IsRoot)
2817 { 3283 {
2818 if (ParentGroup.IsAttachment) 3284 if (ParentGroup.IsAttachment)
@@ -2824,6 +3290,7 @@ namespace OpenSim.Region.Framework.Scenes
2824 SendFullUpdateToClient(remoteClient, AbsolutePosition); 3290 SendFullUpdateToClient(remoteClient, AbsolutePosition);
2825 } 3291 }
2826 } 3292 }
3293*/
2827 else 3294 else
2828 { 3295 {
2829 SendFullUpdateToClient(remoteClient); 3296 SendFullUpdateToClient(remoteClient);
@@ -2833,17 +3300,55 @@ namespace OpenSim.Region.Framework.Scenes
2833 /// <summary> 3300 /// <summary>
2834 /// Send a full update for this part to all clients. 3301 /// Send a full update for this part to all clients.
2835 /// </summary> 3302 /// </summary>
2836 public void SendFullUpdateToAllClients() 3303 public void SendFullUpdateToAllClientsInternal()
2837 { 3304 {
2838 if (ParentGroup == null) 3305 if (ParentGroup == null)
2839 return; 3306 return;
2840 3307
3308 // Update the "last" values
3309 m_lastPosition = OffsetPosition;
3310 m_lastRotation = RotationOffset;
3311 m_lastVelocity = Velocity;
3312 m_lastAcceleration = Acceleration;
3313 m_lastAngularVelocity = AngularVelocity;
3314 m_lastUpdateSentTime = Environment.TickCount;
3315
2841 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 3316 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
2842 { 3317 {
2843 SendFullUpdate(avatar.ControllingClient); 3318 SendFullUpdate(avatar.ControllingClient);
2844 }); 3319 });
2845 } 3320 }
2846 3321
3322 public void SendFullUpdateToAllClients()
3323 {
3324 if (ParentGroup == null)
3325 return;
3326
3327 // Update the "last" values
3328 m_lastPosition = OffsetPosition;
3329 m_lastRotation = RotationOffset;
3330 m_lastVelocity = Velocity;
3331 m_lastAcceleration = Acceleration;
3332 m_lastAngularVelocity = AngularVelocity;
3333 m_lastUpdateSentTime = Environment.TickCount;
3334
3335 if (ParentGroup.IsAttachment)
3336 {
3337 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3338 if (sp != null)
3339 {
3340 sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
3341 }
3342 }
3343 else
3344 {
3345 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
3346 {
3347 SendFullUpdate(avatar.ControllingClient);
3348 });
3349 }
3350 }
3351
2847 /// <summary> 3352 /// <summary>
2848 /// Sends a full update to the client 3353 /// Sends a full update to the client
2849 /// </summary> 3354 /// </summary>
@@ -2864,9 +3369,9 @@ namespace OpenSim.Region.Framework.Scenes
2864 return; 3369 return;
2865 3370
2866 // Suppress full updates during attachment editing 3371 // Suppress full updates during attachment editing
2867 // 3372 // sl Does send them
2868 if (ParentGroup.IsSelected && ParentGroup.IsAttachment) 3373 // if (ParentGroup.IsSelected && ParentGroup.IsAttachment)
2869 return; 3374 // return;
2870 3375
2871 if (ParentGroup.IsDeleted) 3376 if (ParentGroup.IsDeleted)
2872 return; 3377 return;
@@ -2896,8 +3401,8 @@ namespace OpenSim.Region.Framework.Scenes
2896 { 3401 {
2897 const float ROTATION_TOLERANCE = 0.01f; 3402 const float ROTATION_TOLERANCE = 0.01f;
2898 const float VELOCITY_TOLERANCE = 0.001f; 3403 const float VELOCITY_TOLERANCE = 0.001f;
2899 const float POSITION_TOLERANCE = 0.05f; 3404 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2900 const int TIME_MS_TOLERANCE = 3000; 3405 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2901 3406
2902 switch (UpdateFlag) 3407 switch (UpdateFlag)
2903 { 3408 {
@@ -2911,40 +3416,74 @@ namespace OpenSim.Region.Framework.Scenes
2911 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) || 3416 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) ||
2912 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) || 3417 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) ||
2913 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 3418 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
2914 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3419 Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE)
2915 { 3420 {
2916 SendTerseUpdateToAllClients(); 3421 SendTerseUpdateToAllClientsInternal();
2917
2918 // Update the "last" values
2919 m_lastPosition = OffsetPosition;
2920 m_lastRotation = RotationOffset;
2921 m_lastVelocity = Velocity;
2922 m_lastAcceleration = Acceleration;
2923 m_lastAngularVelocity = AngularVelocity;
2924 m_lastTerseSent = Environment.TickCount;
2925 } 3422 }
2926 break; 3423 break;
2927 } 3424 }
2928 case UpdateRequired.FULL: 3425 case UpdateRequired.FULL:
2929 { 3426 {
2930 ClearUpdateSchedule(); 3427 ClearUpdateSchedule();
2931 SendFullUpdateToAllClients(); 3428 SendFullUpdateToAllClientsInternal();
2932 break; 3429 break;
2933 } 3430 }
2934 } 3431 }
2935 } 3432 }
2936 3433
3434
2937 /// <summary> 3435 /// <summary>
2938 /// Send a terse update to all clients 3436 /// Send a terse update to all clients
2939 /// </summary> 3437 /// </summary>
2940 public void SendTerseUpdateToAllClients() 3438 public void SendTerseUpdateToAllClientsInternal()
2941 { 3439 {
3440 if (ParentGroup == null || ParentGroup.Scene == null)
3441 return;
3442
3443 // Update the "last" values
3444 m_lastPosition = OffsetPosition;
3445 m_lastRotation = RotationOffset;
3446 m_lastVelocity = Velocity;
3447 m_lastAcceleration = Acceleration;
3448 m_lastAngularVelocity = AngularVelocity;
3449 m_lastUpdateSentTime = Environment.TickCount;
3450
2942 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) 3451 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
2943 { 3452 {
2944 SendTerseUpdateToClient(client); 3453 SendTerseUpdateToClient(client);
2945 }); 3454 });
2946 } 3455 }
2947 3456
3457 public void SendTerseUpdateToAllClients()
3458 {
3459 if (ParentGroup == null || ParentGroup.Scene == null)
3460 return;
3461
3462 // Update the "last" values
3463 m_lastPosition = OffsetPosition;
3464 m_lastRotation = RotationOffset;
3465 m_lastVelocity = Velocity;
3466 m_lastAcceleration = Acceleration;
3467 m_lastAngularVelocity = AngularVelocity;
3468 m_lastUpdateSentTime = Environment.TickCount;
3469
3470 if (ParentGroup.IsAttachment)
3471 {
3472 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3473 if (sp != null)
3474 {
3475 sp.SendAttachmentUpdate(this, UpdateRequired.TERSE);
3476 }
3477 }
3478 else
3479 {
3480 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
3481 {
3482 SendTerseUpdateToClient(client);
3483 });
3484 }
3485 }
3486
2948 public void SetAxisRotation(int axis, int rotate) 3487 public void SetAxisRotation(int axis, int rotate)
2949 { 3488 {
2950 ParentGroup.SetAxisRotation(axis, rotate); 3489 ParentGroup.SetAxisRotation(axis, rotate);
@@ -2962,10 +3501,13 @@ namespace OpenSim.Region.Framework.Scenes
2962 3501
2963 public void SetBuoyancy(float fvalue) 3502 public void SetBuoyancy(float fvalue)
2964 { 3503 {
2965 PhysicsActor pa = PhysActor; 3504 Buoyancy = fvalue;
2966 3505/*
2967 if (pa != null) 3506 if (PhysActor != null)
2968 pa.Buoyancy = fvalue; 3507 {
3508 PhysActor.Buoyancy = fvalue;
3509 }
3510 */
2969 } 3511 }
2970 3512
2971 public void SetDieAtEdge(bool p) 3513 public void SetDieAtEdge(bool p)
@@ -2981,47 +3523,111 @@ namespace OpenSim.Region.Framework.Scenes
2981 PhysicsActor pa = PhysActor; 3523 PhysicsActor pa = PhysActor;
2982 3524
2983 if (pa != null) 3525 if (pa != null)
2984 pa.FloatOnWater = floatYN == 1; 3526 pa.FloatOnWater = (floatYN == 1);
2985 } 3527 }
2986 3528
2987 public void SetForce(Vector3 force) 3529 public void SetForce(Vector3 force)
2988 { 3530 {
2989 PhysicsActor pa = PhysActor; 3531 Force = force;
3532 }
2990 3533
2991 if (pa != null) 3534 public SOPVehicle VehicleParams
2992 pa.Force = force; 3535 {
3536 get
3537 {
3538 return m_vehicleParams;
3539 }
3540 set
3541 {
3542 m_vehicleParams = value;
3543 }
3544 }
3545
3546
3547 public int VehicleType
3548 {
3549 get
3550 {
3551 if (m_vehicleParams == null)
3552 return (int)Vehicle.TYPE_NONE;
3553 else
3554 return (int)m_vehicleParams.Type;
3555 }
3556 set
3557 {
3558 SetVehicleType(value);
3559 }
2993 } 3560 }
2994 3561
2995 public void SetVehicleType(int type) 3562 public void SetVehicleType(int type)
2996 { 3563 {
2997 PhysicsActor pa = PhysActor; 3564 m_vehicleParams = null;
3565
3566 if (type == (int)Vehicle.TYPE_NONE)
3567 {
3568 if (_parentID ==0 && PhysActor != null)
3569 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3570 return;
3571 }
3572 m_vehicleParams = new SOPVehicle();
3573 m_vehicleParams.ProcessTypeChange((Vehicle)type);
3574 {
3575 if (_parentID ==0 && PhysActor != null)
3576 PhysActor.VehicleType = type;
3577 return;
3578 }
3579 }
2998 3580
2999 if (pa != null) 3581 public void SetVehicleFlags(int param, bool remove)
3000 pa.VehicleType = type; 3582 {
3583 if (m_vehicleParams == null)
3584 return;
3585
3586 m_vehicleParams.ProcessVehicleFlags(param, remove);
3587
3588 if (_parentID ==0 && PhysActor != null)
3589 {
3590 PhysActor.VehicleFlags(param, remove);
3591 }
3001 } 3592 }
3002 3593
3003 public void SetVehicleFloatParam(int param, float value) 3594 public void SetVehicleFloatParam(int param, float value)
3004 { 3595 {
3005 PhysicsActor pa = PhysActor; 3596 if (m_vehicleParams == null)
3597 return;
3006 3598
3007 if (pa != null) 3599 m_vehicleParams.ProcessFloatVehicleParam((Vehicle)param, value);
3008 pa.VehicleFloatParam(param, value); 3600
3601 if (_parentID == 0 && PhysActor != null)
3602 {
3603 PhysActor.VehicleFloatParam(param, value);
3604 }
3009 } 3605 }
3010 3606
3011 public void SetVehicleVectorParam(int param, Vector3 value) 3607 public void SetVehicleVectorParam(int param, Vector3 value)
3012 { 3608 {
3013 PhysicsActor pa = PhysActor; 3609 if (m_vehicleParams == null)
3610 return;
3014 3611
3015 if (pa != null) 3612 m_vehicleParams.ProcessVectorVehicleParam((Vehicle)param, value);
3016 pa.VehicleVectorParam(param, value); 3613
3614 if (_parentID == 0 && PhysActor != null)
3615 {
3616 PhysActor.VehicleVectorParam(param, value);
3617 }
3017 } 3618 }
3018 3619
3019 public void SetVehicleRotationParam(int param, Quaternion rotation) 3620 public void SetVehicleRotationParam(int param, Quaternion rotation)
3020 { 3621 {
3021 PhysicsActor pa = PhysActor; 3622 if (m_vehicleParams == null)
3623 return;
3022 3624
3023 if (pa != null) 3625 m_vehicleParams.ProcessRotationVehicleParam((Vehicle)param, rotation);
3024 pa.VehicleRotationParam(param, rotation); 3626
3627 if (_parentID == 0 && PhysActor != null)
3628 {
3629 PhysActor.VehicleRotationParam(param, rotation);
3630 }
3025 } 3631 }
3026 3632
3027 /// <summary> 3633 /// <summary>
@@ -3222,14 +3828,6 @@ namespace OpenSim.Region.Framework.Scenes
3222 hasProfileCut = hasDimple; // is it the same thing? 3828 hasProfileCut = hasDimple; // is it the same thing?
3223 } 3829 }
3224 3830
3225 public void SetVehicleFlags(int param, bool remove)
3226 {
3227 PhysicsActor pa = PhysActor;
3228
3229 if (pa != null)
3230 pa.VehicleFlags(param, remove);
3231 }
3232
3233 public void SetGroup(UUID groupID, IClientAPI client) 3831 public void SetGroup(UUID groupID, IClientAPI client)
3234 { 3832 {
3235 // Scene.AddNewPrims() calls with client == null so can't use this. 3833 // Scene.AddNewPrims() calls with client == null so can't use this.
@@ -3238,8 +3836,8 @@ namespace OpenSim.Region.Framework.Scenes
3238// Name, groupID, OwnerID); 3836// Name, groupID, OwnerID);
3239 3837
3240 GroupID = groupID; 3838 GroupID = groupID;
3241 if (client != null) 3839// if (client != null)
3242 SendPropertiesToClient(client); 3840// SendPropertiesToClient(client);
3243 UpdateFlag = UpdateRequired.FULL; 3841 UpdateFlag = UpdateRequired.FULL;
3244 } 3842 }
3245 3843
@@ -3263,7 +3861,7 @@ namespace OpenSim.Region.Framework.Scenes
3263 3861
3264 if (pa != null) 3862 if (pa != null)
3265 { 3863 {
3266 pa.LockAngularMotion(RotationAxis); 3864 pa.LockAngularMotion(RotationAxisLocks);
3267 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); 3865 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
3268 } 3866 }
3269 } 3867 }
@@ -3334,67 +3932,16 @@ namespace OpenSim.Region.Framework.Scenes
3334 ParentGroup.StopMoveToTarget(); 3932 ParentGroup.StopMoveToTarget();
3335 } 3933 }
3336 3934
3337 public void StoreUndoState() 3935 public void StoreUndoState(ObjectChangeType change)
3338 { 3936 {
3339 StoreUndoState(false); 3937 if (m_UndoRedo == null)
3340 } 3938 m_UndoRedo = new UndoRedoState(5);
3341 3939
3342 public void StoreUndoState(bool forGroup) 3940 lock (m_UndoRedo)
3343 {
3344 if (ParentGroup == null || ParentGroup.Scene == null)
3345 return;
3346
3347 if (Undoing)
3348 {
3349// m_log.DebugFormat(
3350// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3351 return;
3352 }
3353
3354 if (IgnoreUndoUpdate)
3355 {
3356// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3357 return;
3358 }
3359
3360 lock (m_undo)
3361 { 3941 {
3362 if (m_undo.Count > 0) 3942 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3363 { 3943 {
3364 UndoState last = m_undo[m_undo.Count - 1]; 3944 m_UndoRedo.StoreUndo(this, change);
3365 if (last != null)
3366 {
3367 // TODO: May need to fix for group comparison
3368 if (last.Compare(this))
3369 {
3370// m_log.DebugFormat(
3371// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3372// Name, LocalId, m_undo.Count);
3373
3374 return;
3375 }
3376 }
3377 }
3378
3379// m_log.DebugFormat(
3380// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3381// Name, LocalId, forGroup, m_undo.Count);
3382
3383 if (ParentGroup.Scene.MaxUndoCount > 0)
3384 {
3385 UndoState nUndo = new UndoState(this, forGroup);
3386
3387 m_undo.Add(nUndo);
3388
3389 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3390 m_undo.RemoveAt(0);
3391
3392 if (m_redo.Count > 0)
3393 m_redo.Clear();
3394
3395// m_log.DebugFormat(
3396// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3397// Name, LocalId, forGroup, m_undo.Count);
3398 } 3945 }
3399 } 3946 }
3400 } 3947 }
@@ -3406,88 +3953,46 @@ namespace OpenSim.Region.Framework.Scenes
3406 { 3953 {
3407 get 3954 get
3408 { 3955 {
3409 lock (m_undo) 3956 if (m_UndoRedo == null)
3410 return m_undo.Count; 3957 return 0;
3958 return m_UndoRedo.Count;
3411 } 3959 }
3412 } 3960 }
3413 3961
3414 public void Undo() 3962 public void Undo()
3415 { 3963 {
3416 lock (m_undo) 3964 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3417 { 3965 return;
3418// m_log.DebugFormat(
3419// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3420// Name, LocalId, m_undo.Count);
3421
3422 if (m_undo.Count > 0)
3423 {
3424 UndoState goback = m_undo[m_undo.Count - 1];
3425 m_undo.RemoveAt(m_undo.Count - 1);
3426
3427 UndoState nUndo = null;
3428
3429 if (ParentGroup.Scene.MaxUndoCount > 0)
3430 {
3431 nUndo = new UndoState(this, goback.ForGroup);
3432 }
3433
3434 goback.PlaybackState(this);
3435
3436 if (nUndo != null)
3437 {
3438 m_redo.Add(nUndo);
3439
3440 if (m_redo.Count > ParentGroup.Scene.MaxUndoCount)
3441 m_redo.RemoveAt(0);
3442 }
3443 }
3444 3966
3445// m_log.DebugFormat( 3967 lock (m_UndoRedo)
3446// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3968 {
3447// Name, LocalId, m_undo.Count); 3969 Undoing = true;
3970 m_UndoRedo.Undo(this);
3971 Undoing = false;
3448 } 3972 }
3449 } 3973 }
3450 3974
3451 public void Redo() 3975 public void Redo()
3452 { 3976 {
3453 lock (m_undo) 3977 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3454 { 3978 return;
3455// m_log.DebugFormat(
3456// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3457// Name, LocalId, m_redo.Count);
3458
3459 if (m_redo.Count > 0)
3460 {
3461 UndoState gofwd = m_redo[m_redo.Count - 1];
3462 m_redo.RemoveAt(m_redo.Count - 1);
3463
3464 if (ParentGroup.Scene.MaxUndoCount > 0)
3465 {
3466 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3467
3468 m_undo.Add(nUndo);
3469
3470 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3471 m_undo.RemoveAt(0);
3472 }
3473
3474 gofwd.PlayfwdState(this);
3475 3979
3476// m_log.DebugFormat( 3980 lock (m_UndoRedo)
3477// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3981 {
3478// Name, LocalId, m_redo.Count); 3982 Undoing = true;
3479 } 3983 m_UndoRedo.Redo(this);
3984 Undoing = false;
3480 } 3985 }
3481 } 3986 }
3482 3987
3483 public void ClearUndoState() 3988 public void ClearUndoState()
3484 { 3989 {
3485// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3990 if (m_UndoRedo == null || Undoing)
3991 return;
3486 3992
3487 lock (m_undo) 3993 lock (m_UndoRedo)
3488 { 3994 {
3489 m_undo.Clear(); 3995 m_UndoRedo.Clear();
3490 m_redo.Clear();
3491 } 3996 }
3492 } 3997 }
3493 3998
@@ -4039,7 +4544,7 @@ namespace OpenSim.Region.Framework.Scenes
4039 if (god) 4544 if (god)
4040 { 4545 {
4041 BaseMask = ApplyMask(BaseMask, set, mask); 4546 BaseMask = ApplyMask(BaseMask, set, mask);
4042 Inventory.ApplyGodPermissions(_baseMask); 4547 Inventory.ApplyGodPermissions(BaseMask);
4043 } 4548 }
4044 4549
4045 break; 4550 break;
@@ -4070,7 +4575,7 @@ namespace OpenSim.Region.Framework.Scenes
4070 } 4575 }
4071 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) & 4576 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) &
4072 baseMask; 4577 baseMask;
4073 // Prevent the client from creating no mod, no copy 4578 // Prevent the client from creating no copy, no transfer
4074 // objects 4579 // objects
4075 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0) 4580 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0)
4076 NextOwnerMask |= (uint)PermissionMask.Transfer; 4581 NextOwnerMask |= (uint)PermissionMask.Transfer;
@@ -4086,22 +4591,20 @@ namespace OpenSim.Region.Framework.Scenes
4086 4591
4087 public void ClonePermissions(SceneObjectPart source) 4592 public void ClonePermissions(SceneObjectPart source)
4088 { 4593 {
4089 bool update = false; 4594 uint prevOwnerMask = OwnerMask;
4595 uint prevGroupMask = GroupMask;
4596 uint prevEveryoneMask = EveryoneMask;
4597 uint prevNextOwnerMask = NextOwnerMask;
4090 4598
4091 if (BaseMask != source.BaseMask || 4599 OwnerMask = source.OwnerMask & BaseMask;
4092 OwnerMask != source.OwnerMask || 4600 GroupMask = source.GroupMask & BaseMask;
4093 GroupMask != source.GroupMask || 4601 EveryoneMask = source.EveryoneMask & BaseMask;
4094 EveryoneMask != source.EveryoneMask || 4602 NextOwnerMask = source.NextOwnerMask & BaseMask;
4095 NextOwnerMask != source.NextOwnerMask)
4096 update = true;
4097 4603
4098 BaseMask = source.BaseMask; 4604 if (OwnerMask != prevOwnerMask ||
4099 OwnerMask = source.OwnerMask; 4605 GroupMask != prevGroupMask ||
4100 GroupMask = source.GroupMask; 4606 EveryoneMask != prevEveryoneMask ||
4101 EveryoneMask = source.EveryoneMask; 4607 NextOwnerMask != prevNextOwnerMask)
4102 NextOwnerMask = source.NextOwnerMask;
4103
4104 if (update)
4105 SendFullUpdateToAllClients(); 4608 SendFullUpdateToAllClients();
4106 } 4609 }
4107 4610
@@ -4152,6 +4655,7 @@ namespace OpenSim.Region.Framework.Scenes
4152 } 4655 }
4153 } 4656 }
4154 4657
4658
4155 public void UpdateExtraPhysics(ExtraPhysicsData physdata) 4659 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4156 { 4660 {
4157 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null) 4661 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
@@ -4179,7 +4683,7 @@ namespace OpenSim.Region.Framework.Scenes
4179 /// <param name="SetTemporary"></param> 4683 /// <param name="SetTemporary"></param>
4180 /// <param name="SetPhantom"></param> 4684 /// <param name="SetPhantom"></param>
4181 /// <param name="SetVD"></param> 4685 /// <param name="SetVD"></param>
4182 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4686 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
4183 { 4687 {
4184 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4688 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
4185 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4689 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -4189,99 +4693,104 @@ namespace OpenSim.Region.Framework.Scenes
4189 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4693 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4190 return; 4694 return;
4191 4695
4192 PhysicsActor pa = PhysActor; 4696 VolumeDetectActive = SetVD;
4193
4194 // Special cases for VD. VD can only be called from a script
4195 // and can't be combined with changes to other states. So we can rely
4196 // that...
4197 // ... if VD is changed, all others are not.
4198 // ... if one of the others is changed, VD is not.
4199 if (SetVD) // VD is active, special logic applies
4200 {
4201 // State machine logic for VolumeDetect
4202 // More logic below
4203 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
4204 4697
4205 if (phanReset) // Phantom changes from on to off switch VD off too 4698 // volume detector implies phantom
4206 { 4699 if (VolumeDetectActive)
4207 SetVD = false; // Switch it of for the course of this routine
4208 VolumeDetectActive = false; // and also permanently
4209
4210 if (pa != null)
4211 pa.SetVolumeDetect(0); // Let physics know about it too
4212 }
4213 else
4214 {
4215 // If volumedetect is active we don't want phantom to be applied.
4216 // If this is a new call to VD out of the state "phantom"
4217 // this will also cause the prim to be visible to physics
4218 SetPhantom = false;
4219 }
4220 }
4221
4222 if (UsePhysics && IsJoint())
4223 {
4224 SetPhantom = true; 4700 SetPhantom = true;
4225 }
4226 4701
4227 if (UsePhysics) 4702 if (UsePhysics)
4228 {
4229 AddFlag(PrimFlags.Physics); 4703 AddFlag(PrimFlags.Physics);
4230 if (!wasUsingPhysics)
4231 {
4232 DoPhysicsPropertyUpdate(UsePhysics, false);
4233 }
4234 }
4235 else 4704 else
4236 {
4237 RemFlag(PrimFlags.Physics); 4705 RemFlag(PrimFlags.Physics);
4238 if (wasUsingPhysics)
4239 {
4240 DoPhysicsPropertyUpdate(UsePhysics, false);
4241 }
4242 }
4243 4706
4244 if (SetPhantom 4707 if (SetPhantom)
4245 || ParentGroup.IsAttachmentCheckFull()
4246 || PhysicsShapeType == (byte)PhysShapeType.none
4247 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
4248 {
4249 AddFlag(PrimFlags.Phantom); 4708 AddFlag(PrimFlags.Phantom);
4709 else
4710 RemFlag(PrimFlags.Phantom);
4250 4711
4251 if (PhysActor != null) 4712 if (SetTemporary)
4713 AddFlag(PrimFlags.TemporaryOnRez);
4714 else
4715 RemFlag(PrimFlags.TemporaryOnRez);
4716
4717
4718 if (ParentGroup.Scene == null)
4719 return;
4720
4721 PhysicsActor pa = PhysActor;
4722
4723 if (pa != null && building && pa.Building != building)
4724 pa.Building = building;
4725
4726 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4727 || (Shape.PathCurve == (byte)Extrusion.Flexible))
4728 {
4729 if (pa != null)
4252 { 4730 {
4731 if(wasUsingPhysics)
4732 ParentGroup.Scene.RemovePhysicalPrim(1);
4253 RemoveFromPhysics(); 4733 RemoveFromPhysics();
4254 pa = null;
4255 } 4734 }
4735
4736 Velocity = new Vector3(0, 0, 0);
4737 Acceleration = new Vector3(0, 0, 0);
4738 if (ParentGroup.RootPart == this)
4739 AngularVelocity = new Vector3(0, 0, 0);
4256 } 4740 }
4257 else // Not phantom 4741
4742 else
4258 { 4743 {
4259 RemFlag(PrimFlags.Phantom); 4744 if (ParentGroup.Scene.CollidablePrims)
4260
4261 if (ParentGroup.Scene == null)
4262 return;
4263
4264 if (ParentGroup.Scene.CollidablePrims && pa == null)
4265 { 4745 {
4266 AddToPhysics(UsePhysics, SetPhantom, false); 4746 if (pa == null)
4267 pa = PhysActor; 4747 {
4268 4748 AddToPhysics(UsePhysics, SetPhantom, building, false);
4269 if (pa != null) 4749 pa = PhysActor;
4750/*
4751 if (pa != null)
4752 {
4753 if (
4754// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4755// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4756// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4757// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4758// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4759// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4760 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4761 ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4762 (CollisionSound != UUID.Zero)
4763 )
4764 {
4765 pa.OnCollisionUpdate += PhysicsCollision;
4766 pa.SubscribeEvents(1000);
4767 }
4768 }
4769*/
4770 if (pa != null)
4771 {
4772 pa.SetMaterial(Material);
4773 DoPhysicsPropertyUpdate(UsePhysics, true);
4774 }
4775 }
4776 else // it already has a physical representation
4270 { 4777 {
4271 pa.SetMaterial(Material);
4272 pa.Position = GetWorldPosition();
4273 pa.Orientation = GetWorldRotation();
4274 DoPhysicsPropertyUpdate(UsePhysics, true);
4275 4778
4276 SubscribeForCollisionEvents(); 4779 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4780/* moved into DoPhysicsPropertyUpdate
4781 if(VolumeDetectActive)
4782 pa.SetVolumeDetect(1);
4783 else
4784 pa.SetVolumeDetect(0);
4785*/
4786
4787 if (pa.Building != building)
4788 pa.Building = building;
4277 } 4789 }
4278 }
4279 else // it already has a physical representation
4280 {
4281 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4282 }
4283 }
4284 4790
4791 UpdatePhysicsSubscribedEvents();
4792 }
4793 }
4285 if (SetVD) 4794 if (SetVD)
4286 { 4795 {
4287 // If the above logic worked (this is urgent candidate to unit tests!) 4796 // If the above logic worked (this is urgent candidate to unit tests!)
@@ -4295,6 +4804,7 @@ namespace OpenSim.Region.Framework.Scenes
4295 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4804 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active
4296 VolumeDetectActive = true; 4805 VolumeDetectActive = true;
4297 } 4806 }
4807 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4298 } 4808 }
4299 else if (SetVD != wasVD) 4809 else if (SetVD != wasVD)
4300 { 4810 {
@@ -4306,105 +4816,51 @@ namespace OpenSim.Region.Framework.Scenes
4306 RemFlag(PrimFlags.Phantom); 4816 RemFlag(PrimFlags.Phantom);
4307 VolumeDetectActive = false; 4817 VolumeDetectActive = false;
4308 } 4818 }
4309 4819 // and last in case we have a new actor and not building
4310 if (SetTemporary)
4311 {
4312 AddFlag(PrimFlags.TemporaryOnRez);
4313 }
4314 else
4315 {
4316 RemFlag(PrimFlags.TemporaryOnRez);
4317 }
4318
4319 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4320 4820
4321 if (ParentGroup != null) 4821 if (ParentGroup != null)
4322 { 4822 {
4323 ParentGroup.HasGroupChanged = true; 4823 ParentGroup.HasGroupChanged = true;
4324 ScheduleFullUpdate(); 4824 ScheduleFullUpdate();
4325 } 4825 }
4326 4826
4327// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4827// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4328 } 4828 }
4329 4829
4330 /// <summary> 4830 /// <summary>
4331 /// Subscribe for physics collision events if needed for scripts and sounds
4332 /// </summary>
4333 public void SubscribeForCollisionEvents()
4334 {
4335 PhysicsActor pa = PhysActor;
4336
4337 if (pa != null)
4338 {
4339 if (
4340 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4341 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4342 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4343 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4344 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4345 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4346 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4347 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4348 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4349 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4350 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4351 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4352 (CollisionSound != UUID.Zero)
4353 )
4354 {
4355 if (!pa.SubscribedEvents())
4356 {
4357 // If not already subscribed for event, set up for a collision event.
4358 pa.OnCollisionUpdate += PhysicsCollision;
4359 pa.SubscribeEvents(1000);
4360 }
4361 }
4362 else
4363 {
4364 // There is no need to be subscribed to collisions so, if subscribed, remove subscription
4365 if (pa.SubscribedEvents())
4366 {
4367 pa.OnCollisionUpdate -= PhysicsCollision;
4368 pa.UnSubscribeEvents();
4369 }
4370 }
4371 }
4372 }
4373
4374 /// <summary>
4375 /// Adds this part to the physics scene. 4831 /// Adds this part to the physics scene.
4832 /// and sets the PhysActor property
4376 /// </summary> 4833 /// </summary>
4377 /// <remarks>This method also sets the PhysActor property.</remarks> 4834 /// <param name="isPhysical">Add this prim as physical.</param>
4378 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4835 /// <param name="isPhantom">Add this prim as phantom.</param>
4379 /// <returns> 4836 /// <param name="building">tells physics to delay full construction of object</param>
4380 /// The physics actor. null if there was a failure. 4837 /// <param name="applyDynamics">applies velocities, force and torque</param>
4381 /// </returns> 4838 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4382 private void AddToPhysics(bool isPhysical, bool isPhantom, bool applyDynamics) 4839 {
4383 {
4384 PhysicsActor pa; 4840 PhysicsActor pa;
4385 4841
4386 Vector3 velocity = Velocity; 4842 Vector3 velocity = Velocity;
4387 Vector3 rotationalVelocity = AngularVelocity;; 4843 Vector3 rotationalVelocity = AngularVelocity;;
4388 4844
4389 try 4845 try
4390 { 4846 {
4391 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4847 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4392 string.Format("{0}/{1}", Name, UUID), 4848 string.Format("{0}/{1}", Name, UUID),
4393 Shape, 4849 Shape,
4394 AbsolutePosition, 4850 AbsolutePosition,
4395 Scale, 4851 Scale,
4396 GetWorldRotation(), 4852 GetWorldRotation(),
4397 isPhysical, 4853 isPhysical,
4398 isPhantom, 4854 isPhantom,
4399 PhysicsShapeType, 4855 PhysicsShapeType,
4400 m_localId); 4856 m_localId);
4401 } 4857 }
4402 catch (Exception e) 4858 catch (Exception e)
4403 { 4859 {
4404 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e); 4860 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom. e={1}", m_uuid, e);
4405 pa = null; 4861 pa = null;
4406 } 4862 }
4407 4863
4408 if (pa != null) 4864 if (pa != null)
4409 { 4865 {
4410 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4866 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
@@ -4415,11 +4871,23 @@ namespace OpenSim.Region.Framework.Scenes
4415 pa.Friction = Friction; 4871 pa.Friction = Friction;
4416 pa.Restitution = Restitution; 4872 pa.Restitution = Restitution;
4417 4873
4874 if(LocalId == ParentGroup.RootPart.LocalId)
4875 {
4876 pa.LockAngularMotion(RotationAxisLocks);
4877 }
4878
4418 if (VolumeDetectActive) // change if not the default only 4879 if (VolumeDetectActive) // change if not the default only
4419 pa.SetVolumeDetect(1); 4880 pa.SetVolumeDetect(1);
4881
4882 if (m_vehicleParams != null && LocalId == ParentGroup.RootPart.LocalId)
4883 m_vehicleParams.SetVehicle(pa);
4884
4420 // we are going to tell rest of code about physics so better have this here 4885 // we are going to tell rest of code about physics so better have this here
4421 PhysActor = pa; 4886 PhysActor = pa;
4422 4887
4888 // DoPhysicsPropertyUpdate(isPhysical, true);
4889 // lets expand it here just with what it really needs to do
4890
4423 if (isPhysical) 4891 if (isPhysical)
4424 { 4892 {
4425 if (ParentGroup.RootPart.KeyframeMotion != null) 4893 if (ParentGroup.RootPart.KeyframeMotion != null)
@@ -4441,19 +4909,34 @@ namespace OpenSim.Region.Framework.Scenes
4441 } 4909 }
4442 } 4910 }
4443 4911
4444 if (applyDynamics) 4912 if (applyDynamics)
4445 // do independent of isphysical so parameters get setted (at least some) 4913 // do independent of isphysical so parameters get setted (at least some)
4446 { 4914 {
4447 Velocity = velocity; 4915 Velocity = velocity;
4448 AngularVelocity = rotationalVelocity; 4916 AngularVelocity = rotationalVelocity;
4449// pa.Velocity = velocity; 4917// pa.Velocity = velocity;
4450 pa.RotationalVelocity = rotationalVelocity; 4918 pa.RotationalVelocity = rotationalVelocity;
4919
4920 // if not vehicle and root part apply force and torque
4921 if ((m_vehicleParams == null || m_vehicleParams.Type == Vehicle.TYPE_NONE)
4922 && LocalId == ParentGroup.RootPart.LocalId)
4923 {
4924 pa.Force = Force;
4925 pa.Torque = Torque;
4926 }
4451 } 4927 }
4452 4928
4453 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); 4929// if (Shape.SculptEntry)
4930// CheckSculptAndLoad();
4931// else
4932 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4933
4934 if (!building)
4935 pa.Building = false;
4454 } 4936 }
4455 4937
4456 PhysActor = pa; 4938 PhysActor = pa;
4939
4457 ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this); 4940 ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this);
4458 } 4941 }
4459 4942
@@ -4462,14 +4945,21 @@ namespace OpenSim.Region.Framework.Scenes
4462 /// </summary> 4945 /// </summary>
4463 /// <remarks> 4946 /// <remarks>
4464 /// This isn't the same as turning off physical, since even without being physical the prim has a physics 4947 /// This isn't the same as turning off physical, since even without being physical the prim has a physics
4465 /// representation for collision detection. Rather, this would be used in situations such as making a prim 4948 /// representation for collision detection.
4466 /// phantom.
4467 /// </remarks> 4949 /// </remarks>
4468 public void RemoveFromPhysics() 4950 public void RemoveFromPhysics()
4469 { 4951 {
4470 ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this); 4952 PhysicsActor pa = PhysActor;
4471 if (ParentGroup.Scene.PhysicsScene != null) 4953 if (pa != null)
4472 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 4954 {
4955 pa.OnCollisionUpdate -= PhysicsCollision;
4956 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
4957 pa.OnOutOfBounds -= PhysicsOutOfBounds;
4958
4959 ParentGroup.Scene.PhysicsScene.RemovePrim(pa);
4960
4961 ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this);
4962 }
4473 PhysActor = null; 4963 PhysActor = null;
4474 } 4964 }
4475 4965
@@ -4601,6 +5091,8 @@ namespace OpenSim.Region.Framework.Scenes
4601 { 5091 {
4602// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); 5092// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
4603 5093
5094 return;
5095
4604 if (ParentGroup.IsDeleted) 5096 if (ParentGroup.IsDeleted)
4605 return; 5097 return;
4606 5098
@@ -4724,6 +5216,44 @@ namespace OpenSim.Region.Framework.Scenes
4724 } 5216 }
4725 } 5217 }
4726 5218
5219
5220 private void UpdatePhysicsSubscribedEvents()
5221 {
5222 PhysicsActor pa = PhysActor;
5223 if (pa == null)
5224 return;
5225
5226 pa.OnCollisionUpdate -= PhysicsCollision;
5227
5228 bool hassound = (!VolumeDetectActive && CollisionSoundType >= 0 && ((Flags & PrimFlags.Physics) != 0));
5229
5230 scriptEvents CombinedEvents = AggregateScriptEvents;
5231
5232 // merge with root part
5233 if (ParentGroup != null && ParentGroup.RootPart != null)
5234 CombinedEvents |= ParentGroup.RootPart.AggregateScriptEvents;
5235
5236 // submit to this part case
5237 if (VolumeDetectActive)
5238 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
5239 else if ((Flags & PrimFlags.Phantom) != 0)
5240 CombinedEvents &= PhyscicsPhantonSubsEvents;
5241 else
5242 CombinedEvents &= PhysicsNeededSubsEvents;
5243
5244 if (hassound || CombinedEvents != 0)
5245 {
5246 // subscribe to physics updates.
5247 pa.OnCollisionUpdate += PhysicsCollision;
5248 pa.SubscribeEvents(50); // 20 reports per second
5249 }
5250 else
5251 {
5252 pa.UnSubscribeEvents();
5253 }
5254 }
5255
5256
4727 public void aggregateScriptEvents() 5257 public void aggregateScriptEvents()
4728 { 5258 {
4729 if (ParentGroup == null || ParentGroup.RootPart == null) 5259 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4760,8 +5290,32 @@ namespace OpenSim.Region.Framework.Scenes
4760 { 5290 {
4761 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 5291 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4762 } 5292 }
4763 5293/*
4764 SubscribeForCollisionEvents(); 5294 PhysicsActor pa = PhysActor;
5295 if (pa != null)
5296 {
5297 if (
5298// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
5299// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
5300// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
5301// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
5302// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
5303// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
5304 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
5305 )
5306 {
5307 // subscribe to physics updates.
5308 pa.OnCollisionUpdate += PhysicsCollision;
5309 pa.SubscribeEvents(1000);
5310 }
5311 else
5312 {
5313 pa.UnSubscribeEvents();
5314 pa.OnCollisionUpdate -= PhysicsCollision;
5315 }
5316 }
5317 */
5318 UpdatePhysicsSubscribedEvents();
4765 5319
4766 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 5320 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4767 //{ 5321 //{
@@ -4970,6 +5524,18 @@ namespace OpenSim.Region.Framework.Scenes
4970 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5524 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4971 } 5525 }
4972 5526
5527 public void ResetOwnerChangeFlag()
5528 {
5529 List<UUID> inv = Inventory.GetInventoryList();
5530
5531 foreach (UUID itemID in inv)
5532 {
5533 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5534 item.OwnerChanged = false;
5535 Inventory.UpdateInventoryItem(item, false, false);
5536 }
5537 }
5538
4973 /// <summary> 5539 /// <summary>
4974 /// Record an avatar sitting on this part. 5540 /// Record an avatar sitting on this part.
4975 /// </summary> 5541 /// </summary>
@@ -4990,7 +5556,8 @@ namespace OpenSim.Region.Framework.Scenes
4990 5556
4991 if (m_sittingAvatars.Add(sp)) 5557 if (m_sittingAvatars.Add(sp))
4992 { 5558 {
4993 ParentGroup.m_sittingAvatars.Add(sp); 5559 if(!ParentGroup.m_sittingAvatars.Contains(sp))
5560 ParentGroup.m_sittingAvatars.Add(sp);
4994 5561
4995 return true; 5562 return true;
4996 } 5563 }
@@ -5063,4 +5630,4 @@ namespace OpenSim.Region.Framework.Scenes
5063 } 5630 }
5064 } 5631 }
5065 } 5632 }
5066} \ No newline at end of file 5633}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index ec39726..5811ed9 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -46,9 +46,12 @@ namespace OpenSim.Region.Framework.Scenes
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 string m_inventoryFileName = String.Empty;
50 private byte[] m_inventoryFileData = new byte[0]; 49 private byte[] m_inventoryFileData = new byte[0];
51 private uint m_inventoryFileNameSerial = 0; 50 private uint m_inventoryFileNameSerial = 0;
51 private bool m_inventoryPrivileged = false;
52 private object m_inventoryFileLock = new object();
53
54 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
52 55
53 /// <value> 56 /// <value>
54 /// The part to which the inventory belongs. 57 /// The part to which the inventory belongs.
@@ -85,7 +88,9 @@ namespace OpenSim.Region.Framework.Scenes
85 /// </value> 88 /// </value>
86 protected internal TaskInventoryDictionary Items 89 protected internal TaskInventoryDictionary Items
87 { 90 {
88 get { return m_items; } 91 get {
92 return m_items;
93 }
89 set 94 set
90 { 95 {
91 m_items = value; 96 m_items = value;
@@ -134,38 +139,45 @@ namespace OpenSim.Region.Framework.Scenes
134 public void ResetInventoryIDs() 139 public void ResetInventoryIDs()
135 { 140 {
136 if (null == m_part) 141 if (null == m_part)
137 return; 142 m_items.LockItemsForWrite(true);
138 143
139 lock (m_items) 144 if (Items.Count == 0)
140 { 145 {
141 if (0 == m_items.Count) 146 m_items.LockItemsForWrite(false);
142 return; 147 return;
148 }
143 149
144 IList<TaskInventoryItem> items = GetInventoryItems(); 150 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
145 m_items.Clear(); 151 Items.Clear();
146 152
147 foreach (TaskInventoryItem item in items) 153 foreach (TaskInventoryItem item in items)
148 { 154 {
149 item.ResetIDs(m_part.UUID); 155 item.ResetIDs(m_part.UUID);
150 m_items.Add(item.ItemID, item); 156 Items.Add(item.ItemID, item);
151 }
152 } 157 }
158 m_items.LockItemsForWrite(false);
153 } 159 }
154 160
155 public void ResetObjectID() 161 public void ResetObjectID()
156 { 162 {
157 lock (Items) 163 m_items.LockItemsForWrite(true);
164
165 if (Items.Count == 0)
158 { 166 {
159 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 167 m_items.LockItemsForWrite(false);
160 Items.Clear(); 168 return;
161
162 foreach (TaskInventoryItem item in items)
163 {
164 item.ParentPartID = m_part.UUID;
165 item.ParentID = m_part.UUID;
166 Items.Add(item.ItemID, item);
167 }
168 } 169 }
170
171 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
172 Items.Clear();
173
174 foreach (TaskInventoryItem item in items)
175 {
176 item.ParentPartID = m_part.UUID;
177 item.ParentID = m_part.UUID;
178 Items.Add(item.ItemID, item);
179 }
180 m_items.LockItemsForWrite(false);
169 } 181 }
170 182
171 /// <summary> 183 /// <summary>
@@ -174,17 +186,14 @@ namespace OpenSim.Region.Framework.Scenes
174 /// <param name="ownerId"></param> 186 /// <param name="ownerId"></param>
175 public void ChangeInventoryOwner(UUID ownerId) 187 public void ChangeInventoryOwner(UUID ownerId)
176 { 188 {
177 lock (Items) 189 List<TaskInventoryItem> items = GetInventoryItems();
178 {
179 if (0 == Items.Count)
180 {
181 return;
182 }
183 }
184 190
191 if (items.Count == 0)
192 return;
193
194 m_items.LockItemsForWrite(true);
185 HasInventoryChanged = true; 195 HasInventoryChanged = true;
186 m_part.ParentGroup.HasGroupChanged = true; 196 m_part.ParentGroup.HasGroupChanged = true;
187 List<TaskInventoryItem> items = GetInventoryItems();
188 foreach (TaskInventoryItem item in items) 197 foreach (TaskInventoryItem item in items)
189 { 198 {
190 if (ownerId != item.OwnerID) 199 if (ownerId != item.OwnerID)
@@ -195,6 +204,7 @@ namespace OpenSim.Region.Framework.Scenes
195 item.PermsGranter = UUID.Zero; 204 item.PermsGranter = UUID.Zero;
196 item.OwnerChanged = true; 205 item.OwnerChanged = true;
197 } 206 }
207 m_items.LockItemsForWrite(false);
198 } 208 }
199 209
200 /// <summary> 210 /// <summary>
@@ -203,12 +213,11 @@ namespace OpenSim.Region.Framework.Scenes
203 /// <param name="groupID"></param> 213 /// <param name="groupID"></param>
204 public void ChangeInventoryGroup(UUID groupID) 214 public void ChangeInventoryGroup(UUID groupID)
205 { 215 {
206 lock (Items) 216 m_items.LockItemsForWrite(true);
217 if (0 == Items.Count)
207 { 218 {
208 if (0 == Items.Count) 219 m_items.LockItemsForWrite(false);
209 { 220 return;
210 return;
211 }
212 } 221 }
213 222
214 // Don't let this set the HasGroupChanged flag for attachments 223 // Don't let this set the HasGroupChanged flag for attachments
@@ -220,12 +229,15 @@ namespace OpenSim.Region.Framework.Scenes
220 m_part.ParentGroup.HasGroupChanged = true; 229 m_part.ParentGroup.HasGroupChanged = true;
221 } 230 }
222 231
223 List<TaskInventoryItem> items = GetInventoryItems(); 232 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
224 foreach (TaskInventoryItem item in items) 233 foreach (TaskInventoryItem item in items)
225 { 234 {
226 if (groupID != item.GroupID) 235 if (groupID != item.GroupID)
236 {
227 item.GroupID = groupID; 237 item.GroupID = groupID;
238 }
228 } 239 }
240 m_items.LockItemsForWrite(false);
229 } 241 }
230 242
231 private void QueryScriptStates() 243 private void QueryScriptStates()
@@ -233,15 +245,18 @@ namespace OpenSim.Region.Framework.Scenes
233 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) 245 if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null)
234 return; 246 return;
235 247
236 lock (Items) 248 Items.LockItemsForRead(true);
249 foreach (TaskInventoryItem item in Items.Values)
237 { 250 {
238 foreach (TaskInventoryItem item in Items.Values) 251 if (item.InvType == (int)InventoryType.LSL)
239 { 252 {
240 bool running; 253 bool running;
241 if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running)) 254 if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running))
242 item.ScriptRunning = running; 255 item.ScriptRunning = running;
243 } 256 }
244 } 257 }
258
259 Items.LockItemsForRead(false);
245 } 260 }
246 261
247 public bool TryGetScriptInstanceRunning(UUID itemId, out bool running) 262 public bool TryGetScriptInstanceRunning(UUID itemId, out bool running)
@@ -318,7 +333,10 @@ namespace OpenSim.Region.Framework.Scenes
318 { 333 {
319 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL); 334 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
320 foreach (TaskInventoryItem item in scripts) 335 foreach (TaskInventoryItem item in scripts)
336 {
321 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 337 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
338 m_part.RemoveScriptEvents(item.ItemID);
339 }
322 } 340 }
323 341
324 /// <summary> 342 /// <summary>
@@ -340,7 +358,10 @@ namespace OpenSim.Region.Framework.Scenes
340// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName); 358// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName);
341 359
342 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 360 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
361 {
362 StoreScriptError(item.ItemID, "no permission");
343 return false; 363 return false;
364 }
344 365
345 m_part.AddFlag(PrimFlags.Scripted); 366 m_part.AddFlag(PrimFlags.Scripted);
346 367
@@ -350,14 +371,13 @@ namespace OpenSim.Region.Framework.Scenes
350 if (stateSource == 2 && // Prim crossing 371 if (stateSource == 2 && // Prim crossing
351 m_part.ParentGroup.Scene.m_trustBinaries) 372 m_part.ParentGroup.Scene.m_trustBinaries)
352 { 373 {
353 lock (m_items) 374 m_items.LockItemsForWrite(true);
354 { 375 m_items[item.ItemID].PermsMask = 0;
355 m_items[item.ItemID].PermsMask = 0; 376 m_items[item.ItemID].PermsGranter = UUID.Zero;
356 m_items[item.ItemID].PermsGranter = UUID.Zero; 377 m_items.LockItemsForWrite(false);
357 }
358
359 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 378 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
360 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 379 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
380 StoreScriptErrors(item.ItemID, null);
361 m_part.ParentGroup.AddActiveScriptCount(1); 381 m_part.ParentGroup.AddActiveScriptCount(1);
362 m_part.ScheduleFullUpdate(); 382 m_part.ScheduleFullUpdate();
363 return true; 383 return true;
@@ -366,6 +386,8 @@ namespace OpenSim.Region.Framework.Scenes
366 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 386 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
367 if (null == asset) 387 if (null == asset)
368 { 388 {
389 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
390 StoreScriptError(item.ItemID, msg);
369 m_log.ErrorFormat( 391 m_log.ErrorFormat(
370 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 392 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
371 item.Name, item.ItemID, m_part.AbsolutePosition, 393 item.Name, item.ItemID, m_part.AbsolutePosition,
@@ -378,16 +400,18 @@ namespace OpenSim.Region.Framework.Scenes
378 if (m_part.ParentGroup.m_savedScriptState != null) 400 if (m_part.ParentGroup.m_savedScriptState != null)
379 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); 401 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
380 402
381 lock (m_items) 403 m_items.LockItemsForWrite(true);
382 {
383 m_items[item.ItemID].OldItemID = item.OldItemID;
384 m_items[item.ItemID].PermsMask = 0;
385 m_items[item.ItemID].PermsGranter = UUID.Zero;
386 }
387 404
405 m_items[item.ItemID].OldItemID = item.OldItemID;
406 m_items[item.ItemID].PermsMask = 0;
407 m_items[item.ItemID].PermsGranter = UUID.Zero;
408
409 m_items.LockItemsForWrite(false);
410
388 string script = Utils.BytesToString(asset.Data); 411 string script = Utils.BytesToString(asset.Data);
389 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 412 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
390 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 413 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
414 StoreScriptErrors(item.ItemID, null);
391 if (!item.ScriptRunning) 415 if (!item.ScriptRunning)
392 m_part.ParentGroup.Scene.EventManager.TriggerStopScript( 416 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
393 m_part.LocalId, item.ItemID); 417 m_part.LocalId, item.ItemID);
@@ -466,22 +490,138 @@ namespace OpenSim.Region.Framework.Scenes
466 return stateID; 490 return stateID;
467 } 491 }
468 492
493 /// <summary>
494 /// Start a script which is in this prim's inventory.
495 /// Some processing may occur in the background, but this routine returns asap.
496 /// </summary>
497 /// <param name="itemId">
498 /// A <see cref="UUID"/>
499 /// </param>
469 public bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 500 public bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
470 { 501 {
471 TaskInventoryItem item = GetInventoryItem(itemId); 502 lock (m_scriptErrors)
472 if (item != null) 503 {
504 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
505 m_scriptErrors.Remove(itemId);
506 }
507 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
508 return true;
509 }
510
511 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
512 {
513 m_items.LockItemsForRead(true);
514
515 if (m_items.ContainsKey(itemId))
473 { 516 {
474 return CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 517 TaskInventoryItem it = m_items[itemId];
518 m_items.LockItemsForRead(false);
519
520 CreateScriptInstance(it, startParam, postOnRez, engine, stateSource);
475 } 521 }
476 else 522 else
477 { 523 {
478 m_log.ErrorFormat( 524 m_items.LockItemsForRead(false);
479 "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 525 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
480 itemId, m_part.Name, m_part.UUID,
481 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 526 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
527 StoreScriptError(itemId, msg);
528 m_log.ErrorFormat(
529 "[PRIM INVENTORY]: " +
530 "Couldn't start script with ID {0} since it {1}", itemId, msg);
531 }
532 }
482 533
483 return false; 534 /// <summary>
535 /// Start a script which is in this prim's inventory and return any compilation error messages.
536 /// </summary>
537 /// <param name="itemId">
538 /// A <see cref="UUID"/>
539 /// </param>
540 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
541 {
542 ArrayList errors;
543
544 // Indicate to CreateScriptInstanceInternal() we want it to
545 // post any compilation/loading error messages
546 lock (m_scriptErrors)
547 {
548 m_scriptErrors[itemId] = null;
484 } 549 }
550
551 // Perform compilation/loading
552 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
553
554 // Wait for and retrieve any errors
555 lock (m_scriptErrors)
556 {
557 while ((errors = m_scriptErrors[itemId]) == null)
558 {
559 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
560 {
561 m_log.ErrorFormat(
562 "[PRIM INVENTORY]: " +
563 "timedout waiting for script {0} errors", itemId);
564 errors = m_scriptErrors[itemId];
565 if (errors == null)
566 {
567 errors = new ArrayList(1);
568 errors.Add("timedout waiting for errors");
569 }
570 break;
571 }
572 }
573 m_scriptErrors.Remove(itemId);
574 }
575 return errors;
576 }
577
578 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
579 private void StoreScriptErrors(UUID itemId, ArrayList errors)
580 {
581 lock (m_scriptErrors)
582 {
583 // If compilation/loading initiated via CreateScriptInstance(),
584 // it does not want the errors, so just get out
585 if (!m_scriptErrors.ContainsKey(itemId))
586 {
587 return;
588 }
589
590 // Initiated via CreateScriptInstanceEr(), if we know what the
591 // errors are, save them and wake CreateScriptInstanceEr().
592 if (errors != null)
593 {
594 m_scriptErrors[itemId] = errors;
595 System.Threading.Monitor.PulseAll(m_scriptErrors);
596 return;
597 }
598 }
599
600 // Initiated via CreateScriptInstanceEr() but we don't know what
601 // the errors are yet, so retrieve them from the script engine.
602 // This may involve some waiting internal to GetScriptErrors().
603 errors = GetScriptErrors(itemId);
604
605 // Get a default non-null value to indicate success.
606 if (errors == null)
607 {
608 errors = new ArrayList();
609 }
610
611 // Post to CreateScriptInstanceEr() and wake it up
612 lock (m_scriptErrors)
613 {
614 m_scriptErrors[itemId] = errors;
615 System.Threading.Monitor.PulseAll(m_scriptErrors);
616 }
617 }
618
619 // Like StoreScriptErrors(), but just posts a single string message
620 private void StoreScriptError(UUID itemId, string message)
621 {
622 ArrayList errors = new ArrayList(1);
623 errors.Add(message);
624 StoreScriptErrors(itemId, errors);
485 } 625 }
486 626
487 /// <summary> 627 /// <summary>
@@ -494,15 +634,7 @@ namespace OpenSim.Region.Framework.Scenes
494 /// </param> 634 /// </param>
495 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 635 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
496 { 636 {
497 bool scriptPresent = false; 637 if (m_items.ContainsKey(itemId))
498
499 lock (m_items)
500 {
501 if (m_items.ContainsKey(itemId))
502 scriptPresent = true;
503 }
504
505 if (scriptPresent)
506 { 638 {
507 if (!sceneObjectBeingDeleted) 639 if (!sceneObjectBeingDeleted)
508 m_part.RemoveScriptEvents(itemId); 640 m_part.RemoveScriptEvents(itemId);
@@ -573,14 +705,16 @@ namespace OpenSim.Region.Framework.Scenes
573 /// <returns></returns> 705 /// <returns></returns>
574 private bool InventoryContainsName(string name) 706 private bool InventoryContainsName(string name)
575 { 707 {
576 lock (m_items) 708 m_items.LockItemsForRead(true);
709 foreach (TaskInventoryItem item in m_items.Values)
577 { 710 {
578 foreach (TaskInventoryItem item in m_items.Values) 711 if (item.Name == name)
579 { 712 {
580 if (item.Name == name) 713 m_items.LockItemsForRead(false);
581 return true; 714 return true;
582 } 715 }
583 } 716 }
717 m_items.LockItemsForRead(false);
584 return false; 718 return false;
585 } 719 }
586 720
@@ -622,8 +756,9 @@ namespace OpenSim.Region.Framework.Scenes
622 /// <param name="item"></param> 756 /// <param name="item"></param>
623 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 757 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
624 { 758 {
625 List<TaskInventoryItem> il = GetInventoryItems(); 759 m_items.LockItemsForRead(true);
626 760 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
761 m_items.LockItemsForRead(false);
627 foreach (TaskInventoryItem i in il) 762 foreach (TaskInventoryItem i in il)
628 { 763 {
629 if (i.Name == item.Name) 764 if (i.Name == item.Name)
@@ -661,14 +796,14 @@ namespace OpenSim.Region.Framework.Scenes
661 item.Name = name; 796 item.Name = name;
662 item.GroupID = m_part.GroupID; 797 item.GroupID = m_part.GroupID;
663 798
664 lock (m_items) 799 m_items.LockItemsForWrite(true);
665 m_items.Add(item.ItemID, item); 800 m_items.Add(item.ItemID, item);
666 801 m_items.LockItemsForWrite(false);
667 if (allowedDrop) 802 if (allowedDrop)
668 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 803 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
669 else 804 else
670 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 805 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
671 806
672 m_inventorySerial++; 807 m_inventorySerial++;
673 //m_inventorySerial += 2; 808 //m_inventorySerial += 2;
674 HasInventoryChanged = true; 809 HasInventoryChanged = true;
@@ -684,15 +819,15 @@ namespace OpenSim.Region.Framework.Scenes
684 /// <param name="items"></param> 819 /// <param name="items"></param>
685 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 820 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
686 { 821 {
687 lock (m_items) 822 m_items.LockItemsForWrite(true);
823 foreach (TaskInventoryItem item in items)
688 { 824 {
689 foreach (TaskInventoryItem item in items) 825 m_items.Add(item.ItemID, item);
690 { 826// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
691 m_items.Add(item.ItemID, item);
692// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
693 }
694 m_inventorySerial++;
695 } 827 }
828 m_items.LockItemsForWrite(false);
829
830 m_inventorySerial++;
696 } 831 }
697 832
698 /// <summary> 833 /// <summary>
@@ -703,23 +838,24 @@ namespace OpenSim.Region.Framework.Scenes
703 public TaskInventoryItem GetInventoryItem(UUID itemId) 838 public TaskInventoryItem GetInventoryItem(UUID itemId)
704 { 839 {
705 TaskInventoryItem item; 840 TaskInventoryItem item;
706 841 m_items.LockItemsForRead(true);
707 lock (m_items) 842 m_items.TryGetValue(itemId, out item);
708 m_items.TryGetValue(itemId, out item); 843 m_items.LockItemsForRead(false);
709
710 return item; 844 return item;
711 } 845 }
712 846
713 public TaskInventoryItem GetInventoryItem(string name) 847 public TaskInventoryItem GetInventoryItem(string name)
714 { 848 {
715 lock (m_items) 849 m_items.LockItemsForRead(true);
850 foreach (TaskInventoryItem item in m_items.Values)
716 { 851 {
717 foreach (TaskInventoryItem item in m_items.Values) 852 if (item.Name == name)
718 { 853 {
719 if (item.Name == name) 854 m_items.LockItemsForRead(false);
720 return item; 855 return item;
721 } 856 }
722 } 857 }
858 m_items.LockItemsForRead(false);
723 859
724 return null; 860 return null;
725 } 861 }
@@ -728,19 +864,20 @@ namespace OpenSim.Region.Framework.Scenes
728 { 864 {
729 List<TaskInventoryItem> items = new List<TaskInventoryItem>(); 865 List<TaskInventoryItem> items = new List<TaskInventoryItem>();
730 866
731 lock (m_items) 867 m_items.LockItemsForRead(true);
868
869 foreach (TaskInventoryItem item in m_items.Values)
732 { 870 {
733 foreach (TaskInventoryItem item in m_items.Values) 871 if (item.Name == name)
734 { 872 items.Add(item);
735 if (item.Name == name)
736 items.Add(item);
737 }
738 } 873 }
739 874
875 m_items.LockItemsForRead(false);
876
740 return items; 877 return items;
741 } 878 }
742 879
743 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist) 880 public bool GetRezReadySceneObjects(TaskInventoryItem item, out List<SceneObjectGroup> objlist, out List<Vector3> veclist, out Vector3 bbox, out float offsetHeight)
744 { 881 {
745 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 882 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
746 883
@@ -751,18 +888,21 @@ namespace OpenSim.Region.Framework.Scenes
751 item.AssetID, item.Name, m_part.Name); 888 item.AssetID, item.Name, m_part.Name);
752 objlist = null; 889 objlist = null;
753 veclist = null; 890 veclist = null;
891 bbox = Vector3.Zero;
892 offsetHeight = 0;
754 return false; 893 return false;
755 } 894 }
756 895
757 Vector3 bbox; 896 bool single = m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
758 float offsetHeight;
759
760 m_part.ParentGroup.Scene.GetObjectsToRez(rezAsset.Data, false, out objlist, out veclist, out bbox, out offsetHeight);
761 897
762 for (int i = 0; i < objlist.Count; i++) 898 for (int i = 0; i < objlist.Count; i++)
763 { 899 {
764 SceneObjectGroup group = objlist[i]; 900 SceneObjectGroup group = objlist[i];
765 901/*
902 group.RootPart.AttachPoint = group.RootPart.Shape.State;
903 group.RootPart.AttachedPos = group.AbsolutePosition;
904 group.RootPart.AttachRotation = group.GroupRotation;
905*/
766 group.ResetIDs(); 906 group.ResetIDs();
767 907
768 SceneObjectPart rootPart = group.GetPart(group.UUID); 908 SceneObjectPart rootPart = group.GetPart(group.UUID);
@@ -771,12 +911,14 @@ namespace OpenSim.Region.Framework.Scenes
771 // in the serialization, transfer the correct name from the inventory to the 911 // in the serialization, transfer the correct name from the inventory to the
772 // object itself before we rez. 912 // object itself before we rez.
773 // Only do these for the first object if we are rezzing a coalescence. 913 // Only do these for the first object if we are rezzing a coalescence.
774 if (i == 0) 914 // nahh dont mess with coalescence objects,
915 // the name in inventory can be change for inventory purpuses only
916 if (objlist.Count == 1)
775 { 917 {
776 rootPart.Name = item.Name; 918 rootPart.Name = item.Name;
777 rootPart.Description = item.Description; 919 rootPart.Description = item.Description;
778 } 920 }
779 921/* reverted to old code till part.ApplyPermissionsOnRez is better reviewed/fixed
780 group.SetGroup(m_part.GroupID, null); 922 group.SetGroup(m_part.GroupID, null);
781 923
782 foreach (SceneObjectPart part in group.Parts) 924 foreach (SceneObjectPart part in group.Parts)
@@ -792,7 +934,49 @@ namespace OpenSim.Region.Framework.Scenes
792 934
793 part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene); 935 part.ApplyPermissionsOnRez(dest, false, m_part.ParentGroup.Scene);
794 } 936 }
937*/
938// old code start
939 SceneObjectPart[] partList = group.Parts;
940
941 group.SetGroup(m_part.GroupID, null);
942
943 // TODO: Remove magic number badness
944 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
945 {
946 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
947 {
948 foreach (SceneObjectPart part in partList)
949 {
950 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
951 part.EveryoneMask = item.EveryonePermissions;
952 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
953 part.NextOwnerMask = item.NextPermissions;
954 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
955 part.GroupMask = item.GroupPermissions;
956 }
957
958 group.ApplyNextOwnerPermissions();
959 }
960 }
961
962 foreach (SceneObjectPart part in partList)
963 {
964 // TODO: Remove magic number badness
965 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number
966 {
967 part.LastOwnerID = part.OwnerID;
968 part.OwnerID = item.OwnerID;
969 part.Inventory.ChangeInventoryOwner(item.OwnerID);
970 }
795 971
972 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteEveryone) != 0)
973 part.EveryoneMask = item.EveryonePermissions;
974 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteNextOwner) != 0)
975 part.NextOwnerMask = item.NextPermissions;
976 if ((item.Flags & (uint)InventoryItemFlags.ObjectOverwriteGroup) != 0)
977 part.GroupMask = item.GroupPermissions;
978 }
979// old code end
796 rootPart.TrimPermissions(); 980 rootPart.TrimPermissions();
797 } 981 }
798 982
@@ -817,8 +1001,9 @@ namespace OpenSim.Region.Framework.Scenes
817 1001
818 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 1002 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
819 { 1003 {
820 TaskInventoryItem it = GetInventoryItem(item.ItemID); 1004 m_items.LockItemsForWrite(true);
821 if (it != null) 1005
1006 if (m_items.ContainsKey(item.ItemID))
822 { 1007 {
823// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 1008// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
824 1009
@@ -831,14 +1016,10 @@ namespace OpenSim.Region.Framework.Scenes
831 item.GroupID = m_part.GroupID; 1016 item.GroupID = m_part.GroupID;
832 1017
833 if (item.AssetID == UUID.Zero) 1018 if (item.AssetID == UUID.Zero)
834 item.AssetID = it.AssetID; 1019 item.AssetID = m_items[item.ItemID].AssetID;
835 1020
836 lock (m_items) 1021 m_items[item.ItemID] = item;
837 { 1022 m_inventorySerial++;
838 m_items[item.ItemID] = item;
839 m_inventorySerial++;
840 }
841
842 if (fireScriptEvents) 1023 if (fireScriptEvents)
843 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 1024 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
844 1025
@@ -847,7 +1028,7 @@ namespace OpenSim.Region.Framework.Scenes
847 HasInventoryChanged = true; 1028 HasInventoryChanged = true;
848 m_part.ParentGroup.HasGroupChanged = true; 1029 m_part.ParentGroup.HasGroupChanged = true;
849 } 1030 }
850 1031 m_items.LockItemsForWrite(false);
851 return true; 1032 return true;
852 } 1033 }
853 else 1034 else
@@ -858,8 +1039,9 @@ namespace OpenSim.Region.Framework.Scenes
858 item.ItemID, m_part.Name, m_part.UUID, 1039 item.ItemID, m_part.Name, m_part.UUID,
859 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 1040 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
860 } 1041 }
861 return false; 1042 m_items.LockItemsForWrite(false);
862 1043
1044 return false;
863 } 1045 }
864 1046
865 /// <summary> 1047 /// <summary>
@@ -870,160 +1052,182 @@ namespace OpenSim.Region.Framework.Scenes
870 /// in this prim's inventory.</returns> 1052 /// in this prim's inventory.</returns>
871 public int RemoveInventoryItem(UUID itemID) 1053 public int RemoveInventoryItem(UUID itemID)
872 { 1054 {
873 TaskInventoryItem item = GetInventoryItem(itemID); 1055 m_items.LockItemsForRead(true);
874 if (item != null) 1056
1057 if (m_items.ContainsKey(itemID))
875 { 1058 {
876 int type = m_items[itemID].InvType; 1059 int type = m_items[itemID].InvType;
1060 m_items.LockItemsForRead(false);
877 if (type == 10) // Script 1061 if (type == 10) // Script
878 { 1062 {
879 // route it through here, to handle script cleanup tasks 1063 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
880 RemoveScriptInstance(itemID, false);
881 } 1064 }
1065 m_items.LockItemsForWrite(true);
882 m_items.Remove(itemID); 1066 m_items.Remove(itemID);
1067 m_items.LockItemsForWrite(false);
883 m_inventorySerial++; 1068 m_inventorySerial++;
884 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 1069 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
885 1070
886 HasInventoryChanged = true; 1071 HasInventoryChanged = true;
887 m_part.ParentGroup.HasGroupChanged = true; 1072 m_part.ParentGroup.HasGroupChanged = true;
888 1073
889 if (!ContainsScripts()) 1074 int scriptcount = 0;
1075 m_items.LockItemsForRead(true);
1076 foreach (TaskInventoryItem item in m_items.Values)
1077 {
1078 if (item.Type == 10)
1079 {
1080 scriptcount++;
1081 }
1082 }
1083 m_items.LockItemsForRead(false);
1084
1085
1086 if (scriptcount <= 0)
1087 {
890 m_part.RemFlag(PrimFlags.Scripted); 1088 m_part.RemFlag(PrimFlags.Scripted);
1089 }
891 1090
892 m_part.ScheduleFullUpdate(); 1091 m_part.ScheduleFullUpdate();
893 1092
894 return type; 1093 return type;
895
896 } 1094 }
897 else 1095 else
898 { 1096 {
1097 m_items.LockItemsForRead(false);
899 m_log.ErrorFormat( 1098 m_log.ErrorFormat(
900 "[PRIM INVENTORY]: " + 1099 "[PRIM INVENTORY]: " +
901 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 1100 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
902 itemID, m_part.Name, m_part.UUID, 1101 itemID, m_part.Name, m_part.UUID);
903 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
904 } 1102 }
905 1103
906 return -1; 1104 return -1;
907 } 1105 }
908 1106
909 private bool CreateInventoryFile() 1107
1108 /// <summary>
1109 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1110 /// </summary>
1111 /// <param name="xferManager"></param>
1112 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
910 { 1113 {
911// m_log.DebugFormat(
912// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
913// m_part.Name, m_part.UUID, m_part.LocalId, m_inventorySerial);
914 1114
915 if (m_inventoryFileName == String.Empty || 1115 lock (m_inventoryFileLock)
916 m_inventoryFileNameSerial < m_inventorySerial)
917 { 1116 {
918 // Something changed, we need to create a new file 1117 string filename = "inventory_" + UUID.Random().ToString() + ".tmp";
919 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
920 m_inventoryFileNameSerial = m_inventorySerial;
921
922 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
923 1118
924 lock (m_items) 1119 bool changed = false;
1120 if (m_inventoryFileNameSerial < m_inventorySerial)
925 { 1121 {
926 foreach (TaskInventoryItem item in m_items.Values) 1122 m_inventoryFileNameSerial = m_inventorySerial;
927 { 1123 changed = true;
928// m_log.DebugFormat( 1124 }
929// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}",
930// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
931
932 UUID ownerID = item.OwnerID;
933 uint everyoneMask = 0;
934 uint baseMask = item.BasePermissions;
935 uint ownerMask = item.CurrentPermissions;
936 uint groupMask = item.GroupPermissions;
937 1125
938 invString.AddItemStart(); 1126 if (m_inventoryFileData.Length < 2)
939 invString.AddNameValueLine("item_id", item.ItemID.ToString()); 1127 changed = true;
940 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
941 1128
942 invString.AddPermissionsStart(); 1129 bool includeAssets = false;
1130 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1131 includeAssets = true;
943 1132
944 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1133 if (m_inventoryPrivileged != includeAssets)
945 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1134 changed = true;
946 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
947 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
948 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
949 1135
950 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
951 invString.AddNameValueLine("owner_id", ownerID.ToString());
952 1136
953 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1137 Items.LockItemsForRead(true);
954 1138
955 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1139 if (m_inventorySerial == 0) // No inventory
956 invString.AddSectionEnd(); 1140 {
1141 Items.LockItemsForRead(false);
1142 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1143
1144 return;
1145 }
957 1146
958 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1147 if (m_items.Count == 0) // No inventory
959 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type)); 1148 {
960 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType)); 1149 Items.LockItemsForRead(false);
961 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); 1150 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1151 return;
1152 }
962 1153
963 invString.AddSaleStart(); 1154 if (!changed)
964 invString.AddNameValueLine("sale_type", "not"); 1155 {
965 invString.AddNameValueLine("sale_price", "0"); 1156 Items.LockItemsForRead(false);
966 invString.AddSectionEnd();
967 1157
968 invString.AddNameValueLine("name", item.Name + "|"); 1158 xferManager.AddNewFile(filename,
969 invString.AddNameValueLine("desc", item.Description + "|"); 1159 m_inventoryFileData);
1160 client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,
1161 Util.StringToBytes256(filename));
970 1162
971 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1163 return;
972 invString.AddSectionEnd();
973 }
974 } 1164 }
975 1165
976 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1166 m_inventoryPrivileged = includeAssets;
977 1167
978 return true; 1168 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
979 }
980
981 // No need to recreate, the existing file is fine
982 return false;
983 }
984 1169
985 /// <summary> 1170 foreach (TaskInventoryItem item in m_items.Values)
986 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
987 /// </summary>
988 /// <param name="xferManager"></param>
989 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
990 {
991 lock (m_items)
992 {
993 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
994 // a new script if any previous deletion has left the prim inventory empty.
995 if (m_items.Count == 0) // No inventory
996 { 1171 {
997// m_log.DebugFormat( 1172 UUID ownerID = item.OwnerID;
998// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items", 1173 uint everyoneMask = 0;
999// m_part.Name, m_part.LocalId, m_part.UUID, client.Name); 1174 uint baseMask = item.BasePermissions;
1175 uint ownerMask = item.CurrentPermissions;
1176 uint groupMask = item.GroupPermissions;
1000 1177
1001 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1178 invString.AddItemStart();
1002 return; 1179 invString.AddNameValueLine("item_id", item.ItemID.ToString());
1180 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
1181
1182 invString.AddPermissionsStart();
1183
1184 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1185 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1186 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1187 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1188 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
1189
1190 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
1191 invString.AddNameValueLine("owner_id", ownerID.ToString());
1192
1193 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
1194
1195 invString.AddNameValueLine("group_id", item.GroupID.ToString());
1196 invString.AddSectionEnd();
1197
1198 if (includeAssets)
1199 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1200 else
1201 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1202 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1203 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1204 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
1205
1206 invString.AddSaleStart();
1207 invString.AddNameValueLine("sale_type", "not");
1208 invString.AddNameValueLine("sale_price", "0");
1209 invString.AddSectionEnd();
1210
1211 invString.AddNameValueLine("name", item.Name + "|");
1212 invString.AddNameValueLine("desc", item.Description + "|");
1213
1214 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1215 invString.AddSectionEnd();
1003 } 1216 }
1004 1217
1005 CreateInventoryFile(); 1218 Items.LockItemsForRead(false);
1006 1219
1007 // In principle, we should only do the rest if the inventory changed; 1220 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
1008 // by sending m_inventorySerial to the client, it ought to know 1221
1009 // that nothing changed and that it doesn't need to request the file.
1010 // Unfortunately, it doesn't look like the client optimizes this;
1011 // the client seems to always come back and request the Xfer,
1012 // no matter what value m_inventorySerial has.
1013 // FIXME: Could probably be > 0 here rather than > 2
1014 if (m_inventoryFileData.Length > 2) 1222 if (m_inventoryFileData.Length > 2)
1015 { 1223 {
1016 // Add the file for Xfer 1224 xferManager.AddNewFile(filename, m_inventoryFileData);
1017 // m_log.DebugFormat( 1225 client.SendTaskInventory(m_part.UUID, (short)m_inventoryFileNameSerial,
1018 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}", 1226 Util.StringToBytes256(filename));
1019 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId); 1227 return;
1020
1021 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
1022 } 1228 }
1023 1229
1024 // Tell the client we're ready to Xfer the file 1230 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1025 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
1026 Util.StringToBytes256(m_inventoryFileName));
1027 } 1231 }
1028 } 1232 }
1029 1233
@@ -1033,13 +1237,26 @@ namespace OpenSim.Region.Framework.Scenes
1033 /// <param name="datastore"></param> 1237 /// <param name="datastore"></param>
1034 public void ProcessInventoryBackup(ISimulationDataService datastore) 1238 public void ProcessInventoryBackup(ISimulationDataService datastore)
1035 { 1239 {
1036 if (HasInventoryChanged) 1240// Removed this because linking will cause an immediate delete of the new
1037 { 1241// child prim from the database and the subsequent storing of the prim sees
1242// the inventory of it as unchanged and doesn't store it at all. The overhead
1243// of storing prim inventory needlessly is much less than the aggravation
1244// of prim inventory loss.
1245// if (HasInventoryChanged)
1246// {
1247 Items.LockItemsForRead(true);
1248 try
1249 {
1250 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1251 }
1252 catch {}
1253
1038 HasInventoryChanged = false; 1254 HasInventoryChanged = false;
1039 List<TaskInventoryItem> items = GetInventoryItems();
1040 datastore.StorePrimInventory(m_part.UUID, items);
1041 1255
1042 } 1256 Items.LockItemsForRead(false);
1257
1258
1259// }
1043 } 1260 }
1044 1261
1045 public class InventoryStringBuilder 1262 public class InventoryStringBuilder
@@ -1105,65 +1322,63 @@ namespace OpenSim.Region.Framework.Scenes
1105 { 1322 {
1106 uint mask=0x7fffffff; 1323 uint mask=0x7fffffff;
1107 1324
1108 lock (m_items) 1325 foreach (TaskInventoryItem item in m_items.Values)
1109 { 1326 {
1110 foreach (TaskInventoryItem item in m_items.Values) 1327 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1328 mask &= ~((uint)PermissionMask.Copy >> 13);
1329 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1330 mask &= ~((uint)PermissionMask.Transfer >> 13);
1331 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1332 mask &= ~((uint)PermissionMask.Modify >> 13);
1333
1334 if (item.InvType == (int)InventoryType.Object)
1111 { 1335 {
1112 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1336 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1113 mask &= ~((uint)PermissionMask.Copy >> 13); 1337 mask &= ~((uint)PermissionMask.Copy >> 13);
1114 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1338 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1115 mask &= ~((uint)PermissionMask.Transfer >> 13); 1339 mask &= ~((uint)PermissionMask.Transfer >> 13);
1116 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1340 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1117 mask &= ~((uint)PermissionMask.Modify >> 13); 1341 mask &= ~((uint)PermissionMask.Modify >> 13);
1118
1119 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1120 mask &= ~(uint)PermissionMask.Copy;
1121 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1122 mask &= ~(uint)PermissionMask.Transfer;
1123 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1124 mask &= ~(uint)PermissionMask.Modify;
1125 } 1342 }
1343
1344 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1345 mask &= ~(uint)PermissionMask.Copy;
1346 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1347 mask &= ~(uint)PermissionMask.Transfer;
1348 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1349 mask &= ~(uint)PermissionMask.Modify;
1126 } 1350 }
1127
1128 return mask; 1351 return mask;
1129 } 1352 }
1130 1353
1131 public void ApplyNextOwnerPermissions() 1354 public void ApplyNextOwnerPermissions()
1132 { 1355 {
1133 lock (m_items) 1356 foreach (TaskInventoryItem item in m_items.Values)
1134 { 1357 {
1135 foreach (TaskInventoryItem item in m_items.Values) 1358 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1136 { 1359 {
1137// m_log.DebugFormat ( 1360 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1138// "[SCENE OBJECT PART INVENTORY]: Applying next permissions {0} to {1} in {2} with current {3}, base {4}, everyone {5}", 1361 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1139// item.NextPermissions, item.Name, m_part.Name, item.CurrentPermissions, item.BasePermissions, item.EveryonePermissions); 1362 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1140 1363 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1141 if (item.InvType == (int)InventoryType.Object) 1364 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1142 { 1365 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1143 uint perms = item.CurrentPermissions;
1144 PermissionsUtil.ApplyFoldedPermissions(perms, ref perms);
1145 item.CurrentPermissions = perms;
1146 }
1147
1148 item.CurrentPermissions &= item.NextPermissions;
1149 item.BasePermissions &= item.NextPermissions;
1150 item.EveryonePermissions &= item.NextPermissions;
1151 item.OwnerChanged = true;
1152 item.PermsMask = 0;
1153 item.PermsGranter = UUID.Zero;
1154 } 1366 }
1367 item.CurrentPermissions &= item.NextPermissions;
1368 item.BasePermissions &= item.NextPermissions;
1369 item.EveryonePermissions &= item.NextPermissions;
1370 item.OwnerChanged = true;
1371 item.PermsMask = 0;
1372 item.PermsGranter = UUID.Zero;
1155 } 1373 }
1156 } 1374 }
1157 1375
1158 public void ApplyGodPermissions(uint perms) 1376 public void ApplyGodPermissions(uint perms)
1159 { 1377 {
1160 lock (m_items) 1378 foreach (TaskInventoryItem item in m_items.Values)
1161 { 1379 {
1162 foreach (TaskInventoryItem item in m_items.Values) 1380 item.CurrentPermissions = perms;
1163 { 1381 item.BasePermissions = perms;
1164 item.CurrentPermissions = perms;
1165 item.BasePermissions = perms;
1166 }
1167 } 1382 }
1168 1383
1169 m_inventorySerial++; 1384 m_inventorySerial++;
@@ -1176,14 +1391,11 @@ namespace OpenSim.Region.Framework.Scenes
1176 /// <returns></returns> 1391 /// <returns></returns>
1177 public bool ContainsScripts() 1392 public bool ContainsScripts()
1178 { 1393 {
1179 lock (m_items) 1394 foreach (TaskInventoryItem item in m_items.Values)
1180 { 1395 {
1181 foreach (TaskInventoryItem item in m_items.Values) 1396 if (item.InvType == (int)InventoryType.LSL)
1182 { 1397 {
1183 if (item.InvType == (int)InventoryType.LSL) 1398 return true;
1184 {
1185 return true;
1186 }
1187 } 1399 }
1188 } 1400 }
1189 1401
@@ -1197,17 +1409,15 @@ namespace OpenSim.Region.Framework.Scenes
1197 public int ScriptCount() 1409 public int ScriptCount()
1198 { 1410 {
1199 int count = 0; 1411 int count = 0;
1200 lock (m_items) 1412 Items.LockItemsForRead(true);
1413 foreach (TaskInventoryItem item in m_items.Values)
1201 { 1414 {
1202 foreach (TaskInventoryItem item in m_items.Values) 1415 if (item.InvType == (int)InventoryType.LSL)
1203 { 1416 {
1204 if (item.InvType == (int)InventoryType.LSL) 1417 count++;
1205 {
1206 count++;
1207 }
1208 } 1418 }
1209 } 1419 }
1210 1420 Items.LockItemsForRead(false);
1211 return count; 1421 return count;
1212 } 1422 }
1213 /// <summary> 1423 /// <summary>
@@ -1243,11 +1453,8 @@ namespace OpenSim.Region.Framework.Scenes
1243 { 1453 {
1244 List<UUID> ret = new List<UUID>(); 1454 List<UUID> ret = new List<UUID>();
1245 1455
1246 lock (m_items) 1456 foreach (TaskInventoryItem item in m_items.Values)
1247 { 1457 ret.Add(item.ItemID);
1248 foreach (TaskInventoryItem item in m_items.Values)
1249 ret.Add(item.ItemID);
1250 }
1251 1458
1252 return ret; 1459 return ret;
1253 } 1460 }
@@ -1256,8 +1463,9 @@ namespace OpenSim.Region.Framework.Scenes
1256 { 1463 {
1257 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1464 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1258 1465
1259 lock (m_items) 1466 Items.LockItemsForRead(true);
1260 ret = new List<TaskInventoryItem>(m_items.Values); 1467 ret = new List<TaskInventoryItem>(m_items.Values);
1468 Items.LockItemsForRead(false);
1261 1469
1262 return ret; 1470 return ret;
1263 } 1471 }
@@ -1266,18 +1474,24 @@ namespace OpenSim.Region.Framework.Scenes
1266 { 1474 {
1267 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1475 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1268 1476
1269 lock (m_items) 1477 Items.LockItemsForRead(true);
1270 { 1478
1271 foreach (TaskInventoryItem item in m_items.Values) 1479 foreach (TaskInventoryItem item in m_items.Values)
1272 if (item.InvType == (int)type) 1480 if (item.InvType == (int)type)
1273 ret.Add(item); 1481 ret.Add(item);
1274 } 1482
1483 Items.LockItemsForRead(false);
1275 1484
1276 return ret; 1485 return ret;
1277 } 1486 }
1278 1487
1279 public Dictionary<UUID, string> GetScriptStates() 1488 public Dictionary<UUID, string> GetScriptStates()
1280 { 1489 {
1490 return GetScriptStates(false);
1491 }
1492
1493 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1494 {
1281 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1495 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1282 1496
1283 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1497 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1303,14 +1517,21 @@ namespace OpenSim.Region.Framework.Scenes
1303 string n = e.GetXMLState(item.ItemID); 1517 string n = e.GetXMLState(item.ItemID);
1304 if (n != String.Empty) 1518 if (n != String.Empty)
1305 { 1519 {
1306 if (!ret.ContainsKey(item.ItemID)) 1520 if (oldIDs)
1307 ret[item.ItemID] = n; 1521 {
1522 if (!ret.ContainsKey(item.OldItemID))
1523 ret[item.OldItemID] = n;
1524 }
1525 else
1526 {
1527 if (!ret.ContainsKey(item.ItemID))
1528 ret[item.ItemID] = n;
1529 }
1308 break; 1530 break;
1309 } 1531 }
1310 } 1532 }
1311 } 1533 }
1312 } 1534 }
1313
1314 return ret; 1535 return ret;
1315 } 1536 }
1316 1537
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 1fddd91..c3deeaf 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -90,7 +90,17 @@ namespace OpenSim.Region.Framework.Scenes
90 m_scene.EventManager.TriggerScenePresenceUpdated(this); 90 m_scene.EventManager.TriggerScenePresenceUpdated(this);
91 } 91 }
92 92
93 public PresenceType PresenceType { get; private set; } 93 public bool isNPC { get; private set; }
94
95 private PresenceType m_presenceType;
96 public PresenceType PresenceType {
97 get {return m_presenceType;}
98 private set
99 {
100 m_presenceType = value;
101 isNPC = (m_presenceType == PresenceType.Npc);
102 }
103 }
94 104
95 private ScenePresenceStateMachine m_stateMachine; 105 private ScenePresenceStateMachine m_stateMachine;
96 106
@@ -142,13 +152,100 @@ namespace OpenSim.Region.Framework.Scenes
142 /// </summary> 152 /// </summary>
143 public static readonly float SIGNIFICANT_MOVEMENT = 2.0f; 153 public static readonly float SIGNIFICANT_MOVEMENT = 2.0f;
144 154
145 public UUID currentParcelUUID = UUID.Zero; 155 private UUID m_previusParcelUUID = UUID.Zero;
156 private UUID m_currentParcelUUID = UUID.Zero;
157 private bool m_previusParcelHide = false;
158 private bool m_currentParcelHide = false;
159 private object parcelLock = new Object();
146 160
161 public UUID currentParcelUUID
162 {
163 get { return m_currentParcelUUID; }
164 set
165 {
166 lock (parcelLock)
167 {
168 bool oldhide = m_currentParcelHide;
169 bool checksame = true;
170 if (value != m_currentParcelUUID)
171 {
172 m_previusParcelHide = m_currentParcelHide;
173 m_previusParcelUUID = m_currentParcelUUID;
174 checksame = false;
175 }
176 m_currentParcelUUID = value;
177 m_currentParcelHide = false;
178
179 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
180 if (land != null && !land.LandData.SeeAVs)
181 m_currentParcelHide = true;
182
183 if (m_previusParcelUUID != UUID.Zero || checksame)
184 ParcelCrossCheck(m_currentParcelUUID,m_previusParcelUUID,m_currentParcelHide, m_previusParcelHide, oldhide,checksame);
185 }
186 }
187 }
188
189 public void sitSOGmoved()
190 {
191 if (IsDeleted || !IsSatOnObject)
192 //what me? nahh
193 return;
194 if (IsInTransit)
195 return;
196
197 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
198 if (land == null)
199 return; //??
200 UUID parcelID = land.LandData.GlobalID;
201 if (m_currentParcelUUID != parcelID)
202 currentParcelUUID = parcelID;
203 }
204
205
206 public bool ParcelAllowThisAvatarSounds
207 {
208 get
209 {
210 try
211 {
212 lock (parcelLock)
213 {
214 ILandObject land = m_scene.LandChannel.GetLandObject(AbsolutePosition.X, AbsolutePosition.Y);
215 if (land == null)
216 return true;
217 if (land.LandData.AnyAVSounds)
218 return true;
219 if (!land.LandData.GroupAVSounds)
220 return false;
221 return land.LandData.GroupID == ControllingClient.ActiveGroupId;
222 }
223 }
224 catch
225 {
226 return true;
227 }
228 }
229 }
230
231 public bool ParcelHideThisAvatar
232 {
233 get
234 {
235 return m_currentParcelHide;
236 }
237 }
238
147 /// <value> 239 /// <value>
148 /// The animator for this avatar 240 /// The animator for this avatar
149 /// </value> 241 /// </value>
150 public ScenePresenceAnimator Animator { get; private set; } 242 public ScenePresenceAnimator Animator { get; private set; }
151 243
244 /// <value>
245 /// Server Side Animation Override
246 /// </value>
247 public MovementAnimationOverrides Overrides { get; private set; }
248 public String sitAnimation = "SIT";
152 /// <summary> 249 /// <summary>
153 /// Attachments recorded on this avatar. 250 /// Attachments recorded on this avatar.
154 /// </summary> 251 /// </summary>
@@ -192,14 +289,7 @@ namespace OpenSim.Region.Framework.Scenes
192 set { PhysicsActor.Flying = value; } 289 set { PhysicsActor.Flying = value; }
193 } 290 }
194 291
195 // add for fly velocity control 292 public bool IsColliding
196 private bool FlyingOld {get; set;}
197 public bool WasFlying
198 {
199 get; private set;
200 }
201
202 public bool IsColliding
203 { 293 {
204 get { return PhysicsActor != null && PhysicsActor.IsColliding; } 294 get { return PhysicsActor != null && PhysicsActor.IsColliding; }
205 // We would expect setting IsColliding to be private but it's used by a hack in Scene 295 // We would expect setting IsColliding to be private but it's used by a hack in Scene
@@ -209,6 +299,7 @@ namespace OpenSim.Region.Framework.Scenes
209// private int m_lastColCount = -1; //KF: Look for Collision chnages 299// private int m_lastColCount = -1; //KF: Look for Collision chnages
210// private int m_updateCount = 0; //KF: Update Anims for a while 300// private int m_updateCount = 0; //KF: Update Anims for a while
211// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 301// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
302 private List<uint> m_lastColliders = new List<uint>();
212 303
213 private TeleportFlags m_teleportFlags; 304 private TeleportFlags m_teleportFlags;
214 public TeleportFlags TeleportFlags 305 public TeleportFlags TeleportFlags
@@ -247,7 +338,7 @@ namespace OpenSim.Region.Framework.Scenes
247 338
248 protected ulong crossingFromRegion; 339 protected ulong crossingFromRegion;
249 340
250 private readonly Vector3[] Dir_Vectors = new Vector3[11]; 341 private readonly Vector3[] Dir_Vectors = new Vector3[12];
251 342
252 protected Timer m_reprioritization_timer; 343 protected Timer m_reprioritization_timer;
253 protected bool m_reprioritizing; 344 protected bool m_reprioritizing;
@@ -271,6 +362,9 @@ namespace OpenSim.Region.Framework.Scenes
271 //private int m_moveToPositionStateStatus; 362 //private int m_moveToPositionStateStatus;
272 //***************************************************** 363 //*****************************************************
273 364
365 private bool m_collisionEventFlag = false;
366 private object m_collisionEventLock = new Object();
367
274 private int m_movementAnimationUpdateCounter = 0; 368 private int m_movementAnimationUpdateCounter = 0;
275 369
276 public Vector3 PrevSitOffset { get; set; } 370 public Vector3 PrevSitOffset { get; set; }
@@ -287,7 +381,6 @@ namespace OpenSim.Region.Framework.Scenes
287 } 381 }
288 } 382 }
289 383
290 public bool SentInitialDataToClient { get; private set; }
291 384
292 /// <summary> 385 /// <summary>
293 /// Copy of the script states while the agent is in transit. This state may 386 /// Copy of the script states while the agent is in transit. This state may
@@ -303,7 +396,7 @@ namespace OpenSim.Region.Framework.Scenes
303 /// <summary> 396 /// <summary>
304 /// Implemented Control Flags 397 /// Implemented Control Flags
305 /// </summary> 398 /// </summary>
306 private enum Dir_ControlFlags 399 private enum Dir_ControlFlags:uint
307 { 400 {
308 DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS, 401 DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
309 DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG, 402 DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
@@ -315,6 +408,7 @@ namespace OpenSim.Region.Framework.Scenes
315 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 408 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
316 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS, 409 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
317 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG, 410 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
411 DIR_CONTROL_FLAG_UP_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS,
318 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 412 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
319 } 413 }
320 414
@@ -347,12 +441,6 @@ namespace OpenSim.Region.Framework.Scenes
347 private object m_originRegionIDAccessLock = new object(); 441 private object m_originRegionIDAccessLock = new object();
348 442
349 /// <summary> 443 /// <summary>
350 /// Triggered on entity transfer after to allow CompleteMovement() to proceed after we have received an
351 /// UpdateAgent from the originating region.ddkjjkj
352 /// </summary>
353 private AutoResetEvent m_updateAgentReceivedAfterTransferEvent = new AutoResetEvent(false);
354
355 /// <summary>
356 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent 444 /// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
357 /// teleport is reusing the connection. 445 /// teleport is reusing the connection.
358 /// </summary> 446 /// </summary>
@@ -379,11 +467,6 @@ namespace OpenSim.Region.Framework.Scenes
379 public uint MovementFlag { get; private set; } 467 public uint MovementFlag { get; private set; }
380 468
381 /// <summary> 469 /// <summary>
382 /// Set this if we need to force a movement update on the next received AgentUpdate from the viewer.
383 /// </summary>
384 private const uint ForceUpdateMovementFlagValue = uint.MaxValue;
385
386 /// <summary>
387 /// Is the agent stop control flag currently active? 470 /// Is the agent stop control flag currently active?
388 /// </summary> 471 /// </summary>
389 public bool AgentControlStopActive { get; private set; } 472 public bool AgentControlStopActive { get; private set; }
@@ -413,11 +496,18 @@ namespace OpenSim.Region.Framework.Scenes
413 } 496 }
414 497
415 private ulong m_rootRegionHandle; 498 private ulong m_rootRegionHandle;
499 private Vector3 m_rootRegionPosition = new Vector3();
416 500
417 public ulong RegionHandle 501 public ulong RegionHandle
418 { 502 {
419 get { return m_rootRegionHandle; } 503 get { return m_rootRegionHandle; }
420 private set { m_rootRegionHandle = value; } 504 private set
505 {
506 m_rootRegionHandle = value;
507 // position rounded to lower multiple of 256m
508 m_rootRegionPosition.X = (float)((m_rootRegionHandle >> 32) & 0xffffff00);
509 m_rootRegionPosition.Y = (float)(m_rootRegionHandle & 0xffffff00);
510 }
421 } 511 }
422 512
423 #region Client Camera 513 #region Client Camera
@@ -449,11 +539,8 @@ namespace OpenSim.Region.Framework.Scenes
449 get 539 get
450 { 540 {
451 Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0); 541 Vector3 a = new Vector3(CameraAtAxis.X, CameraAtAxis.Y, 0);
452 542 a.Normalize();
453 if (a == Vector3.Zero) 543 return a;
454 return a;
455
456 return Util.GetNormalizedVector(a);
457 } 544 }
458 } 545 }
459 #endregion 546 #endregion
@@ -474,9 +561,19 @@ namespace OpenSim.Region.Framework.Scenes
474 /// </summary> 561 /// </summary>
475 public bool UseFakeGroupTitle { get; set; } 562 public bool UseFakeGroupTitle { get; set; }
476 563
477
478 // Agent's Draw distance. 564 // Agent's Draw distance.
479 public float DrawDistance { get; set; } 565 private float m_drawDistance = 255f;
566 public float DrawDistance
567 {
568 get
569 {
570 return m_drawDistance;
571 }
572 set
573 {
574 m_drawDistance = Util.Clamp(value, 32f, m_scene.MaxDrawDistance);
575 }
576 }
480 577
481 public bool AllowMovement { get; set; } 578 public bool AllowMovement { get; set; }
482 579
@@ -505,6 +602,7 @@ namespace OpenSim.Region.Framework.Scenes
505 } 602 }
506 } 603 }
507 604
605
508 public byte State { get; set; } 606 public byte State { get; set; }
509 607
510 private AgentManager.ControlFlags m_AgentControlFlags; 608 private AgentManager.ControlFlags m_AgentControlFlags;
@@ -557,10 +655,14 @@ namespace OpenSim.Region.Framework.Scenes
557 // in the sim unless the avatar is on a sit target. While 655 // in the sim unless the avatar is on a sit target. While
558 // on a sit target, m_pos will contain the desired offset 656 // on a sit target, m_pos will contain the desired offset
559 // without the parent rotation applied. 657 // without the parent rotation applied.
560 SceneObjectPart sitPart = ParentPart; 658 if (ParentPart != null)
561 659 {
562 if (sitPart != null) 660 SceneObjectPart rootPart = ParentPart.ParentGroup.RootPart;
563 return sitPart.ParentGroup.AbsolutePosition + (m_pos * sitPart.GetWorldRotation()); 661 // if (sitPart != null)
662 // return sitPart.AbsolutePosition + (m_pos * sitPart.GetWorldRotation());
663 if (rootPart != null)
664 return rootPart.AbsolutePosition + (m_pos * rootPart.GetWorldRotation());
665 }
564 } 666 }
565 667
566 return m_pos; 668 return m_pos;
@@ -614,11 +716,8 @@ namespace OpenSim.Region.Framework.Scenes
614 } 716 }
615 717
616 /// <summary> 718 /// <summary>
617 /// Velocity of the avatar with respect to its local reference frame. 719 /// Current velocity of the avatar.
618 /// </summary> 720 /// </summary>
619 /// <remarks>
620 /// So when sat on a vehicle this will be 0. To get velocity with respect to the world use GetWorldVelocity()
621 /// </remarks>
622 public override Vector3 Velocity 721 public override Vector3 Velocity
623 { 722 {
624 get 723 get
@@ -631,21 +730,12 @@ namespace OpenSim.Region.Framework.Scenes
631// "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", 730// "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!",
632// m_velocity, Name, Scene.RegionInfo.RegionName); 731// m_velocity, Name, Scene.RegionInfo.RegionName);
633 } 732 }
634// else if (ParentPart != null)
635// {
636// return ParentPart.ParentGroup.Velocity;
637// }
638 733
639 return m_velocity; 734 return m_velocity;
640 } 735 }
641 736
642 set 737 set
643 { 738 {
644// Util.PrintCallStack();
645// m_log.DebugFormat(
646// "[SCENE PRESENCE]: In {0} set velocity of {1} to {2}",
647// Scene.RegionInfo.RegionName, Name, value);
648
649 if (PhysicsActor != null) 739 if (PhysicsActor != null)
650 { 740 {
651 try 741 try
@@ -658,27 +748,14 @@ namespace OpenSim.Region.Framework.Scenes
658 } 748 }
659 } 749 }
660 750
661 m_velocity = value; 751 m_velocity = value;
662 }
663 }
664/*
665 public override Vector3 AngularVelocity
666 {
667 get
668 {
669 if (PhysicsActor != null)
670 {
671 m_rotationalvelocity = PhysicsActor.RotationalVelocity;
672
673 // m_log.DebugFormat(
674 // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!",
675 // m_velocity, Name, Scene.RegionInfo.RegionName);
676 }
677 752
678 return m_rotationalvelocity; 753// m_log.DebugFormat(
754// "[SCENE PRESENCE]: In {0} set velocity of {1} to {2}",
755// Scene.RegionInfo.RegionName, Name, m_velocity);
679 } 756 }
680 } 757 }
681*/ 758
682 private Quaternion m_bodyRot = Quaternion.Identity; 759 private Quaternion m_bodyRot = Quaternion.Identity;
683 760
684 /// <summary> 761 /// <summary>
@@ -759,15 +836,21 @@ namespace OpenSim.Region.Framework.Scenes
759 } 836 }
760 837
761 /// <summary> 838 /// <summary>
762 /// Get rotation relative to the world. 839 /// Gets the world rotation of this presence.
763 /// </summary> 840 /// </summary>
841 /// <remarks>
842 /// Unlike Rotation, this returns the world rotation no matter whether the avatar is sitting on a prim or not.
843 /// </remarks>
764 /// <returns></returns> 844 /// <returns></returns>
765 public Quaternion GetWorldRotation() 845 public Quaternion GetWorldRotation()
766 { 846 {
767 SceneObjectPart sitPart = ParentPart; 847 if (IsSatOnObject)
848 {
849 SceneObjectPart sitPart = ParentPart;
768 850
769 if (sitPart != null) 851 if (sitPart != null)
770 return sitPart.GetWorldRotation() * Rotation; 852 return sitPart.GetWorldRotation() * Rotation;
853 }
771 854
772 return Rotation; 855 return Rotation;
773 } 856 }
@@ -794,22 +877,23 @@ namespace OpenSim.Region.Framework.Scenes
794 else 877 else
795 seeds = new Dictionary<ulong, string>(); 878 seeds = new Dictionary<ulong, string>();
796 879
880/* we can't do this anymore
797 List<ulong> old = new List<ulong>(); 881 List<ulong> old = new List<ulong>();
798 foreach (ulong handle in seeds.Keys) 882 foreach (ulong handle in seeds.Keys)
799 { 883 {
800 uint x, y; 884 uint x, y;
801 Util.RegionHandleToRegionLoc(handle, out x, out y); 885 Util.RegionHandleToRegionLoc(handle, out x, out y);
802 886// if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY,))
803 if (Util.IsOutsideView(DrawDistance, x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
804 { 887 {
805 old.Add(handle); 888 old.Add(handle);
806 } 889 }
807 } 890 }
891
808 DropOldNeighbours(old); 892 DropOldNeighbours(old);
809 893
810 if (Scene.CapsModule != null) 894 if (Scene.CapsModule != null)
811 Scene.CapsModule.SetChildrenSeed(UUID, seeds); 895 Scene.CapsModule.SetChildrenSeed(UUID, seeds);
812 896*/
813 KnownRegions = seeds; 897 KnownRegions = seeds;
814 //m_log.Debug(" ++++++++++AFTER+++++++++++++ "); 898 //m_log.Debug(" ++++++++++AFTER+++++++++++++ ");
815 //DumpKnownRegions(); 899 //DumpKnownRegions();
@@ -827,7 +911,7 @@ namespace OpenSim.Region.Framework.Scenes
827 } 911 }
828 912
829 private bool m_mouseLook; 913 private bool m_mouseLook;
830// private bool m_leftButtonDown; 914 private bool m_leftButtonDown;
831 915
832 private bool m_inTransit; 916 private bool m_inTransit;
833 917
@@ -852,13 +936,6 @@ namespace OpenSim.Region.Framework.Scenes
852 } 936 }
853 } 937 }
854 938
855 private float m_speedModifier = 1.0f;
856
857 public float SpeedModifier
858 {
859 get { return m_speedModifier; }
860 set { m_speedModifier = value; }
861 }
862 939
863 /// <summary> 940 /// <summary>
864 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running 941 /// Modifier for agent movement if we get an AGENT_CONTROL_STOP whilst walking or running
@@ -866,7 +943,20 @@ namespace OpenSim.Region.Framework.Scenes
866 /// <remarks> 943 /// <remarks>
867 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers. 944 /// AGENT_CONTRL_STOP comes about if user holds down space key on viewers.
868 /// </remarks> 945 /// </remarks>
869 private float AgentControlStopSlowWhilstMoving = 0.5f; 946 private const float AgentControlStopSlowVel = 0.2f;
947 // velocities
948 public const float AgentControlNudgeVel = 1.0f; // setting this diferent from normal as no effect currently
949 public const float AgentControlNormalVel = 1.0f;
950
951 // old normal speed was tuned to match sl normal plus Fast modifiers
952 // so we need to rescale it
953 private float m_speedModifier = 1.0f;
954
955 public float SpeedModifier
956 {
957 get { return m_speedModifier; }
958 set { m_speedModifier = value; }
959 }
870 960
871 private bool m_forceFly; 961 private bool m_forceFly;
872 962
@@ -888,12 +978,7 @@ namespace OpenSim.Region.Framework.Scenes
888 { 978 {
889 get { return Util.GetViewerName(m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode)); } 979 get { return Util.GetViewerName(m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode)); }
890 } 980 }
891 981
892 /// <summary>
893 /// Count of how many terse updates we have sent out. It doesn't matter if this overflows.
894 /// </summary>
895 private int m_terseUpdateCount;
896
897 #endregion 982 #endregion
898 983
899 #region Constructor(s) 984 #region Constructor(s)
@@ -901,21 +986,21 @@ namespace OpenSim.Region.Framework.Scenes
901 public ScenePresence( 986 public ScenePresence(
902 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type) 987 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
903 { 988 {
989 m_scene = world;
904 AttachmentsSyncLock = new Object(); 990 AttachmentsSyncLock = new Object();
905 AllowMovement = true; 991 AllowMovement = true;
906 IsChildAgent = true; 992 IsChildAgent = true;
907 IsLoggingIn = false; 993 IsLoggingIn = false;
908 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; 994 m_sendCoarseLocationsMethod = SendCoarseLocationsDefault;
909 Animator = new ScenePresenceAnimator(this); 995 Animator = new ScenePresenceAnimator(this);
996 Overrides = new MovementAnimationOverrides();
910 PresenceType = type; 997 PresenceType = type;
911 // DrawDistance = world.DefaultDrawDistance; 998 DrawDistance = world.DefaultDrawDistance;
912 DrawDistance = Constants.RegionSize;
913 RegionHandle = world.RegionInfo.RegionHandle; 999 RegionHandle = world.RegionInfo.RegionHandle;
914 ControllingClient = client; 1000 ControllingClient = client;
915 Firstname = ControllingClient.FirstName; 1001 Firstname = ControllingClient.FirstName;
916 Lastname = ControllingClient.LastName; 1002 Lastname = ControllingClient.LastName;
917 m_name = String.Format("{0} {1}", Firstname, Lastname); 1003 m_name = String.Format("{0} {1}", Firstname, Lastname);
918 m_scene = world;
919 m_uuid = client.AgentId; 1004 m_uuid = client.AgentId;
920 LocalId = m_scene.AllocateLocalId(); 1005 LocalId = m_scene.AllocateLocalId();
921 1006
@@ -930,7 +1015,7 @@ namespace OpenSim.Region.Framework.Scenes
930 1015
931 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1016 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
932 if (gm != null) 1017 if (gm != null)
933 Grouptitle = gm.GetGroupTitle(m_uuid); 1018 Grouptitle = gm.GetGroupTitle(m_uuid);
934 1019
935 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>(); 1020 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>();
936 1021
@@ -988,8 +1073,10 @@ namespace OpenSim.Region.Framework.Scenes
988 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 1073 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
989 ControllingClient.OnStartAnim += HandleStartAnim; 1074 ControllingClient.OnStartAnim += HandleStartAnim;
990 ControllingClient.OnStopAnim += HandleStopAnim; 1075 ControllingClient.OnStopAnim += HandleStopAnim;
1076 ControllingClient.OnChangeAnim += avnHandleChangeAnim;
991 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls; 1077 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls;
992 ControllingClient.OnAutoPilotGo += MoveToTarget; 1078 ControllingClient.OnAutoPilotGo += MoveToTarget;
1079 ControllingClient.OnUpdateThrottles += RaiseUpdateThrottles;
993 1080
994 // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange); 1081 // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
995 // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement); 1082 // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
@@ -997,19 +1084,19 @@ namespace OpenSim.Region.Framework.Scenes
997 1084
998 private void SetDirectionVectors() 1085 private void SetDirectionVectors()
999 { 1086 {
1000 Dir_Vectors[0] = Vector3.UnitX; //FORWARD 1087 Dir_Vectors[0] = new Vector3(AgentControlNormalVel,0,0); //FORWARD
1001 Dir_Vectors[1] = -Vector3.UnitX; //BACK 1088 Dir_Vectors[1] = new Vector3(-AgentControlNormalVel,0,0);; //BACK
1002 Dir_Vectors[2] = Vector3.UnitY; //LEFT 1089 Dir_Vectors[2] = new Vector3(0,AgentControlNormalVel,0); //LEFT
1003 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 1090 Dir_Vectors[3] = new Vector3(0,-AgentControlNormalVel,0); //RIGHT
1004 Dir_Vectors[4] = Vector3.UnitZ; //UP 1091 Dir_Vectors[4] = new Vector3(0,0,AgentControlNormalVel); //UP
1005 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 1092 Dir_Vectors[5] = new Vector3(0,0,-AgentControlNormalVel); //DOWN
1006 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE 1093 Dir_Vectors[6] = new Vector3(AgentControlNudgeVel, 0f, 0f); //FORWARD_NUDGE
1007 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE 1094 Dir_Vectors[7] = new Vector3(-AgentControlNudgeVel, 0f, 0f); //BACK_NUDGE
1008 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE 1095 Dir_Vectors[8] = new Vector3(0f, AgentControlNudgeVel, 0f); //LEFT_NUDGE
1009 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE 1096 Dir_Vectors[9] = new Vector3(0f, -AgentControlNudgeVel, 0f); //RIGHT_NUDGE
1010 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 1097 Dir_Vectors[10] = new Vector3(0f, 0f, AgentControlNudgeVel); //UP_Nudge
1098 Dir_Vectors[11] = new Vector3(0f, 0f, -AgentControlNudgeVel); //DOWN_Nudge
1011 } 1099 }
1012
1013 #endregion 1100 #endregion
1014 1101
1015 #region Status Methods 1102 #region Status Methods
@@ -1026,18 +1113,25 @@ namespace OpenSim.Region.Framework.Scenes
1026 /// This method is on the critical path for transferring an avatar from one region to another. Delay here 1113 /// This method is on the critical path for transferring an avatar from one region to another. Delay here
1027 /// delays that crossing. 1114 /// delays that crossing.
1028 /// </remarks> 1115 /// </remarks>
1116
1117
1118 // only in use as part of completemovement
1119 // other uses need fix
1029 private bool MakeRootAgent(Vector3 pos, bool isFlying) 1120 private bool MakeRootAgent(Vector3 pos, bool isFlying)
1030 { 1121 {
1122 int ts = Util.EnvironmentTickCount();
1123
1031 lock (m_completeMovementLock) 1124 lock (m_completeMovementLock)
1032 { 1125 {
1033 if (!IsChildAgent) 1126 if (!IsChildAgent)
1034 return false; 1127 return false;
1035 1128
1129 m_log.DebugFormat("[MakeRootAgent] enter lock: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1036 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); 1130 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
1037 1131
1038 // m_log.InfoFormat( 1132 // m_log.InfoFormat(
1039 // "[SCENE]: Upgrading child to root agent for {0} in {1}", 1133 // "[SCENE]: Upgrading child to root agent for {0} in {1}",
1040 // Name, m_scene.RegionInfo.RegionName); 1134 // Name, m_scene.RegionInfo.RegionName);
1041 1135
1042 if (ParentUUID != UUID.Zero) 1136 if (ParentUUID != UUID.Zero)
1043 { 1137 {
@@ -1046,20 +1140,23 @@ namespace OpenSim.Region.Framework.Scenes
1046 if (part == null) 1140 if (part == null)
1047 { 1141 {
1048 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); 1142 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
1143 ParentID = 0;
1144 ParentPart = null;
1145 PrevSitOffset = Vector3.Zero;
1146 HandleForceReleaseControls(ControllingClient, UUID); // needs testing
1147 IsLoggingIn = false;
1049 } 1148 }
1050 else 1149 else
1051 { 1150 {
1052 part.AddSittingAvatar(this); 1151 part.AddSittingAvatar(this);
1053 // ParentPosition = part.GetWorldPosition(); 1152 if (part.SitTargetPosition != Vector3.Zero)
1153 part.SitTargetAvatar = UUID;
1054 ParentID = part.LocalId; 1154 ParentID = part.LocalId;
1055 ParentPart = part; 1155 ParentPart = part;
1056 m_pos = PrevSitOffset; 1156 m_pos = PrevSitOffset;
1057 // pos = ParentPosition;
1058 pos = part.GetWorldPosition(); 1157 pos = part.GetWorldPosition();
1059 } 1158 }
1060 ParentUUID = UUID.Zero; 1159 ParentUUID = UUID.Zero;
1061
1062 // Animator.TrySetMovementAnimation("SIT");
1063 } 1160 }
1064 else 1161 else
1065 { 1162 {
@@ -1069,82 +1166,36 @@ namespace OpenSim.Region.Framework.Scenes
1069 IsChildAgent = false; 1166 IsChildAgent = false;
1070 } 1167 }
1071 1168
1169 m_log.DebugFormat("[MakeRootAgent] out lock: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1170
1072 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag 1171 // Must reset this here so that a teleport to a region next to an existing region does not keep the flag
1073 // set and prevent the close of the connection on a subsequent re-teleport. 1172 // set and prevent the close of the connection on a subsequent re-teleport.
1074 // Should not be needed if we are not trying to tell this region to close 1173 // Should not be needed if we are not trying to tell this region to close
1075// DoNotCloseAfterTeleport = false; 1174 // DoNotCloseAfterTeleport = false;
1076 1175
1077 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 1176 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
1078 if (gm != null) 1177 if (gm != null)
1079 Grouptitle = gm.GetGroupTitle(m_uuid); 1178 Grouptitle = gm.GetGroupTitle(m_uuid);
1080 1179
1081 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode); 1180
1082 uint teleportFlags = (aCircuit == null) ? 0 : aCircuit.teleportFlags; 1181 if ((m_teleportFlags & TeleportFlags.ViaHGLogin) != 0)
1083 if ((teleportFlags & (uint)TeleportFlags.ViaHGLogin) != 0)
1084 { 1182 {
1085 // The avatar is arriving from another grid. This means that we may have changed the 1183 // The avatar is arriving from another grid. This means that we may have changed the
1086 // avatar's name to or from the special Hypergrid format ("First.Last @grid.example.com"). 1184 // avatar's name to or from the special Hypergrid format ("First.Last @grid.example.com").
1087 // Unfortunately, due to a viewer bug, viewers don't always show the new name. 1185 // Unfortunately, due to a viewer bug, viewers don't always show the new name.
1088 // But we have a trick that can force them to update the name anyway. 1186 // But we have a trick that can force them to update the name anyway.
1089 ForceViewersUpdateName(); 1187// ForceViewersUpdateName();
1090 } 1188 }
1091 1189
1190 m_log.DebugFormat("[MakeRootAgent] Grouptitle: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1191
1092 RegionHandle = m_scene.RegionInfo.RegionHandle; 1192 RegionHandle = m_scene.RegionInfo.RegionHandle;
1093 1193
1094 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 1194 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
1095 1195 m_log.DebugFormat("[MakeRootAgent] TriggerSetRootAgentScene: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1096 UUID groupUUID = ControllingClient.ActiveGroupId;
1097 string groupName = string.Empty;
1098 ulong groupPowers = 0;
1099
1100 // ----------------------------------
1101 // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status
1102 try
1103 {
1104 if (groupUUID != UUID.Zero && gm != null)
1105 {
1106 GroupRecord record = gm.GetGroupRecord(groupUUID);
1107 if (record != null)
1108 groupName = record.GroupName;
1109
1110 GroupMembershipData groupMembershipData = gm.GetMembershipData(groupUUID, m_uuid);
1111
1112 if (groupMembershipData != null)
1113 groupPowers = groupMembershipData.GroupPowers;
1114 }
1115
1116 ControllingClient.SendAgentDataUpdate(
1117 m_uuid, groupUUID, Firstname, Lastname, groupPowers, groupName, Grouptitle);
1118 }
1119 catch (Exception e)
1120 {
1121 m_log.Error("[AGENTUPDATE]: Error ", e);
1122 }
1123 // ------------------------------------
1124 1196
1125 if (ParentID == 0) 1197 if (ParentID == 0)
1126 { 1198 {
1127 // Moved this from SendInitialData to ensure that Appearance is initialized
1128 // before the inventory is processed in MakeRootAgent. This fixes a race condition
1129 // related to the handling of attachments
1130 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
1131
1132 /* RA 20140111: Commented out these TestBorderCross's.
1133 * Not sure why this code is here. It is not checking all the borders
1134 * and 'in region' sanity checking is done in CheckAndAdjustLandingPoint and below.
1135 if (m_scene.TestBorderCross(pos, Cardinals.E))
1136 {
1137 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
1138 pos.X = crossedBorder.BorderLine.Z - 1;
1139 }
1140
1141 if (m_scene.TestBorderCross(pos, Cardinals.N))
1142 {
1143 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
1144 pos.Y = crossedBorder.BorderLine.Z - 1;
1145 }
1146 */
1147
1148 CheckAndAdjustLandingPoint(ref pos); 1199 CheckAndAdjustLandingPoint(ref pos);
1149 1200
1150 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 1201 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
@@ -1166,7 +1217,7 @@ namespace OpenSim.Region.Framework.Scenes
1166 1217
1167 if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY) 1218 if (pos.X < m_scene.RegionInfo.RegionSizeX && pos.Y < m_scene.RegionInfo.RegionSizeY)
1168 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 1219 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
1169 1220
1170 float newPosZ = posZLimit + localAVHeight / 2; 1221 float newPosZ = posZLimit + localAVHeight / 2;
1171 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 1222 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
1172 { 1223 {
@@ -1180,24 +1231,18 @@ namespace OpenSim.Region.Framework.Scenes
1180// 1231//
1181 if (m_teleportFlags == TeleportFlags.Default) 1232 if (m_teleportFlags == TeleportFlags.Default)
1182 { 1233 {
1234 Vector3 vel = Velocity;
1183 AddToPhysicalScene(isFlying); 1235 AddToPhysicalScene(isFlying);
1184// 1236 if (PhysicsActor != null)
1185// Console.WriteLine( 1237 PhysicsActor.SetMomentum(vel);
1186// "Set velocity of {0} in {1} to {2} from input velocity of {3} on MakeRootAgent",
1187// Name, Scene.Name, PhysicsActor.Velocity, vel);
1188// }
1189 } 1238 }
1190 else 1239 else
1191 { 1240 {
1192 AddToPhysicalScene(isFlying); 1241 AddToPhysicalScene(isFlying);
1193 }
1194 1242
1195 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a 1243 // reset camera to avatar pos
1196 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it 1244 CameraPosition = pos;
1197 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset 1245 }
1198 // the value to a negative position which does not trigger the border cross.
1199 // This may not be the best location for this.
1200 CheckForBorderCrossing();
1201 1246
1202 if (ForceFly) 1247 if (ForceFly)
1203 { 1248 {
@@ -1207,55 +1252,29 @@ namespace OpenSim.Region.Framework.Scenes
1207 { 1252 {
1208 Flying = false; 1253 Flying = false;
1209 } 1254 }
1210 }
1211 1255
1212 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying 1256 // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a
1213 // avatar to return to the standing position in mid-air. On login it looks like this is being sent 1257 // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it
1214 // elsewhere anyway 1258 // since it requires a physics actor to be present. If it is left any later, then physics appears to reset
1215 // Animator.SendAnimPack(); 1259 // the value to a negative position which does not trigger the border cross.
1260 // This may not be the best location for this.
1216 1261
1217 m_scene.SwapRootAgentCount(false);
1218 1262
1219 if (Scene.AttachmentsModule != null) 1263 // its not
1220 { 1264// CheckForBorderCrossing();
1221 // The initial login scene presence is already root when it gets here
1222 // and it has already rezzed the attachments and started their scripts.
1223 // We do the following only for non-login agents, because their scripts
1224 // haven't started yet.
1225 if (PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags))
1226 {
1227 WorkManager.RunJob(
1228 "RezAttachments",
1229 o => Scene.AttachmentsModule.RezAttachments(this),
1230 null,
1231 string.Format("Rez attachments for {0} in {1}", Name, Scene.Name));
1232 }
1233 else
1234 {
1235 WorkManager.RunJob(
1236 "StartAttachmentScripts",
1237 o => RestartAttachmentScripts(),
1238 null,
1239 string.Format("Start attachment scripts for {0} in {1}", Name, Scene.Name),
1240 true);
1241 }
1242 } 1265 }
1243 1266
1244 SendAvatarDataToAllClients(); 1267
1245 1268 m_log.DebugFormat("[MakeRootAgent] position and physical: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1246 // send the animations of the other presences to me 1269 m_scene.SwapRootAgentCount(false);
1247 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
1248 {
1249 if (presence != this)
1250 presence.Animator.SendAnimPackToClient(ControllingClient);
1251 });
1252 1270
1253 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will 1271 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will
1254 // stall on the border crossing since the existing child agent will still have the last movement 1272 // stall on the border crossing since the existing child agent will still have the last movement
1255 // recorded, which stops the input from being processed. 1273 // recorded, which stops the input from being processed.
1256 MovementFlag = ForceUpdateMovementFlagValue; 1274 MovementFlag = 0;
1257 1275
1258 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1276 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1277 m_log.DebugFormat("[MakeRootAgent] TriggerOnMakeRootAgent and done: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1259 1278
1260 return true; 1279 return true;
1261 } 1280 }
@@ -1304,12 +1323,13 @@ namespace OpenSim.Region.Framework.Scenes
1304 /// Group Title. So the following trick makes viewers update the avatar's name by briefly changing 1323 /// Group Title. So the following trick makes viewers update the avatar's name by briefly changing
1305 /// the group title (to "(Loading)"), and then restoring it. 1324 /// the group title (to "(Loading)"), and then restoring it.
1306 /// </remarks> 1325 /// </remarks>
1326/*
1307 public void ForceViewersUpdateName() 1327 public void ForceViewersUpdateName()
1308 { 1328 {
1309 m_log.DebugFormat("[SCENE PRESENCE]: Forcing viewers to update the avatar name for " + Name); 1329 m_log.DebugFormat("[SCENE PRESENCE]: Forcing viewers to update the avatar name for " + Name);
1310 1330
1311 UseFakeGroupTitle = true; 1331 UseFakeGroupTitle = true;
1312 SendAvatarDataToAllClients(false); 1332
1313 1333
1314 Util.FireAndForget(o => 1334 Util.FireAndForget(o =>
1315 { 1335 {
@@ -1323,7 +1343,7 @@ namespace OpenSim.Region.Framework.Scenes
1323 SendAvatarDataToAllClients(false); 1343 SendAvatarDataToAllClients(false);
1324 }, null, "Scenepresence.ForceViewersUpdateName"); 1344 }, null, "Scenepresence.ForceViewersUpdateName");
1325 } 1345 }
1326 1346*/
1327 public int GetStateSource() 1347 public int GetStateSource()
1328 { 1348 {
1329 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(UUID); 1349 AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(UUID);
@@ -1347,11 +1367,14 @@ namespace OpenSim.Region.Framework.Scenes
1347 /// It doesn't get called for a teleport. Reason being, an agent that 1367 /// It doesn't get called for a teleport. Reason being, an agent that
1348 /// teleports out may not end up anywhere near this region 1368 /// teleports out may not end up anywhere near this region
1349 /// </remarks> 1369 /// </remarks>
1350 public void MakeChildAgent() 1370 public void MakeChildAgent(ulong newRegionHandle)
1351 { 1371 {
1352 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; 1372 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1353 1373
1354 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); 1374 RegionHandle = newRegionHandle;
1375
1376 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1} from root region {2}",
1377 Name, Scene.RegionInfo.RegionName, newRegionHandle);
1355 1378
1356 // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating 1379 // Reset the m_originRegionID as it has dual use as a flag to signal that the UpdateAgent() call orignating
1357 // from the source simulator has completed on a V2 teleport. 1380 // from the source simulator has completed on a V2 teleport.
@@ -1371,7 +1394,7 @@ namespace OpenSim.Region.Framework.Scenes
1371 else 1394 else
1372 Animator.ResetAnimations(); 1395 Animator.ResetAnimations();
1373 1396
1374 1397
1375// m_log.DebugFormat( 1398// m_log.DebugFormat(
1376// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", 1399// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
1377// Name, UUID, m_scene.RegionInfo.RegionName); 1400// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1385,8 +1408,15 @@ namespace OpenSim.Region.Framework.Scenes
1385 RemoveFromPhysicalScene(); 1408 RemoveFromPhysicalScene();
1386 ParentID = 0; // Child agents can't be sitting 1409 ParentID = 0; // Child agents can't be sitting
1387 1410
1411// we dont have land information for child
1412 m_previusParcelHide = false;
1413 m_previusParcelUUID = UUID.Zero;
1414 m_currentParcelHide = false;
1415 m_currentParcelUUID = UUID.Zero;
1388 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into 1416 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into
1389 1417
1418 CollisionPlane = Vector4.UnitW;
1419
1390 m_scene.EventManager.TriggerOnMakeChildAgent(this); 1420 m_scene.EventManager.TriggerOnMakeChildAgent(this);
1391 } 1421 }
1392 1422
@@ -1398,9 +1428,10 @@ namespace OpenSim.Region.Framework.Scenes
1398 if (PhysicsActor != null) 1428 if (PhysicsActor != null)
1399 { 1429 {
1400// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1430// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
1401 PhysicsActor.UnSubscribeEvents(); 1431
1402 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall; 1432 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall;
1403 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1433 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1434 PhysicsActor.UnSubscribeEvents();
1404 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1435 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1405 PhysicsActor = null; 1436 PhysicsActor = null;
1406 } 1437 }
@@ -1438,6 +1469,8 @@ namespace OpenSim.Region.Framework.Scenes
1438 else 1469 else
1439 PhysicsActor.SetMomentum(vel); 1470 PhysicsActor.SetMomentum(vel);
1440 } 1471 }
1472
1473 SendTerseUpdateToAllClients();
1441 } 1474 }
1442 1475
1443 public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY) 1476 public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY)
@@ -1469,10 +1502,14 @@ namespace OpenSim.Region.Framework.Scenes
1469 } 1502 }
1470 } 1503 }
1471 } 1504 }
1505 SendTerseUpdateToAllClients();
1472 } 1506 }
1473 1507
1474 public void StopFlying() 1508 public void StopFlying()
1475 { 1509 {
1510 if (IsInTransit)
1511 return;
1512
1476 Vector3 pos = AbsolutePosition; 1513 Vector3 pos = AbsolutePosition;
1477 if (Appearance.AvatarHeight != 127.0f) 1514 if (Appearance.AvatarHeight != 127.0f)
1478 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f)); 1515 pos += new Vector3(0f, 0f, (Appearance.AvatarHeight / 6f));
@@ -1492,7 +1529,7 @@ namespace OpenSim.Region.Framework.Scenes
1492 else 1529 else
1493 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f)); 1530 CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f / 6f));
1494 1531
1495 ControllingClient.SendAgentTerseUpdate(this); 1532 SendAgentTerseUpdate(this);
1496 } 1533 }
1497 1534
1498 /// <summary> 1535 /// <summary>
@@ -1578,15 +1615,46 @@ namespace OpenSim.Region.Framework.Scenes
1578 // holds the seed cap for the child agent in that region 1615 // holds the seed cap for the child agent in that region
1579 private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>(); 1616 private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>();
1580 1617
1581 public void AddNeighbourRegion(ulong regionHandle, string cap) 1618 struct spRegionSizeInfo
1619 {
1620 public int sizeX;
1621 public int sizeY;
1622 }
1623
1624 private Dictionary<ulong, spRegionSizeInfo> m_knownChildRegionsSizeInfo = new Dictionary<ulong, spRegionSizeInfo>();
1625
1626
1627 public void AddNeighbourRegionSizeInfo(GridRegion region)
1628 {
1629 lock (m_knownChildRegions)
1630 {
1631 spRegionSizeInfo sizeInfo = new spRegionSizeInfo();
1632 sizeInfo.sizeX = region.RegionSizeX;
1633 sizeInfo.sizeY = region.RegionSizeY;
1634 ulong regionHandle = region.RegionHandle;
1635
1636 if (!m_knownChildRegionsSizeInfo.ContainsKey(regionHandle))
1637 {
1638 m_knownChildRegionsSizeInfo.Add(regionHandle, sizeInfo);
1639
1640 }
1641 else
1642 m_knownChildRegionsSizeInfo[regionHandle] = sizeInfo;
1643 }
1644 }
1645
1646 public void SetNeighbourRegionSizeInfo(List<GridRegion> regionsList)
1582 { 1647 {
1583 lock (m_knownChildRegions) 1648 lock (m_knownChildRegions)
1584 { 1649 {
1585 if (!m_knownChildRegions.ContainsKey(regionHandle)) 1650 m_knownChildRegionsSizeInfo.Clear();
1651 foreach (GridRegion region in regionsList)
1586 { 1652 {
1587 uint x, y; 1653 spRegionSizeInfo sizeInfo = new spRegionSizeInfo();
1588 Utils.LongToUInts(regionHandle, out x, out y); 1654 sizeInfo.sizeX = region.RegionSizeX;
1589 m_knownChildRegions.Add(regionHandle, cap); 1655 sizeInfo.sizeY = region.RegionSizeY;
1656 ulong regionHandle = region.RegionHandle;
1657 m_knownChildRegionsSizeInfo.Add(regionHandle, sizeInfo);
1590 } 1658 }
1591 } 1659 }
1592 } 1660 }
@@ -1600,6 +1668,7 @@ namespace OpenSim.Region.Framework.Scenes
1600 //if (m_knownChildRegions.ContainsKey(regionHandle)) 1668 //if (m_knownChildRegions.ContainsKey(regionHandle))
1601 // m_log.DebugFormat(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count); 1669 // m_log.DebugFormat(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count);
1602 m_knownChildRegions.Remove(regionHandle); 1670 m_knownChildRegions.Remove(regionHandle);
1671 m_knownChildRegionsSizeInfo.Remove(regionHandle);
1603 } 1672 }
1604 } 1673 }
1605 1674
@@ -1612,6 +1681,13 @@ namespace OpenSim.Region.Framework.Scenes
1612 } 1681 }
1613 } 1682 }
1614 1683
1684 public void DropThisRootRegionFromNeighbours()
1685 {
1686 ulong handle = m_scene.RegionInfo.RegionHandle;
1687 RemoveNeighbourRegion(handle);
1688 Scene.CapsModule.DropChildSeed(UUID, handle);
1689 }
1690
1615 public Dictionary<ulong, string> KnownRegions 1691 public Dictionary<ulong, string> KnownRegions
1616 { 1692 {
1617 get 1693 get
@@ -1662,12 +1738,7 @@ namespace OpenSim.Region.Framework.Scenes
1662 public void SetSize(Vector3 size, float feetoffset) 1738 public void SetSize(Vector3 size, float feetoffset)
1663 { 1739 {
1664 if (PhysicsActor != null && !IsChildAgent) 1740 if (PhysicsActor != null && !IsChildAgent)
1665 { 1741 PhysicsActor.setAvatarSize(size, feetoffset);
1666 // Eventually there will be a physics call that sets avatar size that includes offset info.
1667 // For the moment, just set the size as passed.
1668 PhysicsActor.Size = size;
1669 // PhysicsActor.setAvatarSize(size, feetoffset);
1670 }
1671 } 1742 }
1672 1743
1673 private bool WaitForUpdateAgent(IClientAPI client) 1744 private bool WaitForUpdateAgent(IClientAPI client)
@@ -1676,13 +1747,23 @@ namespace OpenSim.Region.Framework.Scenes
1676 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination, 1747 // (which triggers Scene.IncomingUpdateChildAgent(AgentData cAgentData) here in the destination,
1677 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the 1748 // m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
1678 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero 1749 // viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
1679 m_updateAgentReceivedAfterTransferEvent.WaitOne(10000); 1750// m_updateAgentReceivedAfterTransferEvent.WaitOne(10000);
1680 1751 int count = 50;
1681 UUID originID = UUID.Zero; 1752 UUID originID = UUID.Zero;
1682 1753
1683 lock (m_originRegionIDAccessLock) 1754 lock (m_originRegionIDAccessLock)
1684 originID = m_originRegionID; 1755 originID = m_originRegionID;
1685 1756
1757
1758 while (originID.Equals(UUID.Zero) && count-- > 0)
1759 {
1760 lock (m_originRegionIDAccessLock)
1761 originID = m_originRegionID;
1762
1763 m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
1764 Thread.Sleep(200);
1765 }
1766
1686 if (originID.Equals(UUID.Zero)) 1767 if (originID.Equals(UUID.Zero))
1687 { 1768 {
1688 // Movement into region will fail 1769 // Movement into region will fail
@@ -1704,62 +1785,70 @@ namespace OpenSim.Region.Framework.Scenes
1704 /// </param> 1785 /// </param>
1705 public void CompleteMovement(IClientAPI client, bool openChildAgents) 1786 public void CompleteMovement(IClientAPI client, bool openChildAgents)
1706 { 1787 {
1707// DateTime startTime = DateTime.Now; 1788 int ts = Util.EnvironmentTickCount();
1708 1789
1709 m_log.InfoFormat( 1790 m_log.InfoFormat(
1710 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}", 1791 "[SCENE PRESENCE]: Completing movement of {0} into region {1} in position {2}",
1711 client.Name, Scene.Name, AbsolutePosition); 1792 client.Name, Scene.Name, AbsolutePosition);
1793
1794 m_inTransit = true;
1712 1795
1713 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); // Get this ahead of time because IsInTransit modifies 'm_AgentControlFlags'
1714
1715 IsInTransit = true;
1716 try 1796 try
1717 { 1797 {
1718 // Make sure it's not a login agent. We don't want to wait for updates during login 1798 // Make sure it's not a login agent. We don't want to wait for updates during login
1719 if (!(PresenceType == PresenceType.Npc || IsRealLogin(m_teleportFlags))) 1799 if (!isNPC && !IsRealLogin(m_teleportFlags))
1720 { 1800 {
1801
1721 // Let's wait until UpdateAgent (called by departing region) is done 1802 // Let's wait until UpdateAgent (called by departing region) is done
1722 if (!WaitForUpdateAgent(client)) 1803 if (!WaitForUpdateAgent(client))
1723 // The sending region never sent the UpdateAgent data, we have to refuse 1804 // The sending region never sent the UpdateAgent data, we have to refuse
1724 return; 1805 return;
1725 } 1806 }
1726 1807
1727 Vector3 look = Velocity; 1808 m_log.DebugFormat("[CompleteMovement] WaitForUpdateAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1728 1809
1729 // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) 1810 bool flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
1730 if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1)) 1811
1812 if (!MakeRootAgent(AbsolutePosition, flying))
1731 { 1813 {
1732 look = new Vector3(0.99f, 0.042f, 0); 1814 m_log.DebugFormat(
1815 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root",
1816 Name, Scene.Name);
1817
1818 return;
1733 } 1819 }
1734 1820
1735 // Prevent teleporting to an underground location 1821 m_log.DebugFormat("[CompleteMovement] MakeRootAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1736 // (may crash client otherwise) 1822
1737 // 1823 Vector3 look = Lookat;
1738 Vector3 pos = AbsolutePosition; 1824 if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01))
1739 float ground = m_scene.GetGroundHeight(pos.X, pos.Y);
1740 if (pos.Z < ground + 1.5f)
1741 { 1825 {
1742 pos.Z = ground + 1.5f; 1826 look = Velocity;
1743 AbsolutePosition = pos; 1827 look.Z = 0;
1828 look.Normalize();
1829 if ((Math.Abs(look.X) < 0.01) && (Math.Abs(look.Y) < 0.01) )
1830 look = new Vector3(0.99f, 0.042f, 0);
1744 } 1831 }
1745 1832
1746 if (!MakeRootAgent(AbsolutePosition, flying)) 1833// start sending terrain patchs
1834 if (!isNPC)
1835 Scene.SendLayerData(ControllingClient);
1836
1837 if (!IsChildAgent && !isNPC)
1747 { 1838 {
1748 m_log.DebugFormat( 1839 InventoryFolderBase cof = m_scene.InventoryService.GetFolderForType(client.AgentId, (FolderType)46);
1749 "[SCENE PRESENCE]: Aborting CompleteMovement call for {0} in {1} as they are already root", 1840 if (cof == null)
1750 Name, Scene.Name); 1841 COF = UUID.Zero;
1842 else
1843 COF = cof.ID;
1751 1844
1752 return; 1845 m_log.DebugFormat("[ScenePresence]: CompleteMovement COF for {0} is {1}", client.AgentId, COF);
1753 } 1846 }
1754 1847
1755 // Tell the client that we're totally ready 1848 // Tell the client that we're totally ready
1756 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); 1849 ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1757 1850
1758 // Child agents send initial data up in LLUDPServer.HandleUseCircuitCode() 1851 m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1759 if (!SentInitialDataToClient)
1760 SendInitialDataToClient();
1761
1762 // m_log.DebugFormat("[SCENE PRESENCE] Completed movement");
1763 1852
1764 if (!string.IsNullOrEmpty(m_callbackURI)) 1853 if (!string.IsNullOrEmpty(m_callbackURI))
1765 { 1854 {
@@ -1768,69 +1857,205 @@ namespace OpenSim.Region.Framework.Scenes
1768 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete 1857 // here until we know for sure that the agent is active in this region. Sending AgentMovementComplete
1769 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this 1858 // is not enough for Imprudence clients - there appears to be a small delay (<200ms, <500ms) until they regard this
1770 // region as the current region, meaning that a close sent before then will fail the teleport. 1859 // region as the current region, meaning that a close sent before then will fail the teleport.
1771 // System.Threading.Thread.Sleep(2000); 1860 // System.Threading.Thread.Sleep(2000);
1772 1861
1773 m_log.DebugFormat( 1862 m_log.DebugFormat(
1774 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}", 1863 "[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
1775 client.Name, client.AgentId, m_callbackURI); 1864 client.Name, client.AgentId, m_callbackURI);
1776 1865
1777 Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI); 1866 UUID originID;
1867
1868 lock (m_originRegionIDAccessLock)
1869 originID = m_originRegionID;
1870
1871 Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
1778 m_callbackURI = null; 1872 m_callbackURI = null;
1779 } 1873 }
1780 // else 1874// else
1781 // { 1875// {
1782 // m_log.DebugFormat( 1876// m_log.DebugFormat(
1783 // "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}", 1877// "[SCENE PRESENCE]: No callback provided on CompleteMovement of {0} {1} to {2}",
1784 // client.Name, client.AgentId, m_scene.RegionInfo.RegionName); 1878// client.Name, client.AgentId, m_scene.RegionInfo.RegionName);
1785 // } 1879// }
1786 1880
1787 ValidateAndSendAppearanceAndAgentData(); 1881 m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1788 1882
1789 // Create child agents in neighbouring regions 1883 m_previusParcelHide = false;
1790 if (openChildAgents && !IsChildAgent) 1884 m_previusParcelUUID = UUID.Zero;
1885 m_currentParcelHide = false;
1886 m_currentParcelUUID = UUID.Zero;
1887
1888 // send initial land overlay and parcel
1889 ILandChannel landch = m_scene.LandChannel;
1890 if (landch != null)
1891 landch.sendClientInitialLandInfo(client);
1892
1893 if (!IsChildAgent)
1791 { 1894 {
1792 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); 1895
1793 if (m_agentTransfer != null) 1896 // ValidateAndSendAppearanceAndAgentData();
1897
1898 // do it here in line
1899 // so sequence is clear
1900
1901 // verify baked textures and cache
1902 bool cachedbaked = false;
1903
1904 if (isNPC)
1905 cachedbaked = true;
1906 else
1907 {
1908 if (m_scene.AvatarFactory != null)
1909 cachedbaked = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
1910
1911 // not sure we need this
1912 if (!cachedbaked)
1913 {
1914 if (m_scene.AvatarFactory != null)
1915 m_scene.AvatarFactory.QueueAppearanceSave(UUID);
1916 }
1917 }
1918
1919 List<ScenePresence> allpresences = m_scene.GetScenePresences();
1920
1921 // send avatar object to all presences including us, so they cross it into region
1922 // then hide if necessary
1923 SendInitialAvatarDataToAllAgents(allpresences);
1924
1925 // send this look
1926 SendAppearanceToAgent(this);
1927
1928 // send this animations
1929
1930 UUID[] animIDs = null;
1931 int[] animseqs = null;
1932 UUID[] animsobjs = null;
1933
1934 if (Animator != null)
1935 Animator.GetArrays(out animIDs, out animseqs, out animsobjs);
1936
1937 bool haveAnims = (animIDs != null && animseqs != null && animsobjs != null);
1938
1939 if (haveAnims)
1940 SendAnimPackToAgent(this, animIDs, animseqs, animsobjs);
1941
1942 // we should be able to receive updates, etc
1943 // so release them
1944 m_inTransit = false;
1945
1946 // send look and animations to others
1947 // if not cached we send greys
1948 // uncomented if will wait till avatar does baking
1949 //if (cachedbaked)
1950 {
1951 foreach (ScenePresence p in allpresences)
1952 {
1953 if (p == this)
1954 continue;
1955
1956 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
1957 continue;
1958
1959 SendAppearanceToAgentNF(p);
1960 if (haveAnims)
1961 SendAnimPackToAgentNF(p, animIDs, animseqs, animsobjs);
1962 }
1963 } // greys if
1964
1965 m_log.DebugFormat("[CompleteMovement] ValidateAndSendAppearanceAndAgentData: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1966
1967 // attachments
1968
1969 if (isNPC || IsRealLogin(m_teleportFlags))
1970 {
1971 if (Scene.AttachmentsModule != null)
1972 // Util.FireAndForget(
1973 // o =>
1974 // {
1975 if (!isNPC)
1976 Scene.AttachmentsModule.RezAttachments(this);
1977 else
1978 Util.FireAndForget(x =>
1979 {
1980 Scene.AttachmentsModule.RezAttachments(this);
1981 });
1982 // });
1983 }
1984 else
1794 { 1985 {
1795 // Note: this call can take a while, because it notifies each of the simulator's neighbours. 1986 if (m_attachments.Count > 0)
1796 // It's important that we don't allow the avatar to cross regions meanwhile, as that will 1987 {
1797 // cause serious errors. We've prevented that from happening by setting IsInTransit=true. 1988 m_log.DebugFormat(
1798 m_agentTransfer.EnableChildAgents(this); 1989 "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name);
1990
1991 foreach (SceneObjectGroup sog in m_attachments)
1992 {
1993 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
1994 sog.ResumeScripts();
1995 }
1996
1997 foreach (ScenePresence p in allpresences)
1998 {
1999 if (p == this)
2000 {
2001 SendTerseUpdateToAgentNF(this);
2002 SendAttachmentsToAgentNF(this);
2003 continue;
2004 }
2005
2006 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
2007 continue;
2008
2009 SendTerseUpdateToAgentNF(p);
2010 SendAttachmentsToAgentNF(p);
2011 }
2012 }
1799 } 2013 }
1800 2014
2015 m_log.DebugFormat("[CompleteMovement] attachments: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2016 if (openChildAgents)
2017 {
2018 // Create child agents in neighbouring regions
2019 IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
2020 if (m_agentTransfer != null)
2021 {
2022 m_agentTransfer.EnableChildAgents(this);
2023 }
2024 }
2025 }
2026
2027 m_log.DebugFormat("[CompleteMovement] openChildAgents: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2028
2029 // send the rest of the world
2030 if (m_teleportFlags > 0 && !isNPC || m_currentParcelHide)
2031 SendInitialDataToMe();
2032
2033 m_log.DebugFormat("[CompleteMovement] SendInitialDataToMe: {0}ms", Util.EnvironmentTickCountSubtract(ts));
2034
2035 if (!IsChildAgent && openChildAgents)
2036 {
1801 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>(); 2037 IFriendsModule friendsModule = m_scene.RequestModuleInterface<IFriendsModule>();
1802 if (friendsModule != null) 2038 if (friendsModule != null)
1803 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); 2039 friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
1804 2040
1805 } 2041 m_log.DebugFormat("[CompleteMovement] friendsModule: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1806 2042
1807 // XXX: If we force an update after activity has completed, then multiple attachments do appear correctly on a destination region 2043 }
1808 // If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work.
1809 // This may be due to viewer code or it may be something we're not doing properly simulator side.
1810 WorkManager.RunJob(
1811 "ScheduleAttachmentsForFullUpdate",
1812 o => ScheduleAttachmentsForFullUpdate(),
1813 null,
1814 string.Format("Schedule attachments for full update for {0} in {1}", Name, Scene.Name),
1815 true);
1816
1817 // m_log.DebugFormat(
1818 // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
1819 // client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds);
1820 } 2044 }
1821 finally 2045 finally
1822 { 2046 {
1823 IsInTransit = false; 2047 m_inTransit = false;
1824 } 2048 }
1825 } 2049 // if hide force a check
2050 // if (!IsChildAgent && newhide)
2051 // {
2052 // ParcelLoginCheck(m_currentParcelUUID);
2053 // m_currentParcelHide = newhide;
2054 // }
1826 2055
1827 private void ScheduleAttachmentsForFullUpdate() 2056 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd;
1828 { 2057
1829 lock (m_attachments) 2058 m_log.DebugFormat("[CompleteMovement] end: {0}ms", Util.EnvironmentTickCountSubtract(ts));
1830 {
1831 foreach (SceneObjectGroup sog in m_attachments)
1832 sog.ScheduleGroupForFullUpdate();
1833 }
1834 } 2059 }
1835 2060
1836 /// <summary> 2061 /// <summary>
@@ -1921,6 +2146,9 @@ namespace OpenSim.Region.Framework.Scenes
1921 return; 2146 return;
1922 } 2147 }
1923 2148
2149 if (IsInTransit)
2150 return;
2151
1924 #region Sanity Checking 2152 #region Sanity Checking
1925 2153
1926 // This is irritating. Really. 2154 // This is irritating. Really.
@@ -1955,8 +2183,8 @@ namespace OpenSim.Region.Framework.Scenes
1955 // When we get to the point of re-computing neighbors everytime this 2183 // When we get to the point of re-computing neighbors everytime this
1956 // changes, then start using the agent's drawdistance rather than the 2184 // changes, then start using the agent's drawdistance rather than the
1957 // region's draw distance. 2185 // region's draw distance.
2186
1958 DrawDistance = agentData.Far; 2187 DrawDistance = agentData.Far;
1959 // DrawDistance = Scene.DefaultDrawDistance;
1960 2188
1961 m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0; 2189 m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
1962 2190
@@ -1964,7 +2192,7 @@ namespace OpenSim.Region.Framework.Scenes
1964 // is first pressed, not whilst it is held down. If this is required in the future then need to look 2192 // is first pressed, not whilst it is held down. If this is required in the future then need to look
1965 // for an AGENT_CONTROL_LBUTTON_UP event and make sure to handle cases where an initial DOWN is not 2193 // for an AGENT_CONTROL_LBUTTON_UP event and make sure to handle cases where an initial DOWN is not
1966 // received (e.g. on holding LMB down on the avatar in a viewer). 2194 // received (e.g. on holding LMB down on the avatar in a viewer).
1967// m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0; 2195 m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
1968 2196
1969 #endregion Inputs 2197 #endregion Inputs
1970 2198
@@ -1977,6 +2205,7 @@ namespace OpenSim.Region.Framework.Scenes
1977// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) 2205// (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
1978// m_updateCount = UPDATE_COUNT; 2206// m_updateCount = UPDATE_COUNT;
1979 2207
2208
1980 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0) 2209 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
1981 { 2210 {
1982 StandUp(); 2211 StandUp();
@@ -2032,7 +2261,7 @@ namespace OpenSim.Region.Framework.Scenes
2032 2261
2033 // We need to send this back to the client in order to stop the edit beams 2262 // We need to send this back to the client in order to stop the edit beams
2034 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None) 2263 if ((oldState & (uint)AgentState.Editing) != 0 && State == (uint)AgentState.None)
2035 ControllingClient.SendAgentTerseUpdate(this); 2264 SendAgentTerseUpdate(this);
2036 2265
2037 PhysicsActor actor = PhysicsActor; 2266 PhysicsActor actor = PhysicsActor;
2038 2267
@@ -2045,10 +2274,8 @@ namespace OpenSim.Region.Framework.Scenes
2045 2274
2046 if (AllowMovement && !SitGround) 2275 if (AllowMovement && !SitGround)
2047 { 2276 {
2048// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name); 2277// m_log.DebugFormat("[SCENE PRESENCE]: Initial body rotation {0} for {1}", agentData.BodyRotation, Name);
2049
2050 bool update_rotation = false; 2278 bool update_rotation = false;
2051
2052 if (agentData.BodyRotation != Rotation) 2279 if (agentData.BodyRotation != Rotation)
2053 { 2280 {
2054 Rotation = agentData.BodyRotation; 2281 Rotation = agentData.BodyRotation;
@@ -2057,14 +2284,6 @@ namespace OpenSim.Region.Framework.Scenes
2057 2284
2058 bool update_movementflag = false; 2285 bool update_movementflag = false;
2059 2286
2060 // If we were just made root agent then we must perform movement updates for the first AgentUpdate that
2061 // we get
2062 if (MovementFlag == ForceUpdateMovementFlagValue)
2063 {
2064 MovementFlag = 0;
2065 update_movementflag = true;
2066 }
2067
2068 if (agentData.UseClientAgentPosition) 2287 if (agentData.UseClientAgentPosition)
2069 { 2288 {
2070 MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f; 2289 MovingToTarget = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
@@ -2075,7 +2294,7 @@ namespace OpenSim.Region.Framework.Scenes
2075 bool DCFlagKeyPressed = false; 2294 bool DCFlagKeyPressed = false;
2076 Vector3 agent_control_v3 = Vector3.Zero; 2295 Vector3 agent_control_v3 = Vector3.Zero;
2077 2296
2078 bool newFlying = actor.Flying; 2297 bool newFlying = false;
2079 2298
2080 if (ForceFly) 2299 if (ForceFly)
2081 newFlying = true; 2300 newFlying = true;
@@ -2096,6 +2315,15 @@ namespace OpenSim.Region.Framework.Scenes
2096 { 2315 {
2097 bool bAllowUpdateMoveToPosition = false; 2316 bool bAllowUpdateMoveToPosition = false;
2098 2317
2318 Vector3[] dirVectors;
2319
2320 // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying
2321 // this prevents 'jumping' in inappropriate situations.
2322// if (!Flying && (m_mouseLook || m_leftButtonDown))
2323// dirVectors = GetWalkDirectionVectors();
2324// else
2325 dirVectors = Dir_Vectors;
2326
2099 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. 2327 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction.
2100 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 2328 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
2101 { 2329 {
@@ -2105,9 +2333,7 @@ namespace OpenSim.Region.Framework.Scenes
2105 2333
2106 try 2334 try
2107 { 2335 {
2108 // Don't slide against ground when crouching if camera is panned around avatar 2336 agent_control_v3 += Dir_Vectors[i];
2109 if (Flying || DCF != Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN)
2110 agent_control_v3 += Dir_Vectors[i];
2111 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 2337 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]);
2112 } 2338 }
2113 catch (IndexOutOfRangeException) 2339 catch (IndexOutOfRangeException)
@@ -2115,10 +2341,10 @@ namespace OpenSim.Region.Framework.Scenes
2115 // Why did I get this? 2341 // Why did I get this?
2116 } 2342 }
2117 2343
2118 if (((MovementFlag & (uint)DCF) == 0) & !AgentControlStopActive) 2344 if (((MovementFlag & (uint)DCF) == 0))
2119 { 2345 {
2120 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF); 2346 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with {1}", Name, DCF);
2121 MovementFlag += (uint)DCF; 2347 MovementFlag |= (uint)DCF;
2122 update_movementflag = true; 2348 update_movementflag = true;
2123 } 2349 }
2124 } 2350 }
@@ -2127,7 +2353,7 @@ namespace OpenSim.Region.Framework.Scenes
2127 if ((MovementFlag & (uint)DCF) != 0) 2353 if ((MovementFlag & (uint)DCF) != 0)
2128 { 2354 {
2129 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF); 2355 //m_log.DebugFormat("[SCENE PRESENCE]: Updating MovementFlag for {0} with lack of {1}", Name, DCF);
2130 MovementFlag -= (uint)DCF; 2356 MovementFlag &= (uint)~DCF;
2131 update_movementflag = true; 2357 update_movementflag = true;
2132 2358
2133 /* 2359 /*
@@ -2180,11 +2406,11 @@ namespace OpenSim.Region.Framework.Scenes
2180 if (Flying && !ForceFly) 2406 if (Flying && !ForceFly)
2181 { 2407 {
2182 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP 2408 // Need to stop in mid air if user holds down AGENT_CONTROL_STOP
2183 if (AgentControlStopActive) 2409 // if (AgentControlStopActive)
2184 { 2410 // {
2185 agent_control_v3 = Vector3.Zero; 2411 // agent_control_v3 = Vector3.Zero;
2186 } 2412 // }
2187 else 2413 // else
2188 { 2414 {
2189 // Landing detection code 2415 // Landing detection code
2190 2416
@@ -2192,38 +2418,44 @@ namespace OpenSim.Region.Framework.Scenes
2192 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || 2418 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
2193 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2419 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
2194 2420
2195 //m_log.Debug("[CONTROL]: " +flags); 2421 //m_log.Debug("[CONTROL]: " +flags);
2196 // Applies a satisfying roll effect to the avatar when flying. 2422 // Applies a satisfying roll effect to the avatar when flying.
2197 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0) 2423 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
2198 { 2424 {
2199 ApplyFlyingRoll( 2425 ApplyFlyingRoll(
2200 FLY_ROLL_RADIANS_PER_UPDATE, 2426 FLY_ROLL_RADIANS_PER_UPDATE,
2201 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, 2427 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2202 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); 2428 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2203 } 2429 }
2204 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 && 2430 else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
2205 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0) 2431 (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
2206 { 2432 {
2207 ApplyFlyingRoll( 2433 ApplyFlyingRoll(
2208 -FLY_ROLL_RADIANS_PER_UPDATE, 2434 -FLY_ROLL_RADIANS_PER_UPDATE,
2209 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0, 2435 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
2210 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0); 2436 (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
2211 } 2437 }
2212 else 2438 else
2213 { 2439 {
2214 if (m_AngularVelocity.Z != 0) 2440 if (m_AngularVelocity.Z != 0)
2215 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE); 2441 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
2216 }
2217
2218 if (Flying && IsColliding && controlland)
2219 {
2220 // nesting this check because LengthSquared() is expensive and we don't
2221 // want to do it every step when flying.
2222 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2223 StopFlying();
2224 } 2442 }
2443
2444 /*
2445 if (Flying && IsColliding && controlland)
2446 {
2447 // nesting this check because LengthSquared() is expensive and we don't
2448 // want to do it every step when flying.
2449 if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
2450 StopFlying();
2451 }
2452 */
2225 } 2453 }
2226 } 2454 }
2455 else if (IsColliding && agent_control_v3.Z < 0f)
2456 agent_control_v3.Z = 0;
2457// else if(AgentControlStopActive %% Velocity.Z <0.01f)
2458
2227 2459
2228// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name); 2460// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);
2229 2461
@@ -2236,32 +2468,23 @@ namespace OpenSim.Region.Framework.Scenes
2236 if (update_movementflag 2468 if (update_movementflag
2237 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0))) 2469 || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
2238 { 2470 {
2239// if (update_movementflag || !AgentControlStopActive || MovementFlag != 0)
2240// {
2241// m_log.DebugFormat(
2242// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, mf = {4}, ur = {5}",
2243// m_scene.RegionInfo.RegionName, agent_control_v3, Name,
2244// update_movementflag, MovementFlag, update_rotation);
2245
2246 float speedModifier;
2247 2471
2248 if (AgentControlStopActive) 2472 if (AgentControlStopActive)
2249 speedModifier = AgentControlStopSlowWhilstMoving; 2473 {
2474 // if (MovementFlag == 0 && Animator.Falling)
2475 if (MovementFlag == 0 && Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling)
2476 {
2477 AddNewMovement(agent_control_v3, AgentControlStopSlowVel, true);
2478 }
2250 else 2479 else
2251 speedModifier = 1; 2480 AddNewMovement(agent_control_v3, AgentControlStopSlowVel);
2481 }
2482 else
2483 {
2484 AddNewMovement(agent_control_v3);
2485 }
2252 2486
2253 AddNewMovement(agent_control_v3, speedModifier);
2254// }
2255 } 2487 }
2256// else
2257// {
2258// if (!update_movementflag)
2259// {
2260// m_log.DebugFormat(
2261// "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false",
2262// m_scene.RegionInfo.RegionName, agent_control_v3, Name);
2263// }
2264// }
2265 2488
2266 if (update_movementflag && ParentID == 0) 2489 if (update_movementflag && ParentID == 0)
2267 { 2490 {
@@ -2274,7 +2497,7 @@ namespace OpenSim.Region.Framework.Scenes
2274 2497
2275 // We need to send this back to the client in order to see the edit beams 2498 // We need to send this back to the client in order to see the edit beams
2276 if ((State & (uint)AgentState.Editing) != 0) 2499 if ((State & (uint)AgentState.Editing) != 0)
2277 ControllingClient.SendAgentTerseUpdate(this); 2500 SendAgentTerseUpdate(this);
2278 2501
2279 m_scene.EventManager.TriggerOnClientMovement(this); 2502 m_scene.EventManager.TriggerOnClientMovement(this);
2280 } 2503 }
@@ -2320,8 +2543,8 @@ namespace OpenSim.Region.Framework.Scenes
2320 // When we get to the point of re-computing neighbors everytime this 2543 // When we get to the point of re-computing neighbors everytime this
2321 // changes, then start using the agent's drawdistance rather than the 2544 // changes, then start using the agent's drawdistance rather than the
2322 // region's draw distance. 2545 // region's draw distance.
2546
2323 DrawDistance = agentData.Far; 2547 DrawDistance = agentData.Far;
2324 // DrawDistance = Scene.DefaultDrawDistance;
2325 2548
2326 // Check if Client has camera in 'follow cam' or 'build' mode. 2549 // Check if Client has camera in 'follow cam' or 'build' mode.
2327 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation); 2550 Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation);
@@ -2358,11 +2581,13 @@ namespace OpenSim.Region.Framework.Scenes
2358 2581
2359 bool updated = false; 2582 bool updated = false;
2360 2583
2584 Vector3 LocalVectorToTarget3D = MoveToPositionTarget - AbsolutePosition;
2585
2361// m_log.DebugFormat( 2586// m_log.DebugFormat(
2362// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}", 2587// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}",
2363// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving); 2588// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving);
2364 2589
2365 double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget); 2590 double distanceToTarget = LocalVectorToTarget3D.Length();
2366 2591
2367// m_log.DebugFormat( 2592// m_log.DebugFormat(
2368// "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}", 2593// "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}",
@@ -2385,11 +2610,11 @@ namespace OpenSim.Region.Framework.Scenes
2385 // Theoretically we might need a more complex PID approach here if other 2610 // Theoretically we might need a more complex PID approach here if other
2386 // unknown forces are acting on the avatar and we need to adaptively respond 2611 // unknown forces are acting on the avatar and we need to adaptively respond
2387 // to such forces, but the following simple approach seems to works fine. 2612 // to such forces, but the following simple approach seems to works fine.
2388 Vector3 LocalVectorToTarget3D = 2613
2389 (MoveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords 2614 LocalVectorToTarget3D = LocalVectorToTarget3D * Quaternion.Inverse(Rotation); // change to avatar coords
2390 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(Rotation)); // change to avatar coords
2391 // Ignore z component of vector 2615 // Ignore z component of vector
2392// Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 2616// Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
2617
2393 LocalVectorToTarget3D.Normalize(); 2618 LocalVectorToTarget3D.Normalize();
2394 2619
2395 // update avatar movement flags. the avatar coordinate system is as follows: 2620 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -2413,28 +2638,37 @@ namespace OpenSim.Region.Framework.Scenes
2413 2638
2414 // based on the above avatar coordinate system, classify the movement into 2639 // based on the above avatar coordinate system, classify the movement into
2415 // one of left/right/back/forward. 2640 // one of left/right/back/forward.
2641
2642 const uint noMovFlagsMask = (uint)(~(Dir_ControlFlags.DIR_CONTROL_FLAG_BACK |
2643 Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD | Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT |
2644 Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT | Dir_ControlFlags.DIR_CONTROL_FLAG_UP |
2645 Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN));
2646
2647 MovementFlag &= noMovFlagsMask;
2648 AgentControlFlags &= noMovFlagsMask;
2649
2416 if (LocalVectorToTarget3D.X < 0) //MoveBack 2650 if (LocalVectorToTarget3D.X < 0) //MoveBack
2417 { 2651 {
2418 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; 2652 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2419 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; 2653 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
2420 updated = true; 2654 updated = true;
2421 } 2655 }
2422 else if (LocalVectorToTarget3D.X > 0) //Move Forward 2656 else if (LocalVectorToTarget3D.X > 0) //Move Forward
2423 { 2657 {
2424 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; 2658 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
2425 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; 2659 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
2426 updated = true; 2660 updated = true;
2427 } 2661 }
2428 2662
2429 if (LocalVectorToTarget3D.Y > 0) //MoveLeft 2663 if (LocalVectorToTarget3D.Y > 0) //MoveLeft
2430 { 2664 {
2431 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; 2665 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
2432 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; 2666 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
2433 updated = true; 2667 updated = true;
2434 } 2668 }
2435 else if (LocalVectorToTarget3D.Y < 0) //MoveRight 2669 else if (LocalVectorToTarget3D.Y < 0) //MoveRight
2436 { 2670 {
2437 MovementFlag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; 2671 MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
2438 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; 2672 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
2439 updated = true; 2673 updated = true;
2440 } 2674 }
@@ -2504,37 +2738,25 @@ namespace OpenSim.Region.Framework.Scenes
2504 || pos.Y < 0 || pos.Y >= regionSize.Y 2738 || pos.Y < 0 || pos.Y >= regionSize.Y
2505 || pos.Z < 0) 2739 || pos.Z < 0)
2506 return; 2740 return;
2507 2741
2508 Scene targetScene = m_scene; 2742 Scene targetScene = m_scene;
2509
2510// Vector3 heightAdjust = new Vector3(0, 0, Appearance.AvatarHeight / 2);
2511// pos += heightAdjust;
2512//
2513// // Anti duck-walking measure
2514// if (Math.Abs(pos.Z - AbsolutePosition.Z) < 0.2f)
2515// {
2516//// m_log.DebugFormat("[SCENE PRESENCE]: Adjusting MoveToPosition from {0} to {1}", pos, AbsolutePosition);
2517// pos.Z = AbsolutePosition.Z;
2518// }
2519
2520 // Get terrain height for sub-region in a megaregion if necessary 2743 // Get terrain height for sub-region in a megaregion if necessary
2521
2522 //COMMENT: If its only nessesary in a megaregion, why do it on normal region's too?
2523
2524 if (regionCombinerModule != null) 2744 if (regionCombinerModule != null)
2525 { 2745 {
2526 int x = (int)((m_scene.RegionInfo.WorldLocX) + pos.X); 2746 int X = (int)((m_scene.RegionInfo.WorldLocX) + pos.X);
2527 int y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y); 2747 int Y = (int)((m_scene.RegionInfo.WorldLocY) + pos.Y);
2528 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, x, y); 2748 GridRegion target_region = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, X, Y);
2529
2530 // If X and Y is NaN, target_region will be null 2749 // If X and Y is NaN, target_region will be null
2531 if (target_region == null) 2750 if (target_region == null)
2532 return; 2751 return;
2533 2752 UUID target_regionID = target_region.RegionID;
2534 SceneManager.Instance.TryGetScene(target_region.RegionID, out targetScene); 2753 SceneManager.Instance.TryGetScene(target_region.RegionID, out targetScene);
2535 } 2754 }
2536 2755
2537 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)]; 2756 float terrainHeight = (float)targetScene.Heightmap[(int)(pos.X % regionSize.X), (int)(pos.Y % regionSize.Y)];
2757 // dont try to land underground
2758 terrainHeight += Appearance.AvatarHeight / 2;
2759
2538 pos.Z = Math.Max(terrainHeight, pos.Z); 2760 pos.Z = Math.Max(terrainHeight, pos.Z);
2539 2761
2540 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is 2762 // Fudge factor. It appears that if one clicks "go here" on a piece of ground, the go here request is
@@ -2543,17 +2765,14 @@ namespace OpenSim.Region.Framework.Scenes
2543 if (pos.Z - terrainHeight < 0.2) 2765 if (pos.Z - terrainHeight < 0.2)
2544 pos.Z = terrainHeight; 2766 pos.Z = terrainHeight;
2545 2767
2546 if (noFly)
2547 Flying = false;
2548 else if (pos.Z > terrainHeight)
2549 Flying = true;
2550
2551// m_log.DebugFormat( 2768// m_log.DebugFormat(
2552// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 2769// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
2553// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 2770// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
2554 2771
2555 if (noFly) 2772 if (noFly)
2556 Flying = false; 2773 Flying = false;
2774 else if (pos.Z > terrainHeight + Appearance.AvatarHeight / 2 || Flying)
2775 Flying = true;
2557 2776
2558 LandAtTarget = landAtTarget; 2777 LandAtTarget = landAtTarget;
2559 MovingToTarget = true; 2778 MovingToTarget = true;
@@ -2629,48 +2848,41 @@ namespace OpenSim.Region.Framework.Scenes
2629 } 2848 }
2630 } 2849 }
2631 2850
2851// part.ParentGroup.DeleteAvatar(UUID);
2852
2853 Quaternion standRotation = part.ParentGroup.RootPart.RotationOffset;
2854 Vector3 sitPartWorldPosition = part.ParentGroup.AbsolutePosition + m_pos * standRotation;
2632 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 2855 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
2633 2856
2634 ParentID = 0; 2857 ParentID = 0;
2635 ParentPart = null; 2858 ParentPart = null;
2636 2859
2637 Quaternion standRotation;
2638
2639 if (part.SitTargetAvatar == UUID) 2860 if (part.SitTargetAvatar == UUID)
2640 { 2861 standRotation = standRotation * part.SitTargetOrientation;
2641 standRotation = part.GetWorldRotation(); 2862 else
2863 standRotation = standRotation * m_bodyRot;
2642 2864
2643 if (!part.IsRoot) 2865 m_bodyRot = standRotation;
2644 standRotation = standRotation * part.SitTargetOrientation; 2866
2645// standRotation = part.RotationOffset * part.SitTargetOrientation; 2867 Quaternion standRotationZ = new Quaternion(0,0,standRotation.Z,standRotation.W);
2646// else
2647// standRotation = part.SitTargetOrientation;
2648 2868
2869 float t = standRotationZ.W * standRotationZ.W + standRotationZ.Z * standRotationZ.Z;
2870 if (t > 0)
2871 {
2872 t = 1.0f / (float)Math.Sqrt(t);
2873 standRotationZ.W *= t;
2874 standRotationZ.Z *= t;
2649 } 2875 }
2650 else 2876 else
2651 { 2877 {
2652 standRotation = Rotation; 2878 standRotationZ.W = 1.0f;
2879 standRotationZ.Z = 0f;
2653 } 2880 }
2654 2881
2655 //Vector3 standPos = ParentPosition + new Vector3(0.0f, 0.0f, 2.0f * m_sitAvatarHeight); 2882 Vector3 adjustmentForSitPose = new Vector3(0.75f, 0, m_sitAvatarHeight + .3f) * standRotationZ;
2656 //Vector3 standPos = ParentPosition;
2657
2658// Vector3 standPositionAdjustment
2659// = part.SitTargetPosition + new Vector3(0.5f, 0f, m_sitAvatarHeight / 2f);
2660 Vector3 adjustmentForSitPosition = OffsetPosition * part.ParentGroup.GroupRotation - SIT_TARGET_ADJUSTMENT * part.GetWorldRotation();
2661
2662 // XXX: This is based on the physics capsule sizes. Need to find a better way to read this rather than
2663 // hardcoding here.
2664 Vector3 adjustmentForSitPose = new Vector3(0.74f, 0f, 0f) * standRotation;
2665 2883
2666 Vector3 standPos = part.ParentGroup.AbsolutePosition + adjustmentForSitPosition + adjustmentForSitPose; 2884 Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose;
2667 2885 m_pos = standPos;
2668// m_log.DebugFormat(
2669// "[SCENE PRESENCE]: Setting stand to pos {0}, (adjustmentForSitPosition {1}, adjustmentForSitPose {2}) rotation {3} for {4} in {5}",
2670// standPos, adjustmentForSitPosition, adjustmentForSitPose, standRotation, Name, Scene.Name);
2671
2672 Rotation = standRotation;
2673 AbsolutePosition = standPos;
2674 } 2886 }
2675 2887
2676 // We need to wait until we have calculated proper stand positions before sitting up the physical 2888 // We need to wait until we have calculated proper stand positions before sitting up the physical
@@ -2680,18 +2892,19 @@ namespace OpenSim.Region.Framework.Scenes
2680 2892
2681 if (satOnObject) 2893 if (satOnObject)
2682 { 2894 {
2683 SendAvatarDataToAllClients();
2684 m_requestedSitTargetID = 0; 2895 m_requestedSitTargetID = 0;
2685
2686 part.RemoveSittingAvatar(this); 2896 part.RemoveSittingAvatar(this);
2687
2688 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 2897 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2898
2899 SendAvatarDataToAllAgents();
2689 } 2900 }
2690 2901
2691 else if (PhysicsActor == null) 2902 // reset to default sitAnimation
2692 AddToPhysicalScene(false); 2903 sitAnimation = "SIT";
2904
2905// Animator.TrySetMovementAnimation("STAND");
2906 Animator.SetMovementAnimations("STAND");
2693 2907
2694 Animator.TrySetMovementAnimation("STAND");
2695 TriggerScenePresenceUpdated(); 2908 TriggerScenePresenceUpdated();
2696 } 2909 }
2697 2910
@@ -2739,6 +2952,7 @@ namespace OpenSim.Region.Framework.Scenes
2739 if (part == null) 2952 if (part == null)
2740 return; 2953 return;
2741 2954
2955
2742 if (PhysicsActor != null) 2956 if (PhysicsActor != null)
2743 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; 2957 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
2744 2958
@@ -2746,23 +2960,9 @@ namespace OpenSim.Region.Framework.Scenes
2746 2960
2747 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero) 2961 if (part.IsSitTargetSet && part.SitTargetAvatar == UUID.Zero)
2748 { 2962 {
2749// m_log.DebugFormat(
2750// "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is set and unoccupied",
2751// Name, part.Name, part.LocalId);
2752
2753 offset = part.SitTargetPosition; 2963 offset = part.SitTargetPosition;
2754 sitOrientation = part.SitTargetOrientation; 2964 sitOrientation = part.SitTargetOrientation;
2755 2965
2756 if (!part.IsRoot)
2757 {
2758 // m_log.DebugFormat("Old sit orient {0}", sitOrientation);
2759 sitOrientation = part.RotationOffset * sitOrientation;
2760 // m_log.DebugFormat("New sit orient {0}", sitOrientation);
2761// m_log.DebugFormat("Old sit offset {0}", offset);
2762 offset = offset * part.RotationOffset;
2763// m_log.DebugFormat("New sit offset {0}", offset);
2764 }
2765
2766 canSit = true; 2966 canSit = true;
2767 } 2967 }
2768 else 2968 else
@@ -2796,40 +2996,30 @@ namespace OpenSim.Region.Framework.Scenes
2796 part.AddSittingAvatar(this); 2996 part.AddSittingAvatar(this);
2797 2997
2798 cameraAtOffset = part.GetCameraAtOffset(); 2998 cameraAtOffset = part.GetCameraAtOffset();
2799
2800 if (!part.IsRoot && cameraAtOffset == Vector3.Zero)
2801 cameraAtOffset = part.ParentGroup.RootPart.GetCameraAtOffset();
2802
2803 bool cameraEyeOffsetFromRootForChild = false;
2804 cameraEyeOffset = part.GetCameraEyeOffset(); 2999 cameraEyeOffset = part.GetCameraEyeOffset();
3000
3001 forceMouselook = part.GetForceMouselook();
2805 3002
2806 if (!part.IsRoot && cameraEyeOffset == Vector3.Zero) 3003 if (!part.IsRoot)
2807 {
2808 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
2809 cameraEyeOffsetFromRootForChild = true;
2810 }
2811
2812 if ((cameraEyeOffset != Vector3.Zero && !cameraEyeOffsetFromRootForChild) || cameraAtOffset != Vector3.Zero)
2813 { 3004 {
2814 if (!part.IsRoot) 3005 sitOrientation = part.RotationOffset * sitOrientation;
3006 offset = offset * part.RotationOffset;
3007 offset += part.OffsetPosition;
3008
3009 if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
2815 { 3010 {
2816 cameraEyeOffset = cameraEyeOffset * part.RotationOffset; 3011 CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
3012 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
3013 }
3014 else
3015 {
3016 cameraAtOffset = cameraAtOffset * part.RotationOffset;
2817 cameraAtOffset += part.OffsetPosition; 3017 cameraAtOffset += part.OffsetPosition;
3018 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
3019 cameraEyeOffset += part.OffsetPosition;
2818 } 3020 }
2819
2820 cameraEyeOffset += part.OffsetPosition;
2821 } 3021 }
2822 3022
2823// m_log.DebugFormat(
2824// "[SCENE PRESENCE]: Using cameraAtOffset {0}, cameraEyeOffset {1} for sit on {2} by {3} in {4}",
2825// cameraAtOffset, cameraEyeOffset, part.Name, Name, Scene.Name);
2826
2827 forceMouselook = part.GetForceMouselook();
2828
2829 // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is
2830 // being sat upon.
2831 offset += part.OffsetPosition;
2832
2833 ControllingClient.SendSitResponse( 3023 ControllingClient.SendSitResponse(
2834 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 3024 part.ParentGroup.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2835 3025
@@ -2862,7 +3052,6 @@ namespace OpenSim.Region.Framework.Scenes
2862 { 3052 {
2863 m_requestedSitTargetID = part.LocalId; 3053 m_requestedSitTargetID = part.LocalId;
2864 m_requestedSitTargetUUID = part.UUID; 3054 m_requestedSitTargetUUID = part.UUID;
2865
2866 } 3055 }
2867 else 3056 else
2868 { 3057 {
@@ -2875,13 +3064,8 @@ namespace OpenSim.Region.Framework.Scenes
2875 // returns false if does not suport so older sit can be tried 3064 // returns false if does not suport so older sit can be tried
2876 public bool PhysicsSit(SceneObjectPart part, Vector3 offset) 3065 public bool PhysicsSit(SceneObjectPart part, Vector3 offset)
2877 { 3066 {
2878// TODO: Pull in these bits
2879 return false;
2880/*
2881 if (part == null || part.ParentGroup.IsAttachment) 3067 if (part == null || part.ParentGroup.IsAttachment)
2882 {
2883 return true; 3068 return true;
2884 }
2885 3069
2886 if ( m_scene.PhysicsScene == null) 3070 if ( m_scene.PhysicsScene == null)
2887 return false; 3071 return false;
@@ -2899,15 +3083,12 @@ namespace OpenSim.Region.Framework.Scenes
2899 return true; 3083 return true;
2900 } 3084 }
2901 3085
2902
2903 // not doing autopilot
2904 m_requestedSitTargetID = 0;
2905
2906 if (m_scene.PhysicsScene.SitAvatar(part.PhysActor, AbsolutePosition, CameraPosition, offset, new Vector3(0.35f, 0, 0.65f), PhysicsSitResponse) != 0) 3086 if (m_scene.PhysicsScene.SitAvatar(part.PhysActor, AbsolutePosition, CameraPosition, offset, new Vector3(0.35f, 0, 0.65f), PhysicsSitResponse) != 0)
3087 {
2907 return true; 3088 return true;
3089 }
2908 3090
2909 return false; 3091 return false;
2910*/
2911 } 3092 }
2912 3093
2913 3094
@@ -2952,31 +3133,54 @@ namespace OpenSim.Region.Framework.Scenes
2952 ResetMoveToTarget(); 3133 ResetMoveToTarget();
2953 3134
2954 Velocity = Vector3.Zero; 3135 Velocity = Vector3.Zero;
2955 3136 m_AngularVelocity = Vector3.Zero;
2956 part.AddSittingAvatar(this);
2957 3137
2958 Vector3 cameraAtOffset = part.GetCameraAtOffset(); 3138 Vector3 cameraAtOffset = part.GetCameraAtOffset();
2959 Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); 3139 Vector3 cameraEyeOffset = part.GetCameraEyeOffset();
2960 bool forceMouselook = part.GetForceMouselook(); 3140 bool forceMouselook = part.GetForceMouselook();
2961 3141
2962 ControllingClient.SendSitResponse( 3142 m_bodyRot = Orientation;
2963 part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
2964 3143
2965 // not using autopilot 3144 if (!part.IsRoot)
3145 {
3146 Orientation = part.RotationOffset * Orientation;
3147 offset = offset * part.RotationOffset;
3148 offset += part.OffsetPosition;
3149
3150 if (CameraAtAxis == Vector3.Zero && cameraEyeOffset == Vector3.Zero)
3151 {
3152 CameraAtAxis = part.ParentGroup.RootPart.GetCameraAtOffset();
3153 cameraEyeOffset = part.ParentGroup.RootPart.GetCameraEyeOffset();
3154 }
3155 else
3156 {
3157 cameraAtOffset = cameraAtOffset * part.RotationOffset;
3158 cameraAtOffset += part.OffsetPosition;
3159 cameraEyeOffset = cameraEyeOffset * part.RotationOffset;
3160 cameraEyeOffset += part.OffsetPosition;
3161 }
3162 }
2966 3163
2967 Rotation = Orientation;
2968 m_pos = offset; 3164 m_pos = offset;
2969 3165
3166 ControllingClient.SendSitResponse(
3167 part.ParentGroup.UUID, offset, Orientation, true, cameraAtOffset, cameraEyeOffset, forceMouselook);
3168
3169
2970 m_requestedSitTargetID = 0; 3170 m_requestedSitTargetID = 0;
3171 part.AddSittingAvatar(this);
2971 3172
2972 ParentPart = part; 3173 ParentPart = part;
2973 ParentID = part.LocalId; 3174 ParentID = part.LocalId;
2974 if(status == 3) 3175
2975 Animator.TrySetMovementAnimation("SIT_GROUND"); 3176 SendAvatarDataToAllAgents();
3177
3178 if (status == 3)
3179 sitAnimation = "SIT_GROUND";
2976 else 3180 else
2977 Animator.TrySetMovementAnimation("SIT"); 3181 sitAnimation = "SIT";
2978 SendAvatarDataToAllClients();
2979 3182
3183 Animator.SetMovementAnimations("SIT");
2980 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 3184 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2981 } 3185 }
2982 3186
@@ -2985,7 +3189,7 @@ namespace OpenSim.Region.Framework.Scenes
2985 if (IsChildAgent) 3189 if (IsChildAgent)
2986 return; 3190 return;
2987 3191
2988 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID); 3192 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
2989 3193
2990 if (part != null) 3194 if (part != null)
2991 { 3195 {
@@ -3012,40 +3216,27 @@ namespace OpenSim.Region.Framework.Scenes
3012 3216
3013 //Quaternion result = (sitTargetOrient * vq) * nq; 3217 //Quaternion result = (sitTargetOrient * vq) * nq;
3014 3218
3015 double x, y, z, m1, m2; 3219 double x, y, z, m;
3016 3220
3017 Quaternion r = sitTargetOrient; 3221 Quaternion r = sitTargetOrient;
3018 m1 = r.X * r.X + r.Y * r.Y; 3222 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
3019 m2 = r.Z * r.Z + r.W * r.W;
3020
3021 // Rotate the vector <0, 0, 1>
3022 x = 2 * (r.X * r.Z + r.Y * r.W);
3023 y = 2 * (-r.X * r.W + r.Y * r.Z);
3024 z = m2 - m1;
3025 3223
3026 // Set m to be the square of the norm of r. 3224 if (Math.Abs(1.0 - m) > 0.000001)
3027 double m = m1 + m2;
3028
3029 // This constant is emperically determined to be what is used in SL.
3030 // See also http://opensimulator.org/mantis/view.php?id=7096
3031 double offset = 0.05;
3032
3033 // Normally m will be ~ 1, but if someone passed a handcrafted quaternion
3034 // to llSitTarget with values so small that squaring them is rounded off
3035 // to zero, then m could be zero. The result of this floating point
3036 // round off error (causing us to skip this impossible normalization)
3037 // is only 5 cm.
3038 if (m > 0.000001)
3039 { 3225 {
3040 offset /= m; 3226 m = 1.0 / Math.Sqrt(m);
3227 r.X *= (float)m;
3228 r.Y *= (float)m;
3229 r.Z *= (float)m;
3230 r.W *= (float)m;
3041 } 3231 }
3042 3232
3233 x = 2 * (r.X * r.Z + r.Y * r.W);
3234 y = 2 * (-r.X * r.W + r.Y * r.Z);
3235 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
3043 Vector3 up = new Vector3((float)x, (float)y, (float)z); 3236 Vector3 up = new Vector3((float)x, (float)y, (float)z);
3044 Vector3 sitOffset = up * (float)offset; 3237 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
3045 3238
3046 // sitOffset is in Avatar Center coordinates: from origin to 'sitTargetPos + SIT_TARGET_ADJUSTMENT'. 3239 Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
3047 // So, we need to _substract_ it to get to the origin of the Avatar Center.
3048 Vector3 newPos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset;
3049 Quaternion newRot; 3240 Quaternion newRot;
3050 3241
3051 if (part.IsRoot) 3242 if (part.IsRoot)
@@ -3078,19 +3269,24 @@ namespace OpenSim.Region.Framework.Scenes
3078// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId); 3269// Name, part.AbsolutePosition, m_pos, ParentPosition, part.Name, part.LocalId);
3079 } 3270 }
3080 3271
3272 part.AddSittingAvatar(this);
3081 ParentPart = part; 3273 ParentPart = part;
3082 ParentID = m_requestedSitTargetID; 3274 ParentID = m_requestedSitTargetID;
3083 m_AngularVelocity = Vector3.Zero; 3275 m_AngularVelocity = Vector3.Zero;
3084 Velocity = Vector3.Zero; 3276 Velocity = Vector3.Zero;
3085 RemoveFromPhysicalScene(); 3277 RemoveFromPhysicalScene();
3086 3278
3087 String sitAnimation = "SIT"; 3279 m_requestedSitTargetID = 0;
3280
3281 SendAvatarDataToAllAgents();
3282
3283 sitAnimation = "SIT";
3088 if (!String.IsNullOrEmpty(part.SitAnimation)) 3284 if (!String.IsNullOrEmpty(part.SitAnimation))
3089 { 3285 {
3090 sitAnimation = part.SitAnimation; 3286 sitAnimation = part.SitAnimation;
3091 } 3287 }
3092 Animator.TrySetMovementAnimation(sitAnimation); 3288// Animator.TrySetMovementAnimation(sitAnimation);
3093 SendAvatarDataToAllClients(); 3289 Animator.SetMovementAnimations("SIT");
3094 TriggerScenePresenceUpdated(); 3290 TriggerScenePresenceUpdated();
3095 } 3291 }
3096 } 3292 }
@@ -3102,10 +3298,14 @@ namespace OpenSim.Region.Framework.Scenes
3102 3298
3103// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. 3299// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick..
3104 m_AngularVelocity = Vector3.Zero; 3300 m_AngularVelocity = Vector3.Zero;
3105 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); 3301 sitAnimation = "SIT_GROUND_CONSTRAINED";
3106 TriggerScenePresenceUpdated(); 3302// Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
3303// TriggerScenePresenceUpdated();
3107 SitGround = true; 3304 SitGround = true;
3108 RemoveFromPhysicalScene(); 3305 RemoveFromPhysicalScene();
3306
3307 Animator.SetMovementAnimations("SITGROUND");
3308 TriggerScenePresenceUpdated();
3109 } 3309 }
3110 3310
3111 /// <summary> 3311 /// <summary>
@@ -3129,85 +3329,69 @@ namespace OpenSim.Region.Framework.Scenes
3129 TriggerScenePresenceUpdated(); 3329 TriggerScenePresenceUpdated();
3130 } 3330 }
3131 3331
3332 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
3333 {
3334 Animator.avnChangeAnim(animID, addRemove, sendPack);
3335 }
3336
3337
3338
3132 /// <summary> 3339 /// <summary>
3133 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 3340 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
3134 /// </summary> 3341 /// </summary>
3135 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 3342 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
3136 /// <param name="thisAddSpeedModifier"> 3343 /// <param name="thisAddSpeedModifier">
3137 /// Optional additional speed modifier for this particular add. Default is 1</param> 3344 /// Optional additional speed modifier for this particular add. Default is 1</param>
3138 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1) 3345 public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1, bool breaking = false)
3139 { 3346 {
3140// m_log.DebugFormat( 3347 // m_log.DebugFormat(
3141// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}", 3348 // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
3142// vec, Rotation, thisAddSpeedModifier, Name); 3349 // vec, Rotation, thisAddSpeedModifier, Name);
3143 3350
3144 Quaternion rot = Rotation; 3351 // rotate from avatar coord space to world
3145 if (!Flying && PresenceType != PresenceType.Npc) 3352 // for now all controls assume this is only a rotation around Z
3146 { 3353 // if not all checks below need to be done before this rotation
3147 // The only situation in which we care about X and Y is avatar flying. The rest of the time 3354 Vector3 direc = vec * Rotation;
3148 // these parameters are not relevant for determining avatar movement direction and cause issues such
3149 // as wrong walk speed if the camera is rotated.
3150 rot.X = 0;
3151 rot.Y = 0;
3152 rot.Normalize();
3153 }
3154
3155 Vector3 direc = vec * rot;
3156 direc.Normalize(); 3355 direc.Normalize();
3157 3356
3158 if (Flying != FlyingOld) // add for fly velocity control 3357 // mouse look situation ?
3159 {
3160 FlyingOld = Flying; // add for fly velocity control
3161 if (!Flying)
3162 WasFlying = true; // add for fly velocity control
3163 }
3164
3165 if (IsColliding)
3166 WasFlying = false; // add for fly velocity control
3167
3168 if ((vec.Z == 0f) && !Flying) 3358 if ((vec.Z == 0f) && !Flying)
3169 direc.Z = 0f; // Prevent camera WASD up. 3359 direc.Z = 0f; // Prevent camera WASD up.
3170 3360
3361 // odd rescalings
3171 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier; 3362 direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier;
3172 3363
3173// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); 3364 // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
3174 3365
3175 if (PhysicsActor != null) 3366 if (Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling
3367 && (PhysicsActor == null || !PhysicsActor.PIDHoverActive))
3176 { 3368 {
3177 if (Flying) 3369 if (breaking)
3178 { 3370 direc.Z = -9999f; //hack to tell physics to stop on Z
3371 else
3372 direc = Vector3.Zero;
3373 }
3374 else if (Flying)
3375 {
3376 if (IsColliding && direc.Z < 0)
3377 // landing situation, prevent avatar moving or it may fail to land
3378 // animator will handle this condition and do the land
3379 direc = Vector3.Zero;
3380 else
3179 direc *= 4.0f; 3381 direc *= 4.0f;
3180 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 3382 }
3181 //if (controlland) 3383 else if (IsColliding)
3182 // m_log.Info("[AGENT]: landCommand"); 3384 {
3183 //if (IsColliding) 3385 if (direc.Z > 2.0f) // reinforce jumps
3184 // m_log.Info("[AGENT]: colliding");
3185 //if (Flying && IsColliding && controlland)
3186 //{
3187 // StopFlying();
3188 // m_log.Info("[AGENT]: Stop Flying");
3189 //}
3190 }
3191 if (Animator.Falling && WasFlying) // if falling from flying, disable motion add
3192 { 3386 {
3193 direc *= 0.0f; 3387 direc.Z *= 2.6f;
3194 }
3195 else if (!Flying && IsColliding)
3196 {
3197 if (direc.Z > 2.0f)
3198 {
3199 direc.Z *= 2.6f;
3200
3201 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
3202// Animator.TrySetMovementAnimation("PREJUMP");
3203// Animator.TrySetMovementAnimation("JUMP");
3204 }
3205 } 3388 }
3389 else if (direc.Z < 0) // on a surface moving down (pg down) only changes animation
3390 direc.Z = 0;
3206 } 3391 }
3207 3392
3208// m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name); 3393 // m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name);
3209 3394
3210 // TODO: Add the force instead of only setting it to support multiple forces per frame?
3211 m_forceToApply = direc; 3395 m_forceToApply = direc;
3212 Animator.UpdateMovementAnimations(); 3396 Animator.UpdateMovementAnimations();
3213 } 3397 }
@@ -3218,27 +3402,26 @@ namespace OpenSim.Region.Framework.Scenes
3218 3402
3219 public override void Update() 3403 public override void Update()
3220 { 3404 {
3405 const float ROTATION_TOLERANCE = 0.01f;
3406 const float VELOCITY_TOLERANCE = 0.001f;
3407 const float POSITION_TOLERANCE = 0.05f;
3408
3221 if (IsChildAgent == false) 3409 if (IsChildAgent == false)
3222 { 3410 {
3411 CheckForBorderCrossing();
3412
3413 if (IsInTransit)
3414 return;
3415
3223 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to 3416 // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to
3224 // grab the latest PhysicsActor velocity, whereas m_velocity is often 3417 // grab the latest PhysicsActor velocity, whereas m_velocity is often
3225 // storing a requested force instead of an actual traveling velocity 3418 // storing a requested force instead of an actual traveling velocity
3226 if (Appearance.AvatarSize != m_lastSize && !IsLoggingIn) 3419 if (Appearance.AvatarSize != m_lastSize && !IsLoggingIn)
3227 SendAvatarDataToAllClients(); 3420 SendAvatarDataToAllAgents();
3228 3421
3229 // Allow any updates for sitting avatars to that llSetPrimitiveLinkParams() can work for very 3422 if (!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
3230 // small increments (e.g. sit position adjusters). An alternative may be to eliminate the tolerance 3423 !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
3231 // checks on all updates but the ramifications of this would need careful consideration. 3424 !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
3232 bool updateClients
3233 = IsSatOnObject && (Rotation != m_lastRotation || Velocity != m_lastVelocity || m_pos != m_lastPosition);
3234
3235 if (!updateClients)
3236 updateClients
3237 = !Rotation.ApproxEquals(m_lastRotation, Scene.RootRotationUpdateTolerance)
3238 || !Velocity.ApproxEquals(m_lastVelocity, Scene.RootVelocityUpdateTolerance)
3239 || !m_pos.ApproxEquals(m_lastPosition, Scene.RootPositionUpdateTolerance);
3240
3241 if (updateClients)
3242 { 3425 {
3243 SendTerseUpdateToAllClients(); 3426 SendTerseUpdateToAllClients();
3244 3427
@@ -3248,9 +3431,6 @@ namespace OpenSim.Region.Framework.Scenes
3248 m_lastVelocity = Velocity; 3431 m_lastVelocity = Velocity;
3249 } 3432 }
3250 3433
3251 if (Scene.AllowAvatarCrossing)
3252 CheckForBorderCrossing();
3253
3254 CheckForSignificantMovement(); // sends update to the modules. 3434 CheckForSignificantMovement(); // sends update to the modules.
3255 } 3435 }
3256 } 3436 }
@@ -3259,8 +3439,38 @@ namespace OpenSim.Region.Framework.Scenes
3259 3439
3260 #region Update Client(s) 3440 #region Update Client(s)
3261 3441
3442 public void SendUpdateToAgent(ScenePresence p)
3443 {
3444 IClientAPI remoteClient = p.ControllingClient;
3445
3446 if (remoteClient.IsActive)
3447 {
3448 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3449 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3450 m_scene.StatsReporter.AddAgentUpdates(1);
3451 }
3452 }
3453
3454 public void SendFullUpdateToClient(IClientAPI remoteClient)
3455 {
3456 if (remoteClient.IsActive)
3457 {
3458 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3459 remoteClient.SendEntityUpdate(this, PrimUpdateFlags.FullUpdate);
3460 m_scene.StatsReporter.AddAgentUpdates(1);
3461 }
3462 }
3463
3464 // this is diferente from SendTerseUpdateToClient
3465 // this sends bypassing entities updates
3466 public void SendAgentTerseUpdate(ISceneEntity p)
3467 {
3468 ControllingClient.SendAgentTerseUpdate(p);
3469 }
3470
3262 /// <summary> 3471 /// <summary>
3263 /// Sends a location update to the client connected to this scenePresence 3472 /// Sends a location update to the client connected to this scenePresence
3473 /// via entity updates
3264 /// </summary> 3474 /// </summary>
3265 /// <param name="remoteClient"></param> 3475 /// <param name="remoteClient"></param>
3266 public void SendTerseUpdateToClient(IClientAPI remoteClient) 3476 public void SendTerseUpdateToClient(IClientAPI remoteClient)
@@ -3269,31 +3479,7 @@ namespace OpenSim.Region.Framework.Scenes
3269 // server. 3479 // server.
3270 if (remoteClient.IsActive) 3480 if (remoteClient.IsActive)
3271 { 3481 {
3272 if (Scene.RootTerseUpdatePeriod > 1)
3273 {
3274// Console.WriteLine(
3275// "{0} {1} {2} {3} {4} {5} for {6} to {7}",
3276// remoteClient.AgentId, UUID, remoteClient.SceneAgent.IsChildAgent, m_terseUpdateCount, Scene.RootTerseUpdatePeriod, Velocity.ApproxEquals(Vector3.Zero, 0.001f), Name, remoteClient.Name);
3277 if (remoteClient.AgentId != UUID
3278 && !remoteClient.SceneAgent.IsChildAgent
3279 && m_terseUpdateCount % Scene.RootTerseUpdatePeriod != 0
3280 && !Velocity.ApproxEquals(Vector3.Zero, 0.001f))
3281 {
3282// m_log.DebugFormat("[SCENE PRESENCE]: Discarded update from {0} to {1}, args {2} {3} {4} {5} {6} {7}",
3283// Name, remoteClient.Name, remoteClient.AgentId, UUID, remoteClient.SceneAgent.IsChildAgent, m_terseUpdateCount, Scene.RootTerseUpdatePeriod, Velocity.ApproxEquals(Vector3.Zero, 0.001f));
3284
3285 return;
3286 }
3287 }
3288
3289 if (Scene.ChildTerseUpdatePeriod > 1
3290 && remoteClient.SceneAgent.IsChildAgent
3291 && m_terseUpdateCount % Scene.ChildTerseUpdatePeriod != 0
3292 && !Velocity.ApproxEquals(Vector3.Zero, 0.001f))
3293 return;
3294
3295 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity); 3482 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3296
3297 remoteClient.SendEntityUpdate( 3483 remoteClient.SendEntityUpdate(
3298 this, 3484 this,
3299 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity 3485 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
@@ -3303,6 +3489,38 @@ namespace OpenSim.Region.Framework.Scenes
3303 } 3489 }
3304 } 3490 }
3305 3491
3492 public void SendTerseUpdateToAgent(ScenePresence p)
3493 {
3494 IClientAPI remoteClient = p.ControllingClient;
3495
3496 if (!remoteClient.IsActive)
3497 return;
3498
3499 if (ParcelHideThisAvatar && p.currentParcelUUID != currentParcelUUID && p.GodLevel < 200)
3500 return;
3501
3502 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3503 remoteClient.SendEntityUpdate(
3504 this,
3505 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3506 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3507
3508 m_scene.StatsReporter.AddAgentUpdates(1);
3509 }
3510
3511 public void SendTerseUpdateToAgentNF(ScenePresence p)
3512 {
3513 IClientAPI remoteClient = p.ControllingClient;
3514 if (remoteClient.IsActive)
3515 {
3516 //m_log.DebugFormat("[SCENE PRESENCE]: " + Name + " sending TerseUpdate to " + remoteClient.Name + " : Pos={0} Rot={1} Vel={2}", m_pos, Rotation, m_velocity);
3517 remoteClient.SendEntityUpdate(this,
3518 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
3519 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
3520 m_scene.StatsReporter.AddAgentUpdates(1);
3521 }
3522 }
3523
3306 3524
3307 // vars to support reduced update frequency when velocity is unchanged 3525 // vars to support reduced update frequency when velocity is unchanged
3308 private Vector3 lastVelocitySentToAllClients = Vector3.Zero; 3526 private Vector3 lastVelocitySentToAllClients = Vector3.Zero;
@@ -3331,10 +3549,6 @@ namespace OpenSim.Region.Framework.Scenes
3331 float speed = Velocity.Length(); 3549 float speed = Velocity.Length();
3332 float velocityDiff = Vector3.Distance(lastVelocitySentToAllClients, Velocity); 3550 float velocityDiff = Vector3.Distance(lastVelocitySentToAllClients, Velocity);
3333 3551
3334// m_log.DebugFormat(
3335// "[SCENE PRESENCE]: Delta-v {0}, lastVelocity {1}, Velocity {2} for {3} in {4}",
3336// velocidyDiff, lastVelocitySentToAllClients, Velocity, Name, Scene.Name);
3337
3338 // assuming 5 ms. worst case precision for timer, use 2x that 3552 // assuming 5 ms. worst case precision for timer, use 2x that
3339 // for distance error threshold 3553 // for distance error threshold
3340 float distanceErrorThreshold = speed * 0.01f; 3554 float distanceErrorThreshold = speed * 0.01f;
@@ -3343,18 +3557,13 @@ namespace OpenSim.Region.Framework.Scenes
3343 || Math.Abs(distanceError) > distanceErrorThreshold 3557 || Math.Abs(distanceError) > distanceErrorThreshold
3344 || velocityDiff > 0.01f) // did velocity change from last update? 3558 || velocityDiff > 0.01f) // did velocity change from last update?
3345 { 3559 {
3346// m_log.DebugFormat(
3347// "[SCENE PRESENCE]: Update triggered with speed {0}, distanceError {1}, distanceThreshold {2}, delta-v {3} for {4} in {5}",
3348// speed, distanceError, distanceErrorThreshold, velocidyDiff, Name, Scene.Name);
3349
3350 lastVelocitySentToAllClients = Velocity; 3560 lastVelocitySentToAllClients = Velocity;
3351 lastTerseUpdateToAllClientsTick = currentTick; 3561 lastTerseUpdateToAllClientsTick = currentTick;
3352 lastPositionSentToAllClients = OffsetPosition; 3562 lastPositionSentToAllClients = OffsetPosition;
3353 3563
3354 m_terseUpdateCount++; 3564 // Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name);
3355 3565// m_scene.ForEachClient(SendTerseUpdateToClient);
3356// Console.WriteLine("Scheduled update for {0} in {1}", Name, Scene.Name); 3566 m_scene.ForEachScenePresence(SendTerseUpdateToAgent);
3357 m_scene.ForEachClient(SendTerseUpdateToClient);
3358 } 3567 }
3359 TriggerScenePresenceUpdated(); 3568 TriggerScenePresenceUpdated();
3360 } 3569 }
@@ -3379,36 +3588,41 @@ namespace OpenSim.Region.Framework.Scenes
3379 ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); 3588 ControllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations);
3380 } 3589 }
3381 3590
3382 public void SendInitialDataToClient() 3591 public void SendInitialDataToMe()
3383 { 3592 {
3384 SentInitialDataToClient = true;
3385
3386 // Send all scene object to the new client 3593 // Send all scene object to the new client
3387 WorkManager.RunJob("SendInitialDataToClient", delegate 3594 Util.FireAndForget(delegate
3388 { 3595 {
3389// m_log.DebugFormat(
3390// "[SCENE PRESENCE]: Sending initial data to {0} agent {1} in {2}, tp flags {3}",
3391// IsChildAgent ? "child" : "root", Name, Scene.Name, m_teleportFlags);
3392
3393 // we created a new ScenePresence (a new child agent) in a fresh region. 3596 // we created a new ScenePresence (a new child agent) in a fresh region.
3394 // Request info about all the (root) agents in this region 3597 // Request info about all the (root) agents in this region
3395 // Note: This won't send data *to* other clients in that region (children don't send) 3598 // Note: This won't send data *to* other clients in that region (children don't send)
3396 SendOtherAgentsAvatarDataToClient(); 3599 if (m_teleportFlags <= 0)
3397 SendOtherAgentsAppearanceToClient(); 3600 {
3601 Scene.SendLayerData(ControllingClient);
3398 3602
3603 ILandChannel landch = m_scene.LandChannel;
3604 if (landch != null)
3605 {
3606 landch.sendClientInitialLandInfo(ControllingClient);
3607 }
3608 }
3609
3610 SendOtherAgentsAvatarFullToMe();
3399 EntityBase[] entities = Scene.Entities.GetEntities(); 3611 EntityBase[] entities = Scene.Entities.GetEntities();
3400 foreach (EntityBase e in entities) 3612 foreach (EntityBase e in entities)
3401 { 3613 {
3402 if (e != null && e is SceneObjectGroup) 3614 if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment)
3403 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient); 3615 ((SceneObjectGroup)e).SendFullUpdateToClient(ControllingClient);
3404 } 3616 }
3405 }, null, string.Format("SendInitialDataToClient ({0} in {1})", Name, Scene.Name), false, true); 3617 });
3406 } 3618 }
3407 3619
3408 /// <summary> 3620 /// <summary>
3409 /// Do everything required once a client completes its movement into a region and becomes 3621 /// Do everything required once a client completes its movement into a region and becomes
3410 /// a root agent. 3622 /// a root agent.
3411 /// </summary> 3623 /// </summary>
3624 ///
3625/* only called from on place, do done inline there
3412 private void ValidateAndSendAppearanceAndAgentData() 3626 private void ValidateAndSendAppearanceAndAgentData()
3413 { 3627 {
3414 //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID); 3628 //m_log.DebugFormat("[SCENE PRESENCE] SendInitialData: {0} ({1})", Name, UUID);
@@ -3422,46 +3636,70 @@ namespace OpenSim.Region.Framework.Scenes
3422 // to see if all the baked textures are already here. 3636 // to see if all the baked textures are already here.
3423 if (m_scene.AvatarFactory != null) 3637 if (m_scene.AvatarFactory != null)
3424 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this); 3638 cachedappearance = m_scene.AvatarFactory.ValidateBakedTextureCache(this);
3425 3639
3426 // If we aren't using a cached appearance, then clear out the baked textures 3640 // If we aren't using a cached appearance, then clear out the baked textures
3427 if (!cachedappearance) 3641 if (!cachedappearance)
3428 { 3642 {
3429 Appearance.ResetAppearance();
3430 if (m_scene.AvatarFactory != null) 3643 if (m_scene.AvatarFactory != null)
3431 m_scene.AvatarFactory.QueueAppearanceSave(UUID); 3644 m_scene.AvatarFactory.QueueAppearanceSave(UUID);
3432 } 3645 }
3433
3434 // This agent just became root. We are going to tell everyone about it. The process of
3435 // getting other avatars information was initiated elsewhere immediately after the child circuit connected... don't do it
3436 // again here... this comes after the cached appearance check because the avatars
3437 // appearance goes into the avatar update packet
3438 SendAvatarDataToAllClients();
3439 3646
3440 // This invocation always shows up in the viewer logs as an error. Is it needed? 3647 // send avatar object to all viewers so they cross it into region
3441 SendAppearanceToClient(this); 3648 bool newhide = m_currentParcelHide;
3649 m_currentParcelHide = false;
3442 3650
3443 // If we are using the the cached appearance then send it out to everyone 3651 SendAvatarDataToAllAgents();
3444 if (cachedappearance)
3445 {
3446 m_log.DebugFormat("[SCENE PRESENCE]: Baked textures are in the cache for {0} in {1}", Name, m_scene.Name);
3447 3652
3448 // If the avatars baked textures are all in the cache, then we have a 3653 // now hide
3449 // complete appearance... send it out, if not, then we'll send it when 3654 if (newhide)
3450 // the avatar finishes updating its appearance 3655 {
3451 SendAppearanceToAllOtherClients(); 3656 ParcelLoginCheck(m_currentParcelUUID);
3657 m_currentParcelHide = true;
3452 } 3658 }
3453 }
3454 3659
3455 public void SendAvatarDataToAllClients() 3660 SendAppearanceToAgent(this);
3661
3662 m_inTransit = false;
3663
3664 SendAppearanceToAllOtherAgents();
3665
3666 if(Animator!= null)
3667 Animator.SendAnimPack();
3668 }
3669*/
3670 /// <summary>
3671 /// Send avatar full data appearance and animations for all other root agents to this agent, this agent
3672 /// can be either a child or root
3673 /// </summary>
3674 public void SendOtherAgentsAvatarFullToMe()
3456 { 3675 {
3457 SendAvatarDataToAllClients(true); 3676 int count = 0;
3677 m_scene.ForEachRootScenePresence(delegate(ScenePresence p)
3678 {
3679 // only send information about other root agents
3680 if (p.UUID == UUID)
3681 return;
3682
3683 // get the avatar, then a kill if can't see it
3684 p.SendInitialAvatarDataToAgent(this);
3685
3686 if (p.ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && GodLevel < 200)
3687 return;
3688
3689 p.SendAppearanceToAgentNF(this);
3690 p.SendAnimPackToAgentNF(this);
3691 p.SendAttachmentsToAgentNF(this);
3692 count++;
3693 });
3694
3695 m_scene.StatsReporter.AddAgentUpdates(count);
3458 } 3696 }
3459 3697
3460 /// <summary> 3698 /// <summary>
3461 /// Send this agent's avatar data to all other root and child agents in the scene 3699 /// Send this agent's avatar data to all other root and child agents in the scene
3462 /// This agent must be root. This avatar will receive its own update. 3700 /// This agent must be root. This avatar will receive its own update.
3463 /// </summary> 3701 /// </summary>
3464 public void SendAvatarDataToAllClients(bool full) 3702 public void SendAvatarDataToAllAgents()
3465 { 3703 {
3466 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID); 3704 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAllAgents: {0} ({1})", Name, UUID);
3467 // only send update from root agents to other clients; children are only "listening posts" 3705 // only send update from root agents to other clients; children are only "listening posts"
@@ -3470,64 +3708,73 @@ namespace OpenSim.Region.Framework.Scenes
3470 m_log.WarnFormat( 3708 m_log.WarnFormat(
3471 "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}", 3709 "[SCENE PRESENCE]: Attempt to send avatar data from a child agent for {0} in {1}",
3472 Name, Scene.RegionInfo.RegionName); 3710 Name, Scene.RegionInfo.RegionName);
3473
3474 return; 3711 return;
3475 } 3712 }
3476 3713
3477 m_lastSize = Appearance.AvatarSize; 3714 m_lastSize = Appearance.AvatarSize;
3478
3479 int count = 0; 3715 int count = 0;
3716
3480 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3717 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3481 { 3718 {
3482 if (full) 3719 SendAvatarDataToAgent(scenePresence);
3483 SendAvatarDataToClient(scenePresence);
3484 else
3485 scenePresence.ControllingClient.SendAvatarDataImmediate(this);
3486 count++; 3720 count++;
3487 }); 3721 });
3488 3722
3489 m_scene.StatsReporter.AddAgentUpdates(count); 3723 m_scene.StatsReporter.AddAgentUpdates(count);
3490 } 3724 }
3491 3725 // sends avatar object to all clients so they cross it into region
3492 /// <summary> 3726 // then sends kills to hide
3493 /// Send avatar data for all other root agents to this agent, this agent 3727 public void SendInitialAvatarDataToAllAgents(List<ScenePresence> presences)
3494 /// can be either a child or root
3495 /// </summary>
3496 public void SendOtherAgentsAvatarDataToClient()
3497 { 3728 {
3729 m_lastSize = Appearance.AvatarSize;
3498 int count = 0; 3730 int count = 0;
3499 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) 3731 foreach (ScenePresence p in presences)
3500 { 3732 {
3501 // only send information about other root agents 3733 p.ControllingClient.SendAvatarDataImmediate(this);
3502 if (scenePresence.UUID == UUID) 3734 if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3503 return; 3735 // either just kill the object
3504 3736 // p.ControllingClient.SendKillObject(new List<uint> {LocalId});
3505 scenePresence.SendAvatarDataToClient(this); 3737 // or also attachments viewer may still know about
3506 count++; 3738 SendKillTo(p);
3507 }); 3739 count++;
3508 3740 }
3509 m_scene.StatsReporter.AddAgentUpdates(count); 3741 m_scene.StatsReporter.AddAgentUpdates(count);
3510 } 3742 }
3511 3743
3744 public void SendInitialAvatarDataToAgent(ScenePresence p)
3745 {
3746 p.ControllingClient.SendAvatarDataImmediate(this);
3747 if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3748 // either just kill the object
3749 // p.ControllingClient.SendKillObject(new List<uint> {LocalId});
3750 // or also attachments viewer may still know about
3751 SendKillTo(p);
3752 }
3753
3512 /// <summary> 3754 /// <summary>
3513 /// Send avatar data to an agent. 3755 /// Send avatar data to an agent.
3514 /// </summary> 3756 /// </summary>
3515 /// <param name="avatar"></param> 3757 /// <param name="avatar"></param>
3516 public void SendAvatarDataToClient(ScenePresence avatar) 3758 public void SendAvatarDataToAgent(ScenePresence avatar)
3517 { 3759 {
3518 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToClient from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); 3760 //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID);
3519 3761 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3762 return;
3520 avatar.ControllingClient.SendAvatarDataImmediate(this); 3763 avatar.ControllingClient.SendAvatarDataImmediate(this);
3521 Animator.SendAnimPackToClient(avatar.ControllingClient); 3764 }
3765
3766 public void SendAvatarDataToAgentNF(ScenePresence avatar)
3767 {
3768 avatar.ControllingClient.SendAvatarDataImmediate(this);
3522 } 3769 }
3523 3770
3524 /// <summary> 3771 /// <summary>
3525 /// Send this agent's appearance to all other root and child agents in the scene 3772 /// Send this agent's appearance to all other root and child agents in the scene
3526 /// This agent must be root. 3773 /// This agent must be root.
3527 /// </summary> 3774 /// </summary>
3528 public void SendAppearanceToAllOtherClients() 3775 public void SendAppearanceToAllOtherAgents()
3529 { 3776 {
3530// m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherClients: {0} {1}", Name, UUID); 3777 // m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID);
3531 3778
3532 // only send update from root agents to other clients; children are only "listening posts" 3779 // only send update from root agents to other clients; children are only "listening posts"
3533 if (IsChildAgent) 3780 if (IsChildAgent)
@@ -3538,56 +3785,80 @@ namespace OpenSim.Region.Framework.Scenes
3538 3785
3539 return; 3786 return;
3540 } 3787 }
3541 3788
3542 int count = 0; 3789 int count = 0;
3543 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) 3790 m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
3544 { 3791 {
3545 // only send information to other root agents 3792 // only send information to other root agents
3546 if (scenePresence.UUID == UUID) 3793 if (scenePresence.UUID == UUID)
3547 return; 3794 return;
3548
3549 SendAppearanceToClient(scenePresence);
3550 count++;
3551 });
3552 3795
3796 SendAppearanceToAgent(scenePresence);
3797 count++;
3798 });
3553 m_scene.StatsReporter.AddAgentUpdates(count); 3799 m_scene.StatsReporter.AddAgentUpdates(count);
3554 } 3800 }
3555 3801
3556 /// <summary> 3802 public void SendAppearanceToAgent(ScenePresence avatar)
3557 /// Send appearance from all other root agents to this agent. this agent
3558 /// can be either root or child
3559 /// </summary>
3560 public void SendOtherAgentsAppearanceToClient()
3561 { 3803 {
3562// m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToClient {0} {1}", Name, UUID); 3804 // m_log.DebugFormat(
3805 // "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID);
3806 if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && avatar.GodLevel < 200)
3807 return;
3808 SendAppearanceToAgentNF(avatar);
3809 }
3563 3810
3564 int count = 0; 3811 public void SendAppearanceToAgentNF(ScenePresence avatar)
3565 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) 3812 {
3566 { 3813 avatar.ControllingClient.SendAppearance(
3567 // only send information about other root agents 3814 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes());
3568 if (scenePresence.UUID == UUID) 3815 }
3569 return;
3570
3571 scenePresence.SendAppearanceToClient(this);
3572 count++;
3573 });
3574 3816
3575 m_scene.StatsReporter.AddAgentUpdates(count); 3817 public void SendAnimPackToAgent(ScenePresence p)
3818 {
3819 if (IsChildAgent || Animator == null)
3820 return;
3821
3822 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3823 return;
3824
3825 Animator.SendAnimPackToClient(p.ControllingClient);
3576 } 3826 }
3577 3827
3578 /// <summary> 3828 public void SendAnimPackToAgent(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs)
3579 /// Send appearance data to an agent.
3580 /// </summary>
3581 /// <param name="avatar"></param>
3582 public void SendAppearanceToClient(ScenePresence avatar)
3583 { 3829 {
3584// m_log.DebugFormat( 3830 if (IsChildAgent)
3585// "[SCENE PRESENCE]: Sending appearance data from {0} {1} to {2} {3}", Name, m_uuid, avatar.Name, avatar.UUID); 3831 return;
3586 3832
3587 avatar.ControllingClient.SendAppearance( 3833 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3588 UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); 3834 return;
3589 3835
3590 3836 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3837 }
3838
3839 public void SendAnimPackToAgentNF(ScenePresence p)
3840 {
3841 if (IsChildAgent || Animator == null)
3842 return;
3843 Animator.SendAnimPackToClient(p.ControllingClient);
3844 }
3845
3846 public void SendAnimPackToAgentNF(ScenePresence p, UUID[] animations, int[] seqs, UUID[] objectIDs)
3847 {
3848 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3849 }
3850
3851 public void SendAnimPack(UUID[] animations, int[] seqs, UUID[] objectIDs)
3852 {
3853 if (IsChildAgent)
3854 return;
3855
3856 m_scene.ForEachScenePresence(delegate(ScenePresence p)
3857 {
3858 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
3859 return;
3860 p.ControllingClient.SendAnimations(animations, seqs, ControllingClient.AgentId, objectIDs);
3861 });
3591 } 3862 }
3592 3863
3593 #endregion 3864 #endregion
@@ -3611,6 +3882,7 @@ namespace OpenSim.Region.Framework.Scenes
3611 m_lastChildAgentUpdatePosition = AbsolutePosition; 3882 m_lastChildAgentUpdatePosition = AbsolutePosition;
3612// m_lastChildAgentUpdateCamPosition = CameraPosition; 3883// m_lastChildAgentUpdateCamPosition = CameraPosition;
3613 3884
3885/* cadu is not used
3614 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); 3886 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
3615 cadu.ActiveGroupID = UUID.Zero.Guid; 3887 cadu.ActiveGroupID = UUID.Zero.Guid;
3616 cadu.AgentID = UUID.Guid; 3888 cadu.AgentID = UUID.Guid;
@@ -3624,6 +3896,7 @@ namespace OpenSim.Region.Framework.Scenes
3624 3896
3625 // Throttles 3897 // Throttles
3626 float multiplier = 1; 3898 float multiplier = 1;
3899
3627 int childRegions = KnownRegionCount; 3900 int childRegions = KnownRegionCount;
3628 if (childRegions != 0) 3901 if (childRegions != 0)
3629 multiplier = 1f / childRegions; 3902 multiplier = 1f / childRegions;
@@ -3634,9 +3907,22 @@ namespace OpenSim.Region.Framework.Scenes
3634 3907
3635 cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier); 3908 cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
3636 cadu.Velocity = Velocity; 3909 cadu.Velocity = Velocity;
3637 3910*/
3638 AgentPosition agentpos = new AgentPosition(); 3911 AgentPosition agentpos = new AgentPosition();
3639 agentpos.CopyFrom(cadu, ControllingClient.SessionId); 3912// agentpos.CopyFrom(cadu, ControllingClient.SessionId);
3913
3914 agentpos.AgentID = new UUID(UUID.Guid);
3915 agentpos.SessionID = ControllingClient.SessionId;
3916
3917 agentpos.Size = Appearance.AvatarSize;
3918
3919 agentpos.Center = CameraPosition;
3920 agentpos.Far = DrawDistance;
3921 agentpos.Position = AbsolutePosition;
3922 agentpos.Velocity = Velocity;
3923 agentpos.RegionHandle = RegionHandle;
3924 agentpos.Throttles = ControllingClient.GetThrottlesPacked(1);
3925
3640 3926
3641 // Let's get this out of the update loop 3927 // Let's get this out of the update loop
3642 Util.FireAndForget( 3928 Util.FireAndForget(
@@ -3657,7 +3943,7 @@ namespace OpenSim.Region.Framework.Scenes
3657 protected void CheckForBorderCrossing() 3943 protected void CheckForBorderCrossing()
3658 { 3944 {
3659 // Check that we we are not a child 3945 // Check that we we are not a child
3660 if (IsChildAgent) 3946 if (IsChildAgent || IsInTransit)
3661 return; 3947 return;
3662 3948
3663 // If we don't have a PhysActor, we can't cross anyway 3949 // If we don't have a PhysActor, we can't cross anyway
@@ -3667,79 +3953,67 @@ namespace OpenSim.Region.Framework.Scenes
3667 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) 3953 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero)
3668 return; 3954 return;
3669 3955
3670 if (IsInTransit)
3671 return;
3672
3673 Vector3 pos2 = AbsolutePosition; 3956 Vector3 pos2 = AbsolutePosition;
3674 Vector3 origPosition = pos2;
3675 Vector3 vel = Velocity; 3957 Vector3 vel = Velocity;
3676 3958
3677 // Compute the future avatar position. 3959 float timeStep = 0.1f;
3678 // If the avatar will be crossing, we force the crossing to happen now 3960 pos2.X += vel.X * timeStep;
3679 // in the hope that this will make the avatar movement smoother when crossing. 3961 pos2.Y += vel.Y * timeStep;
3680 pos2 += vel * 0.05f; 3962 pos2.Z += vel.Z * timeStep;
3681
3682 if (m_scene.PositionIsInCurrentRegion(pos2))
3683 return;
3684
3685 m_log.DebugFormat("{0} CheckForBorderCrossing: position outside region. {1} in {2} at pos {3}",
3686 LogHeader, Name, Scene.Name, pos2);
3687 3963
3688 // Disconnect from the current region 3964// m_log.DebugFormat(
3689 bool isFlying = Flying; 3965// "[SCENE PRESENCE]: Testing border check for projected position {0} of {1} in {2}",
3690 RemoveFromPhysicalScene(); 3966// pos2, Name, Scene.Name);
3691 3967
3692 // pos2 is the forcasted position so make that the 'current' position so the crossing 3968 if (Scene.PositionIsInCurrentRegion(pos2))
3693 // code will move us into the newly addressed region. 3969 return;
3694 m_pos = pos2;
3695 3970
3696 if (CrossToNewRegion()) 3971 if (!CrossToNewRegion() && m_requestedSitTargetUUID == UUID.Zero)
3697 {
3698 AddToPhysicalScene(isFlying);
3699 }
3700 else
3701 { 3972 {
3702 // Tried to make crossing happen but it failed. 3973 // we don't have entity transfer module
3703 if (m_requestedSitTargetUUID == UUID.Zero) 3974 Vector3 pos = AbsolutePosition;
3704 { 3975 float px = pos.X;
3705 m_log.DebugFormat("{0} CheckForBorderCrossing: Crossing failed. Restoring old position.", LogHeader); 3976 if (px < 0)
3706 3977 pos.X += Velocity.X * 2;
3707 Velocity = Vector3.Zero; 3978 else if (px > m_scene.RegionInfo.RegionSizeX)
3708 AbsolutePosition = EnforceSanityOnPosition(origPosition); 3979 pos.X -= Velocity.X * 2;
3980
3981 float py = pos.Y;
3982 if (py < 0)
3983 pos.Y += Velocity.Y * 2;
3984 else if (py > m_scene.RegionInfo.RegionSizeY)
3985 pos.Y -= Velocity.Y * 2;
3709 3986
3710 AddToPhysicalScene(isFlying); 3987 Velocity = Vector3.Zero;
3711 } 3988 AbsolutePosition = pos;
3712 } 3989 }
3713 } 3990 }
3714 3991
3715 // Given a position, make sure it is within the current region. 3992 public void CrossToNewRegionFail()
3716 // If just outside some border, the returned position will be just inside the border on that side.
3717 private Vector3 EnforceSanityOnPosition(Vector3 origPosition)
3718 { 3993 {
3719 const float borderFudge = 0.1f; 3994 if (m_requestedSitTargetUUID == UUID.Zero)
3720 Vector3 ret = origPosition;
3721
3722 // Sanity checking on the position to make sure it is in the region we couldn't cross from
3723 float extentX = (float)m_scene.RegionInfo.RegionSizeX;
3724 float extentY = (float)m_scene.RegionInfo.RegionSizeY;
3725 IRegionCombinerModule combiner = m_scene.RequestModuleInterface<IRegionCombinerModule>();
3726 if (combiner != null)
3727 { 3995 {
3728 // If a mega-region, the size could be much bigger 3996 bool isFlying = Flying;
3729 Vector2 megaExtent = combiner.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); 3997 RemoveFromPhysicalScene();
3730 extentX = megaExtent.X; 3998
3731 extentY = megaExtent.Y; 3999 Vector3 pos = AbsolutePosition;
3732 } 4000 float px = pos.X;
3733 if (ret.X < 0) 4001 if (px < 0)
3734 ret.X = borderFudge; 4002 pos.X += Velocity.X * 2;
3735 else if (ret.X >= extentX) 4003 else if (px > m_scene.RegionInfo.RegionSizeX)
3736 ret.X = extentX - borderFudge; 4004 pos.X -= Velocity.X * 2;
3737 if (ret.Y < 0) 4005
3738 ret.Y = borderFudge; 4006 float py = pos.Y;
3739 else if (ret.Y >= extentY) 4007 if (py < 0)
3740 ret.Y = extentY - borderFudge; 4008 pos.Y += Velocity.Y * 2;
4009 else if (py > m_scene.RegionInfo.RegionSizeY)
4010 pos.Y -= Velocity.Y * 2;
3741 4011
3742 return ret; 4012 Velocity = Vector3.Zero;
4013 AbsolutePosition = pos;
4014
4015 AddToPhysicalScene(isFlying);
4016 }
3743 } 4017 }
3744 4018
3745 /// <summary> 4019 /// <summary>
@@ -3750,27 +4024,36 @@ namespace OpenSim.Region.Framework.Scenes
3750 /// </summary> 4024 /// </summary>
3751 protected bool CrossToNewRegion() 4025 protected bool CrossToNewRegion()
3752 { 4026 {
4027 bool result = false;
4028// parcelRegionCross(false);
3753 try 4029 try
3754 { 4030 {
3755 return m_scene.CrossAgentToNewRegion(this, Flying); 4031 result = m_scene.CrossAgentToNewRegion(this, Flying);
3756 } 4032 }
3757 catch 4033 catch
3758 { 4034 {
3759 return m_scene.CrossAgentToNewRegion(this, false); 4035// result = m_scene.CrossAgentToNewRegion(this, false);
4036 return false;
3760 } 4037 }
3761 } 4038 // if(!result)
3762 4039 // parcelRegionCross(true);
3763 public void Reset()
3764 {
3765// m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
3766 4040
3767 // Put the child agent back at the center 4041 return result;
3768 AbsolutePosition
3769 = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
3770 4042
3771 Animator.ResetAnimations();
3772 } 4043 }
3773 4044
4045 /* useless. Either use MakeChild or delete the presence
4046 public void Reset()
4047 {
4048 // m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName);
4049
4050 // Put the child agent back at the center
4051 AbsolutePosition
4052 = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70);
4053
4054 Animator.ResetAnimations();
4055 }
4056 */
3774 /// <summary> 4057 /// <summary>
3775 /// Computes which child agents to close when the scene presence moves to another region. 4058 /// Computes which child agents to close when the scene presence moves to another region.
3776 /// Removes those regions from m_knownRegions. 4059 /// Removes those regions from m_knownRegions.
@@ -3778,34 +4061,63 @@ namespace OpenSim.Region.Framework.Scenes
3778 /// <param name="newRegionX">The new region's x on the map</param> 4061 /// <param name="newRegionX">The new region's x on the map</param>
3779 /// <param name="newRegionY">The new region's y on the map</param> 4062 /// <param name="newRegionY">The new region's y on the map</param>
3780 /// <returns></returns> 4063 /// <returns></returns>
3781 public void CloseChildAgents(uint newRegionX, uint newRegionY) 4064 public void CloseChildAgents(bool logout, ulong newRegionHandle, int newRegionSizeX, int newRegionSizeY)
3782 { 4065 {
4066 uint newRegionX, newRegionY;
3783 List<ulong> byebyeRegions = new List<ulong>(); 4067 List<ulong> byebyeRegions = new List<ulong>();
3784 List<ulong> knownRegions = KnownRegionHandles; 4068 List<ulong> knownRegions = KnownRegionHandles;
3785 m_log.DebugFormat( 4069 m_log.DebugFormat(
3786 "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}", 4070 "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}",
3787 knownRegions.Count, Scene.RegionInfo.RegionName); 4071 knownRegions.Count, Scene.RegionInfo.RegionName);
3788 //DumpKnownRegions(); 4072 //DumpKnownRegions();
3789 4073
4074 Util.RegionHandleToRegionLoc(newRegionHandle, out newRegionX, out newRegionY);
4075
4076 uint x, y;
4077 spRegionSizeInfo regInfo;
4078
4079 // this should not be here
4080 IEventQueue eventQueue = Scene.RequestModuleInterface<IEventQueue>();
4081
3790 foreach (ulong handle in knownRegions) 4082 foreach (ulong handle in knownRegions)
3791 { 4083 {
3792 // Don't close the agent on this region yet 4084 // Don't close the agent on this region yet
3793 if (handle != Scene.RegionInfo.RegionHandle) 4085 if (handle != Scene.RegionInfo.RegionHandle)
3794 { 4086 {
3795 uint x, y; 4087 if (logout)
3796 Util.RegionHandleToRegionLoc(handle, out x, out y);
3797
3798// m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
3799// m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
3800 float dist = (float)Math.Max(Scene.DefaultDrawDistance,
3801 (float)Math.Max(Scene.RegionInfo.RegionSizeX, Scene.RegionInfo.RegionSizeY));
3802 if (Util.IsOutsideView(dist, x, newRegionX, y, newRegionY))
3803 {
3804 byebyeRegions.Add(handle); 4088 byebyeRegions.Add(handle);
4089 else
4090 {
4091 Util.RegionHandleToRegionLoc(handle, out x, out y);
4092 if (m_knownChildRegionsSizeInfo.TryGetValue(handle, out regInfo))
4093 {
4094
4095 // m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
4096 // m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
4097 if (Util.IsOutsideView(DrawDistance, x, newRegionX, y, newRegionY,
4098 regInfo.sizeX, regInfo.sizeY, newRegionSizeX, newRegionSizeY))
4099 {
4100 byebyeRegions.Add(handle);
4101 // this should not be here
4102 if(eventQueue != null)
4103 eventQueue.DisableSimulator(handle,UUID);
4104 }
4105 }
4106 else
4107 {
4108 if (Util.IsOutsideView(DrawDistance, x, newRegionX, y, newRegionY,
4109 (int)Constants.RegionSize, (int)Constants.RegionSize, newRegionSizeX, newRegionSizeY))
4110 {
4111 byebyeRegions.Add(handle);
4112 // this should not be here
4113 if(eventQueue != null)
4114 eventQueue.DisableSimulator(handle,UUID);
4115 }
4116 }
3805 } 4117 }
3806 } 4118 }
3807 } 4119 }
3808 4120
3809 if (byebyeRegions.Count > 0) 4121 if (byebyeRegions.Count > 0)
3810 { 4122 {
3811 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); 4123 m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
@@ -3814,12 +4126,13 @@ namespace OpenSim.Region.Framework.Scenes
3814 string auth = string.Empty; 4126 string auth = string.Empty;
3815 if (acd != null) 4127 if (acd != null)
3816 auth = acd.SessionID.ToString(); 4128 auth = acd.SessionID.ToString();
3817 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions); 4129 m_scene.SceneGridService.SendCloseChildAgentConnections(ControllingClient.AgentId, auth, byebyeRegions);
3818 } 4130 }
3819 4131
3820 foreach (ulong handle in byebyeRegions) 4132 foreach (ulong handle in byebyeRegions)
3821 { 4133 {
3822 RemoveNeighbourRegion(handle); 4134 RemoveNeighbourRegion(handle);
4135 Scene.CapsModule.DropChildSeed(UUID, handle);
3823 } 4136 }
3824 } 4137 }
3825 4138
@@ -3831,6 +4144,8 @@ namespace OpenSim.Region.Framework.Scenes
3831 /// </summary> 4144 /// </summary>
3832 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus) 4145 public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
3833 { 4146 {
4147 int oldgodlevel = GodLevel;
4148
3834 if (godStatus) 4149 if (godStatus)
3835 { 4150 {
3836 // For now, assign god level 200 to anyone 4151 // For now, assign god level 200 to anyone
@@ -3851,6 +4166,9 @@ namespace OpenSim.Region.Framework.Scenes
3851 } 4166 }
3852 4167
3853 ControllingClient.SendAdminResponse(token, (uint)GodLevel); 4168 ControllingClient.SendAdminResponse(token, (uint)GodLevel);
4169
4170 if(oldgodlevel != GodLevel)
4171 parcelGodCheck(m_currentParcelUUID, GodLevel >= 200);
3854 } 4172 }
3855 4173
3856 #region Child Agent Updates 4174 #region Child Agent Updates
@@ -3862,12 +4180,16 @@ namespace OpenSim.Region.Framework.Scenes
3862 return; 4180 return;
3863 4181
3864 CopyFrom(cAgentData); 4182 CopyFrom(cAgentData);
3865 4183
3866 m_updateAgentReceivedAfterTransferEvent.Set();
3867 } 4184 }
3868 4185
3869 private static Vector3 marker = new Vector3(-1f, -1f, -1f); 4186 private static Vector3 marker = new Vector3(-1f, -1f, -1f);
3870 4187
4188 private void RaiseUpdateThrottles()
4189 {
4190 m_scene.EventManager.TriggerThrottleUpdate(this);
4191 }
4192
3871 /// <summary> 4193 /// <summary>
3872 /// This updates important decision making data about a child agent 4194 /// This updates important decision making data about a child agent
3873 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region 4195 /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
@@ -3877,23 +4199,15 @@ namespace OpenSim.Region.Framework.Scenes
3877 if (!IsChildAgent) 4199 if (!IsChildAgent)
3878 return; 4200 return;
3879 4201
3880// m_log.DebugFormat( 4202 RegionHandle = cAgentData.RegionHandle;
3881// "[SCENE PRESENCE]: ChildAgentPositionUpdate for {0} in {1}, tRegion {2},{3}, rRegion {4},{5}, pos {6}",
3882// Name, Scene.Name, tRegionX, tRegionY, rRegionX, rRegionY, cAgentData.Position);
3883 4203
3884 // Find the distance (in meters) between the two regions 4204 //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
3885 // XXX: We cannot use Util.RegionLocToHandle() here because a negative value will silently overflow the 4205 int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize;
3886 // uint 4206 int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize;
3887 int shiftx = (int)(((int)rRegionX - (int)tRegionX) * Constants.RegionSize);
3888 int shifty = (int)(((int)rRegionY - (int)tRegionY) * Constants.RegionSize);
3889 4207
3890 Vector3 offset = new Vector3(shiftx, shifty, 0f); 4208 Vector3 offset = new Vector3(shiftx, shifty, 0f);
3891 4209
3892 // When we get to the point of re-computing neighbors everytime this
3893 // changes, then start using the agent's drawdistance rather than the
3894 // region's draw distance.
3895 DrawDistance = cAgentData.Far; 4210 DrawDistance = cAgentData.Far;
3896 // DrawDistance = Scene.DefaultDrawDistance;
3897 4211
3898 if (cAgentData.Position != marker) // UGH!! 4212 if (cAgentData.Position != marker) // UGH!!
3899 m_pos = cAgentData.Position + offset; 4213 m_pos = cAgentData.Position + offset;
@@ -3907,10 +4221,36 @@ namespace OpenSim.Region.Framework.Scenes
3907 CameraPosition = cAgentData.Center + offset; 4221 CameraPosition = cAgentData.Center + offset;
3908 4222
3909 if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0) 4223 if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0)
3910 ControllingClient.SetChildAgentThrottle(cAgentData.Throttles); 4224 {
4225 // some scaling factor
4226 float x = m_pos.X;
4227 if (x > m_scene.RegionInfo.RegionSizeX)
4228 x -= m_scene.RegionInfo.RegionSizeX;
4229 float y = m_pos.Y;
4230 if (y > m_scene.RegionInfo.RegionSizeY)
4231 y -= m_scene.RegionInfo.RegionSizeY;
4232
4233 x = x * x + y * y;
4234
4235 const float distScale = 0.4f / Constants.RegionSize / Constants.RegionSize;
4236 float factor = 1.0f - distScale * x;
4237 if (factor < 0.2f)
4238 factor = 0.2f;
4239
4240 ControllingClient.SetChildAgentThrottle(cAgentData.Throttles,factor);
4241 }
4242
4243 if(cAgentData.ChildrenCapSeeds != null && cAgentData.ChildrenCapSeeds.Count >0)
4244 {
4245 if (Scene.CapsModule != null)
4246 {
4247 Scene.CapsModule.SetChildrenSeed(UUID, cAgentData.ChildrenCapSeeds);
4248 }
4249
4250 KnownRegions = cAgentData.ChildrenCapSeeds;
4251 }
3911 4252
3912 //cAgentData.AVHeight; 4253 //cAgentData.AVHeight;
3913 RegionHandle = cAgentData.RegionHandle;
3914 //m_velocity = cAgentData.Velocity; 4254 //m_velocity = cAgentData.Velocity;
3915 } 4255 }
3916 4256
@@ -3932,16 +4272,7 @@ namespace OpenSim.Region.Framework.Scenes
3932 cAgent.Far = DrawDistance; 4272 cAgent.Far = DrawDistance;
3933 4273
3934 // Throttles 4274 // Throttles
3935 float multiplier = 1; 4275 cAgent.Throttles = ControllingClient.GetThrottlesPacked(1);
3936 int childRegions = KnownRegionCount;
3937 if (childRegions != 0)
3938 multiplier = 1f / childRegions;
3939
3940 // Minimum throttle for a child region is 1/4 of the root region throttle
3941 if (multiplier <= 0.25f)
3942 multiplier = 0.25f;
3943
3944 cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
3945 4276
3946 cAgent.HeadRotation = m_headrotation; 4277 cAgent.HeadRotation = m_headrotation;
3947 cAgent.BodyRotation = Rotation; 4278 cAgent.BodyRotation = Rotation;
@@ -3954,7 +4285,8 @@ namespace OpenSim.Region.Framework.Scenes
3954 4285
3955 cAgent.AlwaysRun = SetAlwaysRun; 4286 cAgent.AlwaysRun = SetAlwaysRun;
3956 4287
3957 cAgent.Appearance = new AvatarAppearance(Appearance); 4288 // make clear we want the all thing
4289 cAgent.Appearance = new AvatarAppearance(Appearance,true,true);
3958 4290
3959 cAgent.ParentPart = ParentUUID; 4291 cAgent.ParentPart = ParentUUID;
3960 cAgent.SitOffset = PrevSitOffset; 4292 cAgent.SitOffset = PrevSitOffset;
@@ -3980,6 +4312,10 @@ namespace OpenSim.Region.Framework.Scenes
3980 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; 4312 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation;
3981 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation; 4313 cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation;
3982 4314
4315 cAgent.MovementAnimationOverRides = Overrides.CloneAOPairs();
4316
4317 cAgent.MotionState = (byte)Animator.currentControlState;
4318
3983 if (Scene.AttachmentsModule != null) 4319 if (Scene.AttachmentsModule != null)
3984 Scene.AttachmentsModule.CopyAttachments(this, cAgent); 4320 Scene.AttachmentsModule.CopyAttachments(this, cAgent);
3985 } 4321 }
@@ -4004,7 +4340,16 @@ namespace OpenSim.Region.Framework.Scenes
4004 // changes, then start using the agent's drawdistance rather than the 4340 // changes, then start using the agent's drawdistance rather than the
4005 // region's draw distance. 4341 // region's draw distance.
4006 DrawDistance = cAgent.Far; 4342 DrawDistance = cAgent.Far;
4007 // DrawDistance = Scene.DefaultDrawDistance; 4343 //DrawDistance = Scene.DefaultDrawDistance;
4344
4345 if (cAgent.ChildrenCapSeeds != null && cAgent.ChildrenCapSeeds.Count > 0)
4346 {
4347 if (Scene.CapsModule != null)
4348 {
4349 Scene.CapsModule.SetChildrenSeed(UUID, cAgent.ChildrenCapSeeds);
4350 }
4351 KnownRegions = cAgent.ChildrenCapSeeds;
4352 }
4008 4353
4009 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0) 4354 if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
4010 ControllingClient.SetChildAgentThrottle(cAgent.Throttles); 4355 ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
@@ -4017,14 +4362,17 @@ namespace OpenSim.Region.Framework.Scenes
4017 GodLevel = cAgent.GodLevel; 4362 GodLevel = cAgent.GodLevel;
4018 SetAlwaysRun = cAgent.AlwaysRun; 4363 SetAlwaysRun = cAgent.AlwaysRun;
4019 4364
4365
4020 Appearance = new AvatarAppearance(cAgent.Appearance); 4366 Appearance = new AvatarAppearance(cAgent.Appearance);
4367/*
4368 bool isFlying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
4369
4021 if (PhysicsActor != null) 4370 if (PhysicsActor != null)
4022 { 4371 {
4023 bool isFlying = Flying;
4024 RemoveFromPhysicalScene(); 4372 RemoveFromPhysicalScene();
4025 AddToPhysicalScene(isFlying); 4373 AddToPhysicalScene(isFlying);
4026 } 4374 }
4027 4375*/
4028 try 4376 try
4029 { 4377 {
4030 lock (scriptedcontrols) 4378 lock (scriptedcontrols)
@@ -4048,34 +4396,23 @@ namespace OpenSim.Region.Framework.Scenes
4048 } 4396 }
4049 catch { } 4397 catch { }
4050 4398
4399 Animator.ResetAnimations();
4400
4401 Overrides.CopyAOPairsFrom(cAgent.MovementAnimationOverRides);
4402
4051 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? 4403 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object?
4052 if (cAgent.Anims != null)
4053 Animator.Animations.FromArray(cAgent.Anims);
4054 if (cAgent.DefaultAnim != null) 4404 if (cAgent.DefaultAnim != null)
4055 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); 4405 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
4056 if (cAgent.AnimState != null) 4406 if (cAgent.AnimState != null)
4057 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); 4407 Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero);
4408 if (cAgent.Anims != null)
4409 Animator.Animations.FromArray(cAgent.Anims);
4410 if (cAgent.MotionState != 0)
4411 Animator.currentControlState = (ScenePresenceAnimator.motionControlStates) cAgent.MotionState;
4058 4412
4059 if (Scene.AttachmentsModule != null) 4413 if (Scene.AttachmentsModule != null)
4060 { 4414 Scene.AttachmentsModule.CopyAttachments(cAgent, this);
4061 // If the JobEngine is running we can schedule this job now and continue rather than waiting for all 4415
4062 // attachments to copy, which might take a long time in the Hypergrid case as the entire inventory
4063 // graph is inspected for each attachments and assets possibly fetched.
4064 //
4065 // We don't need to worry about a race condition as the job to later start the scripts is also
4066 // JobEngine scheduled and so will always occur after this task.
4067 // XXX: This will not be true if JobEngine ever gets more than one thread.
4068 WorkManager.RunJob(
4069 "CopyAttachments",
4070 o => Scene.AttachmentsModule.CopyAttachments(cAgent, this),
4071 null,
4072 string.Format("Copy attachments for {0} entering {1}", Name, Scene.Name),
4073 true);
4074 }
4075
4076 // This must occur after attachments are copied or scheduled to be copied, as it releases the CompleteMovement() calling thread
4077 // originating from the client completing a teleport. Otherwise, CompleteMovement() code to restart
4078 // script attachments can outrace this thread.
4079 lock (m_originRegionIDAccessLock) 4416 lock (m_originRegionIDAccessLock)
4080 m_originRegionID = cAgent.RegionID; 4417 m_originRegionID = cAgent.RegionID;
4081 } 4418 }
@@ -4094,6 +4431,8 @@ namespace OpenSim.Region.Framework.Scenes
4094 /// </summary> 4431 /// </summary>
4095 public void UpdateMovement() 4432 public void UpdateMovement()
4096 { 4433 {
4434 if (IsInTransit)
4435 return;
4097 if (m_forceToApply.HasValue) 4436 if (m_forceToApply.HasValue)
4098 { 4437 {
4099 Vector3 force = m_forceToApply.Value; 4438 Vector3 force = m_forceToApply.Value;
@@ -4124,17 +4463,14 @@ namespace OpenSim.Region.Framework.Scenes
4124 if (Appearance.AvatarHeight == 0) 4463 if (Appearance.AvatarHeight == 0)
4125// Appearance.SetHeight(); 4464// Appearance.SetHeight();
4126 Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f)); 4465 Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f));
4127
4128/*
4129 PhysicsActor = scene.AddAvatar(
4130 LocalId, Firstname + "." + Lastname, pVec,
4131 new Vector3(0.45f, 0.6f, Appearance.AvatarHeight), isFlying);
4132*/
4133 4466
4134 PhysicsActor = m_scene.PhysicsScene.AddAvatar( 4467 PhysicsScene scene = m_scene.PhysicsScene;
4135 LocalId, Firstname + "." + Lastname, AbsolutePosition, Velocity, 4468 Vector3 pVec = AbsolutePosition;
4136 Appearance.AvatarBoxSize, isFlying);
4137 4469
4470 PhysicsActor = scene.AddAvatar(
4471 LocalId, Firstname + "." + Lastname, pVec,
4472 Appearance.AvatarBoxSize,Appearance.AvatarFeetOffset, isFlying);
4473 PhysicsActor.Orientation = m_bodyRot;
4138 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 4474 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
4139 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 4475 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
4140 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong 4476 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
@@ -4168,7 +4504,9 @@ namespace OpenSim.Region.Framework.Scenes
4168 { 4504 {
4169 if (IsChildAgent || Animator == null) 4505 if (IsChildAgent || Animator == null)
4170 return; 4506 return;
4171 4507
4508 if(IsInTransit)
4509 return;
4172 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 4510 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
4173 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents( 4511 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
4174 // as of this comment the interval is set in AddToPhysicalScene 4512 // as of this comment the interval is set in AddToPhysicalScene
@@ -4192,7 +4530,49 @@ namespace OpenSim.Region.Framework.Scenes
4192// m_lastColCount = coldata.Count; 4530// m_lastColCount = coldata.Count;
4193// } 4531// }
4194 4532
4195 CollisionPlane = Vector4.UnitW; 4533 if (coldata.Count != 0)
4534 {
4535/*
4536 switch (Animator.CurrentMovementAnimation)
4537 {
4538 case "STAND":
4539 case "WALK":
4540 case "RUN":
4541 case "CROUCH":
4542 case "CROUCHWALK":
4543 {
4544 */
4545 ContactPoint lowest;
4546 lowest.SurfaceNormal = Vector3.Zero;
4547 lowest.Position = Vector3.Zero;
4548 lowest.Position.Z = float.MaxValue;
4549
4550 foreach (ContactPoint contact in coldata.Values)
4551 {
4552
4553 if (contact.CharacterFeet && contact.Position.Z < lowest.Position.Z)
4554 {
4555 lowest = contact;
4556 }
4557 }
4558
4559 if (lowest.Position.Z != float.MaxValue)
4560 {
4561 lowest.SurfaceNormal = -lowest.SurfaceNormal;
4562 CollisionPlane = new Vector4(lowest.SurfaceNormal, Vector3.Dot(lowest.Position, lowest.SurfaceNormal));
4563 }
4564 else
4565 CollisionPlane = Vector4.UnitW;
4566/*
4567 }
4568 break;
4569 }
4570*/
4571 }
4572 else
4573 CollisionPlane = Vector4.UnitW;
4574
4575 RaiseCollisionScriptEvents(coldata);
4196 4576
4197 // Gods do not take damage and Invulnerable is set depending on parcel/region flags 4577 // Gods do not take damage and Invulnerable is set depending on parcel/region flags
4198 if (Invulnerable || GodLevel > 0) 4578 if (Invulnerable || GodLevel > 0)
@@ -4311,6 +4691,10 @@ namespace OpenSim.Region.Framework.Scenes
4311 4691
4312 m_attachments.Add(gobj); 4692 m_attachments.Add(gobj);
4313 } 4693 }
4694
4695 IBakedTextureModule bakedModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
4696 if (bakedModule != null)
4697 bakedModule.UpdateMeshAvatar(m_uuid);
4314 } 4698 }
4315 4699
4316 /// <summary> 4700 /// <summary>
@@ -4474,6 +4858,287 @@ namespace OpenSim.Region.Framework.Scenes
4474 return validated; 4858 return validated;
4475 } 4859 }
4476 4860
4861 public void SendAttachmentsToAllAgents()
4862 {
4863 lock (m_attachments)
4864 {
4865 foreach (SceneObjectGroup sog in m_attachments)
4866 {
4867 m_scene.ForEachScenePresence(delegate(ScenePresence p)
4868 {
4869 if (p != this && sog.HasPrivateAttachmentPoint)
4870 return;
4871
4872 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4873 return;
4874
4875 SendTerseUpdateToAgentNF(p);
4876 SendAttachmentFullUpdateToAgentNF(sog, p);
4877 });
4878 }
4879 }
4880 }
4881
4882 // send attachments to a client without filters except for huds
4883 // for now they are checked in several places down the line...
4884 public void SendAttachmentsToAgentNF(ScenePresence p)
4885 {
4886 SendTerseUpdateToAgentNF(p);
4887 lock (m_attachments)
4888 {
4889 foreach (SceneObjectGroup sog in m_attachments)
4890 {
4891 SendAttachmentFullUpdateToAgentNF(sog, p);
4892 }
4893 }
4894 }
4895
4896 public void SendAttachmentFullUpdateToAgentNF(SceneObjectGroup sog, ScenePresence p)
4897 {
4898 if (p != this && sog.HasPrivateAttachmentPoint)
4899 return;
4900
4901 SceneObjectPart[] parts = sog.Parts;
4902 SceneObjectPart rootpart = sog.RootPart;
4903
4904 p.ControllingClient.SendEntityUpdate(rootpart, PrimUpdateFlags.FullUpdate);
4905
4906 for (int i = 0; i < parts.Length; i++)
4907 {
4908 SceneObjectPart part = parts[i];
4909 if (part == rootpart)
4910 continue;
4911 p.ControllingClient.SendEntityUpdate(part, PrimUpdateFlags.FullUpdate);
4912 }
4913 }
4914
4915 public void SendAttachmentScheduleUpdate(SceneObjectGroup sog)
4916 {
4917 if (IsChildAgent || IsInTransit)
4918 return;
4919
4920 SceneObjectPart[] origparts = sog.Parts;
4921 SceneObjectPart[] parts = new SceneObjectPart[origparts.Length];
4922 PrimUpdateFlags[] flags = new PrimUpdateFlags[origparts.Length];
4923
4924 SceneObjectPart rootpart = sog.RootPart;
4925 UpdateRequired rootreq = sog.RootPart.UpdateFlag;
4926
4927 int j = 0;
4928 bool allterse = true;
4929 for (int i = 0; i < origparts.Length; i++)
4930 {
4931 if (origparts[i] != rootpart)
4932 {
4933 switch (origparts[i].UpdateFlag)
4934 {
4935 case UpdateRequired.NONE:
4936 break;
4937
4938 case UpdateRequired.TERSE:
4939 flags[j] = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4940 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4941 parts[j] = origparts[i];
4942 j++;
4943 break;
4944
4945 case UpdateRequired.FULL:
4946 flags[j] = PrimUpdateFlags.FullUpdate;
4947 allterse = false;
4948 parts[j] = origparts[i];
4949 j++;
4950 break;
4951 }
4952 }
4953 origparts[i].UpdateFlag = 0;
4954 }
4955
4956 if (j == 0 && rootreq == UpdateRequired.NONE)
4957 return;
4958
4959 PrimUpdateFlags rootflag = PrimUpdateFlags.FullUpdate;
4960
4961 if (rootreq != UpdateRequired.FULL && allterse)
4962 {
4963 rootflag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4964 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
4965 }
4966
4967 int nparts = j;
4968
4969 ControllingClient.SendEntityUpdate(rootpart, rootflag);
4970
4971 for (int i = 0; i < nparts; i++)
4972 {
4973 ControllingClient.SendEntityUpdate(parts[i], flags[i]);
4974 }
4975
4976 if (sog.HasPrivateAttachmentPoint)
4977 return;
4978
4979 List<ScenePresence> allPresences = m_scene.GetScenePresences();
4980 foreach (ScenePresence p in allPresences)
4981 {
4982 if (p == this)
4983 continue;
4984
4985 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
4986 continue;
4987
4988 p.ControllingClient.SendEntityUpdate(rootpart, rootflag);
4989
4990 for (int i = 0; i < nparts; i++)
4991 {
4992 p.ControllingClient.SendEntityUpdate(parts[i], flags[i]);
4993 }
4994 }
4995 }
4996
4997 public void SendAttachmentUpdate(SceneObjectGroup sog, UpdateRequired UpdateFlag)
4998 {
4999 if (IsChildAgent || IsInTransit)
5000 return;
5001
5002 PrimUpdateFlags flag;
5003 switch (UpdateFlag)
5004 {
5005 case UpdateRequired.TERSE:
5006 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5007 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5008 break;
5009
5010 case UpdateRequired.FULL:
5011 flag = PrimUpdateFlags.FullUpdate;
5012 break;
5013
5014 default:
5015 return;
5016 }
5017
5018 SceneObjectPart[] parts = sog.Parts;
5019 SceneObjectPart rootpart = sog.RootPart;
5020
5021// rootpart.UpdateFlag = 0;
5022
5023 ControllingClient.SendEntityUpdate(rootpart, flag);
5024
5025 for (int i = 0; i < parts.Length; i++)
5026 {
5027 SceneObjectPart part = parts[i];
5028 if (part == rootpart)
5029 continue;
5030 ControllingClient.SendEntityUpdate(part, flag);
5031// part.UpdateFlag = 0;
5032 }
5033
5034 if (sog.HasPrivateAttachmentPoint)
5035 return;
5036
5037
5038 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5039 foreach (ScenePresence p in allPresences)
5040 {
5041 if (p == this)
5042 continue;
5043
5044 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5045 continue;
5046
5047 p.ControllingClient.SendEntityUpdate(rootpart, flag);
5048
5049 for (int i = 0; i < parts.Length; i++)
5050 {
5051 SceneObjectPart part = parts[i];
5052 if (part == rootpart)
5053 continue;
5054 p.ControllingClient.SendEntityUpdate(part, flag);
5055 }
5056 }
5057 }
5058
5059 public void SendAttachmentScheduleUpdate(SceneObjectPart part)
5060 {
5061 if (IsChildAgent || IsInTransit)
5062 return;
5063
5064
5065 PrimUpdateFlags flag;
5066 switch (part.UpdateFlag)
5067 {
5068 case UpdateRequired.TERSE:
5069 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5070 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5071 break;
5072
5073 case UpdateRequired.FULL:
5074 flag = PrimUpdateFlags.FullUpdate;
5075 break;
5076
5077 default:
5078 return;
5079 }
5080
5081 part.UpdateFlag = 0;
5082
5083 ControllingClient.SendEntityUpdate(part, flag);
5084
5085 if (part.ParentGroup.HasPrivateAttachmentPoint)
5086 return;
5087
5088 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5089 foreach (ScenePresence p in allPresences)
5090 {
5091 if (p == this)
5092 continue;
5093
5094 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5095 continue;
5096
5097 p.ControllingClient.SendEntityUpdate(part, flag);
5098 }
5099 }
5100
5101
5102 public void SendAttachmentUpdate(SceneObjectPart part, UpdateRequired UpdateFlag)
5103 {
5104 if (IsChildAgent || IsInTransit)
5105 return;
5106
5107 PrimUpdateFlags flag;
5108 switch (UpdateFlag)
5109 {
5110 case UpdateRequired.TERSE:
5111 flag = PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
5112 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity;
5113 break;
5114
5115 case UpdateRequired.FULL:
5116 flag = PrimUpdateFlags.FullUpdate;
5117 break;
5118
5119 default:
5120 return;
5121 }
5122
5123// part.UpdateFlag = 0;
5124
5125 ControllingClient.SendEntityUpdate(part, flag);
5126
5127 if (part.ParentGroup.HasPrivateAttachmentPoint)
5128 return;
5129
5130 List<ScenePresence> allPresences = m_scene.GetScenePresences();
5131 foreach (ScenePresence p in allPresences)
5132 {
5133 if (p == this)
5134 continue;
5135 if (ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && p.GodLevel < 200)
5136 continue;
5137
5138 p.ControllingClient.SendEntityUpdate(part, flag);
5139 }
5140 }
5141
4477 /// <summary> 5142 /// <summary>
4478 /// Send a script event to this scene presence's attachments 5143 /// Send a script event to this scene presence's attachments
4479 /// </summary> 5144 /// </summary>
@@ -4592,7 +5257,16 @@ namespace OpenSim.Region.Framework.Scenes
4592 ControllingClient.SendTakeControls(int.MaxValue, false, false); 5257 ControllingClient.SendTakeControls(int.MaxValue, false, false);
4593 } 5258 }
4594 5259
4595 private void UnRegisterSeatControls(UUID obj) 5260 public void ClearControls()
5261 {
5262 IgnoredControls = ScriptControlled.CONTROL_ZERO;
5263 lock (scriptedcontrols)
5264 {
5265 scriptedcontrols.Clear();
5266 }
5267 }
5268
5269 public void UnRegisterSeatControls(UUID obj)
4596 { 5270 {
4597 List<UUID> takers = new List<UUID>(); 5271 List<UUID> takers = new List<UUID>();
4598 5272
@@ -4833,11 +5507,8 @@ namespace OpenSim.Region.Framework.Scenes
4833 SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray(); 5507 SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray();
4834 if (spawnPoints.Length == 0) 5508 if (spawnPoints.Length == 0)
4835 { 5509 {
4836 if(m_scene.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_uuid)) 5510 pos.X = 128.0f;
4837 { 5511 pos.Y = 128.0f;
4838 pos.X = 128.0f;
4839 pos.Y = 128.0f;
4840 }
4841 return; 5512 return;
4842 } 5513 }
4843 5514
@@ -4982,8 +5653,8 @@ namespace OpenSim.Region.Framework.Scenes
4982 pos = land.LandData.UserLocation; 5653 pos = land.LandData.UserLocation;
4983 } 5654 }
4984 } 5655 }
4985 5656// this is now done in completeMovement for all cases and not just this
4986 land.SendLandUpdateToClient(ControllingClient); 5657// land.SendLandUpdateToClient(ControllingClient);
4987 } 5658 }
4988 } 5659 }
4989 5660
@@ -4998,6 +5669,7 @@ namespace OpenSim.Region.Framework.Scenes
4998 detobj.velVector = obj.Velocity; 5669 detobj.velVector = obj.Velocity;
4999 detobj.colliderType = 0; 5670 detobj.colliderType = 0;
5000 detobj.groupUUID = obj.GroupID; 5671 detobj.groupUUID = obj.GroupID;
5672 detobj.linkNumber = 0;
5001 5673
5002 return detobj; 5674 return detobj;
5003 } 5675 }
@@ -5013,6 +5685,7 @@ namespace OpenSim.Region.Framework.Scenes
5013 detobj.velVector = av.Velocity; 5685 detobj.velVector = av.Velocity;
5014 detobj.colliderType = 0; 5686 detobj.colliderType = 0;
5015 detobj.groupUUID = av.ControllingClient.ActiveGroupId; 5687 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
5688 detobj.linkNumber = 0;
5016 5689
5017 return detobj; 5690 return detobj;
5018 } 5691 }
@@ -5028,7 +5701,7 @@ namespace OpenSim.Region.Framework.Scenes
5028 detobj.velVector = Vector3.Zero; 5701 detobj.velVector = Vector3.Zero;
5029 detobj.colliderType = 0; 5702 detobj.colliderType = 0;
5030 detobj.groupUUID = UUID.Zero; 5703 detobj.groupUUID = UUID.Zero;
5031 5704 detobj.linkNumber = 0;
5032 return detobj; 5705 return detobj;
5033 } 5706 }
5034 5707
@@ -5095,6 +5768,95 @@ namespace OpenSim.Region.Framework.Scenes
5095 } 5768 }
5096 } 5769 }
5097 5770
5771 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
5772 {
5773 try
5774 {
5775 List<uint> thisHitColliders = new List<uint>();
5776 List<uint> endedColliders = new List<uint>();
5777 List<uint> startedColliders = new List<uint>();
5778 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
5779 CollisionForSoundInfo soundinfo;
5780 ContactPoint curcontact;
5781
5782 if (coldata.Count == 0)
5783 {
5784 if (m_lastColliders.Count == 0)
5785 return; // nothing to do
5786
5787 foreach (uint localID in m_lastColliders)
5788 {
5789 endedColliders.Add(localID);
5790 }
5791 m_lastColliders.Clear();
5792 }
5793
5794 else
5795 {
5796 bool candoparcelSound = ParcelAllowThisAvatarSounds;
5797
5798 foreach (uint id in coldata.Keys)
5799 {
5800 thisHitColliders.Add(id);
5801 if (!m_lastColliders.Contains(id))
5802 {
5803 startedColliders.Add(id);
5804 curcontact = coldata[id];
5805 if (candoparcelSound && Math.Abs(curcontact.RelativeSpeed) > 0.2)
5806 {
5807 soundinfo = new CollisionForSoundInfo();
5808 soundinfo.colliderID = id;
5809 soundinfo.position = curcontact.Position;
5810 soundinfo.relativeVel = curcontact.RelativeSpeed;
5811 soundinfolist.Add(soundinfo);
5812 }
5813 }
5814 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
5815 }
5816
5817 // calculate things that ended colliding
5818 foreach (uint localID in m_lastColliders)
5819 {
5820 if (!thisHitColliders.Contains(localID))
5821 {
5822 endedColliders.Add(localID);
5823 }
5824 }
5825 //add the items that started colliding this time to the last colliders list.
5826 foreach (uint localID in startedColliders)
5827 {
5828 m_lastColliders.Add(localID);
5829 }
5830 // remove things that ended colliding from the last colliders list
5831 foreach (uint localID in endedColliders)
5832 {
5833 m_lastColliders.Remove(localID);
5834 }
5835
5836 if (soundinfolist.Count > 0)
5837 CollisionSounds.AvatarCollisionSound(this, soundinfolist);
5838 }
5839
5840 foreach (SceneObjectGroup att in GetAttachments())
5841 {
5842 SendCollisionEvent(att, scriptEvents.collision_start, startedColliders, m_scene.EventManager.TriggerScriptCollidingStart);
5843 SendCollisionEvent(att, scriptEvents.collision , m_lastColliders , m_scene.EventManager.TriggerScriptColliding);
5844 SendCollisionEvent(att, scriptEvents.collision_end , endedColliders , m_scene.EventManager.TriggerScriptCollidingEnd);
5845
5846 if (startedColliders.Contains(0))
5847 SendLandCollisionEvent(att, scriptEvents.land_collision_start, m_scene.EventManager.TriggerScriptLandCollidingStart);
5848 if (m_lastColliders.Contains(0))
5849 SendLandCollisionEvent(att, scriptEvents.land_collision, m_scene.EventManager.TriggerScriptLandColliding);
5850 if (endedColliders.Contains(0))
5851 SendLandCollisionEvent(att, scriptEvents.land_collision_end, m_scene.EventManager.TriggerScriptLandCollidingEnd);
5852 }
5853 }
5854 finally
5855 {
5856 m_collisionEventFlag = false;
5857 }
5858 }
5859
5098 private void TeleportFlagsDebug() { 5860 private void TeleportFlagsDebug() {
5099 5861
5100 // Some temporary debugging help to show all the TeleportFlags we have... 5862 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -5119,5 +5881,282 @@ namespace OpenSim.Region.Framework.Scenes
5119 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 5881 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
5120 5882
5121 } 5883 }
5884
5885 private void parcelGodCheck(UUID currentParcelID, bool isGod)
5886 {
5887 List<ScenePresence> allpresences = m_scene.GetScenePresences();
5888
5889 foreach (ScenePresence p in allpresences)
5890 {
5891 if (p.IsDeleted || p.IsChildAgent || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5892 continue;
5893
5894 if (p.ParcelHideThisAvatar && p.currentParcelUUID != currentParcelID)
5895 {
5896 if (isGod)
5897 p.SendViewTo(this);
5898 else
5899 p.SendKillTo(this);
5900 }
5901 }
5902 }
5903
5904 private void ParcelCrossCheck(UUID currentParcelID,UUID previusParcelID,
5905 bool currentParcelHide, bool previusParcelHide, bool oldhide,bool check)
5906 {
5907 List<ScenePresence> killsToSendto = new List<ScenePresence>();
5908 List<ScenePresence> killsToSendme = new List<ScenePresence>();
5909 List<ScenePresence> viewsToSendto = new List<ScenePresence>();
5910 List<ScenePresence> viewsToSendme = new List<ScenePresence>();
5911 List<ScenePresence> allpresences = null;
5912
5913 if (IsInTransit || IsChildAgent)
5914 return;
5915
5916 if (check)
5917 {
5918 // check is relative to current parcel only
5919 if (currentParcelUUID == null || oldhide == currentParcelHide)
5920 return;
5921
5922 allpresences = m_scene.GetScenePresences();
5923
5924 if (oldhide)
5925 { // where private
5926 foreach (ScenePresence p in allpresences)
5927 {
5928 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5929 continue;
5930
5931 // those on not on parcel see me
5932 if (currentParcelID != p.currentParcelUUID)
5933 {
5934 viewsToSendto.Add(p); // they see me
5935 }
5936 }
5937 } // where private end
5938
5939 else
5940 { // where public
5941 foreach (ScenePresence p in allpresences)
5942 {
5943 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5944 continue;
5945
5946 // those not on parcel dont see me
5947 if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
5948 {
5949 killsToSendto.Add(p); // they dont see me
5950 }
5951 }
5952 } // where public end
5953
5954 allpresences.Clear();
5955 }
5956 else
5957 {
5958 if (currentParcelHide)
5959 {
5960 // now on a private parcel
5961 allpresences = m_scene.GetScenePresences();
5962
5963 if (previusParcelHide && previusParcelID != UUID.Zero)
5964 {
5965 foreach (ScenePresence p in allpresences)
5966 {
5967 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5968 continue;
5969
5970 // only those on previus parcel need receive kills
5971 if (previusParcelID == p.currentParcelUUID)
5972 {
5973 if(p.GodLevel < 200)
5974 killsToSendto.Add(p); // they dont see me
5975 if(GodLevel < 200)
5976 killsToSendme.Add(p); // i dont see them
5977 }
5978 // only those on new parcel need see
5979 if (currentParcelID == p.currentParcelUUID)
5980 {
5981 viewsToSendto.Add(p); // they see me
5982 viewsToSendme.Add(p); // i see them
5983 }
5984 }
5985 }
5986 else
5987 {
5988 //was on a public area
5989 allpresences = m_scene.GetScenePresences();
5990
5991 foreach (ScenePresence p in allpresences)
5992 {
5993 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
5994 continue;
5995
5996 // those not on new parcel dont see me
5997 if (currentParcelID != p.currentParcelUUID && p.GodLevel < 200)
5998 {
5999 killsToSendto.Add(p); // they dont see me
6000 }
6001 else
6002 {
6003 viewsToSendme.Add(p); // i see those on it
6004 }
6005 }
6006 }
6007 allpresences.Clear();
6008 } // now on a private parcel end
6009
6010 else
6011 {
6012 // now on public parcel
6013 if (previusParcelHide && previusParcelID != UUID.Zero)
6014 {
6015 // was on private area
6016 allpresences = m_scene.GetScenePresences();
6017
6018 foreach (ScenePresence p in allpresences)
6019 {
6020 if (p.IsDeleted || p == this || p.ControllingClient == null || !p.ControllingClient.IsActive)
6021 continue;
6022 // only those old parcel need kills
6023 if (previusParcelID == p.currentParcelUUID && GodLevel < 200)
6024 {
6025 killsToSendme.Add(p); // i dont see them
6026 }
6027 else
6028 {
6029 viewsToSendto.Add(p); // they see me
6030 }
6031 }
6032 }
6033 else
6034 return; // was on a public area also
6035 } // now on public parcel end
6036 }
6037
6038 // send the things
6039
6040 if (killsToSendto.Count > 0)
6041 {
6042 foreach (ScenePresence p in killsToSendto)
6043 {
6044 m_log.Debug("[AVATAR]: killTo: " + Lastname + " " + p.Lastname);
6045 SendKillTo(p);
6046 }
6047 }
6048
6049 if (killsToSendme.Count > 0)
6050 {
6051 foreach (ScenePresence p in killsToSendme)
6052 {
6053 m_log.Debug("[AVATAR]: killToMe: " + Lastname + " " + p.Lastname);
6054 p.SendKillTo(this);
6055 }
6056 }
6057
6058 if (viewsToSendto.Count > 0)
6059 {
6060 foreach (ScenePresence p in viewsToSendto)
6061 {
6062 SendViewTo(p);
6063 }
6064 }
6065
6066 if (viewsToSendme.Count > 0 )
6067 {
6068 foreach (ScenePresence p in viewsToSendme)
6069 {
6070 if (p.IsChildAgent)
6071 continue;
6072// m_log.Debug("[AVATAR]: viewMe: " + Lastname + "<-" + p.Lastname);
6073 p.SendViewTo(this);
6074 }
6075 }
6076 }
6077
6078 public void HasMovedAway(bool nearRegion)
6079 {
6080
6081 if (nearRegion)
6082 {
6083 if (Scene.AttachmentsModule != null)
6084 Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
6085
6086 if (!ParcelHideThisAvatar || GodLevel >= 200)
6087 return;
6088
6089 List<ScenePresence> allpresences = m_scene.GetScenePresences();
6090 foreach (ScenePresence p in allpresences)
6091 {
6092 if (p.IsDeleted || p == this || p.IsChildAgent || p.ControllingClient == null || !p.ControllingClient.IsActive)
6093 continue;
6094
6095 if (p.currentParcelUUID == m_currentParcelUUID)
6096 {
6097 p.SendKillTo(this);
6098 }
6099 }
6100 }
6101 else
6102 {
6103 List<ScenePresence> allpresences = m_scene.GetScenePresences();
6104 foreach (ScenePresence p in allpresences)
6105 {
6106 if (p == this)
6107 continue;
6108 SendKillTo(p);
6109 if (!p.IsChildAgent)
6110 p.SendKillTo(this);
6111 }
6112
6113 if (Scene.AttachmentsModule != null)
6114 Scene.AttachmentsModule.DeleteAttachmentsFromScene(this, true);
6115 }
6116 }
6117
6118
6119// kill with attachs root kills
6120 public void SendKillTo(ScenePresence p)
6121 {
6122 List<uint> ids = new List<uint>(m_attachments.Count + 1);
6123 foreach (SceneObjectGroup sog in m_attachments)
6124 {
6125 ids.Add(sog.RootPart.LocalId);
6126 }
6127
6128 ids.Add(LocalId);
6129 p.ControllingClient.SendKillObject(ids);
6130 }
6131
6132/*
6133// kill with hack
6134 public void SendKillTo(ScenePresence p)
6135 {
6136 foreach (SceneObjectGroup sog in m_attachments)
6137 p.ControllingClient.SendPartFullUpdate(sog.RootPart, LocalId + 1);
6138 p.ControllingClient.SendKillObject(new List<uint> { LocalId });
6139 }
6140*/
6141 public void SendViewTo(ScenePresence p)
6142 {
6143 SendAvatarDataToAgentNF(p);
6144 SendAppearanceToAgent(p);
6145 if (Animator != null)
6146 Animator.SendAnimPackToClient(p.ControllingClient);
6147 SendAttachmentsToAgentNF(p);
6148 }
6149
6150 public void SetAnimationOverride(string animState, UUID animID)
6151 {
6152 Overrides.SetOverride(animState, animID);
6153// Animator.SendAnimPack();
6154 Animator.ForceUpdateMovementAnimations();
6155 }
6156
6157 public UUID GetAnimationOverride(string animState)
6158 {
6159 return Overrides.GetOverriddenAnimation(animState);
6160 }
5122 } 6161 }
5123} 6162}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 4caa9cb..7d3a168 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -278,7 +278,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
278 // Script state may, or may not, exist. Not having any, is NOT 278 // Script state may, or may not, exist. Not having any, is NOT
279 // ever a problem. 279 // ever a problem.
280 sceneObject.LoadScriptState(doc); 280 sceneObject.LoadScriptState(doc);
281 281
282 return sceneObject; 282 return sceneObject;
283 } 283 }
284 catch (Exception e) 284 catch (Exception e)
@@ -307,14 +307,13 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
307 } 307 }
308 } 308 }
309 309
310
311 /// <summary> 310 /// <summary>
312 /// Modifies a SceneObjectGroup. 311 /// Modifies a SceneObjectGroup.
313 /// </summary> 312 /// </summary>
314 /// <param name="sog">The object</param> 313 /// <param name="sog">The object</param>
315 /// <returns>Whether the object was actually modified</returns> 314 /// <returns>Whether the object was actually modified</returns>
316 public delegate bool SceneObjectModifier(SceneObjectGroup sog); 315 public delegate bool SceneObjectModifier(SceneObjectGroup sog);
317 316
318 /// <summary> 317 /// <summary>
319 /// Modifies an object by deserializing it; applying 'modifier' to each SceneObjectGroup; and reserializing. 318 /// Modifies an object by deserializing it; applying 'modifier' to each SceneObjectGroup; and reserializing.
320 /// </summary> 319 /// </summary>
@@ -328,7 +327,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
328 CoalescedSceneObjects coa = null; 327 CoalescedSceneObjects coa = null;
329 328
330 string xmlData = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(data)); 329 string xmlData = ExternalRepresentationUtils.SanitizeXml(Utils.BytesToString(data));
331
332 if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa)) 330 if (CoalescedSceneObjectsSerializer.TryFromXml(xmlData, out coa))
333 { 331 {
334 // m_log.DebugFormat("[SERIALIZER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count); 332 // m_log.DebugFormat("[SERIALIZER]: Loaded coalescence {0} has {1} objects", assetId, coa.Count);
@@ -374,7 +372,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
374 return data; 372 return data;
375 } 373 }
376 374
377
378 #region manual serialization 375 #region manual serialization
379 376
380 private static Dictionary<string, Action<SceneObjectPart, XmlReader>> m_SOPXmlProcessors 377 private static Dictionary<string, Action<SceneObjectPart, XmlReader>> m_SOPXmlProcessors
@@ -450,11 +447,28 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
450 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 447 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
451 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 448 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
452 449
450 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
451 m_SOPXmlProcessors.Add("Force", ProcessForce);
452 m_SOPXmlProcessors.Add("Torque", ProcessTorque);
453 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive);
454
455
456 m_SOPXmlProcessors.Add("Vehicle", ProcessVehicle);
457
458 m_SOPXmlProcessors.Add("RotationAxisLocks", ProcessRotationAxisLocks);
453 m_SOPXmlProcessors.Add("PhysicsShapeType", ProcessPhysicsShapeType); 459 m_SOPXmlProcessors.Add("PhysicsShapeType", ProcessPhysicsShapeType);
454 m_SOPXmlProcessors.Add("Density", ProcessDensity); 460 m_SOPXmlProcessors.Add("Density", ProcessDensity);
455 m_SOPXmlProcessors.Add("Friction", ProcessFriction); 461 m_SOPXmlProcessors.Add("Friction", ProcessFriction);
456 m_SOPXmlProcessors.Add("Bounce", ProcessBounce); 462 m_SOPXmlProcessors.Add("Bounce", ProcessBounce);
457 m_SOPXmlProcessors.Add("GravityModifier", ProcessGravityModifier); 463 m_SOPXmlProcessors.Add("GravityModifier", ProcessGravityModifier);
464 m_SOPXmlProcessors.Add("CameraEyeOffset", ProcessCameraEyeOffset);
465 m_SOPXmlProcessors.Add("CameraAtOffset", ProcessCameraAtOffset);
466
467 m_SOPXmlProcessors.Add("SoundID", ProcessSoundID);
468 m_SOPXmlProcessors.Add("SoundGain", ProcessSoundGain);
469 m_SOPXmlProcessors.Add("SoundFlags", ProcessSoundFlags);
470 m_SOPXmlProcessors.Add("SoundRadius", ProcessSoundRadius);
471 m_SOPXmlProcessors.Add("SoundQueueing", ProcessSoundQueueing);
458 472
459 #endregion 473 #endregion
460 474
@@ -483,7 +497,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
483 m_TaskInventoryXmlProcessors.Add("PermsMask", ProcessTIPermsMask); 497 m_TaskInventoryXmlProcessors.Add("PermsMask", ProcessTIPermsMask);
484 m_TaskInventoryXmlProcessors.Add("Type", ProcessTIType); 498 m_TaskInventoryXmlProcessors.Add("Type", ProcessTIType);
485 m_TaskInventoryXmlProcessors.Add("OwnerChanged", ProcessTIOwnerChanged); 499 m_TaskInventoryXmlProcessors.Add("OwnerChanged", ProcessTIOwnerChanged);
486 500
487 #endregion 501 #endregion
488 502
489 #region ShapeXmlProcessors initialization 503 #region ShapeXmlProcessors initialization
@@ -684,6 +698,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
684 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty); 698 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty);
685 } 699 }
686 700
701 private static void ProcessRotationAxisLocks(SceneObjectPart obj, XmlReader reader)
702 {
703 obj.RotationAxisLocks = (byte)reader.ReadElementContentAsInt("RotationAxisLocks", String.Empty);
704 }
705
687 private static void ProcessPhysicsShapeType(SceneObjectPart obj, XmlReader reader) 706 private static void ProcessPhysicsShapeType(SceneObjectPart obj, XmlReader reader)
688 { 707 {
689 obj.PhysicsShapeType = (byte)reader.ReadElementContentAsInt("PhysicsShapeType", String.Empty); 708 obj.PhysicsShapeType = (byte)reader.ReadElementContentAsInt("PhysicsShapeType", String.Empty);
@@ -709,6 +728,58 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
709 obj.GravityModifier = reader.ReadElementContentAsFloat("GravityModifier", String.Empty); 728 obj.GravityModifier = reader.ReadElementContentAsFloat("GravityModifier", String.Empty);
710 } 729 }
711 730
731 private static void ProcessCameraEyeOffset(SceneObjectPart obj, XmlReader reader)
732 {
733 obj.SetCameraEyeOffset(Util.ReadVector(reader, "CameraEyeOffset"));
734 }
735
736 private static void ProcessCameraAtOffset(SceneObjectPart obj, XmlReader reader)
737 {
738 obj.SetCameraAtOffset(Util.ReadVector(reader, "CameraAtOffset"));
739 }
740
741 private static void ProcessSoundID(SceneObjectPart obj, XmlReader reader)
742 {
743 obj.Sound = Util.ReadUUID(reader, "SoundID");
744 }
745
746 private static void ProcessSoundGain(SceneObjectPart obj, XmlReader reader)
747 {
748 obj.SoundGain = reader.ReadElementContentAsDouble("SoundGain", String.Empty);
749 }
750
751 private static void ProcessSoundFlags(SceneObjectPart obj, XmlReader reader)
752 {
753 obj.SoundFlags = (byte)reader.ReadElementContentAsInt("SoundFlags", String.Empty);
754 }
755
756 private static void ProcessSoundRadius(SceneObjectPart obj, XmlReader reader)
757 {
758 obj.SoundRadius = reader.ReadElementContentAsDouble("SoundRadius", String.Empty);
759 }
760
761 private static void ProcessSoundQueueing(SceneObjectPart obj, XmlReader reader)
762 {
763 obj.SoundQueueing = Util.ReadBoolean(reader);
764 }
765
766 private static void ProcessVehicle(SceneObjectPart obj, XmlReader reader)
767 {
768 SOPVehicle vehicle = SOPVehicle.FromXml2(reader);
769
770 if (vehicle == null)
771 {
772 obj.VehicleParams = null;
773 m_log.DebugFormat(
774 "[SceneObjectSerializer]: Parsing Vehicle for object part {0} {1} encountered errors. Please see earlier log entries.",
775 obj.Name, obj.UUID);
776 }
777 else
778 {
779 obj.VehicleParams = vehicle;
780 }
781 }
782
712 private static void ProcessShape(SceneObjectPart obj, XmlReader reader) 783 private static void ProcessShape(SceneObjectPart obj, XmlReader reader)
713 { 784 {
714 List<string> errorNodeNames; 785 List<string> errorNodeNames;
@@ -883,6 +954,25 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
883 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 954 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
884 } 955 }
885 956
957 private static void ProcessBuoyancy(SceneObjectPart obj, XmlReader reader)
958 {
959 obj.Buoyancy = (float)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
960 }
961
962 private static void ProcessForce(SceneObjectPart obj, XmlReader reader)
963 {
964 obj.Force = Util.ReadVector(reader, "Force");
965 }
966 private static void ProcessTorque(SceneObjectPart obj, XmlReader reader)
967 {
968 obj.Torque = Util.ReadVector(reader, "Torque");
969 }
970
971 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlReader reader)
972 {
973 obj.VolumeDetectActive = Util.ReadBoolean(reader);
974 }
975
886 #endregion 976 #endregion
887 977
888 #region TaskInventoryXmlProcessors 978 #region TaskInventoryXmlProcessors
@@ -1271,12 +1361,13 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1271 1361
1272 if (sog.RootPart.KeyframeMotion != null) 1362 if (sog.RootPart.KeyframeMotion != null)
1273 { 1363 {
1274 Byte[] data = sog.RootPart.KeyframeMotion.Serialize(); 1364 Byte[] data = sog.RootPart.KeyframeMotion.Serialize();
1275 1365
1276 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty); 1366 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty);
1277 writer.WriteBase64(data, 0, data.Length); 1367 writer.WriteBase64(data, 0, data.Length);
1278 writer.WriteEndElement(); 1368 writer.WriteEndElement();
1279 } 1369 }
1370
1280 1371
1281 writer.WriteEndElement(); 1372 writer.WriteEndElement();
1282 } 1373 }
@@ -1388,8 +1479,19 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1388 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1479 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1389 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1480 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1390 1481
1391 if(sop.PhysicsShapeType != sop.DefaultPhysicsShapeType()) 1482 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1392 writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower()); 1483
1484 WriteVector(writer, "Force", sop.Force);
1485 WriteVector(writer, "Torque", sop.Torque);
1486
1487 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1488
1489 if (sop.VehicleParams != null)
1490 sop.VehicleParams.ToXml2(writer);
1491
1492 if(sop.RotationAxisLocks != 0)
1493 writer.WriteElementString("RotationAxisLocks", sop.RotationAxisLocks.ToString().ToLower());
1494 writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower());
1393 if (sop.Density != 1000.0f) 1495 if (sop.Density != 1000.0f)
1394 writer.WriteElementString("Density", sop.Density.ToString().ToLower()); 1496 writer.WriteElementString("Density", sop.Density.ToString().ToLower());
1395 if (sop.Friction != 0.6f) 1497 if (sop.Friction != 0.6f)
@@ -1398,7 +1500,18 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1398 writer.WriteElementString("Bounce", sop.Restitution.ToString().ToLower()); 1500 writer.WriteElementString("Bounce", sop.Restitution.ToString().ToLower());
1399 if (sop.GravityModifier != 1.0f) 1501 if (sop.GravityModifier != 1.0f)
1400 writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower()); 1502 writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower());
1503 WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset());
1504 WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset());
1401 1505
1506 // if (sop.Sound != UUID.Zero) force it till sop crossing does clear it on child prim
1507 {
1508 WriteUUID(writer, "SoundID", sop.Sound, options);
1509 writer.WriteElementString("SoundGain", sop.SoundGain.ToString().ToLower());
1510 writer.WriteElementString("SoundFlags", sop.SoundFlags.ToString().ToLower());
1511 writer.WriteElementString("SoundRadius", sop.SoundRadius.ToString().ToLower());
1512 }
1513 writer.WriteElementString("SoundQueueing", sop.SoundQueueing.ToString().ToLower());
1514
1402 writer.WriteEndElement(); 1515 writer.WriteEndElement();
1403 } 1516 }
1404 1517
@@ -1625,12 +1738,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1625 { 1738 {
1626 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1739 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1627 1740
1628 if (reader.IsEmptyElement)
1629 {
1630 reader.Read();
1631 return tinv;
1632 }
1633
1634 reader.ReadStartElement(name, String.Empty); 1741 reader.ReadStartElement(name, String.Empty);
1635 1742
1636 while (reader.Name == "TaskInventoryItem") 1743 while (reader.Name == "TaskInventoryItem")
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 3effee7..c8f525e 100755
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Timers; 30using System.Timers;
31using System.Threading;
31using OpenMetaverse.Packets; 32using OpenMetaverse.Packets;
32using OpenSim.Framework; 33using OpenSim.Framework;
33using OpenSim.Framework.Monitoring; 34using OpenSim.Framework.Monitoring;
@@ -62,8 +63,10 @@ namespace OpenSim.Region.Framework.Scenes
62 private YourStatsAreWrong handlerStatsIncorrect; 63 private YourStatsAreWrong handlerStatsIncorrect;
63 64
64 // Determines the size of the array that is used to collect StatBlocks 65 // Determines the size of the array that is used to collect StatBlocks
65 // for sending to the SimStats and SimExtraStatsCollector 66 // for sending viewer compatible stats must be conform with sb array filling below
66 private const int m_statisticArraySize = 28; 67 private const int m_statisticViewerArraySize = 38;
68 // size of LastReportedSimFPS with extra stats.
69 private const int m_statisticExtraArraySize = (int)(Stats.SimExtraCountEnd - Stats.SimExtraCountStart);
67 70
68 /// <summary> 71 /// <summary>
69 /// These are the IDs of stats sent in the StatsPacket to the viewer. 72 /// These are the IDs of stats sent in the StatsPacket to the viewer.
@@ -74,6 +77,7 @@ namespace OpenSim.Region.Framework.Scenes
74 /// </remarks> 77 /// </remarks>
75 public enum Stats : uint 78 public enum Stats : uint
76 { 79 {
80// viewers defined IDs
77 TimeDilation = 0, 81 TimeDilation = 0,
78 SimFPS = 1, 82 SimFPS = 1,
79 PhysicsFPS = 2, 83 PhysicsFPS = 2,
@@ -90,7 +94,7 @@ namespace OpenSim.Region.Framework.Scenes
90 Agents = 13, 94 Agents = 13,
91 ChildAgents = 14, 95 ChildAgents = 14,
92 ActiveScripts = 15, 96 ActiveScripts = 15,
93 ScriptLinesPerSecond = 16, 97 LSLScriptLinesPerSecond = 16, // viewers don't like this anymore
94 InPacketsPerSecond = 17, 98 InPacketsPerSecond = 17,
95 OutPacketsPerSecond = 18, 99 OutPacketsPerSecond = 18,
96 PendingDownloads = 19, 100 PendingDownloads = 19,
@@ -109,11 +113,24 @@ namespace OpenSim.Region.Framework.Scenes
109 SimSpareMs = 32, 113 SimSpareMs = 32,
110 SimSleepMs = 33, 114 SimSleepMs = 33,
111 SimIoPumpTime = 34, 115 SimIoPumpTime = 34,
112 FrameDilation = 35, 116 SimPCTSscriptsRun = 35,
113 UsersLoggingIn = 36, 117 SimRegionIdle = 36, // dataserver only
114 TotalGeoPrim = 37, 118 SimRegionIdlePossible = 37, // dataserver only
115 TotalMesh = 38, 119 SimAIStepTimeMS = 38,
116 ThreadCount = 39 120 SimSkippedSillouet_PS = 39,
121 SimSkippedCharsPerC = 40,
122
123// extra stats IDs irrelevant, just far from viewer defined ones
124 SimExtraCountStart = 1000,
125
126 internalLSLScriptLinesPerSecond = 1000,
127 FrameDilation2 = 1001,
128 UsersLoggingIn = 1002,
129 TotalGeoPrim = 1003,
130 TotalMesh = 1004,
131 ThreadCount = 1005,
132
133 SimExtraCountEnd = 1006
117 } 134 }
118 135
119 /// <summary> 136 /// <summary>
@@ -158,19 +175,14 @@ namespace OpenSim.Region.Framework.Scenes
158 175
159 // Sending a stats update every 3 seconds- 176 // Sending a stats update every 3 seconds-
160 private int m_statsUpdatesEveryMS = 3000; 177 private int m_statsUpdatesEveryMS = 3000;
161 private float m_statsUpdateFactor; 178 private double m_lastUpdateTS;
179 private double m_prevFrameStatsTS;
180 private double m_FrameStatsTS;
162 private float m_timeDilation; 181 private float m_timeDilation;
163 private int m_fps; 182 private int m_fps;
164 183
165 /// <summary> 184 private object m_statsLock = new object();
166 /// Number of the last frame on which we processed a stats udpate. 185 private object m_statsFrameLock = new object();
167 /// </summary>
168 private uint m_lastUpdateFrame;
169
170 /// <summary>
171 /// Our nominal fps target, as expected in fps stats when a sim is running normally.
172 /// </summary>
173 private float m_nominalReportedFps = 55;
174 186
175 /// <summary> 187 /// <summary>
176 /// Parameter to adjust reported scene fps 188 /// Parameter to adjust reported scene fps
@@ -186,10 +198,10 @@ namespace OpenSim.Region.Framework.Scenes
186 /// corresponding, with default heartbeat rate, to a value of 5. 198 /// corresponding, with default heartbeat rate, to a value of 5.
187 /// </remarks> 199 /// </remarks>
188 private float m_statisticsFPSfactor = 5.0f; 200 private float m_statisticsFPSfactor = 5.0f;
189 201 private float m_targetFrameTime = 0.1f;
190 // saved last reported value so there is something available for llGetRegionFPS 202 // saved last reported value so there is something available for llGetRegionFPS
191 private float lastReportedSimFPS; 203 private float lastReportedSimFPS;
192 private float[] lastReportedSimStats = new float[m_statisticArraySize]; 204 private float[] lastReportedSimStats = new float[m_statisticExtraArraySize + m_statisticViewerArraySize];
193 private float m_pfps; 205 private float m_pfps;
194 206
195 /// <summary> 207 /// <summary>
@@ -202,14 +214,15 @@ namespace OpenSim.Region.Framework.Scenes
202 /// </summary> 214 /// </summary>
203 private int m_objectUpdates; 215 private int m_objectUpdates;
204 216
205 private int m_frameMS; 217 private float m_frameMS;
206 private int m_spareMS; 218
207 private int m_netMS; 219 private float m_netMS;
208 private int m_agentMS; 220 private float m_agentMS;
209 private int m_physicsMS; 221 private float m_physicsMS;
210 private int m_imageMS; 222 private float m_imageMS;
211 private int m_otherMS; 223 private float m_otherMS;
212 private int m_scriptMS; 224 private float m_sleeptimeMS;
225 private float m_scriptTimeMS;
213 226
214 private int m_rootAgents; 227 private int m_rootAgents;
215 private int m_childAgents; 228 private int m_childAgents;
@@ -224,31 +237,11 @@ namespace OpenSim.Region.Framework.Scenes
224 private int m_pendingUploads = 0; // FIXME: Not currently filled in 237 private int m_pendingUploads = 0; // FIXME: Not currently filled in
225 private int m_activeScripts; 238 private int m_activeScripts;
226 private int m_scriptLinesPerSecond; 239 private int m_scriptLinesPerSecond;
240 private int m_scriptEventsPerSecond;
227 241
228 private int m_objectCapacity = 45000; 242 private int m_objectCapacity = 45000;
229 243
230 // This is the number of frames that will be stored and then averaged for 244 // The current number of users attempting to login to the region
231 // the Total, Simulation, Physics, and Network Frame Time; It is set to
232 // 10 by default but can be changed by the OpenSim.ini configuration file
233 // NumberOfFrames parameter
234 private int m_numberFramesStored;
235
236 // The arrays that will hold the time it took to run the past N frames,
237 // where N is the num_frames_to_average given by the configuration file
238 private double[] m_totalFrameTimeMilliseconds;
239 private double[] m_simulationFrameTimeMilliseconds;
240 private double[] m_physicsFrameTimeMilliseconds;
241 private double[] m_networkFrameTimeMilliseconds;
242
243 // The location of the next time in milliseconds that will be
244 // (over)written when the next frame completes
245 private int m_nextLocation = 0;
246
247 // The correct number of frames that have completed since the last stats
248 // update for physics
249 private int m_numberPhysicsFrames;
250
251 // The current number of users attempting to login to the region
252 private int m_usersLoggingIn; 245 private int m_usersLoggingIn;
253 246
254 // The last reported value of threads from the SmartThreadPool inside of 247 // The last reported value of threads from the SmartThreadPool inside of
@@ -259,51 +252,39 @@ namespace OpenSim.Region.Framework.Scenes
259 252
260 private RegionInfo ReportingRegion; 253 private RegionInfo ReportingRegion;
261 254
262 private Timer m_report = new Timer(); 255 private System.Timers.Timer m_report = new System.Timers.Timer();
263 256
264 private IEstateModule estateModule; 257 private IEstateModule estateModule;
265 258
266 public SimStatsReporter(Scene scene) 259 public SimStatsReporter(Scene scene)
267 : this(scene, Scene.m_defaultNumberFramesStored)
268 {
269 }
270
271 public SimStatsReporter(Scene scene, int numberOfFrames)
272 { 260 {
273 // Store the number of frames from the OpenSim.ini configuration file
274 m_numberFramesStored = numberOfFrames;
275
276 // Initialize the different frame time arrays to the correct sizes
277 m_totalFrameTimeMilliseconds = new double[m_numberFramesStored];
278 m_simulationFrameTimeMilliseconds = new double[m_numberFramesStored];
279 m_physicsFrameTimeMilliseconds = new double[m_numberFramesStored];
280 m_networkFrameTimeMilliseconds = new double[m_numberFramesStored];
281
282 // Initialize the current number of users logging into the region
283 m_usersLoggingIn = 0;
284
285 m_scene = scene; 261 m_scene = scene;
286 262
287 m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000);
288 ReportingRegion = scene.RegionInfo; 263 ReportingRegion = scene.RegionInfo;
289 264
290 if(scene.Normalized55FPS) 265 if(scene.Normalized55FPS)
291 m_statisticsFPSfactor = 55.0f * m_scene.MinFrameTicks / 1000.0f; 266 m_statisticsFPSfactor = 55.0f * m_scene.FrameTime;
292 else 267 else
293 m_statisticsFPSfactor = 1.0f; 268 m_statisticsFPSfactor = 1.0f;
294 269
270 m_targetFrameTime = 1000.0f * m_scene.FrameTime / m_statisticsFPSfactor;
271
295 m_objectCapacity = scene.RegionInfo.ObjectCapacity; 272 m_objectCapacity = scene.RegionInfo.ObjectCapacity;
296 m_report.AutoReset = true; 273 m_report.AutoReset = true;
297 m_report.Interval = m_statsUpdatesEveryMS; 274 m_report.Interval = m_statsUpdatesEveryMS;
298 m_report.Elapsed += TriggerStatsHeartbeat; 275 m_report.Elapsed += TriggerStatsHeartbeat;
299 m_report.Enabled = true; 276 m_report.Enabled = true;
300 277
278 m_lastUpdateTS = Util.GetTimeStampMS();
279 m_FrameStatsTS = m_lastUpdateTS;
280 m_prevFrameStatsTS = m_lastUpdateTS;
281
301 if (StatsManager.SimExtraStats != null) 282 if (StatsManager.SimExtraStats != null)
302 OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; 283 OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket;
303 284
304 /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit 285 /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit
305 /// longer than ideal (which in itself is a concern). 286 /// longer than ideal (which in itself is a concern).
306 SlowFramesStatReportThreshold = (int)Math.Ceiling(scene.MinFrameTicks * 1.2); 287 SlowFramesStatReportThreshold = (int)Math.Ceiling(m_scene.FrameTime * 1000 * 1.2);
307 288
308 SlowFramesStat 289 SlowFramesStat
309 = new Stat( 290 = new Stat(
@@ -318,7 +299,6 @@ namespace OpenSim.Region.Framework.Scenes
318 StatVerbosity.Info); 299 StatVerbosity.Info);
319 300
320 StatsManager.RegisterStat(SlowFramesStat); 301 StatsManager.RegisterStat(SlowFramesStat);
321
322 } 302 }
323 303
324 304
@@ -335,7 +315,6 @@ namespace OpenSim.Region.Framework.Scenes
335 public void SetUpdateMS(int ms) 315 public void SetUpdateMS(int ms)
336 { 316 {
337 m_statsUpdatesEveryMS = ms; 317 m_statsUpdatesEveryMS = ms;
338 m_statsUpdateFactor = (float)(m_statsUpdatesEveryMS / 1000);
339 m_report.Interval = m_statsUpdatesEveryMS; 318 m_report.Interval = m_statsUpdatesEveryMS;
340 } 319 }
341 320
@@ -355,29 +334,20 @@ namespace OpenSim.Region.Framework.Scenes
355 334
356 private void statsHeartBeat(object sender, EventArgs e) 335 private void statsHeartBeat(object sender, EventArgs e)
357 { 336 {
358 double totalSumFrameTime; 337 if (!m_scene.Active)
359 double simulationSumFrameTime;
360 double physicsSumFrameTime;
361 double networkSumFrameTime;
362 float frameDilation;
363 int currentFrame;
364
365 if (!m_scene.Active)
366 return; 338 return;
367
368 // Create arrays to hold the statistics for this current scene,
369 // these will be passed to the SimExtraStatsCollector, they are also
370 // sent to the SimStats class
371 SimStatsPacket.StatBlock[] sb = new
372 SimStatsPacket.StatBlock[m_statisticArraySize];
373 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
374 339
375 // Know what's not thread safe in Mono... modifying timers. 340 // dont do it if if still been done
376 // m_log.Debug("Firing Stats Heart Beat"); 341
377 lock (m_report) 342 if(Monitor.TryEnter(m_statsLock))
378 { 343 {
344 // m_log.Debug("Firing Stats Heart Beat");
345
346 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[m_statisticViewerArraySize];
347 SimStatsPacket.StatBlock[] sbex = new SimStatsPacket.StatBlock[m_statisticExtraArraySize];
348 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
379 uint regionFlags = 0; 349 uint regionFlags = 0;
380 350
381 try 351 try
382 { 352 {
383 if (estateModule == null) 353 if (estateModule == null)
@@ -390,22 +360,93 @@ namespace OpenSim.Region.Framework.Scenes
390 } 360 }
391 361
392#region various statistic googly moogly 362#region various statistic googly moogly
363 double timeTmp = m_lastUpdateTS;
364 m_lastUpdateTS = Util.GetTimeStampMS();
365 float updateElapsed = (float)((m_lastUpdateTS - timeTmp)/1000.0);
366
367 // factor to consider updates integration time
368 float updateTimeFactor = 1.0f / updateElapsed;
369
370
371 // scene frame stats
372 float reportedFPS;
373 float physfps;
374 float timeDilation;
375 float agentMS;
376 float physicsMS;
377 float otherMS;
378 float sleeptime;
379 float scriptTimeMS;
380 float totalFrameTime;
381
382 float invFrameElapsed;
383
384 // get a copy under lock and reset
385 lock(m_statsFrameLock)
386 {
387 timeDilation = m_timeDilation;
388 reportedFPS = m_fps;
389 physfps = m_pfps;
390 agentMS = m_agentMS;
391 physicsMS = m_physicsMS;
392 otherMS = m_otherMS;
393 sleeptime = m_sleeptimeMS;
394 scriptTimeMS = m_scriptTimeMS;
395 totalFrameTime = m_frameMS;
396 // still not inv
397 invFrameElapsed = (float)((m_FrameStatsTS - m_prevFrameStatsTS) / 1000.0);
398
399 ResetFrameStats();
400 }
401
402 if (invFrameElapsed / updateElapsed < 0.8)
403 // scene is in trouble, its account of time is most likely wrong
404 // can even be in stall
405 invFrameElapsed = updateTimeFactor;
406 else
407 invFrameElapsed = 1.0f / invFrameElapsed;
408
409 float perframefactor;
410 if (reportedFPS <= 0)
411 {
412 reportedFPS = 0.0f;
413 physfps = 0.0f;
414 perframefactor = 1.0f;
415 timeDilation = 0.0f;
416 }
417 else
418 {
419 timeDilation /= reportedFPS;
420 reportedFPS *= m_statisticsFPSfactor;
421 perframefactor = 1.0f / (float)reportedFPS;
422 reportedFPS *= invFrameElapsed;
423 physfps *= invFrameElapsed * m_statisticsFPSfactor;
424 }
393 425
394 int reportedFPS = (int)(m_fps * m_statisticsFPSfactor); 426 // some engines track frame time with error related to the simulation step size
427 if(physfps > reportedFPS)
428 physfps = reportedFPS;
395 429
396 // save the reported value so there is something available for llGetRegionFPS 430 // save the reported value so there is something available for llGetRegionFPS
397 lastReportedSimFPS = reportedFPS / m_statsUpdateFactor; 431 lastReportedSimFPS = reportedFPS;
398 432
399 // ORIGINAL code commented out until we have time to add our own 433 // scale frame stats
400 // statistics to the statistics window
401 //float physfps = ((m_pfps / 1000));
402 float physfps = m_numberPhysicsFrames * m_statisticsFPSfactor;
403 434
404 //if (physfps > 600) 435 totalFrameTime *= perframefactor;
405 //physfps = physfps - (physfps - 600); 436 sleeptime *= perframefactor;
437 otherMS *= perframefactor;
438 physicsMS *= perframefactor;
439 agentMS *= perframefactor;
440 scriptTimeMS *= perframefactor;
406 441
407 if (physfps < 0) 442 // estimate spare time
408 physfps = 0; 443 float sparetime;
444 sparetime = m_targetFrameTime - (physicsMS + agentMS + otherMS);
445
446 if (sparetime < 0)
447 sparetime = 0;
448 else if (sparetime > totalFrameTime)
449 sparetime = totalFrameTime;
409 450
410#endregion 451#endregion
411 452
@@ -416,79 +457,28 @@ namespace OpenSim.Region.Framework.Scenes
416 m_numMesh = m_scene.SceneGraph.GetTotalMeshObjectsCount(); 457 m_numMesh = m_scene.SceneGraph.GetTotalMeshObjectsCount();
417 m_activePrim = m_scene.SceneGraph.GetActiveObjectsCount(); 458 m_activePrim = m_scene.SceneGraph.GetActiveObjectsCount();
418 m_activeScripts = m_scene.SceneGraph.GetActiveScriptsCount(); 459 m_activeScripts = m_scene.SceneGraph.GetActiveScriptsCount();
460 m_scriptLinesPerSecond = m_scene.SceneGraph.GetScriptLPS();
419 461
420 // FIXME: Checking for stat sanity is a complex approach. What we really need to do is fix the code 462 // FIXME: Checking for stat sanity is a complex approach. What we really need to do is fix the code
421 // so that stat numbers are always consistent. 463 // so that stat numbers are always consistent.
422 CheckStatSanity(); 464 CheckStatSanity();
423 465
424 //Our time dilation is 0.91 when we're running a full speed, 466 for (int i = 0; i < m_statisticViewerArraySize; i++)
425 // therefore to make sure we get an appropriate range,
426 // we have to factor in our error. (0.10f * statsUpdateFactor)
427 // multiplies the fix for the error times the amount of times it'll occur a second
428 // / 10 divides the value by the number of times the sim heartbeat runs (10fps)
429 // Then we divide the whole amount by the amount of seconds pass in between stats updates.
430
431 // 'statsUpdateFactor' is how often stats packets are sent in seconds. Used below to change
432 // values to X-per-second values.
433
434 uint thisFrame = m_scene.Frame;
435 uint numFrames = thisFrame - m_lastUpdateFrame;
436 float framesUpdated = (float)numFrames * m_statisticsFPSfactor;
437 m_lastUpdateFrame = thisFrame;
438
439 // Avoid div-by-zero if somehow we've not updated any frames.
440 if (framesUpdated == 0)
441 framesUpdated = 1;
442
443 for (int i = 0; i < m_statisticArraySize; i++)
444 { 467 {
445 sb[i] = new SimStatsPacket.StatBlock(); 468 sb[i] = new SimStatsPacket.StatBlock();
446 } 469 }
447 470
448 // Resetting the sums of the frame times to prevent any errors
449 // in calculating the moving average for frame time
450 totalSumFrameTime = 0;
451 simulationSumFrameTime = 0;
452 physicsSumFrameTime = 0;
453 networkSumFrameTime = 0;
454
455 // Loop through all the frames that were stored for the current
456 // heartbeat to process the moving average of frame times
457 for (int i = 0; i < m_numberFramesStored; i++)
458 {
459 // Sum up each frame time in order to calculate the moving
460 // average of frame time
461 totalSumFrameTime += m_totalFrameTimeMilliseconds[i];
462 simulationSumFrameTime +=
463 m_simulationFrameTimeMilliseconds[i];
464 physicsSumFrameTime += m_physicsFrameTimeMilliseconds[i];
465 networkSumFrameTime += m_networkFrameTimeMilliseconds[i];
466 }
467
468 // Get the index that represents the current frame based on the next one known; go back
469 // to the last index if next one is stated to restart at 0
470 if (m_nextLocation == 0)
471 currentFrame = m_numberFramesStored - 1;
472 else
473 currentFrame = m_nextLocation - 1;
474
475 // Calculate the frame dilation; which is currently based on the ratio between the sum of the
476 // physics and simulation rate, and the set minimum time to run a scene's frame
477 frameDilation = (float)(m_simulationFrameTimeMilliseconds[currentFrame] +
478 m_physicsFrameTimeMilliseconds[currentFrame]) / m_scene.MinFrameTicks;
479
480 // ORIGINAL code commented out until we have time to add our own
481 sb[0].StatID = (uint) Stats.TimeDilation; 471 sb[0].StatID = (uint) Stats.TimeDilation;
482 sb[0].StatValue = (Single.IsNaN(m_timeDilation)) ? 0.1f : m_timeDilation ; //((((m_timeDilation + (0.10f * statsUpdateFactor)) /10) / statsUpdateFactor)); 472 sb[0].StatValue = (Single.IsNaN(timeDilation)) ? 0.0f : (float)Math.Round(timeDilation,3);
483 473
484 sb[1].StatID = (uint) Stats.SimFPS; 474 sb[1].StatID = (uint) Stats.SimFPS;
485 sb[1].StatValue = reportedFPS / m_statsUpdateFactor; 475 sb[1].StatValue = (float)Math.Round(reportedFPS,1);;
486 476
487 sb[2].StatID = (uint) Stats.PhysicsFPS; 477 sb[2].StatID = (uint) Stats.PhysicsFPS;
488 sb[2].StatValue = physfps / m_statsUpdateFactor; 478 sb[2].StatValue = (float)Math.Round(physfps,1);
489 479
490 sb[3].StatID = (uint) Stats.AgentUpdates; 480 sb[3].StatID = (uint) Stats.AgentUpdates;
491 sb[3].StatValue = (m_agentUpdates / m_statsUpdateFactor); 481 sb[3].StatValue = m_agentUpdates * updateTimeFactor;
492 482
493 sb[4].StatID = (uint) Stats.Agents; 483 sb[4].StatID = (uint) Stats.Agents;
494 sb[4].StatValue = m_rootAgents; 484 sb[4].StatValue = m_rootAgents;
@@ -502,38 +492,32 @@ namespace OpenSim.Region.Framework.Scenes
502 sb[7].StatID = (uint) Stats.ActivePrim; 492 sb[7].StatID = (uint) Stats.ActivePrim;
503 sb[7].StatValue = m_activePrim; 493 sb[7].StatValue = m_activePrim;
504 494
505 // ORIGINAL code commented out until we have time to add our own
506 // statistics to the statistics window
507 sb[8].StatID = (uint)Stats.FrameMS; 495 sb[8].StatID = (uint)Stats.FrameMS;
508 //sb[8].StatValue = m_frameMS / framesUpdated; 496 sb[8].StatValue = totalFrameTime;
509 sb[8].StatValue = (float) totalSumFrameTime / m_numberFramesStored / m_statisticsFPSfactor;
510 497
511 sb[9].StatID = (uint)Stats.NetMS; 498 sb[9].StatID = (uint)Stats.NetMS;
512 //sb[9].StatValue = m_netMS / framesUpdated; 499 sb[9].StatValue = m_netMS * perframefactor;
513 sb[9].StatValue = (float) networkSumFrameTime / m_numberFramesStored / m_statisticsFPSfactor;
514 500
515 sb[10].StatID = (uint)Stats.PhysicsMS; 501 sb[10].StatID = (uint)Stats.PhysicsMS;
516 //sb[10].StatValue = m_physicsMS / framesUpdated; 502 sb[10].StatValue = physicsMS;
517 sb[10].StatValue = (float) physicsSumFrameTime / m_numberFramesStored / m_statisticsFPSfactor;
518 503
519 sb[11].StatID = (uint)Stats.ImageMS ; 504 sb[11].StatID = (uint)Stats.ImageMS ;
520 sb[11].StatValue = m_imageMS / framesUpdated; 505 sb[11].StatValue = m_imageMS * perframefactor;
521 506
522 sb[12].StatID = (uint)Stats.OtherMS; 507 sb[12].StatID = (uint)Stats.OtherMS;
523 //sb[12].StatValue = m_otherMS / framesUpdated; 508 sb[12].StatValue = otherMS;
524 sb[12].StatValue = (float) simulationSumFrameTime / m_numberFramesStored / m_statisticsFPSfactor;
525 509
526 sb[13].StatID = (uint)Stats.InPacketsPerSecond; 510 sb[13].StatID = (uint)Stats.InPacketsPerSecond;
527 sb[13].StatValue = (m_inPacketsPerSecond / m_statsUpdateFactor); 511 sb[13].StatValue = (float)Math.Round(m_inPacketsPerSecond * updateTimeFactor);
528 512
529 sb[14].StatID = (uint)Stats.OutPacketsPerSecond; 513 sb[14].StatID = (uint)Stats.OutPacketsPerSecond;
530 sb[14].StatValue = (m_outPacketsPerSecond / m_statsUpdateFactor); 514 sb[14].StatValue = (float)Math.Round(m_outPacketsPerSecond * updateTimeFactor);
531 515
532 sb[15].StatID = (uint)Stats.UnAckedBytes; 516 sb[15].StatID = (uint)Stats.UnAckedBytes;
533 sb[15].StatValue = m_unAckedBytes; 517 sb[15].StatValue = m_unAckedBytes;
534 518
535 sb[16].StatID = (uint)Stats.AgentMS; 519 sb[16].StatID = (uint)Stats.AgentMS;
536 sb[16].StatValue = m_agentMS / framesUpdated; 520 sb[16].StatValue = agentMS;
537 521
538 sb[17].StatID = (uint)Stats.PendingDownloads; 522 sb[17].StatID = (uint)Stats.PendingDownloads;
539 sb[17].StatValue = m_pendingDownloads; 523 sb[17].StatValue = m_pendingDownloads;
@@ -544,120 +528,155 @@ namespace OpenSim.Region.Framework.Scenes
544 sb[19].StatID = (uint)Stats.ActiveScripts; 528 sb[19].StatID = (uint)Stats.ActiveScripts;
545 sb[19].StatValue = m_activeScripts; 529 sb[19].StatValue = m_activeScripts;
546 530
547 sb[20].StatID = (uint)Stats.ScriptLinesPerSecond; 531 sb[20].StatID = (uint)Stats.SimSleepMs;
548 sb[20].StatValue = m_scriptLinesPerSecond / m_statsUpdateFactor; 532 sb[20].StatValue = sleeptime;
549 533
550 sb[21].StatID = (uint)Stats.SimSpareMs; 534 sb[21].StatID = (uint)Stats.SimSpareMs;
551 sb[21].StatValue = m_spareMS / framesUpdated; 535 sb[21].StatValue = sparetime;
536
537 // this should came from phys engine
538 sb[22].StatID = (uint)Stats.SimPhysicsStepMs;
539 sb[22].StatValue = 20;
540
541 // send the ones we dont have as zeros, to clean viewers state
542 // specially arriving from regions with wrond IDs in use
543
544 sb[23].StatID = (uint)Stats.VirtualSizeKb;
545 sb[23].StatValue = 0;
546
547 sb[24].StatID = (uint)Stats.ResidentSizeKb;
548 sb[24].StatValue = 0;
549
550 sb[25].StatID = (uint)Stats.PendingLocalUploads;
551 sb[25].StatValue = 0;
552
553 sb[26].StatID = (uint)Stats.PhysicsPinnedTasks;
554 sb[26].StatValue = 0;
555
556 sb[27].StatID = (uint)Stats.PhysicsLodTasks;
557 sb[27].StatValue = 0;
552 558
553 // Current ratio between the sum of physics and sim rate, and the 559 sb[28].StatID = (uint)Stats.ScriptEps; // we actuall have this, but not messing array order AGAIN
554 // minimum time to run a scene's frame 560 sb[28].StatValue = (float)Math.Round(m_scriptEventsPerSecond * updateTimeFactor);
555 sb[22].StatID = (uint)Stats.FrameDilation;
556 sb[22].StatValue = frameDilation;
557 561
558 // Current number of users currently attemptint to login to region 562 sb[29].StatID = (uint)Stats.SimAIStepTimeMS;
559 sb[23].StatID = (uint)Stats.UsersLoggingIn; 563 sb[29].StatValue = 0;
560 sb[23].StatValue = m_usersLoggingIn;
561 564
562 // Total number of geometric primitives in the scene 565 sb[30].StatID = (uint)Stats.SimIoPumpTime;
563 sb[24].StatID = (uint)Stats.TotalGeoPrim; 566 sb[30].StatValue = 0;
564 sb[24].StatValue = m_numGeoPrim;
565 567
566 // Total number of mesh objects in the scene 568 sb[31].StatID = (uint)Stats.SimPCTSscriptsRun;
567 sb[25].StatID = (uint)Stats.TotalMesh; 569 sb[31].StatValue = 0;
568 sb[25].StatValue = m_numMesh;
569 570
570 // Current number of threads that XEngine is using 571 sb[32].StatID = (uint)Stats.SimRegionIdle;
571 sb[26].StatID = (uint)Stats.ThreadCount; 572 sb[32].StatValue = 0;
572 sb[26].StatValue = m_inUseThreads;
573 573
574 sb[27].StatID = (uint)Stats.ScriptMS; 574 sb[33].StatID = (uint)Stats.SimRegionIdlePossible;
575 sb[27].StatValue = (numFrames <= 0) ? 0 : ((float)m_scriptMS / numFrames); 575 sb[33].StatValue = 0;
576 576
577 for (int i = 0; i < m_statisticArraySize; i++) 577 sb[34].StatID = (uint)Stats.SimSkippedSillouet_PS;
578 sb[34].StatValue = 0;
579
580 sb[35].StatID = (uint)Stats.SimSkippedCharsPerC;
581 sb[35].StatValue = 0;
582
583 sb[36].StatID = (uint)Stats.SimPhysicsMemory;
584 sb[36].StatValue = 0;
585
586 sb[37].StatID = (uint)Stats.ScriptMS;
587 sb[37].StatValue = scriptTimeMS;
588
589 for (int i = 0; i < m_statisticViewerArraySize; i++)
578 { 590 {
579 lastReportedSimStats[i] = sb[i].StatValue; 591 lastReportedSimStats[i] = sb[i].StatValue;
580 } 592 }
581 593
594
595 // add extra stats for internal use
596
597 for (int i = 0; i < m_statisticExtraArraySize; i++)
598 {
599 sbex[i] = new SimStatsPacket.StatBlock();
600 }
601
602 sbex[0].StatID = (uint)Stats.LSLScriptLinesPerSecond;
603 sbex[0].StatValue = m_scriptLinesPerSecond * updateTimeFactor;
604 lastReportedSimStats[38] = m_scriptLinesPerSecond * updateTimeFactor;
605
606 sbex[1].StatID = (uint)Stats.FrameDilation2;
607 sbex[1].StatValue = (Single.IsNaN(timeDilation)) ? 0.1f : timeDilation;
608 lastReportedSimStats[39] = (Single.IsNaN(timeDilation)) ? 0.1f : timeDilation;
609
610 sbex[2].StatID = (uint)Stats.UsersLoggingIn;
611 sbex[2].StatValue = m_usersLoggingIn;
612 lastReportedSimStats[40] = m_usersLoggingIn;
613
614 sbex[3].StatID = (uint)Stats.TotalGeoPrim;
615 sbex[3].StatValue = m_numGeoPrim;
616 lastReportedSimStats[41] = m_numGeoPrim;
617
618 sbex[4].StatID = (uint)Stats.TotalMesh;
619 sbex[4].StatValue = m_numMesh;
620 lastReportedSimStats[42] = m_numMesh;
621
622 sbex[5].StatID = (uint)Stats.ThreadCount;
623 sbex[5].StatValue = m_inUseThreads;
624 lastReportedSimStats[43] = m_inUseThreads;
625
582 SimStats simStats 626 SimStats simStats
583 = new SimStats( 627 = new SimStats(
584 ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)m_objectCapacity, 628 ReportingRegion.RegionLocX, ReportingRegion.RegionLocY, regionFlags, (uint)m_objectCapacity,
585 rb, sb, m_scene.RegionInfo.originRegionID); 629 rb, sb, sbex, m_scene.RegionInfo.originRegionID);
586 630
587 handlerSendStatResult = OnSendStatsResult; 631 handlerSendStatResult = OnSendStatsResult;
588 if (handlerSendStatResult != null) 632 if (handlerSendStatResult != null)
589 { 633 {
590 handlerSendStatResult(simStats); 634 handlerSendStatResult(simStats);
591 } 635 }
592 636
593 // Extra statistics that aren't currently sent to clients 637 // Extra statistics that aren't currently sent to clients
594 lock (m_lastReportedExtraSimStats) 638 if (m_scene.PhysicsScene != null)
595 { 639 {
596 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; 640 lock (m_lastReportedExtraSimStats)
597 m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value;
598
599 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
600
601 if (physicsStats != null)
602 { 641 {
603 foreach (KeyValuePair<string, float> tuple in physicsStats) 642 m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates * updateTimeFactor;
643 m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value;
644
645 Dictionary<string, float> physicsStats = m_scene.PhysicsScene.GetStats();
646
647 if (physicsStats != null)
604 { 648 {
605 // FIXME: An extremely dirty hack to divide MS stats per frame rather than per second 649 foreach (KeyValuePair<string, float> tuple in physicsStats)
606 // Need to change things so that stats source can indicate whether they are per second or 650 {
607 // per frame. 651 // FIXME: An extremely dirty hack to divide MS stats per frame rather than per second
608 if (tuple.Key.EndsWith("MS")) 652 // Need to change things so that stats source can indicate whether they are per second or
609 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / framesUpdated; 653 // per frame.
610 else 654 if (tuple.Key.EndsWith("MS"))
611 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value / m_statsUpdateFactor; 655 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value * perframefactor;
656 else
657 m_lastReportedExtraSimStats[tuple.Key] = tuple.Value * updateTimeFactor;
658 }
612 } 659 }
613 } 660 }
614 } 661 }
615 662
663// LastReportedObjectUpdates = m_objectUpdates / m_statsUpdateFactor;
616 ResetValues(); 664 ResetValues();
665 Monitor.Exit(m_statsLock);
617 } 666 }
618 } 667 }
619 668
620 private void ResetValues() 669 private void ResetValues()
621 { 670 {
622 // Reset the number of frames that the physics library has
623 // processed since the last stats report
624 m_numberPhysicsFrames = 0;
625
626 m_timeDilation = 0;
627 m_fps = 0;
628 m_pfps = 0;
629 m_agentUpdates = 0; 671 m_agentUpdates = 0;
630 m_objectUpdates = 0; 672 m_objectUpdates = 0;
631 //m_inPacketsPerSecond = 0;
632 //m_outPacketsPerSecond = 0;
633 m_unAckedBytes = 0; 673 m_unAckedBytes = 0;
634 m_scriptLinesPerSecond = 0; 674 m_scriptEventsPerSecond = 0;
635 675
636 m_frameMS = 0;
637 m_agentMS = 0;
638 m_netMS = 0; 676 m_netMS = 0;
639 m_physicsMS = 0;
640 m_imageMS = 0; 677 m_imageMS = 0;
641 m_otherMS = 0;
642 m_scriptMS = 0;
643 m_spareMS = 0;
644 } 678 }
645 679
646 # region methods called from Scene
647 // The majority of these functions are additive
648 // so that you can easily change the amount of
649 // seconds in between sim stats updates
650
651 public void AddTimeDilation(float td)
652 {
653 //float tdsetting = td;
654 //if (tdsetting > 1.0f)
655 //tdsetting = (tdsetting - (tdsetting - 0.91f));
656
657 //if (tdsetting < 0)
658 //tdsetting = 0.0f;
659 m_timeDilation = td;
660 }
661 680
662 internal void CheckStatSanity() 681 internal void CheckStatSanity()
663 { 682 {
@@ -675,14 +694,44 @@ namespace OpenSim.Region.Framework.Scenes
675 } 694 }
676 } 695 }
677 696
678 public void AddFPS(int frames) 697 # region methods called from Scene
698
699 public void AddFrameStats(float _timeDilation, float _physicsFPS, float _agentMS,
700 float _physicsMS, float _otherMS , float _sleepMS,
701 float _frameMS, float _scriptTimeMS)
679 { 702 {
680 m_fps += frames; 703 lock(m_statsFrameLock)
681 } 704 {
705 m_fps++;
706 m_timeDilation += _timeDilation;
707 m_pfps += _physicsFPS;
708 m_agentMS += _agentMS;
709 m_physicsMS += _physicsMS;
710 m_otherMS += _otherMS;
711 m_sleeptimeMS += _sleepMS;
712 m_frameMS += _frameMS;
713 m_scriptTimeMS += _scriptTimeMS;
714
715 if (_frameMS > SlowFramesStatReportThreshold)
716 SlowFramesStat.Value++;
717
718 m_FrameStatsTS = Util.GetTimeStampMS();
719 }
720 }
682 721
683 public void AddPhysicsFPS(float frames) 722 private void ResetFrameStats()
684 { 723 {
685 m_pfps += frames; 724 m_fps = 0;
725 m_timeDilation = 0.0f;
726 m_pfps = 0.0f;
727 m_agentMS = 0.0f;
728 m_physicsMS = 0.0f;
729 m_otherMS = 0.0f;
730 m_sleeptimeMS = 0.0f;
731 m_frameMS = 0.0f;
732 m_scriptTimeMS = 0.0f;
733
734 m_prevFrameStatsTS = m_FrameStatsTS;
686 } 735 }
687 736
688 public void AddObjectUpdates(int numUpdates) 737 public void AddObjectUpdates(int numUpdates)
@@ -711,77 +760,17 @@ namespace OpenSim.Region.Framework.Scenes
711 if (m_unAckedBytes < 0) m_unAckedBytes = 0; 760 if (m_unAckedBytes < 0) m_unAckedBytes = 0;
712 } 761 }
713 762
714 public void addFrameMS(int ms)
715 {
716 m_frameMS += ms;
717
718 // At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit
719 // longer than ideal due to the inaccuracy of the Sleep in Scene.Update() (which in itself is a concern).
720 if (ms > SlowFramesStatReportThreshold)
721 SlowFramesStat.Value++;
722 }
723
724 public void AddSpareMS(int ms)
725 {
726 m_spareMS += ms;
727 }
728 763
729 public void addNetMS(int ms) 764 public void addNetMS(float ms)
730 { 765 {
731 m_netMS += ms; 766 m_netMS += ms;
732 } 767 }
733 768
734 public void addAgentMS(int ms) 769 public void addImageMS(float ms)
735 {
736 m_agentMS += ms;
737 }
738
739 public void addPhysicsMS(int ms)
740 {
741 m_physicsMS += ms;
742 }
743
744 public void addImageMS(int ms)
745 { 770 {
746 m_imageMS += ms; 771 m_imageMS += ms;
747 } 772 }
748 773
749 public void addOtherMS(int ms)
750 {
751 m_otherMS += ms;
752 }
753
754 public void AddScriptMS(int ms)
755 {
756 m_scriptMS += ms;
757 }
758
759 public void addPhysicsFrame(int frames)
760 {
761 // Add the number of physics frames to the correct total physics
762 // frames
763 m_numberPhysicsFrames += frames;
764 }
765
766 public void addFrameTimeMilliseconds(double total, double simulation,
767 double physics, double network)
768 {
769 // Save the frame times from the current frame into the appropriate
770 // arrays
771 m_totalFrameTimeMilliseconds[m_nextLocation] = total;
772 m_simulationFrameTimeMilliseconds[m_nextLocation] = simulation;
773 m_physicsFrameTimeMilliseconds[m_nextLocation] = physics;
774 m_networkFrameTimeMilliseconds[m_nextLocation] = network;
775
776 // Update to the next location in the list
777 m_nextLocation++;
778
779 // Since the list will begin to overwrite the oldest frame values
780 // first, the next location needs to loop back to the beginning of the
781 // list whenever it reaches the end
782 m_nextLocation = m_nextLocation % m_numberFramesStored;
783 }
784
785 public void AddPendingDownloads(int count) 774 public void AddPendingDownloads(int count)
786 { 775 {
787 m_pendingDownloads += count; 776 m_pendingDownloads += count;
@@ -792,9 +781,9 @@ namespace OpenSim.Region.Framework.Scenes
792 //m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads); 781 //m_log.InfoFormat("[stats]: Adding {0} to pending downloads to make {1}", count, m_pendingDownloads);
793 } 782 }
794 783
795 public void addScriptLines(int count) 784 public void addScriptEvents(int count)
796 { 785 {
797 m_scriptLinesPerSecond += count; 786 m_scriptEventsPerSecond += count;
798 } 787 }
799 788
800 public void AddPacketsStats(int inPackets, int outPackets, int unAckedBytes) 789 public void AddPacketsStats(int inPackets, int outPackets, int unAckedBytes)
diff --git a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
index 3d563a6..506ad24 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainChannel.cs
@@ -57,6 +57,7 @@ namespace OpenSim.Region.Framework.Scenes
57 public int Height { get { return m_terrainData.SizeY; } } // Y dimension 57 public int Height { get { return m_terrainData.SizeY; } } // Y dimension
58 public int Altitude { get { return m_terrainData.SizeZ; } } // Y dimension 58 public int Altitude { get { return m_terrainData.SizeZ; } } // Y dimension
59 59
60
60 // Default, not-often-used builder 61 // Default, not-often-used builder
61 public TerrainChannel() 62 public TerrainChannel()
62 { 63 {
@@ -157,7 +158,11 @@ namespace OpenSim.Region.Framework.Scenes
157 { 158 {
158 if (Double.IsNaN(value) || Double.IsInfinity(value)) 159 if (Double.IsNaN(value) || Double.IsInfinity(value))
159 return; 160 return;
160 161 if (value < 0)
162 value = 0;
163 else
164 if (value > 655.35)
165 value = 655.35;
161 m_terrainData[x, y] = (float)value; 166 m_terrainData[x, y] = (float)value;
162 } 167 }
163 } 168 }
@@ -363,8 +368,8 @@ namespace OpenSim.Region.Framework.Scenes
363 public int SizeY; 368 public int SizeY;
364 public int SizeZ; 369 public int SizeZ;
365 public float CompressionFactor; 370 public float CompressionFactor;
366 public int[] Map; 371 public float[] Map;
367 public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, int[] pMap) 372 public TerrainChannelXMLPackage(int pX, int pY, int pZ, float pCompressionFactor, float[] pMap)
368 { 373 {
369 Version = 1; 374 Version = 1;
370 SizeX = pX; 375 SizeX = pX;
@@ -395,17 +400,22 @@ namespace OpenSim.Region.Framework.Scenes
395 // Fill the heightmap with the center bump terrain 400 // Fill the heightmap with the center bump terrain
396 private void PinHeadIsland() 401 private void PinHeadIsland()
397 { 402 {
403 float cx = m_terrainData.SizeX * 0.5f;
404 float cy = m_terrainData.SizeY * 0.5f;
405 float h;
398 for (int x = 0; x < Width; x++) 406 for (int x = 0; x < Width; x++)
399 { 407 {
400 for (int y = 0; y < Height; y++) 408 for (int y = 0; y < Height; y++)
401 { 409 {
402 m_terrainData[x, y] = (float)TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10; 410 // h = (float)TerrainUtil.PerlinNoise2D(x, y, 2, 0.125) * 10;
403 float spherFacA = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 50) * 0.01d); 411 h = 1.0f;
404 float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, m_terrainData.SizeX / 2.0, m_terrainData.SizeY / 2.0, 100) * 0.001d); 412 float spherFacA = (float)(TerrainUtil.SphericalFactor(x, y, cx, cy, 50) * 0.01d);
405 if (m_terrainData[x, y]< spherFacA) 413 float spherFacB = (float)(TerrainUtil.SphericalFactor(x, y, cx, cy, 100) * 0.001d);
406 m_terrainData[x, y]= spherFacA; 414 if (h < spherFacA)
407 if (m_terrainData[x, y]< spherFacB) 415 h = spherFacA;
408 m_terrainData[x, y] = spherFacB; 416 if (h < spherFacB)
417 h = spherFacB;
418 m_terrainData[x, y] = h;
409 } 419 }
410 } 420 }
411 } 421 }
diff --git a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
index fc8f8cd..fd65735 100644
--- a/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
+++ b/OpenSim/Region/Framework/Scenes/TerrainCompressor.cs
@@ -27,10 +27,13 @@
27 27
28/* Freely adapted from the Aurora version of the terrain compressor. 28/* Freely adapted from the Aurora version of the terrain compressor.
29 * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/ 29 * Copyright (c) Contributors, http://aurora-sim.org/, http://opensimulator.org/
30 * Aurora version created from libOpenMetaverse Library terrain compressor
30 */ 31 */
31 32
32using System; 33using System;
34using System.Collections.Generic;
33using System.Reflection; 35using System.Reflection;
36using System.Diagnostics;
34 37
35using log4net; 38using log4net;
36 39
@@ -45,7 +48,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
45{ 48{
46 public static class OpenSimTerrainCompressor 49 public static class OpenSimTerrainCompressor
47 { 50 {
48// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 51 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49 52
50#pragma warning disable 414 53#pragma warning disable 414
51 private static string LogHeader = "[TERRAIN COMPRESSOR]"; 54 private static string LogHeader = "[TERRAIN COMPRESSOR]";
@@ -61,47 +64,41 @@ namespace OpenSim.Region.ClientStack.LindenUDP
61 private const int POSITIVE_VALUE = 0x6; 64 private const int POSITIVE_VALUE = 0x6;
62 private const int NEGATIVE_VALUE = 0x7; 65 private const int NEGATIVE_VALUE = 0x7;
63 66
64 private static readonly float[] DequantizeTable16 =
65 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
66
67 private static readonly float[] DequantizeTable32 =
68 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
69 67
70 private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 68// private static readonly float[] CosineTable16 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
71 //private static readonly float[] CosineTable32 = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize]; 69 private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
72 private static readonly int[] CopyMatrix16 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
73 private static readonly int[] CopyMatrix32 = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
74 70
75 private static readonly float[] QuantizeTable16 = 71 private static readonly float[] QuantizeTable16 =
76 new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 72 new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
73 private static readonly float[] DequantizeTable16 =
74 new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
77 75
78 static OpenSimTerrainCompressor() 76 static OpenSimTerrainCompressor()
79 { 77 {
80 // Initialize the decompression tables 78 // Initialize the decompression tables
81 BuildDequantizeTable16(); 79 BuildDequantizeTable16();
82 SetupCosines16(); 80// SetupCosines16();
83 BuildCopyMatrix16(); 81 BuildCopyMatrix16();
84 BuildQuantizeTable16(); 82 BuildQuantizeTable16();
85 } 83 }
86 84
87 // Used to send cloud and wind patches 85 // Used to send cloud and wind patches
88 public static LayerDataPacket CreateLayerDataPacket(TerrainPatch[] patches, byte type, int pRegionSizeX, 86 public static LayerDataPacket CreateLayerDataPacketStandardSize(TerrainPatch[] patches, byte type)
89 int pRegionSizeY)
90 { 87 {
91 LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}}; 88 LayerDataPacket layer = new LayerDataPacket { LayerID = { Type = type } };
92 89
93 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader 90 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
94 {Stride = STRIDE, PatchSize = Constants.TerrainPatchSize}; 91 { Stride = STRIDE, PatchSize = Constants.TerrainPatchSize };
95 92
96 // Should be enough to fit even the most poorly packed data 93 // Should be enough to fit even the most poorly packed data
97 byte[] data = new byte[patches.Length*Constants.TerrainPatchSize*Constants.TerrainPatchSize*2]; 94 byte[] data = new byte[patches.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
98 BitPack bitpack = new BitPack(data, 0); 95 BitPack bitpack = new BitPack(data, 0);
99 bitpack.PackBits(header.Stride, 16); 96 bitpack.PackBits(header.Stride, 16);
100 bitpack.PackBits(header.PatchSize, 8); 97 bitpack.PackBits(header.PatchSize, 8);
101 bitpack.PackBits(type, 8); 98 bitpack.PackBits(type, 8);
102 99
103 foreach (TerrainPatch t in patches) 100 foreach (TerrainPatch t in patches)
104 CreatePatch(bitpack, t.Data, t.X, t.Y, pRegionSizeX, pRegionSizeY); 101 CreatePatchtStandardSize(bitpack, t.Data, t.X, t.Y);
105 102
106 bitpack.PackBits(END_OF_PATCHES, 8); 103 bitpack.PackBits(END_OF_PATCHES, 8);
107 104
@@ -111,122 +108,131 @@ namespace OpenSim.Region.ClientStack.LindenUDP
111 return layer; 108 return layer;
112 } 109 }
113 110
114 // Create a land packet for a single patch. 111 public static void CreatePatchtStandardSize(BitPack output, float[] patchData, int x, int y)
115 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int patchX, int patchY)
116 { 112 {
117 int[] xPieces = new int[1]; 113 TerrainPatch.Header header = PrescanPatch(patchData);
118 int[] yPieces = new int[1]; 114 header.QuantWBits = 136;
119 xPieces[0] = patchX; // patch X dimension
120 yPieces[0] = patchY;
121 115
122 return CreateLandPacket(terrData, xPieces, yPieces); 116 header.PatchIDs = (y & 0x1F);
117 header.PatchIDs += (x << 5);
118
119 int wbits;
120 int[] patch = CompressPatch(patchData, header, 10, out wbits);
121 EncodePatchHeader(output, header, patch, false, ref wbits);
122 EncodePatch(output, patch, 0, wbits);
123 } 123 }
124 124
125 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] xPieces, int[] yPieces) 125 private static TerrainPatch.Header PrescanPatch(float[] patch)
126 { 126 {
127 byte landPacketType = (byte)TerrainPatch.LayerType.Land; 127 TerrainPatch.Header header = new TerrainPatch.Header();
128 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) 128 float zmax = -99999999.0f;
129 float zmin = 99999999.0f;
130
131 for (int i = 0; i < Constants.TerrainPatchSize * Constants.TerrainPatchSize; i++)
129 { 132 {
130 landPacketType = (byte)TerrainPatch.LayerType.LandExtended; 133 float val = patch[i];
134 if (val > zmax) zmax = val;
135 if (val < zmin) zmin = val;
131 } 136 }
132 137
133 return CreateLandPacket(terrData, xPieces, yPieces, landPacketType); 138 header.DCOffset = zmin;
139 header.Range = (int)((zmax - zmin) + 1.0f);
140
141 return header;
134 } 142 }
135 143
136 /// <summary> 144 private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits)
137 /// Creates a LayerData packet for compressed land data given a full
138 /// simulator heightmap and an array of indices of patches to compress
139 /// </summary>
140 /// <param name="terrData">
141 /// Terrain data that can result in a meter square heightmap.
142 /// </param>
143 /// <param name="x">
144 /// Array of indexes in the grid of patches
145 /// for this simulator.
146 /// If creating a packet for multiple patches, there will be entries in
147 /// both the X and Y arrays for each of the patches.
148 /// For example if patches 1 and 17 are to be sent,
149 /// x[] = {1,1} and y[] = {0,1} which specifies the patches at
150 /// indexes <1,0> and <1,1> (presuming the terrain size is 16x16 patches).
151 /// </param>
152 /// <param name="y">
153 /// Array of indexes in the grid of patches.
154 /// </param>
155 /// <param name="type"></param>
156 /// <returns></returns>
157 public static LayerDataPacket CreateLandPacket(TerrainData terrData, int[] x, int[] y, byte type)
158 { 145 {
159 LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = type}}; 146 float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
147 float oozrange = 1.0f / header.Range;
148 float range = (1 << prequant);
149 float premult = oozrange * range;
160 150
161 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
162 {Stride = STRIDE, PatchSize = Constants.TerrainPatchSize};
163 151
164 byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2]; 152 float sub = 0.5f * header.Range + header.DCOffset;
165 BitPack bitpack = new BitPack(data, 0);
166 bitpack.PackBits(header.Stride, 16);
167 bitpack.PackBits(header.PatchSize, 8);
168 bitpack.PackBits(type, 8);
169 153
170 for (int i = 0; i < x.Length; i++) 154 int wordsize = (prequant - 2) & 0x0f;
171 CreatePatchFromHeightmap(bitpack, terrData, x[i], y[i]); 155 header.QuantWBits = wordsize;
156 header.QuantWBits |= wordsize << 4;
172 157
173 bitpack.PackBits(END_OF_PATCHES, 8); 158 int k = 0;
159 for (int j = 0; j < Constants.TerrainPatchSize; j++)
160 {
161 for (int i = 0; i < Constants.TerrainPatchSize; i++)
162 block[k++] = (patchData[j * Constants.TerrainPatchSize + i] - sub) * premult;
163 }
174 164
175 layer.LayerData.Data = new byte[bitpack.BytePos + 1]; 165 float[] ftemp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
176 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1); 166 int[] iout = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
177 167
178 return layer; 168 wbits = (prequant >> 1);
169
170 dct16x16(block, iout, ref wbits);
171
172 return iout;
179 } 173 }
180 174
181 // Unused: left for historical reference. 175 // new using terrain data and patchs indexes
182 public static void CreatePatch(BitPack output, float[] patchData, int x, int y, int pRegionSizeX, int pRegionSizeY) 176 public static List<LayerDataPacket> CreateLayerDataPackets(TerrainData terrData, int[] x, int[] y, byte landPacketType)
183 { 177 {
184 TerrainPatch.Header header = PrescanPatch(patchData); 178 List<LayerDataPacket> ret = new List<LayerDataPacket>();
185 header.QuantWBits = 136; 179
186 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize) 180 //create packet and global header
187 { 181 LayerDataPacket layer = new LayerDataPacket();
188 header.PatchIDs = (y & 0xFFFF); 182
189 header.PatchIDs += (x << 16); 183 layer.LayerID.Type = landPacketType;
190 } 184
191 else 185 byte[] data = new byte[x.Length * Constants.TerrainPatchSize * Constants.TerrainPatchSize * 2];
186 BitPack bitpack = new BitPack(data, 0);
187 bitpack.PackBits(STRIDE, 16);
188 bitpack.PackBits(Constants.TerrainPatchSize, 8);
189 bitpack.PackBits(landPacketType, 8);
190
191 for (int i = 0; i < x.Length; i++)
192 { 192 {
193 header.PatchIDs = (y & 0x1F); 193 CreatePatchFromTerrainData(bitpack, terrData, x[i], y[i]);
194 header.PatchIDs += (x << 5); 194 if (bitpack.BytePos > 980 && i != x.Length - 1)
195 {
196 //finish this packet
197 bitpack.PackBits(END_OF_PATCHES, 8);
198
199 layer.LayerData.Data = new byte[bitpack.BytePos + 1];
200 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
201 ret.Add(layer);
202
203 // start another
204 layer = new LayerDataPacket();
205 layer.LayerID.Type = landPacketType;
206
207 bitpack = new BitPack(data, 0);
208 bitpack.PackBits(STRIDE, 16);
209 bitpack.PackBits(Constants.TerrainPatchSize, 8);
210 bitpack.PackBits(landPacketType, 8);
211 }
195 } 212 }
196 213
197 // NOTE: No idea what prequant and postquant should be or what they do 214 bitpack.PackBits(END_OF_PATCHES, 8);
198 215
199 int wbits; 216 layer.LayerData.Data = new byte[bitpack.BytePos + 1];
200 int[] patch = CompressPatch(patchData, header, 10, out wbits); 217 Buffer.BlockCopy(bitpack.Data, 0, layer.LayerData.Data, 0, bitpack.BytePos + 1);
201 wbits = EncodePatchHeader(output, header, patch, Constants.RegionSize, Constants.RegionSize, wbits); 218 ret.Add(layer);
202 EncodePatch(output, patch, 0, wbits); 219
220 return ret;
203 } 221 }
204 222
205 /// <summary> 223 public static void CreatePatchFromTerrainData(BitPack output, TerrainData terrData, int patchX, int patchY)
206 /// Add a patch of terrain to a BitPacker
207 /// </summary>
208 /// <param name="output">BitPacker to write the patch to</param>
209 /// <param name="heightmap">
210 /// Heightmap of the simulator. Presumed to be an sizeX*sizeY array.
211 /// </param>
212 /// <param name="patchX">
213 /// X offset of the patch to create.
214 /// </param>
215 /// <param name="patchY">
216 /// Y offset of the patch to create.
217 /// </param>
218 /// <param name="pRegionSizeX"></param>
219 /// <param name="pRegionSizeY"></param>
220 public static void CreatePatchFromHeightmap(BitPack output, TerrainData terrData, int patchX, int patchY)
221 { 224 {
222 TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY); 225 float frange;
223 header.QuantWBits = 136; 226 TerrainPatch.Header header = PrescanPatch(terrData, patchX, patchY, out frange);
227 header.QuantWBits = 130;
224 228
229 bool largeRegion = false;
225 // If larger than legacy region size, pack patch X and Y info differently. 230 // If larger than legacy region size, pack patch X and Y info differently.
226 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize) 231 if (terrData.SizeX > Constants.RegionSize || terrData.SizeY > Constants.RegionSize)
227 { 232 {
228 header.PatchIDs = (patchY & 0xFFFF); 233 header.PatchIDs = (patchY & 0xFFFF);
229 header.PatchIDs += (patchX << 16); 234 header.PatchIDs += (patchX << 16);
235 largeRegion = true;
230 } 236 }
231 else 237 else
232 { 238 {
@@ -234,45 +240,45 @@ namespace OpenSim.Region.ClientStack.LindenUDP
234 header.PatchIDs += (patchX << 5); 240 header.PatchIDs += (patchX << 5);
235 } 241 }
236 242
237 // m_log.DebugFormat("{0} CreatePatchFromHeightmap. patchX={1}, patchY={2}, DCOffset={3}, range={4}", 243 if (Math.Round((double)frange, 2) == 1.0)
238 // LogHeader, patchX, patchY, header.DCOffset, header.Range); 244 {
245 // flat terrain speed up things
239 246
240 // NOTE: No idea what prequant and postquant should be or what they do 247 header.DCOffset -= 0.5f;
241 int wbits;
242 int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
243 wbits = EncodePatchHeader(output, header, patch, (uint)terrData.SizeX, (uint)terrData.SizeY, wbits);
244 EncodePatch(output, patch, 0, wbits);
245 }
246 248
247 private static TerrainPatch.Header PrescanPatch(float[] patch) 249 header.QuantWBits = 0x00;
248 { 250 output.PackBits(header.QuantWBits, 8);
249 TerrainPatch.Header header = new TerrainPatch.Header(); 251 output.PackFloat(header.DCOffset);
250 float zmax = -99999999.0f; 252 output.PackBits(1, 16);
251 float zmin = 99999999.0f; 253 if (largeRegion)
254 output.PackBits(header.PatchIDs, 32);
255 else
256 output.PackBits(header.PatchIDs, 10);
252 257
253 for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++) 258 // and thats all
254 { 259 output.PackBits(ZERO_EOB, 2);
255 float val = patch[i]; 260 return;
256 if (val > zmax) zmax = val;
257 if (val < zmin) zmin = val;
258 } 261 }
259 262
260 header.DCOffset = zmin; 263 int wbits;
261 header.Range = (int) ((zmax - zmin) + 1.0f); 264 int[] patch = CompressPatch(terrData, patchX, patchY, header, 10, out wbits);
262 265 EncodePatchHeader(output, header, patch, largeRegion, ref wbits);
263 return header; 266 EncodePatch(output, patch, 0, wbits);
264 } 267 }
265 268
266 // Scan the height info we're returning and return a patch packet header for this patch. 269 // Scan the height info we're returning and return a patch packet header for this patch.
267 private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY) 270 private static TerrainPatch.Header PrescanPatch(TerrainData terrData, int patchX, int patchY, out float frange)
268 { 271 {
269 TerrainPatch.Header header = new TerrainPatch.Header(); 272 TerrainPatch.Header header = new TerrainPatch.Header();
270 float zmax = -99999999.0f; 273 float zmax = float.MinValue;
271 float zmin = 99999999.0f; 274 float zmin = float.MaxValue;
272 275
273 for (int j = patchY*Constants.TerrainPatchSize; j < (patchY + 1)*Constants.TerrainPatchSize; j++) 276 int startx = patchX * Constants.TerrainPatchSize;
277 int starty = patchY * Constants.TerrainPatchSize;
278
279 for (int j = starty; j < starty + Constants.TerrainPatchSize; j++)
274 { 280 {
275 for (int i = patchX*Constants.TerrainPatchSize; i < (patchX + 1)*Constants.TerrainPatchSize; i++) 281 for (int i = startx; i < startx + Constants.TerrainPatchSize; i++)
276 { 282 {
277 float val = terrData[i, j]; 283 float val = terrData[i, j];
278 if (val > zmax) zmax = val; 284 if (val > zmax) zmax = val;
@@ -281,309 +287,430 @@ namespace OpenSim.Region.ClientStack.LindenUDP
281 } 287 }
282 288
283 header.DCOffset = zmin; 289 header.DCOffset = zmin;
284 header.Range = (int)((zmax - zmin) + 1.0f); 290 frange = ((zmax - zmin) + 1.0f);
285 291 header.Range = (int)frange;
286 return header;
287 }
288
289 public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
290 {
291 TerrainPatch.Header header = new TerrainPatch.Header {QuantWBits = bitpack.UnpackBits(8)};
292
293 // Quantized word bits
294 if (header.QuantWBits == END_OF_PATCHES)
295 return header;
296
297 // DC offset
298 header.DCOffset = bitpack.UnpackFloat();
299
300 // Range
301 header.Range = bitpack.UnpackBits(16);
302
303 // Patch IDs (10 bits)
304 header.PatchIDs = bitpack.UnpackBits(10);
305
306 // Word bits
307 header.WordBits = (uint) ((header.QuantWBits & 0x0f) + 2);
308 292
309 return header; 293 return header;
310 } 294 }
311 295
312 private static int EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, uint pRegionSizeX, 296 private static void EncodePatchHeader(BitPack output, TerrainPatch.Header header, int[] patch, bool largeRegion, ref int wbits)
313 uint pRegionSizeY, int wbits)
314 { 297 {
315 /*
316 int temp;
317 int wbits = (header.QuantWBits & 0x0f) + 2;
318 uint maxWbits = (uint)wbits + 5;
319 uint minWbits = ((uint)wbits >> 1);
320 int wbitsMaxValue;
321 */
322 // goal is to determ minimum number of bits to use so all data fits
323 /*
324 wbits = (int)minWbits;
325 wbitsMaxValue = (1 << wbits);
326
327 for (int i = 0; i < patch.Length; i++)
328 {
329 temp = patch[i];
330 if (temp != 0)
331 {
332 // Get the absolute value
333 if (temp < 0) temp *= -1;
334
335 no coments..
336
337 for (int j = (int)maxWbits; j > (int)minWbits; j--)
338 {
339 if ((temp & (1 << j)) != 0)
340 {
341 if (j > wbits) wbits = j;
342 break;
343 }
344 }
345
346 while (temp > wbitsMaxValue)
347 {
348 wbits++;
349 if (wbits == maxWbits)
350 goto Done;
351 wbitsMaxValue = 1 << wbits;
352 }
353 }
354 }
355
356 Done:
357
358 // wbits += 1;
359 */
360 // better check
361 if (wbits > 17) 298 if (wbits > 17)
362 wbits = 16; 299 wbits = 17;
363 else if (wbits < 3) 300 else if (wbits < 2)
364 wbits = 3; 301 wbits = 2;
365 302
366 header.QuantWBits &= 0xf0; 303 header.QuantWBits &= 0xf0;
367
368 header.QuantWBits |= (wbits - 2); 304 header.QuantWBits |= (wbits - 2);
369 305
370 output.PackBits(header.QuantWBits, 8); 306 output.PackBits(header.QuantWBits, 8);
371 output.PackFloat(header.DCOffset); 307 output.PackFloat(header.DCOffset);
372 output.PackBits(header.Range, 16); 308 output.PackBits(header.Range, 16);
373 if (pRegionSizeX > Constants.RegionSize || pRegionSizeY > Constants.RegionSize) 309 if (largeRegion)
374 output.PackBits(header.PatchIDs, 32); 310 output.PackBits(header.PatchIDs, 32);
375 else 311 else
376 output.PackBits(header.PatchIDs, 10); 312 output.PackBits(header.PatchIDs, 10);
377
378 return wbits;
379 } 313 }
380 314
381 private static void IDCTColumn16(float[] linein, float[] lineout, int column) 315 private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits)
382 { 316 {
383 for (int n = 0; n < Constants.TerrainPatchSize; n++) 317 int maxwbitssize = (1 << wbits) - 1;
384 { 318 int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
385 float total = OO_SQRT2*linein[column];
386
387 for (int u = 1; u < Constants.TerrainPatchSize; u++)
388 {
389 int usize = u*Constants.TerrainPatchSize;
390 total += linein[usize + column]*CosineTable16[usize + n];
391 }
392 319
393 lineout[Constants.TerrainPatchSize*n + column] = total; 320 if (postquant > fullSize || postquant < 0)
321 {
322 Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error);
323 return;
394 } 324 }
395 }
396 325
397 private static void IDCTLine16(float[] linein, float[] lineout, int line) 326 if (postquant != 0)
398 { 327 patch[fullSize - postquant] = 0;
399 const float oosob = 2.0f/Constants.TerrainPatchSize;
400 int lineSize = line*Constants.TerrainPatchSize;
401 328
402 for (int n = 0; n < Constants.TerrainPatchSize; n++) 329 int lastZeroindx = fullSize - postquant;
330
331 for (int i = 0; i < fullSize; i++)
403 { 332 {
404 float total = OO_SQRT2*linein[lineSize]; 333 int temp = patch[i];
405 334
406 for (int u = 1; u < Constants.TerrainPatchSize; u++) 335 if (temp == 0)
407 { 336 {
408 total += linein[lineSize + u]*CosineTable16[u*Constants.TerrainPatchSize + n]; 337 bool eob = true;
338
339 for (int j = i; j < lastZeroindx; j++)
340 {
341 if (patch[j] != 0)
342 {
343 eob = false;
344 break;
345 }
346 }
347
348 if (eob)
349 {
350 output.PackBits(ZERO_EOB, 2);
351 return;
352 }
353 output.PackBits(ZERO_CODE, 1);
409 } 354 }
355 else
356 {
357 if (temp < 0)
358 {
359 temp *= -1;
360
361 if (temp > maxwbitssize) temp = maxwbitssize;
410 362
411 lineout[lineSize + n] = total*oosob; 363 output.PackBits(NEGATIVE_VALUE, 3);
364 output.PackBits(temp, wbits);
365 }
366 else
367 {
368 if (temp > maxwbitssize) temp = maxwbitssize;
369
370 output.PackBits(POSITIVE_VALUE, 3);
371 output.PackBits(temp, wbits);
372 }
373 }
412 } 374 }
413 } 375 }
414 376
415/* 377 private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header,
416 private static void DCTLine16(float[] linein, float[] lineout, int line) 378 int prequant, out int wbits)
417 { 379 {
418 float total = 0.0f; 380 float[] block = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
419 int lineSize = line * Constants.TerrainPatchSize; 381 int[] iout = new int[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
420 382
421 for (int n = 0; n < Constants.TerrainPatchSize; n++) 383 float oozrange = 1.0f / header.Range;
422 { 384 float invprequat = (1 << prequant);
423 total += linein[lineSize + n]; 385 float premult = oozrange * invprequat;
424 }
425 386
426 lineout[lineSize] = OO_SQRT2 * total; 387 float sub = 0.5f * header.Range + header.DCOffset;
427 388
428 int uptr = 0; 389 int wordsize = (prequant - 2) & 0x0f;
429 for (int u = 1; u < Constants.TerrainPatchSize; u++) 390 header.QuantWBits = wordsize;
430 { 391 header.QuantWBits |= wordsize << 4;
431 total = 0.0f;
432 uptr += Constants.TerrainPatchSize;
433 392
434 for (int n = 0; n < Constants.TerrainPatchSize; n++) 393 int k = 0;
394 int startX = patchX * Constants.TerrainPatchSize;
395 int startY = patchY * Constants.TerrainPatchSize;
396 for (int y = startY; y < startY + Constants.TerrainPatchSize; y++)
397 {
398 for (int x = startX; x < startX + Constants.TerrainPatchSize; x++)
435 { 399 {
436 total += linein[lineSize + n] * CosineTable16[uptr + n]; 400 block[k++] = (terrData[x, y] - sub) * premult;
437 } 401 }
438
439 lineout[lineSize + u] = total;
440 } 402 }
403
404 wbits = (prequant >> 1);
405
406 dct16x16(block, iout, ref wbits);
407
408 return iout;
441 } 409 }
442*/
443 410
444 private static void DCTLine16(float[] linein, float[] lineout, int line) 411 #region Initialization
445 {
446 // outputs transpose data (lines exchanged with coluns )
447 // so to save a bit of cpu when doing coluns
448 float total = 0.0f;
449 int lineSize = line*Constants.TerrainPatchSize;
450 412
451 for (int n = 0; n < Constants.TerrainPatchSize; n++) 413 private static void BuildDequantizeTable16()
414 {
415 for (int j = 0; j < Constants.TerrainPatchSize; j++)
452 { 416 {
453 total += linein[lineSize + n]; 417 for (int i = 0; i < Constants.TerrainPatchSize; i++)
418 {
419 DequantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f + 2.0f * (i + j);
420 }
454 } 421 }
422 }
455 423
456 lineout[line] = OO_SQRT2*total; 424 private static void BuildQuantizeTable16()
457 425 {
458 for (int u = Constants.TerrainPatchSize; 426 const float oosob = 2.0f / Constants.TerrainPatchSize;
459 u < Constants.TerrainPatchSize*Constants.TerrainPatchSize; 427 for (int j = 0; j < Constants.TerrainPatchSize; j++)
460 u += Constants.TerrainPatchSize)
461 { 428 {
462 total = 0.0f; 429 for (int i = 0; i < Constants.TerrainPatchSize; i++)
463 for (int ptrn = lineSize, ptru = u; ptrn < lineSize + Constants.TerrainPatchSize; ptrn++,ptru++)
464 { 430 {
465 total += linein[ptrn]*CosineTable16[ptru]; 431 QuantizeTable16[j * Constants.TerrainPatchSize + i] = oosob / (1.0f + 2.0f * (i + (float)j));
466 } 432 }
467
468 lineout[line + u] = total;
469 } 433 }
470 } 434 }
471 435
436 private static void BuildCopyMatrix16()
437 {
438 bool diag = false;
439 bool right = true;
440 int i = 0;
441 int j = 0;
442 int count = 0;
443
444 while (i < Constants.TerrainPatchSize && j < Constants.TerrainPatchSize)
445 {
446 CopyMatrix16[j * Constants.TerrainPatchSize + i] = count++;
472 447
473 /* 448 if (!diag)
474 private static void DCTColumn16(float[] linein, int[] lineout, int column)
475 { 449 {
476 float total = 0.0f; 450 if (right)
477 // const float oosob = 2.0f / Constants.TerrainPatchSize;
478
479 for (int n = 0; n < Constants.TerrainPatchSize; n++)
480 { 451 {
481 total += linein[Constants.TerrainPatchSize * n + column]; 452 if (i < Constants.TerrainPatchSize - 1) i++;
482 } 453 else j++;
483
484 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
485 lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * QuantizeTable16[column]);
486 454
487 for (int uptr = Constants.TerrainPatchSize; uptr < Constants.TerrainPatchSize * Constants.TerrainPatchSize; uptr += Constants.TerrainPatchSize) 455 right = false;
456 diag = true;
457 }
458 else
488 { 459 {
489 total = 0.0f; 460 if (j < Constants.TerrainPatchSize - 1) j++;
490 461 else i++;
491 for (int n = 0; n < Constants.TerrainPatchSize; n++)
492 {
493 total += linein[Constants.TerrainPatchSize * n + column] * CosineTable16[uptr + n];
494 }
495 462
496 // lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]); 463 right = true;
497 lineout[CopyMatrix16[uptr + column]] = (int)(total * QuantizeTable16[uptr + column]); 464 diag = true;
498 } 465 }
466 }
467 else
468 {
469 if (right)
470 {
471 i++;
472 j--;
473 if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false;
474 }
475 else
476 {
477 i--;
478 j++;
479 if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false;
480 }
499 } 481 }
482 }
483 }
500 484
501 private static void DCTColumn16(float[] linein, int[] lineout, int column) 485 #endregion Initialization
502 {
503 // input columns are in fact stored in lines now
504 486
505 float total = 0.0f;
506// const float oosob = 2.0f / Constants.TerrainPatchSize;
507 int inlinesptr = Constants.TerrainPatchSize*column;
508 487
509 for (int n = 0; n < Constants.TerrainPatchSize; n++)
510 {
511 total += linein[inlinesptr + n];
512 }
513 488
514 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]);
515 lineout[CopyMatrix16[column]] = (int) (OO_SQRT2*total*QuantizeTable16[column]);
516 489
517 for (int uptr = Constants.TerrainPatchSize; 490 #region DCT
518 uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize;
519 uptr += Constants.TerrainPatchSize)
520 {
521 total = 0.0f;
522 491
523 for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++) 492 /* DCT (Discrete Cosine Transform)
524 { 493 adaptation from
525 total += linein[n]*CosineTable16[ptru]; 494 General Purpose 2D,3D FFT (Fast Fourier Transform) Package
526 } 495 by Takuya OOURA (email: ooura@kurims.kyoto-u.ac.jp)
527 496
528// lineout[CopyMatrix16[Constants.TerrainPatchSize * u + column]] = (int)(total * oosob * QuantizeTable16[Constants.TerrainPatchSize * u + column]); 497 -------- 16x16 DCT (Discrete Cosine Transform) / Inverse of DCT --------
529 lineout[CopyMatrix16[uptr + column]] = (int) (total*QuantizeTable16[uptr + column]); 498 [definition]
530 } 499 <case1> Normalized 16x16 IDCT
531 } 500 C[k1 + k2] = (1/8) * sum_j1=0^15 sum_j2=0^15
501 tmp[j1 + j2] * s[j1] * s[j2] *
502 cos(pi*j1*(k1+1/2)/16) *
503 cos(pi*j2*(k2+1/2)/16), 0<=k1<16, 0<=k2<16
504 (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
505 <case2> Normalized 16x16 DCT
506 C[k1 + k2] = (1/8) * s[k1] * s[k2] * sum_j1=0^15 sum_j2=0^15
507 tmp[j1 + j2] *
508 cos(pi*(j1+1/2)*k1/16) *
509 cos(pi*(j2+1/2)*k2/16), 0<=k1<16, 0<=k2<16
510 (s[0] = 1/sqrt(2), s[j] = 1, j > 0)
532 */ 511 */
533 512
534 private static int DCTColumn16Wbits(float[] linein, int[] lineout, int column, int wbits, int maxwbits) 513 /* Cn_kR = sqrt(2.0/n) * cos(pi/2*k/n) */
514 /* Cn_kI = sqrt(2.0/n) * sin(pi/2*k/n) */
515 /* Wn_kR = cos(pi/2*k/n) */
516 /* Wn_kI = sin(pi/2*k/n) */
517
518 const float C16_1R = 0.35185093438159561476f * 2.82842712474619f;
519 const float C16_1I = 0.03465429229977286565f * 2.82842712474619f;
520 const float C16_2R = 0.34675996133053686546f * 2.82842712474619f;
521 const float C16_2I = 0.06897484482073575308f * 2.82842712474619f;
522 const float C16_3R = 0.33832950029358816957f * 2.82842712474619f;
523 const float C16_3I = 0.10263113188058934529f * 2.82842712474619f;
524 const float C16_4R = 0.32664074121909413196f * 2.82842712474619f;
525 const float C16_4I = 0.13529902503654924610f * 2.82842712474619f;
526 const float C16_5R = 0.31180625324666780814f * 2.82842712474619f;
527 const float C16_5I = 0.16666391461943662432f * 2.82842712474619f;
528 const float C16_6R = 0.29396890060483967924f * 2.82842712474619f;
529 const float C16_6I = 0.19642373959677554532f * 2.82842712474619f;
530 const float C16_7R = 0.27330046675043937206f * 2.82842712474619f;
531 const float C16_7I = 0.22429189658565907106f * 2.82842712474619f;
532 const float C16_8R = 0.25f * 2.82842712474619f;
533 const float W16_4R = 0.92387953251128675613f;
534 const float W16_4I = 0.38268343236508977173f;
535 const float W16_8R = 0.70710678118654752440f;
536
537 static void dct16x16(float[] a, int[] iout, ref int wbits)
535 { 538 {
536 // input columns are in fact stored in lines now 539 float[] tmp = new float[Constants.TerrainPatchSize * Constants.TerrainPatchSize];
537 540
538 bool dowbits = wbits != maxwbits; 541 float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
539 int wbitsMaxValue = 1 << wbits; 542 float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
543 float xr, xi;
544 float ftmp;
540 545
541 float total = 0.0f; 546 int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
542 // const float oosob = 2.0f / Constants.TerrainPatchSize; 547 int itmp;
543 int inlinesptr = Constants.TerrainPatchSize*column; 548 int j, k;
549 int indx;
544 550
545 for (int n = 0; n < Constants.TerrainPatchSize; n++) 551 const int maxwbits = 17; // per header encoding
552 int wbitsMaxValue = 1 << wbits;
553 bool dowbits = wbits < 17;
554
555 for (j = 0, k = 0; j < fullSize; j += Constants.TerrainPatchSize, k++)
546 { 556 {
547 total += linein[inlinesptr + n]; 557 x4r = a[0 + j] - a[15 + j];
558 xr = a[0 + j] + a[15 + j];
559 x4i = a[8 + j] - a[7 + j];
560 xi = a[8 + j] + a[7 + j];
561 x0r = xr + xi;
562 x0i = xr - xi;
563 x5r = a[2 + j] - a[13 + j];
564 xr = a[2 + j] + a[13 + j];
565 x5i = a[10 + j] - a[5 + j];
566 xi = a[10 + j] + a[5 + j];
567 x1r = xr + xi;
568 x1i = xr - xi;
569 x6r = a[4 + j] - a[11 + j];
570 xr = a[4 + j] + a[11 + j];
571 x6i = a[12 + j] - a[3 + j];
572 xi = a[12 + j] + a[3 + j];
573 x2r = xr + xi;
574 x2i = xr - xi;
575 x7r = a[6 + j] - a[9 + j];
576 xr = a[6 + j] + a[9 + j];
577 x7i = a[14 + j] - a[1 + j];
578 xi = a[14 + j] + a[1 + j];
579 x3r = xr + xi;
580 x3i = xr - xi;
581 xr = x0r + x2r;
582 xi = x1r + x3r;
583 tmp[k] = C16_8R * (xr + xi); //
584 tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
585 xr = x0r - x2r;
586 xi = x1r - x3r;
587 tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
588 tmp[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
589 x0r = W16_8R * (x1i - x3i);
590 x2r = W16_8R * (x1i + x3i);
591 xr = x0i + x0r;
592 xi = x2r + x2i;
593 tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
594 tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
595 xr = x0i - x0r;
596 xi = x2r - x2i;
597 tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
598 tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
599 xr = W16_8R * (x6r - x6i);
600 xi = W16_8R * (x6i + x6r);
601 x6r = x4r - xr;
602 x6i = x4i - xi;
603 x4r += xr;
604 x4i += xi;
605 xr = W16_4I * x7r - W16_4R * x7i;
606 xi = W16_4I * x7i + W16_4R * x7r;
607 x7r = W16_4R * x5r - W16_4I * x5i;
608 x7i = W16_4R * x5i + W16_4I * x5r;
609 x5r = x7r + xr;
610 x5i = x7i + xi;
611 x7r -= xr;
612 x7i -= xi;
613 xr = x4r + x5r;
614 xi = x5i + x4i;
615 tmp[Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
616 tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
617 xr = x4r - x5r;
618 xi = x5i - x4i;
619 tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
620 tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
621 xr = x6r - x7i;
622 xi = x7r + x6i;
623 tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
624 tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
625 xr = x6r + x7i;
626 xi = x7r - x6i;
627 tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
628 tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
548 } 629 }
549 630
550 // lineout[CopyMatrix16[column]] = (int)(OO_SQRT2 * total * oosob * QuantizeTable16[column]); 631 for (j = 0, k = 0; j < fullSize; j += Constants.TerrainPatchSize, k++)
551 int tmp = (int) (OO_SQRT2*total*QuantizeTable16[column]);
552 lineout[CopyMatrix16[column]] = tmp;
553
554 if (dowbits)
555 { 632 {
556 if (tmp < 0) tmp *= -1; 633 x4r = tmp[0 + j] - tmp[15 + j];
557 while (tmp > wbitsMaxValue) 634 xr = tmp[0 + j] + tmp[15 + j];
635 x4i = tmp[8 + j] - tmp[7 + j];
636 xi = tmp[8 + j] + tmp[7 + j];
637 x0r = xr + xi;
638 x0i = xr - xi;
639 x5r = tmp[2 + j] - tmp[13 + j];
640 xr = tmp[2 + j] + tmp[13 + j];
641 x5i = tmp[10 + j] - tmp[5 + j];
642 xi = tmp[10 + j] + tmp[5 + j];
643 x1r = xr + xi;
644 x1i = xr - xi;
645 x6r = tmp[4 + j] - tmp[11 + j];
646 xr = tmp[4 + j] + tmp[11 + j];
647 x6i = tmp[12 + j] - tmp[3 + j];
648 xi = tmp[12 + j] + tmp[3 + j];
649 x2r = xr + xi;
650 x2i = xr - xi;
651 x7r = tmp[6 + j] - tmp[9 + j];
652 xr = tmp[6 + j] + tmp[9 + j];
653 x7i = tmp[14 + j] - tmp[1 + j];
654 xi = tmp[14 + j] + tmp[1 + j];
655 x3r = xr + xi;
656 x3i = xr - xi;
657 xr = x0r + x2r;
658 xi = x1r + x3r;
659
660 //tmp[0 + k] = C16_8R * (xr + xi); //
661 ftmp = C16_8R * (xr + xi);
662 itmp = (int)(ftmp * QuantizeTable16[k]);
663 iout[CopyMatrix16[k]] = itmp;
664
665 if (dowbits)
558 { 666 {
559 wbits++; 667 if (itmp < 0) itmp *= -1;
560 wbitsMaxValue = 1 << wbits; 668 while (itmp > wbitsMaxValue)
561 if (wbits == maxwbits)
562 { 669 {
563 dowbits = false; 670 wbits++;
564 break; 671 wbitsMaxValue = 1 << wbits;
672 if (wbits == maxwbits)
673 {
674 dowbits = false;
675 break;
676 }
565 } 677 }
566 } 678 }
567 }
568 679
569 for (int uptr = Constants.TerrainPatchSize; 680 //tmp[8 * Constants.TerrainPatchSize + k] = C16_8R * (xr - xi); //
570 uptr < Constants.TerrainPatchSize*Constants.TerrainPatchSize; 681 ftmp = C16_8R * (xr - xi);
571 uptr += Constants.TerrainPatchSize) 682 indx = 8 * Constants.TerrainPatchSize + k;
572 { 683 itmp = (int)(ftmp * QuantizeTable16[indx]);
573 total = 0.0f; 684 iout[CopyMatrix16[indx]] = itmp;
574 685
575 for (int n = inlinesptr, ptru = uptr; n < inlinesptr + Constants.TerrainPatchSize; n++, ptru++) 686 if (dowbits)
576 { 687 {
577 total += linein[n]*CosineTable16[ptru]; 688 if (itmp < 0) itmp *= -1;
689 while (itmp > wbitsMaxValue)
690 {
691 wbits++;
692 wbitsMaxValue = 1 << wbits;
693 if (wbits == maxwbits)
694 {
695 dowbits = false;
696 break;
697 }
698 }
578 } 699 }
579 700
580 tmp = (int) (total*QuantizeTable16[uptr + column]); 701 xr = x0r - x2r;
581 lineout[CopyMatrix16[uptr + column]] = tmp; 702 xi = x1r - x3r;
703
704 //tmp[4 * Constants.TerrainPatchSize + k] = C16_4R * xr - C16_4I * xi; //
705 ftmp = C16_4R * xr - C16_4I * xi;
706 indx = 4 * Constants.TerrainPatchSize + k;
707 itmp = (int)(ftmp * QuantizeTable16[indx]);
708 iout[CopyMatrix16[indx]] = itmp;
582 709
583 if (dowbits) 710 if (dowbits)
584 { 711 {
585 if (tmp < 0) tmp *= -1; 712 if (itmp < 0) itmp *= -1;
586 while (tmp > wbitsMaxValue) 713 while (itmp > wbitsMaxValue)
587 { 714 {
588 wbits++; 715 wbits++;
589 wbitsMaxValue = 1 << wbits; 716 wbitsMaxValue = 1 << wbits;
@@ -594,355 +721,605 @@ namespace OpenSim.Region.ClientStack.LindenUDP
594 } 721 }
595 } 722 }
596 } 723 }
597 }
598 return wbits;
599 }
600 724
601 public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size) 725 //tmp[12 * Constants.TerrainPatchSize + k] = C16_4R * xi + C16_4I * xr; //
602 { 726 ftmp = C16_4R * xi + C16_4I * xr;
603 for (int n = 0; n < size*size; n++) 727 indx = 12 * Constants.TerrainPatchSize + k;
604 { 728 itmp = (int)(ftmp * QuantizeTable16[indx]);
605 // ? 729 iout[CopyMatrix16[indx]] = itmp;
606 int temp = bitpack.UnpackBits(1); 730
607 if (temp != 0) 731 if (dowbits)
608 { 732 {
609 // Value or EOB 733 if (itmp < 0) itmp *= -1;
610 temp = bitpack.UnpackBits(1); 734 while (itmp > wbitsMaxValue)
611 if (temp != 0)
612 { 735 {
613 // Value 736 wbits++;
614 temp = bitpack.UnpackBits(1); 737 wbitsMaxValue = 1 << wbits;
615 if (temp != 0) 738 if (wbits == maxwbits)
616 {
617 // Negative
618 temp = bitpack.UnpackBits((int) header.WordBits);
619 patches[n] = temp*-1;
620 }
621 else
622 { 739 {
623 // Positive 740 dowbits = false;
624 temp = bitpack.UnpackBits((int) header.WordBits); 741 break;
625 patches[n] = temp;
626 } 742 }
627 } 743 }
628 else 744 }
745
746 x0r = W16_8R * (x1i - x3i);
747 x2r = W16_8R * (x1i + x3i);
748 xr = x0i + x0r;
749 xi = x2r + x2i;
750
751 //tmp[2 * Constants.TerrainPatchSize + k] = C16_2R * xr - C16_2I * xi; //
752 ftmp = C16_2R * xr - C16_2I * xi;
753 indx = 2 * Constants.TerrainPatchSize + k;
754 itmp = (int)(ftmp * QuantizeTable16[indx]);
755 iout[CopyMatrix16[indx]] = itmp;
756
757 if (dowbits)
758 {
759 if (itmp < 0) itmp *= -1;
760 while (itmp > wbitsMaxValue)
629 { 761 {
630 // Set the rest to zero 762 wbits++;
631 // TODO: This might not be necessary 763 wbitsMaxValue = 1 << wbits;
632 for (int o = n; o < size*size; o++) 764 if (wbits == maxwbits)
633 { 765 {
634 patches[o] = 0; 766 dowbits = false;
767 break;
635 } 768 }
636 break;
637 } 769 }
638 } 770 }
639 else
640 {
641 patches[n] = 0;
642 }
643 }
644 }
645 771
646 private static void EncodePatch(BitPack output, int[] patch, int postquant, int wbits) 772 //tmp[14 * Constants.TerrainPatchSize + k] = C16_2R * xi + C16_2I * xr; //
647 { 773 ftmp = C16_2R * xi + C16_2I * xr;
648 int maxwbitssize = (1 << wbits) - 1; 774 indx = 14 * Constants.TerrainPatchSize + k;
775 itmp = (int)(ftmp * QuantizeTable16[indx]);
776 iout[CopyMatrix16[indx]] = itmp;
649 777
650 if (postquant > Constants.TerrainPatchSize*Constants.TerrainPatchSize || postquant < 0) 778 if (dowbits)
651 { 779 {
652 Logger.Log("Postquant is outside the range of allowed values in EncodePatch()", Helpers.LogLevel.Error); 780 if (itmp < 0) itmp *= -1;
653 return; 781 while (itmp > wbitsMaxValue)
654 } 782 {
783 wbits++;
784 wbitsMaxValue = 1 << wbits;
785 if (wbits == maxwbits)
786 {
787 dowbits = false;
788 break;
789 }
790 }
791 }
655 792
656 if (postquant != 0) patch[Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant] = 0; 793 xr = x0i - x0r;
794 xi = x2r - x2i;
657 795
658 for (int i = 0; i < Constants.TerrainPatchSize*Constants.TerrainPatchSize; i++) 796 //tmp[6 * Constants.TerrainPatchSize + k] = C16_6R * xr - C16_6I * xi; //
659 { 797 ftmp = C16_6R * xr - C16_6I * xi;
660 int temp = patch[i]; 798 indx = 6 * Constants.TerrainPatchSize + k;
799 itmp = (int)(ftmp * QuantizeTable16[indx]);
800 iout[CopyMatrix16[indx]] = itmp;
661 801
662 if (temp == 0) 802 if (dowbits)
663 { 803 {
664 bool eob = true; 804 if (itmp < 0) itmp *= -1;
665 805 while (itmp > wbitsMaxValue)
666 for (int j = i; j < Constants.TerrainPatchSize*Constants.TerrainPatchSize - postquant; j++)
667 { 806 {
668 if (patch[j] != 0) 807 wbits++;
808 wbitsMaxValue = 1 << wbits;
809 if (wbits == maxwbits)
669 { 810 {
670 eob = false; 811 dowbits = false;
671 break; 812 break;
672 } 813 }
673 } 814 }
815 }
674 816
675 if (eob) 817 //tmp[10 * Constants.TerrainPatchSize + k] = C16_6R * xi + C16_6I * xr; //
818 ftmp = C16_6R * xi + C16_6I * xr;
819 indx = 10 * Constants.TerrainPatchSize + k;
820 itmp = (int)(ftmp * QuantizeTable16[indx]);
821 iout[CopyMatrix16[indx]] = itmp;
822
823 if (dowbits)
824 {
825 if (itmp < 0) itmp *= -1;
826 while (itmp > wbitsMaxValue)
676 { 827 {
677 output.PackBits(ZERO_EOB, 2); 828 wbits++;
678 return; 829 wbitsMaxValue = 1 << wbits;
830 if (wbits == maxwbits)
831 {
832 dowbits = false;
833 break;
834 }
679 } 835 }
680 output.PackBits(ZERO_CODE, 1);
681 } 836 }
682 else
683 {
684 if (temp < 0)
685 {
686 temp *= -1;
687 837
688 if (temp > maxwbitssize) temp = maxwbitssize; 838 xr = W16_8R * (x6r - x6i);
839 xi = W16_8R * (x6i + x6r);
840 x6r = x4r - xr;
841 x6i = x4i - xi;
842 x4r += xr;
843 x4i += xi;
844 xr = W16_4I * x7r - W16_4R * x7i;
845 xi = W16_4I * x7i + W16_4R * x7r;
846 x7r = W16_4R * x5r - W16_4I * x5i;
847 x7i = W16_4R * x5i + W16_4I * x5r;
848 x5r = x7r + xr;
849 x5i = x7i + xi;
850 x7r -= xr;
851 x7i -= xi;
852 xr = x4r + x5r;
853 xi = x5i + x4i;
854
855 //tmp[1 * Constants.TerrainPatchSize + k] = C16_1R * xr - C16_1I * xi; //
856 ftmp = C16_1R * xr - C16_1I * xi;
857 indx = Constants.TerrainPatchSize + k;
858 itmp = (int)(ftmp * QuantizeTable16[indx]);
859 iout[CopyMatrix16[indx]] = itmp;
689 860
690 output.PackBits(NEGATIVE_VALUE, 3); 861 if (dowbits)
691 output.PackBits(temp, wbits); 862 {
692 } 863 if (itmp < 0) itmp *= -1;
693 else 864 while (itmp > wbitsMaxValue)
694 { 865 {
695 if (temp > maxwbitssize) temp = maxwbitssize; 866 wbits++;
696 867 wbitsMaxValue = 1 << wbits;
697 output.PackBits(POSITIVE_VALUE, 3); 868 if (wbits == maxwbits)
698 output.PackBits(temp, wbits); 869 {
870 dowbits = false;
871 break;
872 }
699 } 873 }
700 } 874 }
701 }
702 }
703 875
704 public static float[] DecompressPatch(int[] patches, TerrainPatch.Header header, TerrainPatch.GroupHeader group) 876 //tmp[15 * Constants.TerrainPatchSize + k] = C16_1R * xi + C16_1I * xr; //
705 { 877 ftmp = C16_1R * xi + C16_1I * xr;
706 float[] block = new float[group.PatchSize*group.PatchSize]; 878 indx = 15 * Constants.TerrainPatchSize + k;
707 float[] output = new float[group.PatchSize*group.PatchSize]; 879 itmp = (int)(ftmp * QuantizeTable16[indx]);
708 int prequant = (header.QuantWBits >> 4) + 2; 880 iout[CopyMatrix16[indx]] = itmp;
709 int quantize = 1 << prequant; 881
710 float ooq = 1.0f/quantize; 882 if (dowbits)
711 float mult = ooq*header.Range;
712 float addval = mult*(1 << (prequant - 1)) + header.DCOffset;
713
714 if (group.PatchSize == Constants.TerrainPatchSize)
715 {
716 for (int n = 0; n < Constants.TerrainPatchSize*Constants.TerrainPatchSize; n++)
717 { 883 {
718 block[n] = patches[CopyMatrix16[n]]*DequantizeTable16[n]; 884 if (itmp < 0) itmp *= -1;
885 while (itmp > wbitsMaxValue)
886 {
887 wbits++;
888 wbitsMaxValue = 1 << wbits;
889 if (wbits == maxwbits)
890 {
891 dowbits = false;
892 break;
893 }
894 }
719 } 895 }
720 896
721 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 897 xr = x4r - x5r;
898 xi = x5i - x4i;
722 899
723 for (int o = 0; o < Constants.TerrainPatchSize; o++) 900 //tmp[7 * Constants.TerrainPatchSize + k] = C16_7R * xr - C16_7I * xi; //
724 IDCTColumn16(block, ftemp, o); 901 ftmp = C16_7R * xr - C16_7I * xi;
725 for (int o = 0; o < Constants.TerrainPatchSize; o++) 902 indx = 7 * Constants.TerrainPatchSize + k;
726 IDCTLine16(ftemp, block, o); 903 itmp = (int)(ftmp * QuantizeTable16[indx]);
727 } 904 iout[CopyMatrix16[indx]] = itmp;
728 else 905
729 { 906 if (dowbits)
730 for (int n = 0; n < Constants.TerrainPatchSize*2*Constants.TerrainPatchSize*2; n++)
731 { 907 {
732 block[n] = patches[CopyMatrix32[n]]*DequantizeTable32[n]; 908 if (itmp < 0) itmp *= -1;
909 while (itmp > wbitsMaxValue)
910 {
911 wbits++;
912 wbitsMaxValue = 1 << wbits;
913 if (wbits == maxwbits)
914 {
915 dowbits = false;
916 break;
917 }
918 }
733 } 919 }
734 920
735 Logger.Log("Implement IDCTPatchLarge", Helpers.LogLevel.Error); 921 //tmp[9 * Constants.TerrainPatchSize + k] = C16_7R * xi + C16_7I * xr; //
736 } 922 ftmp = C16_7R * xi + C16_7I * xr;
737 923 indx = 9 * Constants.TerrainPatchSize + k;
738 for (int j = 0; j < block.Length; j++) 924 itmp = (int)(ftmp * QuantizeTable16[indx]);
739 { 925 iout[CopyMatrix16[indx]] = itmp;
740 output[j] = block[j]*mult + addval;
741 }
742
743 return output;
744 }
745 926
746 private static int[] CompressPatch(float[] patchData, TerrainPatch.Header header, int prequant, out int wbits) 927 if (dowbits)
747 { 928 {
748 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 929 if (itmp < 0) itmp *= -1;
749 int wordsize = (prequant - 2) & 0x0f; 930 while (itmp > wbitsMaxValue)
750 float oozrange = 1.0f/header.Range; 931 {
751 float range = (1 << prequant); 932 wbits++;
752 float premult = oozrange*range; 933 wbitsMaxValue = 1 << wbits;
753 float sub = (1 << (prequant - 1)) + header.DCOffset*premult; 934 if (wbits == maxwbits)
935 {
936 dowbits = false;
937 break;
938 }
939 }
940 }
754 941
755 header.QuantWBits = wordsize; 942 xr = x6r - x7i;
756 header.QuantWBits |= wordsize << 4; 943 xi = x7r + x6i;
757 944
758 int k = 0; 945 //tmp[5 * Constants.TerrainPatchSize + k] = C16_5R * xr - C16_5I * xi; //
759 for (int j = 0; j < Constants.TerrainPatchSize; j++) 946 ftmp = C16_5R * xr - C16_5I * xi;
760 { 947 indx = 5 * Constants.TerrainPatchSize + k;
761 for (int i = 0; i < Constants.TerrainPatchSize; i++) 948 itmp = (int)(ftmp * QuantizeTable16[indx]);
762 block[k++] = patchData[j*Constants.TerrainPatchSize + i]*premult - sub; 949 iout[CopyMatrix16[indx]] = itmp;
763 }
764 950
765 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 951 if (dowbits)
766 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 952 {
953 if (itmp < 0) itmp *= -1;
954 while (itmp > wbitsMaxValue)
955 {
956 wbits++;
957 wbitsMaxValue = 1 << wbits;
958 if (wbits == maxwbits)
959 {
960 dowbits = false;
961 break;
962 }
963 }
964 }
767 965
966 //tmp[11 * Constants.TerrainPatchSize + k] = C16_5R * xi + C16_5I * xr; //
967 ftmp = C16_5R * xi + C16_5I * xr;
968 indx = 11 * Constants.TerrainPatchSize + k;
969 itmp = (int)(ftmp * QuantizeTable16[indx]);
970 iout[CopyMatrix16[indx]] = itmp;
768 971
769 int maxWbits = prequant + 5; 972 if (dowbits)
770 wbits = (prequant >> 1); 973 {
974 if (itmp < 0) itmp *= -1;
975 while (itmp > wbitsMaxValue)
976 {
977 wbits++;
978 wbitsMaxValue = 1 << wbits;
979 if (wbits == maxwbits)
980 {
981 dowbits = false;
982 break;
983 }
984 }
985 }
771 986
772 for (int o = 0; o < Constants.TerrainPatchSize; o++) 987 xr = x6r + x7i;
773 DCTLine16(block, ftemp, o); 988 xi = x7r - x6i;
774 for (int o = 0; o < Constants.TerrainPatchSize; o++)
775 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
776 989
777 return itemp; 990 //tmp[3 * Constants.TerrainPatchSize + k] = C16_3R * xr - C16_3I * xi; //
778 } 991 ftmp = C16_3R * xr - C16_3I * xi;
992 indx = 3 * Constants.TerrainPatchSize + k;
993 itmp = (int)(ftmp * QuantizeTable16[indx]);
994 iout[CopyMatrix16[indx]] = itmp;
779 995
780 private static int[] CompressPatch(float[,] patchData, TerrainPatch.Header header, int prequant, out int wbits) 996 if (dowbits)
781 { 997 {
782 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 998 if (itmp < 0) itmp *= -1;
783 float oozrange = 1.0f/header.Range; 999 while (itmp > wbitsMaxValue)
784 float range = (1 << prequant); 1000 {
785 float premult = oozrange*range; 1001 wbits++;
786 float sub = (1 << (prequant - 1)) + header.DCOffset*premult; 1002 wbitsMaxValue = 1 << wbits;
787 int wordsize = (prequant - 2) & 0x0f; 1003 if (wbits == maxwbits)
1004 {
1005 dowbits = false;
1006 break;
1007 }
1008 }
1009 }
788 1010
789 header.QuantWBits = wordsize; 1011 //tmp[13 * Constants.TerrainPatchSize + k] = C16_3R * xi + C16_3I * xr; //
790 header.QuantWBits |= wordsize << 4; 1012 ftmp = C16_3R * xi + C16_3I * xr;
1013 indx = 13 * Constants.TerrainPatchSize + k;
1014 itmp = (int)(ftmp * QuantizeTable16[indx]);
1015 iout[CopyMatrix16[indx]] = itmp;
791 1016
792 int k = 0; 1017 if (dowbits)
793 for (int j = 0; j < Constants.TerrainPatchSize; j++) 1018 {
794 { 1019 if (itmp < 0) itmp *= -1;
795 for (int i = 0; i < Constants.TerrainPatchSize; i++) 1020 while (itmp > wbitsMaxValue)
796 block[k++] = patchData[j, i]*premult - sub; 1021 {
1022 wbits++;
1023 wbitsMaxValue = 1 << wbits;
1024 if (wbits == maxwbits)
1025 {
1026 dowbits = false;
1027 break;
1028 }
1029 }
1030 }
797 } 1031 }
1032 }
798 1033
799 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 1034 #endregion DCT
800 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
801
802 int maxWbits = prequant + 5;
803 wbits = (prequant >> 1);
804 1035
805 for (int o = 0; o < Constants.TerrainPatchSize; o++) 1036 #region Decode
806 DCTLine16(block, ftemp, o); 1037 /*
807 for (int o = 0; o < Constants.TerrainPatchSize; o++) 1038 public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
808 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits); 1039 {
1040 TerrainPatch.Header header = new TerrainPatch.Header { QuantWBits = bitpack.UnpackBits(8) };
809 1041
810 return itemp; 1042 // Quantized word bits
811 } 1043 if (header.QuantWBits == END_OF_PATCHES)
1044 return header;
812 1045
813 private static int[] CompressPatch(TerrainData terrData, int patchX, int patchY, TerrainPatch.Header header, 1046 // DC offset
814 int prequant, out int wbits) 1047 header.DCOffset = bitpack.UnpackFloat();
815 {
816 float[] block = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize];
817 int wordsize = prequant;
818 float oozrange = 1.0f/header.Range;
819 float range = (1 << prequant);
820 float premult = oozrange*range;
821 float sub = (1 << (prequant - 1)) + header.DCOffset*premult;
822 1048
823 header.QuantWBits = wordsize - 2; 1049 // Range
824 header.QuantWBits |= (prequant - 2) << 4; 1050 header.Range = bitpack.UnpackBits(16);
825 1051
826 int k = 0; 1052 // Patch IDs (10 bits)
1053 header.PatchIDs = bitpack.UnpackBits(10);
827 1054
828 int yPatchLimit = patchY >= (terrData.SizeY / Constants.TerrainPatchSize) ? 1055 // Word bits
829 (terrData.SizeY - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchY; 1056 header.WordBits = (uint)((header.QuantWBits & 0x0f) + 2);
830 yPatchLimit = (yPatchLimit + 1) * Constants.TerrainPatchSize;
831 1057
832 int xPatchLimit = patchX >= (terrData.SizeX / Constants.TerrainPatchSize) ? 1058 return header;
833 (terrData.SizeX - Constants.TerrainPatchSize) / Constants.TerrainPatchSize : patchX; 1059 }
834 xPatchLimit = (xPatchLimit + 1) * Constants.TerrainPatchSize; 1060 */
835 1061
836 for (int yy = patchY * Constants.TerrainPatchSize; yy < yPatchLimit; yy++) 1062 /*
837 { 1063 public static void DecodePatch(int[] patches, BitPack bitpack, TerrainPatch.Header header, int size)
838 for (int xx = patchX * Constants.TerrainPatchSize; xx < xPatchLimit; xx++)
839 { 1064 {
840 block[k++] = terrData[xx, yy] * premult - sub; 1065 for (int n = 0; n < size * size; n++)
1066 {
1067 // ?
1068 int temp = bitpack.UnpackBits(1);
1069 if (temp != 0)
1070 {
1071 // Value or EOB
1072 temp = bitpack.UnpackBits(1);
1073 if (temp != 0)
1074 {
1075 // Value
1076 temp = bitpack.UnpackBits(1);
1077 if (temp != 0)
1078 {
1079 // Negative
1080 temp = bitpack.UnpackBits((int)header.WordBits);
1081 patches[n] = temp * -1;
1082 }
1083 else
1084 {
1085 // Positive
1086 temp = bitpack.UnpackBits((int)header.WordBits);
1087 patches[n] = temp;
1088 }
1089 }
1090 else
1091 {
1092 // Set the rest to zero
1093 // TODO: This might not be necessary
1094 for (int o = n; o < size * size; o++)
1095 {
1096 patches[o] = 0;
1097 }
1098 break;
1099 }
1100 }
1101 else
1102 {
1103 patches[n] = 0;
1104 }
1105 }
841 } 1106 }
842 } 1107 */
843 1108 #region IDCT
844 float[] ftemp = new float[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 1109 /* not in use
845 int[] itemp = new int[Constants.TerrainPatchSize*Constants.TerrainPatchSize]; 1110 private static void IDCTColumn16(float[] linein, float[] lineout, int column)
846
847 int maxWbits = prequant + 5;
848 wbits = (prequant >> 1);
849
850 for (int o = 0; o < Constants.TerrainPatchSize; o++)
851 DCTLine16(block, ftemp, o);
852 for (int o = 0; o < Constants.TerrainPatchSize; o++)
853 wbits = DCTColumn16Wbits(ftemp, itemp, o, wbits, maxWbits);
854
855 return itemp;
856 }
857
858 #region Initialization
859
860 private static void BuildDequantizeTable16()
861 { 1111 {
862 for (int j = 0; j < Constants.TerrainPatchSize; j++) 1112 for (int n = 0; n < Constants.TerrainPatchSize; n++)
863 { 1113 {
864 for (int i = 0; i < Constants.TerrainPatchSize; i++) 1114 float total = OO_SQRT2 * linein[column];
1115
1116 for (int u = 1; u < Constants.TerrainPatchSize; u++)
865 { 1117 {
866 DequantizeTable16[j*Constants.TerrainPatchSize + i] = 1.0f + 2.0f*(i + j); 1118 int usize = u * Constants.TerrainPatchSize;
1119 total += linein[usize + column] * CosineTable16[usize + n];
867 } 1120 }
1121
1122 lineout[Constants.TerrainPatchSize * n + column] = total;
868 } 1123 }
869 } 1124 }
870 1125
871 private static void BuildQuantizeTable16() 1126 private static void IDCTLine16(float[] linein, float[] lineout, int line)
872 { 1127 {
873 const float oosob = 2.0f/Constants.TerrainPatchSize; 1128 const float oosob = 2.0f / Constants.TerrainPatchSize;
874 for (int j = 0; j < Constants.TerrainPatchSize; j++) 1129 int lineSize = line * Constants.TerrainPatchSize;
1130
1131 for (int n = 0; n < Constants.TerrainPatchSize; n++)
875 { 1132 {
876 for (int i = 0; i < Constants.TerrainPatchSize; i++) 1133 float total = OO_SQRT2 * linein[lineSize];
1134
1135 for (int u = 1; u < Constants.TerrainPatchSize; u++)
877 { 1136 {
878// QuantizeTable16[j * Constants.TerrainPatchSize + i] = 1.0f / (1.0f + 2.0f * ((float)i + (float)j)); 1137 total += linein[lineSize + u] * CosineTable16[u * Constants.TerrainPatchSize + n];
879 QuantizeTable16[j*Constants.TerrainPatchSize + i] = oosob/(1.0f + 2.0f*(i + (float) j));
880 } 1138 }
1139
1140 lineout[lineSize + n] = total * oosob;
881 } 1141 }
882 } 1142 }
883 1143
1144/*
884 private static void SetupCosines16() 1145 private static void SetupCosines16()
885 { 1146 {
886 const float hposz = (float) Math.PI*0.5f/Constants.TerrainPatchSize; 1147 const float hposz = (float)Math.PI * 0.5f / Constants.TerrainPatchSize;
887 1148
888 for (int u = 0; u < Constants.TerrainPatchSize; u++) 1149 for (int u = 0; u < Constants.TerrainPatchSize; u++)
889 { 1150 {
890 for (int n = 0; n < Constants.TerrainPatchSize; n++) 1151 for (int n = 0; n < Constants.TerrainPatchSize; n++)
891 { 1152 {
892 CosineTable16[u*Constants.TerrainPatchSize + n] = (float) Math.Cos((2.0f*n + 1.0f)*u*hposz); 1153 CosineTable16[u * Constants.TerrainPatchSize + n] = (float)Math.Cos((2.0f * n + 1.0f) * u * hposz);
893 } 1154 }
894 } 1155 }
895 } 1156 }
1157*/
1158 //not in use, and still not fixed
1159 /*
1160 static void idct16x16(float[] a)
1161 {
1162 int j;
1163 float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
1164 float x4r, x4i, x5r, x5i, x6r, x6i, x7r, x7i;
1165 float xr, xi;
896 1166
897 private static void BuildCopyMatrix16() 1167 int fullSize = Constants.TerrainPatchSize * Constants.TerrainPatchSize;
898 {
899 bool diag = false;
900 bool right = true;
901 int i = 0;
902 int j = 0;
903 int count = 0;
904
905 while (i < Constants.TerrainPatchSize && j < Constants.TerrainPatchSize)
906 {
907 CopyMatrix16[j*Constants.TerrainPatchSize + i] = count++;
908
909 if (!diag)
910 {
911 if (right)
912 {
913 if (i < Constants.TerrainPatchSize - 1) i++;
914 else j++;
915
916 right = false;
917 diag = true;
918 }
919 else
920 {
921 if (j < Constants.TerrainPatchSize - 1) j++;
922 else i++;
923
924 right = true;
925 diag = true;
926 }
927 }
928 else
929 {
930 if (right)
931 {
932 i++;
933 j--;
934 if (i == Constants.TerrainPatchSize - 1 || j == 0) diag = false;
935 }
936 else
937 {
938 i--;
939 j++;
940 if (j == Constants.TerrainPatchSize - 1 || i == 0) diag = false;
941 }
942 }
943 }
944 }
945 1168
946 #endregion Initialization 1169 for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
1170 {
1171 x5r = C16_1R * tmp[1 + j] + C16_1I * tmp[15 + j];
1172 x5i = C16_1R * tmp[15 + j] - C16_1I * tmp[1 + j];
1173 xr = C16_7R * tmp[7 + j] + C16_7I * tmp[9 + j];
1174 xi = C16_7R * tmp[9 + j] - C16_7I * tmp[7 + j];
1175 x4r = x5r + xr;
1176 x4i = x5i - xi;
1177 x5r -= xr;
1178 x5i += xi;
1179 x7r = C16_5R * tmp[5 + j] + C16_5I * tmp[11 + j];
1180 x7i = C16_5R * tmp[11 + j] - C16_5I * tmp[5 + j];
1181 xr = C16_3R * tmp[3 + j] + C16_3I * tmp[13 + j];
1182 xi = C16_3R * tmp[13 + j] - C16_3I * tmp[3 + j];
1183 x6r = x7r + xr;
1184 x6i = x7i - xi;
1185 x7r -= xr;
1186 x7i += xi;
1187 xr = x4r - x6r;
1188 xi = x4i - x6i;
1189 x4r += x6r;
1190 x4i += x6i;
1191 x6r = W16_8R * (xi + xr);
1192 x6i = W16_8R * (xi - xr);
1193 xr = x5r + x7i;
1194 xi = x5i - x7r;
1195 x5r -= x7i;
1196 x5i += x7r;
1197 x7r = W16_4I * x5r + W16_4R * x5i;
1198 x7i = W16_4I * x5i - W16_4R * x5r;
1199 x5r = W16_4R * xr + W16_4I * xi;
1200 x5i = W16_4R * xi - W16_4I * xr;
1201 xr = C16_4R * tmp[4 + j] + C16_4I * tmp[12 + j];
1202 xi = C16_4R * tmp[12 + j] - C16_4I * tmp[4 + j];
1203 x2r = C16_8R * (tmp[0 + j] + tmp[8 + j]);
1204 x3r = C16_8R * (tmp[0 + j] - tmp[8 + j]);
1205 x0r = x2r + xr;
1206 x1r = x3r + xi;
1207 x2r -= xr;
1208 x3r -= xi;
1209 x0i = C16_2R * tmp[2 + j] + C16_2I * tmp[14 + j];
1210 x2i = C16_2R * tmp[14 + j] - C16_2I * tmp[2 + j];
1211 x1i = C16_6R * tmp[6 + j] + C16_6I * tmp[10 + j];
1212 x3i = C16_6R * tmp[10 + j] - C16_6I * tmp[6 + j];
1213 xr = x0i - x1i;
1214 xi = x2i + x3i;
1215 x0i += x1i;
1216 x2i -= x3i;
1217 x1i = W16_8R * (xi + xr);
1218 x3i = W16_8R * (xi - xr);
1219 xr = x0r + x0i;
1220 xi = x0r - x0i;
1221 tmp[0 + j] = xr + x4r;
1222 tmp[15 + j] = xr - x4r;
1223 tmp[8 + j] = xi + x4i;
1224 tmp[7 + j] = xi - x4i;
1225 xr = x1r + x1i;
1226 xi = x1r - x1i;
1227 tmp[2 + j] = xr + x5r;
1228 tmp[13 + j] = xr - x5r;
1229 tmp[10 + j] = xi + x5i;
1230 tmp[5 + j] = xi - x5i;
1231 xr = x2r + x2i;
1232 xi = x2r - x2i;
1233 tmp[4 + j] = xr + x6r;
1234 tmp[11 + j] = xr - x6r;
1235 tmp[12 + j] = xi + x6i;
1236 tmp[3 + j] = xi - x6i;
1237 xr = x3r + x3i;
1238 xi = x3r - x3i;
1239 tmp[6 + j] = xr + x7r;
1240 tmp[9 + j] = xr - x7r;
1241 tmp[14 + j] = xi + x7i;
1242 tmp[1 + j] = xi - x7i;
1243 }
1244 for (j = 0; j < fullSize; j += Constants.TerrainPatchSize)
1245 {
1246 x5r = C16_1R * tmp[j + 1] + C16_1I * tmp[j + 15];
1247 x5i = C16_1R * tmp[j + 15] - C16_1I * tmp[j + 1];
1248 xr = C16_7R * tmp[j + 7] + C16_7I * tmp[j + 9];
1249 xi = C16_7R * tmp[j + 9] - C16_7I * tmp[j + 7];
1250 x4r = x5r + xr;
1251 x4i = x5i - xi;
1252 x5r -= xr;
1253 x5i += xi;
1254 x7r = C16_5R * tmp[j + 5] + C16_5I * tmp[j + 11];
1255 x7i = C16_5R * tmp[j + 11] - C16_5I * tmp[j + 5];
1256 xr = C16_3R * tmp[j + 3] + C16_3I * tmp[j + 13];
1257 xi = C16_3R * tmp[j + 13] - C16_3I * tmp[j + 3];
1258 x6r = x7r + xr;
1259 x6i = x7i - xi;
1260 x7r -= xr;
1261 x7i += xi;
1262 xr = x4r - x6r;
1263 xi = x4i - x6i;
1264 x4r += x6r;
1265 x4i += x6i;
1266 x6r = W16_8R * (xi + xr);
1267 x6i = W16_8R * (xi - xr);
1268 xr = x5r + x7i;
1269 xi = x5i - x7r;
1270 x5r -= x7i;
1271 x5i += x7r;
1272 x7r = W16_4I * x5r + W16_4R * x5i;
1273 x7i = W16_4I * x5i - W16_4R * x5r;
1274 x5r = W16_4R * xr + W16_4I * xi;
1275 x5i = W16_4R * xi - W16_4I * xr;
1276 xr = C16_4R * tmp[j + 4] + C16_4I * tmp[j + 12];
1277 xi = C16_4R * tmp[j + 12] - C16_4I * tmp[j + 4];
1278 x2r = C16_8R * (tmp[j + 0] + tmp[j + 8]);
1279 x3r = C16_8R * (tmp[j + 0] - tmp[j + 8]);
1280 x0r = x2r + xr;
1281 x1r = x3r + xi;
1282 x2r -= xr;
1283 x3r -= xi;
1284 x0i = C16_2R * tmp[j + 2] + C16_2I * tmp[j + 14];
1285 x2i = C16_2R * tmp[j + 14] - C16_2I * tmp[j + 2];
1286 x1i = C16_6R * tmp[j + 6] + C16_6I * tmp[j + 10];
1287 x3i = C16_6R * tmp[j + 10] - C16_6I * tmp[j + 6];
1288 xr = x0i - x1i;
1289 xi = x2i + x3i;
1290 x0i += x1i;
1291 x2i -= x3i;
1292 x1i = W16_8R * (xi + xr);
1293 x3i = W16_8R * (xi - xr);
1294 xr = x0r + x0i;
1295 xi = x0r - x0i;
1296 tmp[j + 0] = xr + x4r;
1297 tmp[j + 15] = xr - x4r;
1298 tmp[j + 8] = xi + x4i;
1299 tmp[j + 7] = xi - x4i;
1300 xr = x1r + x1i;
1301 xi = x1r - x1i;
1302 tmp[j + 2] = xr + x5r;
1303 tmp[j + 13] = xr - x5r;
1304 tmp[j + 10] = xi + x5i;
1305 tmp[j + 5] = xi - x5i;
1306 xr = x2r + x2i;
1307 xi = x2r - x2i;
1308 tmp[j + 4] = xr + x6r;
1309 tmp[j + 11] = xr - x6r;
1310 tmp[j + 12] = xi + x6i;
1311 tmp[j + 3] = xi - x6i;
1312 xr = x3r + x3i;
1313 xi = x3r - x3i;
1314 tmp[j + 6] = xr + x7r;
1315 tmp[j + 9] = xr - x7r;
1316 tmp[j + 14] = xi + x7i;
1317 tmp[j + 1] = xi - x7i;
1318 }
1319 }
1320 */
1321 #endregion IDCT
1322 #endregion Decode
947 } 1323 }
1324
948} 1325}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs
index 0b196c1..dc3b717 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCopyTests.cs
@@ -42,6 +42,7 @@ using OpenSim.Tests.Common;
42 42
43namespace OpenSim.Region.Framework.Scenes.Tests 43namespace OpenSim.Region.Framework.Scenes.Tests
44{ 44{
45 /*
45 /// <summary> 46 /// <summary>
46 /// Test copying of scene objects. 47 /// Test copying of scene objects.
47 /// </summary> 48 /// </summary>
@@ -343,4 +344,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests
343 } 344 }
344 } 345 }
345 } 346 }
347 */
346} \ No newline at end of file 348} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
index 1c396ac..f980209 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectDeRezTests.cs
@@ -81,8 +81,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
81 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 81 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
82 82
83 TestScene scene = new SceneHelpers().SetupScene(); 83 TestScene scene = new SceneHelpers().SetupScene();
84 SceneHelpers.SetupSceneModules(scene, new PermissionsModule()); 84 IConfigSource configSource = new IniConfigSource();
85 TestClient client = (TestClient)SceneHelpers.AddScenePresence(scene, userId).ControllingClient; 85 IConfig config = configSource.AddConfig("Startup");
86 config.Set("serverside_object_permissions", true);
87 SceneHelpers.SetupSceneModules(scene, configSource, new object[] { new DefaultPermissionsModule() });
88 IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient;
86 89
87 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 90 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
88 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter; 91 AsyncSceneObjectGroupDeleter sogd = scene.SceneObjectGroupDeleter;
@@ -104,9 +107,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
104 107
105 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId); 108 SceneObjectPart retrievedPart2 = scene.GetSceneObjectPart(so.LocalId);
106 Assert.That(retrievedPart2, Is.Null); 109 Assert.That(retrievedPart2, Is.Null);
107
108 Assert.That(client.ReceivedKills.Count, Is.EqualTo(1));
109 Assert.That(client.ReceivedKills[0], Is.EqualTo(soLocalId));
110 } 110 }
111 111
112 /// <summary> 112 /// <summary>
@@ -133,7 +133,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
133 SceneHelpers.SetupSceneModules(sceneB, config, etmB); 133 SceneHelpers.SetupSceneModules(sceneB, config, etmB);
134 134
135 // We need this for derez 135 // We need this for derez
136 SceneHelpers.SetupSceneModules(sceneA, new PermissionsModule()); 136 //SceneHelpers.SetupSceneModules(sceneA, new PermissionsModule());
137 137
138 UserAccount uaA = UserAccountHelpers.CreateUserWithInventory(sceneA, "Andy", "AAA", 0x1, ""); 138 UserAccount uaA = UserAccountHelpers.CreateUserWithInventory(sceneA, "Andy", "AAA", 0x1, "");
139 UserAccount uaB = UserAccountHelpers.CreateUserWithInventory(sceneA, "Brian", "BBB", 0x2, ""); 139 UserAccount uaB = UserAccountHelpers.CreateUserWithInventory(sceneA, "Brian", "BBB", 0x2, "");
@@ -153,12 +153,6 @@ namespace OpenSim.Region.Framework.Scenes.Tests
153 uint soLocalId = so.LocalId; 153 uint soLocalId = so.LocalId;
154 154
155 sceneA.DeleteSceneObject(so, false); 155 sceneA.DeleteSceneObject(so, false);
156
157 Assert.That(clientA.ReceivedKills.Count, Is.EqualTo(1));
158 Assert.That(clientA.ReceivedKills[0], Is.EqualTo(soLocalId));
159
160 Assert.That(childClientsB[0].ReceivedKills.Count, Is.EqualTo(1));
161 Assert.That(childClientsB[0].ReceivedKills[0], Is.EqualTo(soLocalId));
162 } 156 }
163 157
164 /// <summary> 158 /// <summary>
@@ -177,7 +171,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
177 UUID objectOwnerId = UUID.Parse("20000000-0000-0000-0000-000000000001"); 171 UUID objectOwnerId = UUID.Parse("20000000-0000-0000-0000-000000000001");
178 172
179 TestScene scene = new SceneHelpers().SetupScene(); 173 TestScene scene = new SceneHelpers().SetupScene();
180 SceneHelpers.SetupSceneModules(scene, new PermissionsModule()); 174 IConfigSource configSource = new IniConfigSource();
175 IConfig config = configSource.AddConfig("Startup");
176 config.Set("serverside_object_permissions", true);
177 SceneHelpers.SetupSceneModules(scene, configSource, new object[] { new DefaultPermissionsModule() });
181 IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient; 178 IClientAPI client = SceneHelpers.AddScenePresence(scene, userId).ControllingClient;
182 179
183 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test. 180 // Turn off the timer on the async sog deleter - we'll crank it by hand for this test.
@@ -260,4 +257,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
260// Assert.That(retrievedPart, Is.Null); 257// Assert.That(retrievedPart, Is.Null);
261 } 258 }
262 } 259 }
263} \ No newline at end of file 260}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
index 975c4d9..9a665f6 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
@@ -60,6 +60,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
60 Assert.That(g1Post.RootPart.Scale.X, Is.EqualTo(2)); 60 Assert.That(g1Post.RootPart.Scale.X, Is.EqualTo(2));
61 Assert.That(g1Post.RootPart.Scale.Y, Is.EqualTo(3)); 61 Assert.That(g1Post.RootPart.Scale.Y, Is.EqualTo(3));
62 Assert.That(g1Post.RootPart.Scale.Z, Is.EqualTo(4)); 62 Assert.That(g1Post.RootPart.Scale.Z, Is.EqualTo(4));
63
64 Assert.That(g1Post.RootPart.UndoCount, Is.EqualTo(1));
63 } 65 }
64 66
65 /// <summary> 67 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
index aadf7c6..a92e364 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectUserGroupTests.cs
@@ -42,7 +42,7 @@ using OpenSim.Tests.Common;
42namespace OpenSim.Region.Framework.Scenes.Tests 42namespace OpenSim.Region.Framework.Scenes.Tests
43{ 43{
44 [TestFixture] 44 [TestFixture]
45 public class SceneObjectUserGroupTests : OpenSimTestCase 45 public class SceneObjectUserGroupTests
46 { 46 {
47 /// <summary> 47 /// <summary>
48 /// Test share with group object functionality 48 /// Test share with group object functionality
@@ -52,6 +52,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
52 public void TestShareWithGroup() 52 public void TestShareWithGroup()
53 { 53 {
54 TestHelpers.InMethod(); 54 TestHelpers.InMethod();
55// log4net.Config.XmlConfigurator.Configure();
55 56
56 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001"); 57 UUID userId = UUID.Parse("10000000-0000-0000-0000-000000000001");
57 58
@@ -68,7 +69,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
68 69
69 SceneHelpers.SetupSceneModules( 70 SceneHelpers.SetupSceneModules(
70 scene, configSource, new object[] 71 scene, configSource, new object[]
71 { new PermissionsModule(), 72 { new DefaultPermissionsModule(),
72 new GroupsModule(), 73 new GroupsModule(),
73 new MockGroupsServicesConnector() }); 74 new MockGroupsServicesConnector() });
74 75
@@ -79,4 +80,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
79 groupsModule.CreateGroup(client, "group1", "To boldly go", true, UUID.Zero, 5, true, true, true); 80 groupsModule.CreateGroup(client, "group1", "To boldly go", true, UUID.Zero, 5, true, true, true);
80 } 81 }
81 } 82 }
82} \ No newline at end of file 83}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
index 96d112d..568cd34 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs
@@ -44,6 +44,7 @@ using OpenSim.Region.CoreModules.World.Serialiser;
44using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation; 44using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
45using OpenSim.Tests.Common; 45using OpenSim.Tests.Common;
46using GridRegion = OpenSim.Services.Interfaces.GridRegion; 46using GridRegion = OpenSim.Services.Interfaces.GridRegion;
47using OpenSim.Services.Interfaces;
47 48
48namespace OpenSim.Region.Framework.Scenes.Tests 49namespace OpenSim.Region.Framework.Scenes.Tests
49{ 50{
@@ -226,7 +227,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
226 // *** This is the first stage, when a neighbouring region is told that a viewer is about to try and 227 // *** This is the first stage, when a neighbouring region is told that a viewer is about to try and
227 // establish a child scene presence. We pass in the circuit code that the client has to connect with *** 228 // establish a child scene presence. We pass in the circuit code that the client has to connect with ***
228 // XXX: ViaLogin may not be correct here. 229 // XXX: ViaLogin may not be correct here.
229 scene.SimulationService.CreateAgent(null, region, acd, (uint)TeleportFlags.ViaLogin, out reason); 230 EntityTransferContext ctx = new EntityTransferContext();
231 scene.SimulationService.CreateAgent(null, region, acd, (uint)TeleportFlags.ViaLogin, ctx, out reason);
230 232
231 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null); 233 Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(agentId), Is.Not.Null);
232 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); 234 Assert.That(scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1));
@@ -287,4 +289,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
287// Assert.That(childPresence.IsChildAgent, Is.True); 289// Assert.That(childPresence.IsChildAgent, Is.True);
288 } 290 }
289 } 291 }
290} \ No newline at end of file 292}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
index 2e6dc70..aa26767 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCapabilityTests.cs
@@ -73,14 +73,16 @@ namespace OpenSim.Region.Framework.Scenes.Tests
73 SceneHelpers.SetupSceneModules(scene, capsMod); 73 SceneHelpers.SetupSceneModules(scene, capsMod);
74 74
75 ScenePresence sp = SceneHelpers.AddChildScenePresence(scene, spUuid); 75 ScenePresence sp = SceneHelpers.AddChildScenePresence(scene, spUuid);
76 Assert.That(capsMod.GetCapsForUser(spUuid), Is.Not.Null); 76 //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Not.Null);
77 77
78 // TODO: Need to add tests for other ICapabiltiesModule methods. 78 // TODO: Need to add tests for other ICapabiltiesModule methods.
79 79
80// scene.IncomingCloseAgent(sp.UUID, false);
81// //Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
80 scene.CloseAgent(sp.UUID, false); 82 scene.CloseAgent(sp.UUID, false);
81 Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null); 83// Assert.That(capsMod.GetCapsForUser(spUuid), Is.Null);
82 84
83 // TODO: Need to add tests for other ICapabiltiesModule methods. 85 // TODO: Need to add tests for other ICapabiltiesModule methods.
84 } 86 }
85 } 87 }
86} \ No newline at end of file 88}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
index 7127644..37eec52 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceCrossingTests.cs
@@ -190,7 +190,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
190 // We need to set up the permisions module on scene B so that our later use of agent limit to deny 190 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
191 // QueryAccess won't succeed anyway because administrators are always allowed in and the default 191 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
192 // IsAdministrator if no permissions module is present is true. 192 // IsAdministrator if no permissions module is present is true.
193 SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new PermissionsModule(), etmB); 193// SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), new PermissionsModule(), etmB);
194 194
195 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); 195 AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
196 TestClient tc = new TestClient(acd, sceneA); 196 TestClient tc = new TestClient(acd, sceneA);
@@ -244,4 +244,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
244 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True); 244 Assert.That(spAfterCrossSceneB.IsChildAgent, Is.True);
245 } 245 }
246 } 246 }
247} \ No newline at end of file 247}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
index b232a44..8b194e6 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs
@@ -246,4 +246,4 @@ namespace OpenSim.Region.Framework.Scenes.Tests
246 Assert.That(m_sp.PhysicsActor, Is.Not.Null); 246 Assert.That(m_sp.PhysicsActor, Is.Not.Null);
247 } 247 }
248 } 248 }
249} \ No newline at end of file 249}
diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
index 443ec51..b8f7458 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceTeleportTests.cs
@@ -282,7 +282,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
282 // We need to set up the permisions module on scene B so that our later use of agent limit to deny 282 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
283 // QueryAccess won't succeed anyway because administrators are always allowed in and the default 283 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
284 // IsAdministrator if no permissions module is present is true. 284 // IsAdministrator if no permissions module is present is true.
285 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new PermissionsModule(), etmB }); 285 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new DefaultPermissionsModule(), etmB });
286 286
287 // Shared scene modules 287 // Shared scene modules
288 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); 288 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
@@ -447,7 +447,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
447 // We need to set up the permisions module on scene B so that our later use of agent limit to deny 447 // We need to set up the permisions module on scene B so that our later use of agent limit to deny
448 // QueryAccess won't succeed anyway because administrators are always allowed in and the default 448 // QueryAccess won't succeed anyway because administrators are always allowed in and the default
449 // IsAdministrator if no permissions module is present is true. 449 // IsAdministrator if no permissions module is present is true.
450 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new PermissionsModule(), etmB }); 450 SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new DefaultPermissionsModule(), etmB });
451 451
452 // Shared scene modules 452 // Shared scene modules
453 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm); 453 SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
index b01088d..33a630c 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
@@ -95,7 +95,7 @@ namespace OpenSim.Region.Framework.Tests
95 Quaternion rezRot = new Quaternion(0.5f, 0.5f, 0.5f, 0.5f); 95 Quaternion rezRot = new Quaternion(0.5f, 0.5f, 0.5f, 0.5f);
96 Vector3 rezVel = new Vector3(2, 2, 2); 96 Vector3 rezVel = new Vector3(2, 2, 2);
97 97
98 scene.RezObject(sop1, taskSceneObjectItem, rezPos, rezRot, rezVel, 0); 98 scene.RezObject(sop1, taskSceneObjectItem, rezPos, rezRot, rezVel, 0,false);
99 99
100 SceneObjectGroup rezzedObject = scene.GetSceneObjectGroup("tso"); 100 SceneObjectGroup rezzedObject = scene.GetSceneObjectGroup("tso");
101 101
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 860172c..7bbf1bd 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -27,202 +27,307 @@
27 27
28using System; 28using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic;
30using log4net; 31using log4net;
31using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
33 35
34namespace OpenSim.Region.Framework.Scenes 36namespace OpenSim.Region.Framework.Scenes
35{ 37{
36 public class UndoState 38 public class UndoState
37 { 39 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40 const int UNDOEXPIRESECONDS = 300; // undo expire time (nice to have it came from a ini later)
39
40 public Vector3 Position = Vector3.Zero;
41 public Vector3 Scale = Vector3.Zero;
42 public Quaternion Rotation = Quaternion.Identity;
43
44 /// <summary>
45 /// Is this undo state for an entire group?
46 /// </summary>
47 public bool ForGroup;
48 41
42 public ObjectChangeData data;
43 public DateTime creationtime;
49 /// <summary> 44 /// <summary>
50 /// Constructor. 45 /// Constructor.
51 /// </summary> 46 /// </summary>
52 /// <param name="part"></param> 47 /// <param name="part"></param>
53 /// <param name="forGroup">True if the undo is for an entire group</param> 48 /// <param name="change">bit field with what is changed</param>
54 public UndoState(SceneObjectPart part, bool forGroup) 49 ///
50 public UndoState(SceneObjectPart part, ObjectChangeType change)
55 { 51 {
56 if (part.ParentID == 0) 52 data = new ObjectChangeData();
57 { 53 data.change = change;
58 ForGroup = forGroup; 54 creationtime = DateTime.UtcNow;
59
60// if (ForGroup)
61 Position = part.ParentGroup.AbsolutePosition;
62// else
63// Position = part.OffsetPosition;
64
65// m_log.DebugFormat(
66// "[UNDO STATE]: Storing undo position {0} for root part", Position);
67 55
68 Rotation = part.RotationOffset; 56 if (part.ParentGroup.RootPart == part)
69 57 {
70// m_log.DebugFormat( 58 if ((change & ObjectChangeType.Position) != 0)
71// "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation); 59 data.position = part.ParentGroup.AbsolutePosition;
72 60 if ((change & ObjectChangeType.Rotation) != 0)
73 Scale = part.Shape.Scale; 61 data.rotation = part.RotationOffset;
74 62 if ((change & ObjectChangeType.Scale) != 0)
75// m_log.DebugFormat( 63 data.scale = part.Shape.Scale;
76// "[UNDO STATE]: Storing undo scale {0} for root part", Scale);
77 } 64 }
78 else 65 else
79 { 66 {
80 Position = part.OffsetPosition; 67 if ((change & ObjectChangeType.Position) != 0)
81// m_log.DebugFormat( 68 data.position = part.OffsetPosition;
82// "[UNDO STATE]: Storing undo position {0} for child part", Position); 69 if ((change & ObjectChangeType.Rotation) != 0)
70 data.rotation = part.RotationOffset;
71 if ((change & ObjectChangeType.Scale) != 0)
72 data.scale = part.Shape.Scale;
73 }
74 }
75 /// <summary>
76 /// check if undo or redo is too old
77 /// </summary>
83 78
84 Rotation = part.RotationOffset; 79 public bool checkExpire()
85// m_log.DebugFormat( 80 {
86// "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation); 81 TimeSpan t = DateTime.UtcNow - creationtime;
82 if (t.Seconds > UNDOEXPIRESECONDS)
83 return true;
84 return false;
85 }
87 86
88 Scale = part.Shape.Scale; 87 /// <summary>
89// m_log.DebugFormat( 88 /// updates undo or redo creation time to now
90// "[UNDO STATE]: Storing undo scale {0} for child part", Scale); 89 /// </summary>
91 } 90 public void updateExpire()
91 {
92 creationtime = DateTime.UtcNow;
92 } 93 }
93 94
94 /// <summary> 95 /// <summary>
95 /// Compare the relevant state in the given part to this state. 96 /// Compare the relevant state in the given part to this state.
96 /// </summary> 97 /// </summary>
97 /// <param name="part"></param> 98 /// <param name="part"></param>
98 /// <returns>true if both the part's position, rotation and scale match those in this undo state. False otherwise.</returns> 99 /// <returns>true what fiels and related data are equal, False otherwise.</returns>
99 public bool Compare(SceneObjectPart part) 100 ///
101 public bool Compare(SceneObjectPart part, ObjectChangeType change)
100 { 102 {
103 if (data.change != change) // if diferent targets, then they are diferent
104 return false;
105
101 if (part != null) 106 if (part != null)
102 { 107 {
103 if (part.ParentID == 0) 108 if (part.ParentID == 0)
104 return 109 {
105 Position == part.ParentGroup.AbsolutePosition 110 if ((change & ObjectChangeType.Position) != 0 && data.position != part.ParentGroup.AbsolutePosition)
106 && Rotation == part.RotationOffset 111 return false;
107 && Scale == part.Shape.Scale; 112 }
108 else 113 else
109 return 114 {
110 Position == part.OffsetPosition 115 if ((change & ObjectChangeType.Position) != 0 && data.position != part.OffsetPosition)
111 && Rotation == part.RotationOffset 116 return false;
112 && Scale == part.Shape.Scale; 117 }
113 } 118
119 if ((change & ObjectChangeType.Rotation) != 0 && data.rotation != part.RotationOffset)
120 return false;
121 if ((change & ObjectChangeType.Rotation) != 0 && data.scale == part.Shape.Scale)
122 return false;
123 return true;
114 124
125 }
115 return false; 126 return false;
116 } 127 }
117 128
118 public void PlaybackState(SceneObjectPart part) 129 /// <summary>
130 /// executes the undo or redo to a part or its group
131 /// </summary>
132 /// <param name="part"></param>
133 ///
134
135 public void PlayState(SceneObjectPart part)
119 { 136 {
120 part.Undoing = true; 137 part.Undoing = true;
121 138
122 if (part.ParentID == 0) 139 SceneObjectGroup grp = part.ParentGroup;
123 {
124// m_log.DebugFormat(
125// "[UNDO STATE]: Undoing position to {0} for root part {1} {2}",
126// Position, part.Name, part.LocalId);
127 140
128 if (Position != Vector3.Zero) 141 if (grp != null)
129 { 142 {
130 if (ForGroup) 143 grp.doChangeObject(part, data);
131 part.ParentGroup.AbsolutePosition = Position; 144 }
132 else 145 part.Undoing = false;
133 part.ParentGroup.UpdateRootPosition(Position); 146 }
134 } 147 }
135 148
136// m_log.DebugFormat( 149 public class UndoRedoState
137// "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}", 150 {
138// part.RotationOffset, Rotation, part.Name, part.LocalId); 151 int size;
152 public LinkedList<UndoState> m_redo = new LinkedList<UndoState>();
153 public LinkedList<UndoState> m_undo = new LinkedList<UndoState>();
139 154
140 if (ForGroup) 155 /// <summary>
141 part.UpdateRotation(Rotation); 156 /// creates a new UndoRedoState with default states memory size
142 else 157 /// </summary>
143 part.ParentGroup.UpdateRootRotation(Rotation);
144 158
145 if (Scale != Vector3.Zero) 159 public UndoRedoState()
146 { 160 {
147// m_log.DebugFormat( 161 size = 5;
148// "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}", 162 }
149// part.Shape.Scale, Scale, part.Name, part.LocalId);
150 163
151 if (ForGroup) 164 /// <summary>
152 part.ParentGroup.GroupResize(Scale); 165 /// creates a new UndoRedoState with states memory having indicated size
153 else 166 /// </summary>
154 part.Resize(Scale); 167 /// <param name="size"></param>
155 }
156 168
157 part.ParentGroup.ScheduleGroupForTerseUpdate(); 169 public UndoRedoState(int _size)
158 } 170 {
171 if (_size < 3)
172 size = 3;
159 else 173 else
160 { 174 size = _size;
161 // Note: Updating these properties on sop automatically schedules an update if needed 175 }
162 if (Position != Vector3.Zero)
163 {
164// m_log.DebugFormat(
165// "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}",
166// part.OffsetPosition, Position, part.Name, part.LocalId);
167 176
168 part.OffsetPosition = Position; 177 /// <summary>
169 } 178 /// returns number of undo entries in memory
179 /// </summary>
170 180
171// m_log.DebugFormat( 181 public int Count
172// "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}", 182 {
173// part.RotationOffset, Rotation, part.Name, part.LocalId); 183 get { return m_undo.Count; }
184 }
174 185
175 part.UpdateRotation(Rotation); 186 /// <summary>
187 /// clears all undo and redo entries
188 /// </summary>
176 189
177 if (Scale != Vector3.Zero) 190 public void Clear()
191 {
192 m_undo.Clear();
193 m_redo.Clear();
194 }
195
196 /// <summary>
197 /// adds a new state undo to part or its group, with changes indicated by what bits
198 /// </summary>
199 /// <param name="part"></param>
200 /// <param name="change">bit field with what is changed</param>
201
202 public void StoreUndo(SceneObjectPart part, ObjectChangeType change)
203 {
204 lock (m_undo)
205 {
206 UndoState last;
207
208 if (m_redo.Count > 0) // last code seems to clear redo on every new undo
178 { 209 {
179// m_log.DebugFormat( 210 m_redo.Clear();
180// "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}", 211 }
181// part.Shape.Scale, Scale, part.Name, part.LocalId);
182 212
183 part.Resize(Scale); 213 if (m_undo.Count > 0)
214 {
215 // check expired entry
216 last = m_undo.First.Value;
217 if (last != null && last.checkExpire())
218 m_undo.Clear();
219 else
220 {
221 // see if we actually have a change
222 if (last != null)
223 {
224 if (last.Compare(part, change))
225 return;
226 }
227 }
184 } 228 }
185 }
186 229
187 part.Undoing = false; 230 // limite size
231 while (m_undo.Count >= size)
232 m_undo.RemoveLast();
233
234 UndoState nUndo = new UndoState(part, change);
235 m_undo.AddFirst(nUndo);
236 }
188 } 237 }
189 238
190 public void PlayfwdState(SceneObjectPart part) 239 /// <summary>
191 { 240 /// executes last state undo to part or its group
192 part.Undoing = true; 241 /// current state is pushed into redo
242 /// </summary>
243 /// <param name="part"></param>
193 244
194 if (part.ParentID == 0) 245 public void Undo(SceneObjectPart part)
246 {
247 lock (m_undo)
195 { 248 {
196 if (Position != Vector3.Zero) 249 UndoState nUndo;
197 part.ParentGroup.AbsolutePosition = Position;
198
199 if (Rotation != Quaternion.Identity)
200 part.UpdateRotation(Rotation);
201 250
202 if (Scale != Vector3.Zero) 251 // expire redo
252 if (m_redo.Count > 0)
203 { 253 {
204 if (ForGroup) 254 nUndo = m_redo.First.Value;
205 part.ParentGroup.GroupResize(Scale); 255 if (nUndo != null && nUndo.checkExpire())
206 else 256 m_redo.Clear();
207 part.Resize(Scale);
208 } 257 }
209 258
210 part.ParentGroup.ScheduleGroupForTerseUpdate(); 259 if (m_undo.Count > 0)
260 {
261 UndoState goback = m_undo.First.Value;
262 // check expired
263 if (goback != null && goback.checkExpire())
264 {
265 m_undo.Clear();
266 return;
267 }
268
269 if (goback != null)
270 {
271 m_undo.RemoveFirst();
272
273 // redo limite size
274 while (m_redo.Count >= size)
275 m_redo.RemoveLast();
276
277 nUndo = new UndoState(part, goback.data.change); // new value in part should it be full goback copy?
278 m_redo.AddFirst(nUndo);
279
280 goback.PlayState(part);
281 }
282 }
211 } 283 }
212 else 284 }
285
286 /// <summary>
287 /// executes last state redo to part or its group
288 /// current state is pushed into undo
289 /// </summary>
290 /// <param name="part"></param>
291
292 public void Redo(SceneObjectPart part)
293 {
294 lock (m_undo)
213 { 295 {
214 // Note: Updating these properties on sop automatically schedules an update if needed 296 UndoState nUndo;
215 if (Position != Vector3.Zero)
216 part.OffsetPosition = Position;
217 297
218 if (Rotation != Quaternion.Identity) 298 // expire undo
219 part.UpdateRotation(Rotation); 299 if (m_undo.Count > 0)
300 {
301 nUndo = m_undo.First.Value;
302 if (nUndo != null && nUndo.checkExpire())
303 m_undo.Clear();
304 }
220 305
221 if (Scale != Vector3.Zero) 306 if (m_redo.Count > 0)
222 part.Resize(Scale); 307 {
308 UndoState gofwd = m_redo.First.Value;
309 // check expired
310 if (gofwd != null && gofwd.checkExpire())
311 {
312 m_redo.Clear();
313 return;
314 }
315
316 if (gofwd != null)
317 {
318 m_redo.RemoveFirst();
319
320 // limite undo size
321 while (m_undo.Count >= size)
322 m_undo.RemoveLast();
323
324 nUndo = new UndoState(part, gofwd.data.change); // new value in part should it be full gofwd copy?
325 m_undo.AddFirst(nUndo);
326
327 gofwd.PlayState(part);
328 }
329 }
223 } 330 }
224
225 part.Undoing = false;
226 } 331 }
227 } 332 }
228 333
@@ -247,4 +352,4 @@ namespace OpenSim.Region.Framework.Scenes
247 m_terrainModule.UndoTerrain(m_terrainChannel); 352 m_terrainModule.UndoTerrain(m_terrainChannel);
248 } 353 }
249 } 354 }
250} \ No newline at end of file 355}
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 9ec4e1d..d8928ee 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -126,7 +126,6 @@ namespace OpenSim.Region.Framework.Scenes
126// m_log.DebugFormat("[UUID GATHERER]: Adding asset {0} for inspection", uuid); 126// m_log.DebugFormat("[UUID GATHERER]: Adding asset {0} for inspection", uuid);
127 127
128 m_assetUuidsToInspect.Enqueue(uuid); 128 m_assetUuidsToInspect.Enqueue(uuid);
129
130 return true; 129 return true;
131 } 130 }
132 131