aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs32
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEventQueue.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInterregionComms.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IRestartModule.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs1
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs27
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs13
-rw-r--r--OpenSim/Region/Framework/Interfaces/IWorldComm.cs2
-rw-r--r--OpenSim/Region/Framework/ModuleLoader.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/CollisionSounds.cs304
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs422
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPMaterial.cs95
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPVehicle.cs742
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs320
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs95
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs723
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs32
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs480
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs268
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs1359
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs1639
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs787
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs574
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs122
-rw-r--r--OpenSim/Region/Framework/Scenes/SimStatsReporter.cs30
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs367
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
36 files changed, 6597 insertions, 1936 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index ba35a41..e7b9ba5 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;
@@ -83,7 +84,7 @@ namespace OpenSim.Region.Framework.Interfaces
83 /// <param name="AttachmentPt"></param> 84 /// <param name="AttachmentPt"></param>
84 /// <param name="silent"></param> 85 /// <param name="silent"></param>
85 /// <returns>true if the object was successfully attached, false otherwise</returns> 86 /// <returns>true if the object was successfully attached, false otherwise</returns>
86 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent); 87 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo);
87 88
88 /// <summary> 89 /// <summary>
89 /// Rez an attachment from user inventory and change inventory status to match. 90 /// Rez an attachment from user inventory and change inventory status to match.
@@ -94,6 +95,10 @@ namespace OpenSim.Region.Framework.Interfaces
94 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns> 95 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns>
95 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt); 96 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt);
96 97
98 // Same as above, but also load script states from a separate doc
99 ISceneEntity RezSingleAttachmentFromInventory(
100 IScenePresence presence, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc);
101
97 /// <summary> 102 /// <summary>
98 /// Rez multiple attachments from a user's inventory 103 /// Rez multiple attachments from a user's inventory
99 /// </summary> 104 /// </summary>
@@ -115,7 +120,6 @@ namespace OpenSim.Region.Framework.Interfaces
115 /// <param name="grp">The attachment to detach.</param> 120 /// <param name="grp">The attachment to detach.</param>
116 void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup grp); 121 void DetachSingleAttachmentToInv(IScenePresence sp, SceneObjectGroup grp);
117 122
118 /// <summary>
119 /// Update the position of an attachment. 123 /// Update the position of an attachment.
120 /// </summary> 124 /// </summary>
121 /// <param name="sog"></param> 125 /// <param name="sog"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 1c9bdce..4f0e100 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -128,6 +128,8 @@ namespace OpenSim.Region.Framework.Interfaces
128 /// </returns> 128 /// </returns>
129 bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 129 bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
130 130
131 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
132
131 /// <summary> 133 /// <summary>
132 /// Stop a script which is in this prim's inventory. 134 /// Stop a script which is in this prim's inventory.
133 /// </summary> 135 /// </summary>
@@ -284,5 +286,6 @@ namespace OpenSim.Region.Framework.Interfaces
284 /// A <see cref="Dictionary`2"/> 286 /// A <see cref="Dictionary`2"/>
285 /// </returns> 287 /// </returns>
286 Dictionary<UUID, string> GetScriptStates(); 288 Dictionary<UUID, string> GetScriptStates();
289 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
287 } 290 }
288} 291}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 69be83e..5bc8e51 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -35,6 +35,8 @@ using OpenSim.Region.Framework.Scenes;
35 35
36namespace OpenSim.Region.Framework.Interfaces 36namespace OpenSim.Region.Framework.Interfaces
37{ 37{
38 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version);
39
38 public interface IEntityTransferModule 40 public interface IEntityTransferModule
39 { 41 {
40 /// <summary> 42 /// <summary>
@@ -50,29 +52,10 @@ namespace OpenSim.Region.Framework.Interfaces
50 /// <param name='teleportFlags'></param> 52 /// <param name='teleportFlags'></param>
51 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); 53 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags);
52 54
53 /// <summary> 55 bool TeleportHome(UUID id, IClientAPI client);
54 /// Teleport an agent directly to a given region without checking whether the region should be subsituted.
55 /// </summary>
56 /// <remarks>
57 /// Please use Teleport() instead unless you know exactly what you're doing.
58 /// Do not use for same region teleports.
59 /// </remarks>
60 /// <param name='sp'></param>
61 /// <param name='reg'></param>
62 /// <param name='finalDestination'>/param>
63 /// <param name='position'></param>
64 /// <param name='lookAt'></param>
65 /// <param name='teleportFlags'></param>
66 void DoTeleport(
67 ScenePresence sp, GridRegion reg, GridRegion finalDestination,
68 Vector3 position, Vector3 lookAt, uint teleportFlags);
69 56
70 /// <summary> 57 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
71 /// Teleports the agent for the given client to their home destination. 58 Vector3 position, Vector3 lookAt, uint teleportFlags);
72 /// </summary>
73 /// <param name='id'></param>
74 /// <param name='client'></param>
75 void TeleportHome(UUID id, IClientAPI client);
76 59
77 /// <summary> 60 /// <summary>
78 /// Show whether the given agent is being teleported. 61 /// Show whether the given agent is being teleported.
@@ -89,7 +72,12 @@ namespace OpenSim.Region.Framework.Interfaces
89 72
90 void EnableChildAgent(ScenePresence agent, GridRegion region); 73 void EnableChildAgent(ScenePresence agent, GridRegion region);
91 74
75 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos);
76
92 void Cross(SceneObjectGroup sog, Vector3 position, bool silent); 77 void Cross(SceneObjectGroup sog, Vector3 position, bool silent);
78
79 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version);
80
93 } 81 }
94 82
95 public interface IUserAgentVerificationModule 83 public interface IUserAgentVerificationModule
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 15cd238..ca2ad94 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -45,6 +45,8 @@ namespace OpenSim.Region.Framework.Interfaces
45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.). 45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.).
46 /// </summary> 46 /// </summary>
47 void sendRegionHandshakeToAll(); 47 void sendRegionHandshakeToAll();
48 void TriggerEstateInfoChange();
49 void TriggerRegionInfoChange();
48 50
49 void setEstateTerrainBaseTexture(int level, UUID texture); 51 void setEstateTerrainBaseTexture(int level, UUID texture);
50 void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue); 52 void setEstateTerrainTextureHeights(int corner, float lowValue, float highValue);
diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
index bfa5d17..5512642 100644
--- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
@@ -59,5 +59,7 @@ namespace OpenSim.Region.Framework.Interfaces
59 void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID); 59 void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID);
60 OSD ScriptRunningEvent(UUID objectID, UUID itemID, bool running, bool mono); 60 OSD ScriptRunningEvent(UUID objectID, UUID itemID, bool running, bool mono);
61 OSD BuildEvent(string eventName, OSD eventBody); 61 OSD BuildEvent(string eventName, OSD eventBody);
62 void partPhysicsProperties(uint localID, byte physhapetype, float density, float friction, float bounce, float gravmod, UUID avatarID);
63
62 } 64 }
63} 65}
diff --git a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
index 2d6287f..67a500f 100644
--- a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
@@ -68,6 +68,14 @@ namespace OpenSim.Region.Framework.Interfaces
68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri); 68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri);
69 69
70 /// <summary> 70 /// <summary>
71 /// Close chid agent.
72 /// </summary>
73 /// <param name="regionHandle"></param>
74 /// <param name="id"></param>
75 /// <returns></returns>
76 bool SendCloseChildAgent(ulong regionHandle, UUID id);
77
78 /// <summary>
71 /// Close agent. 79 /// Close agent.
72 /// </summary> 80 /// </summary>
73 /// <param name="regionHandle"></param> 81 /// <param name="regionHandle"></param>
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/ISimulationDataService.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
index 0fcafcc..ccb583d 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataService.cs
@@ -116,5 +116,6 @@ namespace OpenSim.Region.Framework.Interfaces
116 /// <param name="regionUUID">the region UUID</param> 116 /// <param name="regionUUID">the region UUID</param>
117 void RemoveRegionEnvironmentSettings(UUID regionUUID); 117 void RemoveRegionEnvironmentSettings(UUID regionUUID);
118 118
119 UUID[] GetObjectIDs(UUID regionID);
119 } 120 }
120} 121}
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
index e424976..d7c80f7 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulationDataStore.cs
@@ -106,6 +106,7 @@ namespace OpenSim.Region.Framework.Interfaces
106 RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID); 106 RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID);
107 void StoreRegionWindlightSettings(RegionLightShareData wl); 107 void StoreRegionWindlightSettings(RegionLightShareData wl);
108 void RemoveRegionWindlightSettings(UUID regionID); 108 void RemoveRegionWindlightSettings(UUID regionID);
109 UUID[] GetObjectIDs(UUID regionID);
109 110
110 /// <summary> 111 /// <summary>
111 /// Load Environment settings from region storage 112 /// 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..e01f649
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
@@ -0,0 +1,27 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster LImited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6// Mod 2
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface ISnmpModule
11{
12 void Trap(int code, string Message, Scene scene);
13 void Critical(string Message, Scene scene);
14 void Warning(string Message, Scene scene);
15 void Major(string Message, Scene scene);
16 void ColdStart(int step , Scene scene);
17 void Shutdown(int step , Scene scene);
18 //
19 // Node Start/stop events
20 //
21 void LinkUp(Scene scene);
22 void LinkDown(Scene scene);
23 void BootInfo(string data, Scene scene);
24 void trapDebug(string Module,string data, Scene scene);
25 void trapXMRE(int data, string Message, Scene scene);
26
27}
diff --git a/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
new file mode 100644
index 0000000..d1a4d8e
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
@@ -0,0 +1,13 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster Limited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6//
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface IUserAccountCacheModule
11{
12 void Remove(string name);
13}
diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
index 4e74781..e8e375e 100644
--- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
+++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs
@@ -103,7 +103,7 @@ namespace OpenSim.Region.Framework.Interfaces
103 /// <param name='msg'> 103 /// <param name='msg'>
104 /// Message. 104 /// Message.
105 /// </param> 105 /// </param>
106 void DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg); 106 bool DeliverMessageTo(UUID target, int channel, Vector3 pos, string name, UUID id, string msg, out string error);
107 107
108 /// <summary> 108 /// <summary>
109 /// Are there any listen events ready to be dispatched? 109 /// Are there any listen events ready to be dispatched?
diff --git a/OpenSim/Region/Framework/ModuleLoader.cs b/OpenSim/Region/Framework/ModuleLoader.cs
index 14ecd44..32ee674 100644
--- a/OpenSim/Region/Framework/ModuleLoader.cs
+++ b/OpenSim/Region/Framework/ModuleLoader.cs
@@ -227,7 +227,8 @@ namespace OpenSim.Region.Framework
227 pluginAssembly.FullName, e.Message, e.StackTrace); 227 pluginAssembly.FullName, e.Message, e.StackTrace);
228 228
229 // justincc: Right now this is fatal to really get the user's attention 229 // justincc: Right now this is fatal to really get the user's attention
230 throw e; 230 // TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to?
231 //throw e;
231 } 232 }
232 } 233 }
233 234
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 14ae287..9ddac19 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -79,13 +79,13 @@ namespace OpenSim.Region.Framework.Scenes.Animation
79 m_scenePresence = sp; 79 m_scenePresence = sp;
80 CurrentMovementAnimation = "CROUCH"; 80 CurrentMovementAnimation = "CROUCH";
81 } 81 }
82 82
83 public void AddAnimation(UUID animID, UUID objectID) 83 public void AddAnimation(UUID animID, UUID objectID)
84 { 84 {
85 if (m_scenePresence.IsChildAgent) 85 if (m_scenePresence.IsChildAgent)
86 return; 86 return;
87 87
88// m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} for {1}", animID, m_scenePresence.Name); 88 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} for {1}", animID, m_scenePresence.Name);
89 89
90 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) 90 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
91 SendAnimPack(); 91 SendAnimPack();
@@ -117,6 +117,22 @@ namespace OpenSim.Region.Framework.Scenes.Animation
117 SendAnimPack(); 117 SendAnimPack();
118 } 118 }
119 119
120 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack)
121 {
122 if (m_scenePresence.IsChildAgent)
123 return;
124
125 if (animID != UUID.Zero)
126 {
127 if (addRemove)
128 m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero);
129 else
130 m_animations.Remove(animID);
131 }
132 if(sendPack)
133 SendAnimPack();
134 }
135
120 // Called from scripts 136 // Called from scripts
121 public void RemoveAnimation(string name) 137 public void RemoveAnimation(string name)
122 { 138 {
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 f92ed8e..76a952b 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -59,8 +59,12 @@ namespace OpenSim.Region.Framework.Scenes
59 59
60 public delegate void OnTerrainTickDelegate(); 60 public delegate void OnTerrainTickDelegate();
61 61
62 public delegate void OnTerrainUpdateDelegate();
63
62 public event OnTerrainTickDelegate OnTerrainTick; 64 public event OnTerrainTickDelegate OnTerrainTick;
63 65
66 public event OnTerrainUpdateDelegate OnTerrainUpdate;
67
64 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 68 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
65 69
66 public event OnBackupDelegate OnBackup; 70 public event OnBackupDelegate OnBackup;
@@ -896,6 +900,26 @@ namespace OpenSim.Region.Framework.Scenes
896 } 900 }
897 } 901 }
898 } 902 }
903 public void TriggerTerrainUpdate()
904 {
905 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
906 if (handlerTerrainUpdate != null)
907 {
908 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
909 {
910 try
911 {
912 d();
913 }
914 catch (Exception e)
915 {
916 m_log.ErrorFormat(
917 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
918 e.Message, e.StackTrace);
919 }
920 }
921 }
922 }
899 923
900 public void TriggerTerrainTick() 924 public void TriggerTerrainTick()
901 { 925 {
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
new file mode 100644
index 0000000..b7b0d27
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -0,0 +1,422 @@
1// Proprietary code of Avination Virtual Limited
2// (c) 2012 Melanie Thielker
3//
4
5using System;
6using System.Timers;
7using System.Collections;
8using System.Collections.Generic;
9using System.IO;
10using System.Diagnostics;
11using System.Reflection;
12using System.Threading;
13using OpenMetaverse;
14using OpenSim.Framework;
15using OpenSim.Region.Framework.Interfaces;
16using OpenSim.Region.Physics.Manager;
17using OpenSim.Region.Framework.Scenes.Serialization;
18using System.Runtime.Serialization.Formatters.Binary;
19using System.Runtime.Serialization;
20using Timer = System.Timers.Timer;
21using log4net;
22
23namespace OpenSim.Region.Framework.Scenes
24{
25 [Serializable]
26 public class KeyframeMotion
27 {
28 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
29
30 public enum PlayMode : int
31 {
32 Forward = 0,
33 Reverse = 1,
34 Loop = 2,
35 PingPong = 3
36 };
37
38 [Flags]
39 public enum DataFormat : int
40 {
41 Translation = 1,
42 Rotation = 2
43 }
44
45 [Serializable]
46 public struct Keyframe
47 {
48 public Vector3? Position;
49 public Quaternion? Rotation;
50 public Quaternion StartRotation;
51 public int TimeMS;
52 public int TimeTotal;
53 public Vector3 AngularVelocity;
54 };
55
56 private Vector3 m_basePosition;
57 private Quaternion m_baseRotation;
58 private Vector3 m_serializedPosition;
59
60 private Keyframe m_currentFrame;
61 private List<Keyframe> m_frames = new List<Keyframe>();
62
63 private Keyframe[] m_keyframes;
64
65 [NonSerialized()]
66 protected Timer m_timer = new Timer();
67
68 [NonSerialized()]
69 private SceneObjectGroup m_group;
70
71 private PlayMode m_mode = PlayMode.Forward;
72 private DataFormat m_data = DataFormat.Translation | DataFormat.Rotation;
73
74 private bool m_running = false;
75 [NonSerialized()]
76 private bool m_selected = false;
77
78 private int m_iterations = 0;
79
80 private const double timerInterval = 50.0;
81
82 public DataFormat Data
83 {
84 get { return m_data; }
85 }
86
87 public bool Selected
88 {
89 set
90 {
91 if (value)
92 {
93 // Once we're let go, recompute positions
94 if (m_selected)
95 UpdateSceneObject(m_group);
96 }
97 else
98 {
99 // Save selection position in case we get moved
100 if (!m_selected)
101 m_serializedPosition = m_group.AbsolutePosition;
102 }
103 m_selected = value; }
104 }
105
106 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
107 {
108 MemoryStream ms = new MemoryStream(data);
109
110 BinaryFormatter fmt = new BinaryFormatter();
111
112 KeyframeMotion newMotion = (KeyframeMotion)fmt.Deserialize(ms);
113
114 // This will be started when position is updated
115 newMotion.m_timer = new Timer();
116 newMotion.m_timer.Interval = (int)timerInterval;
117 newMotion.m_timer.AutoReset = true;
118 newMotion.m_timer.Elapsed += newMotion.OnTimer;
119
120 return newMotion;
121 }
122
123 public void UpdateSceneObject(SceneObjectGroup grp)
124 {
125 m_group = grp;
126 Vector3 offset = grp.AbsolutePosition - m_serializedPosition;
127
128 m_basePosition += offset;
129 m_currentFrame.Position += offset;
130 for (int i = 0 ; i < m_frames.Count ; i++)
131 {
132 Keyframe k = m_frames[i];
133 k.Position += offset;
134 m_frames[i] = k;
135 }
136
137 if (m_running)
138 Start();
139 }
140
141 public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data)
142 {
143 m_mode = mode;
144 m_data = data;
145
146 m_group = grp;
147 m_basePosition = grp.AbsolutePosition;
148 m_baseRotation = grp.GroupRotation;
149
150 m_timer.Interval = (int)timerInterval;
151 m_timer.AutoReset = true;
152 m_timer.Elapsed += OnTimer;
153 }
154
155 public void SetKeyframes(Keyframe[] frames)
156 {
157 m_keyframes = frames;
158 }
159
160 public void Start()
161 {
162 if (m_keyframes.Length > 0)
163 m_timer.Start();
164 m_running = true;
165 }
166
167 public void Stop()
168 {
169 // Failed object creation
170 if (m_timer == null)
171 return;
172 m_timer.Stop();
173
174 m_basePosition = m_group.AbsolutePosition;
175 m_baseRotation = m_group.GroupRotation;
176
177 m_group.RootPart.Velocity = Vector3.Zero;
178 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
179 m_group.SendGroupRootTerseUpdate();
180
181 m_frames.Clear();
182 m_running = false;
183 }
184
185 public void Pause()
186 {
187 m_group.RootPart.Velocity = Vector3.Zero;
188 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
189 m_group.SendGroupRootTerseUpdate();
190
191 m_timer.Stop();
192 m_running = false;
193 }
194
195 private void GetNextList()
196 {
197 m_frames.Clear();
198 Vector3 pos = m_basePosition;
199 Quaternion rot = m_baseRotation;
200
201 if (m_mode == PlayMode.Loop || m_mode == PlayMode.PingPong || m_iterations == 0)
202 {
203 int direction = 1;
204 if (m_mode == PlayMode.Reverse || ((m_mode == PlayMode.PingPong) && ((m_iterations & 1) != 0)))
205 direction = -1;
206
207 int start = 0;
208 int end = m_keyframes.Length;
209// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
210// end = m_keyframes.Length - 1;
211
212 if (direction < 0)
213 {
214 start = m_keyframes.Length - 1;
215 end = -1;
216// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
217// end = 0;
218 }
219
220 for (int i = start; i != end ; i += direction)
221 {
222 Keyframe k = m_keyframes[i];
223
224 if (k.Position.HasValue)
225 k.Position = (k.Position * direction) + pos;
226 else
227 k.Position = pos;
228
229 k.StartRotation = rot;
230 if (k.Rotation.HasValue)
231 {
232 if (direction == -1)
233 k.Rotation = Quaternion.Conjugate((Quaternion)k.Rotation);
234 k.Rotation = rot * k.Rotation;
235 }
236 else
237 {
238 k.Rotation = rot;
239 }
240
241 float angle = 0;
242
243 float aa = k.StartRotation.X * k.StartRotation.X + k.StartRotation.Y * k.StartRotation.Y + k.StartRotation.Z * k.StartRotation.Z + k.StartRotation.W * k.StartRotation.W;
244 float bb = ((Quaternion)k.Rotation).X * ((Quaternion)k.Rotation).X + ((Quaternion)k.Rotation).Y * ((Quaternion)k.Rotation).Y + ((Quaternion)k.Rotation).Z * ((Quaternion)k.Rotation).Z + ((Quaternion)k.Rotation).W * ((Quaternion)k.Rotation).W;
245 float aa_bb = aa * bb;
246
247 if (aa_bb == 0)
248 {
249 angle = 0;
250 }
251 else
252 {
253 float ab = k.StartRotation.X * ((Quaternion)k.Rotation).X +
254 k.StartRotation.Y * ((Quaternion)k.Rotation).Y +
255 k.StartRotation.Z * ((Quaternion)k.Rotation).Z +
256 k.StartRotation.W * ((Quaternion)k.Rotation).W;
257 float q = (ab * ab) / aa_bb;
258
259 if (q > 1.0f)
260 {
261 angle = 0;
262 }
263 else
264 {
265 angle = (float)Math.Acos(2 * q - 1);
266 }
267 }
268
269 k.AngularVelocity = (new Vector3(0, 0, 1) * (Quaternion)k.Rotation) * (angle / (k.TimeMS / 1000));
270 k.TimeTotal = k.TimeMS;
271
272 m_frames.Add(k);
273
274 pos = (Vector3)k.Position;
275 rot = (Quaternion)k.Rotation;
276 }
277
278 m_basePosition = pos;
279 m_baseRotation = rot;
280
281 m_iterations++;
282 }
283 }
284
285 protected void OnTimer(object sender, ElapsedEventArgs e)
286 {
287 if (m_frames.Count == 0)
288 {
289 GetNextList();
290
291 if (m_frames.Count == 0)
292 {
293 Stop();
294 return;
295 }
296
297 m_currentFrame = m_frames[0];
298 }
299
300 if (m_selected)
301 {
302 if (m_group.RootPart.Velocity != Vector3.Zero)
303 {
304 m_group.RootPart.Velocity = Vector3.Zero;
305 m_group.SendGroupRootTerseUpdate();
306 }
307 return;
308 }
309
310 // Do the frame processing
311 double steps = (double)m_currentFrame.TimeMS / timerInterval;
312 float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
313
314 if (steps <= 1.0)
315 {
316 m_currentFrame.TimeMS = 0;
317
318 m_group.AbsolutePosition = (Vector3)m_currentFrame.Position;
319 m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
320 }
321 else
322 {
323 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
324 Vector3 motionThisFrame = v / (float)steps;
325 v = v * 1000 / m_currentFrame.TimeMS;
326
327 bool update = false;
328
329 if (Vector3.Mag(motionThisFrame) >= 0.05f)
330 {
331 m_group.AbsolutePosition += motionThisFrame;
332 m_group.RootPart.Velocity = v;
333 update = true;
334 }
335
336 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
337 {
338 Quaternion current = m_group.GroupRotation;
339
340 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
341
342 float angle = 0;
343
344 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
345 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
346 float aa_bb = aa * bb;
347
348 if (aa_bb == 0)
349 {
350 angle = 0;
351 }
352 else
353 {
354 float ab = current.X * step.X +
355 current.Y * step.Y +
356 current.Z * step.Z +
357 current.W * step.W;
358 float q = (ab * ab) / aa_bb;
359
360 if (q > 1.0f)
361 {
362 angle = 0;
363 }
364 else
365 {
366 angle = (float)Math.Acos(2 * q - 1);
367 }
368 }
369
370 if (angle > 0.01f)
371 {
372 m_group.UpdateGroupRotationR(step);
373 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
374 update = true;
375 }
376 }
377
378 if (update)
379 m_group.SendGroupRootTerseUpdate();
380 }
381
382 m_currentFrame.TimeMS -= (int)timerInterval;
383
384 if (m_currentFrame.TimeMS <= 0)
385 {
386 m_group.RootPart.Velocity = Vector3.Zero;
387 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
388 m_group.SendGroupRootTerseUpdate();
389
390 m_frames.RemoveAt(0);
391 if (m_frames.Count > 0)
392 m_currentFrame = m_frames[0];
393 }
394 }
395
396 public Byte[] Serialize()
397 {
398 MemoryStream ms = new MemoryStream();
399 m_timer.Stop();
400
401 BinaryFormatter fmt = new BinaryFormatter();
402 SceneObjectGroup tmp = m_group;
403 m_group = null;
404 m_serializedPosition = tmp.AbsolutePosition;
405 fmt.Serialize(ms, this);
406 m_group = tmp;
407 return ms.ToArray();
408 }
409
410 public void CrossingFailure()
411 {
412 // The serialization has stopped the timer, so let's wait a moment
413 // then retry the crossing. We'll get back here if it fails.
414 Util.FireAndForget(delegate (object x)
415 {
416 Thread.Sleep(60000);
417 if (m_running)
418 m_timer.Start();
419 });
420 }
421 }
422}
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index 1b10e3c..0a34a4c 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -157,7 +157,7 @@ namespace OpenSim.Region.Framework.Scenes
157 157
158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
159 { 159 {
160 uint pqueue = ComputeDistancePriority(client,entity,true); 160 uint pqueue = ComputeDistancePriority(client,entity,false);
161 161
162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
163 if (presence != null) 163 if (presence != null)
@@ -226,7 +226,7 @@ namespace OpenSim.Region.Framework.Scenes
226 226
227 for (int i = 0; i < queues - 1; i++) 227 for (int i = 0; i < queues - 1; i++)
228 { 228 {
229 if (distance < 10 * Math.Pow(2.0,i)) 229 if (distance < 30 * Math.Pow(2.0,i))
230 break; 230 break;
231 pqueue++; 231 pqueue++;
232 } 232 }
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..d3c2d27
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs
@@ -0,0 +1,742 @@
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.Physics.Manager;
33using System.Xml;
34using OpenSim.Framework.Serialization;
35using OpenSim.Framework.Serialization.External;
36using OpenSim.Region.Framework.Scenes.Serialization;
37using OpenSim.Region.Framework.Scenes.Serialization;
38
39namespace OpenSim.Region.Framework.Scenes
40{
41 public class SOPVehicle
42 {
43 public VehicleData vd;
44
45 public Vehicle Type
46 {
47 get { return vd.m_type; }
48 }
49
50 public SOPVehicle()
51 {
52 vd = new VehicleData();
53 ProcessTypeChange(Vehicle.TYPE_NONE); // is needed?
54 }
55
56 public void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
57 {
58 float len;
59 float timestep = 0.01f;
60 switch (pParam)
61 {
62 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
63 if (pValue < 0f) pValue = 0f;
64 if (pValue > 1f) pValue = 1f;
65 vd.m_angularDeflectionEfficiency = pValue;
66 break;
67 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
68 if (pValue < timestep) pValue = timestep;
69 vd.m_angularDeflectionTimescale = pValue;
70 break;
71 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
72 if (pValue < timestep) pValue = timestep;
73 else if (pValue > 120) pValue = 120;
74 vd.m_angularMotorDecayTimescale = pValue;
75 break;
76 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
77 if (pValue < timestep) pValue = timestep;
78 vd.m_angularMotorTimescale = pValue;
79 break;
80 case Vehicle.BANKING_EFFICIENCY:
81 if (pValue < -1f) pValue = -1f;
82 if (pValue > 1f) pValue = 1f;
83 vd.m_bankingEfficiency = pValue;
84 break;
85 case Vehicle.BANKING_MIX:
86 if (pValue < 0f) pValue = 0f;
87 if (pValue > 1f) pValue = 1f;
88 vd.m_bankingMix = pValue;
89 break;
90 case Vehicle.BANKING_TIMESCALE:
91 if (pValue < timestep) pValue = timestep;
92 vd.m_bankingTimescale = pValue;
93 break;
94 case Vehicle.BUOYANCY:
95 if (pValue < -1f) pValue = -1f;
96 if (pValue > 1f) pValue = 1f;
97 vd.m_VehicleBuoyancy = pValue;
98 break;
99 case Vehicle.HOVER_EFFICIENCY:
100 if (pValue < 0f) pValue = 0f;
101 if (pValue > 1f) pValue = 1f;
102 vd.m_VhoverEfficiency = pValue;
103 break;
104 case Vehicle.HOVER_HEIGHT:
105 vd.m_VhoverHeight = pValue;
106 break;
107 case Vehicle.HOVER_TIMESCALE:
108 if (pValue < timestep) pValue = timestep;
109 vd.m_VhoverTimescale = pValue;
110 break;
111 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
112 if (pValue < 0f) pValue = 0f;
113 if (pValue > 1f) pValue = 1f;
114 vd.m_linearDeflectionEfficiency = pValue;
115 break;
116 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
117 if (pValue < timestep) pValue = timestep;
118 vd.m_linearDeflectionTimescale = pValue;
119 break;
120 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
121 if (pValue < timestep) pValue = timestep;
122 else if (pValue > 120) pValue = 120;
123 vd.m_linearMotorDecayTimescale = pValue;
124 break;
125 case Vehicle.LINEAR_MOTOR_TIMESCALE:
126 if (pValue < timestep) pValue = timestep;
127 vd.m_linearMotorTimescale = pValue;
128 break;
129 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
130 if (pValue < 0f) pValue = 0f;
131 if (pValue > 1f) pValue = 1f;
132 vd.m_verticalAttractionEfficiency = pValue;
133 break;
134 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
135 if (pValue < timestep) pValue = timestep;
136 vd.m_verticalAttractionTimescale = pValue;
137 break;
138
139 // These are vector properties but the engine lets you use a single float value to
140 // set all of the components to the same value
141 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
142 if (pValue < timestep) pValue = timestep;
143 vd.m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
144 break;
145 case Vehicle.ANGULAR_MOTOR_DIRECTION:
146 vd.m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
147 len = vd.m_angularMotorDirection.Length();
148 if (len > 12.566f)
149 vd.m_angularMotorDirection *= (12.566f / len);
150 break;
151 case Vehicle.LINEAR_FRICTION_TIMESCALE:
152 if (pValue < timestep) pValue = timestep;
153 vd.m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
154 break;
155 case Vehicle.LINEAR_MOTOR_DIRECTION:
156 vd.m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
157 len = vd.m_linearMotorDirection.Length();
158 if (len > 30.0f)
159 vd.m_linearMotorDirection *= (30.0f / len);
160 break;
161 case Vehicle.LINEAR_MOTOR_OFFSET:
162 vd.m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
163 len = vd.m_linearMotorOffset.Length();
164 if (len > 100.0f)
165 vd.m_linearMotorOffset *= (100.0f / len);
166 break;
167 }
168 }//end ProcessFloatVehicleParam
169
170 public void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
171 {
172 float len;
173 float timestep = 0.01f;
174 switch (pParam)
175 {
176 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
177 if (pValue.X < timestep) pValue.X = timestep;
178 if (pValue.Y < timestep) pValue.Y = timestep;
179 if (pValue.Z < timestep) pValue.Z = timestep;
180
181 vd.m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
182 break;
183 case Vehicle.ANGULAR_MOTOR_DIRECTION:
184 vd.m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
185 // Limit requested angular speed to 2 rps= 4 pi rads/sec
186 len = vd.m_angularMotorDirection.Length();
187 if (len > 12.566f)
188 vd.m_angularMotorDirection *= (12.566f / len);
189 break;
190 case Vehicle.LINEAR_FRICTION_TIMESCALE:
191 if (pValue.X < timestep) pValue.X = timestep;
192 if (pValue.Y < timestep) pValue.Y = timestep;
193 if (pValue.Z < timestep) pValue.Z = timestep;
194 vd.m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
195 break;
196 case Vehicle.LINEAR_MOTOR_DIRECTION:
197 vd.m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
198 len = vd.m_linearMotorDirection.Length();
199 if (len > 30.0f)
200 vd.m_linearMotorDirection *= (30.0f / len);
201 break;
202 case Vehicle.LINEAR_MOTOR_OFFSET:
203 vd.m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
204 len = vd.m_linearMotorOffset.Length();
205 if (len > 100.0f)
206 vd.m_linearMotorOffset *= (100.0f / len);
207 break;
208 }
209 }//end ProcessVectorVehicleParam
210
211 public void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
212 {
213 switch (pParam)
214 {
215 case Vehicle.REFERENCE_FRAME:
216 vd.m_referenceFrame = Quaternion.Inverse(pValue);
217 break;
218 }
219 }//end ProcessRotationVehicleParam
220
221 public void ProcessVehicleFlags(int pParam, bool remove)
222 {
223 if (remove)
224 {
225 vd.m_flags &= ~((VehicleFlag)pParam);
226 }
227 else
228 {
229 vd.m_flags |= (VehicleFlag)pParam;
230 }
231 }//end ProcessVehicleFlags
232
233 public void ProcessTypeChange(Vehicle pType)
234 {
235 vd.m_linearMotorDirection = Vector3.Zero;
236 vd.m_angularMotorDirection = Vector3.Zero;
237 vd.m_linearMotorOffset = Vector3.Zero;
238 vd.m_referenceFrame = Quaternion.Identity;
239
240 // Set Defaults For Type
241 vd.m_type = pType;
242 switch (pType)
243 {
244 case Vehicle.TYPE_NONE:
245 vd.m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
246 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
247 vd.m_linearMotorTimescale = 1000;
248 vd.m_linearMotorDecayTimescale = 120;
249 vd.m_angularMotorTimescale = 1000;
250 vd.m_angularMotorDecayTimescale = 1000;
251 vd.m_VhoverHeight = 0;
252 vd.m_VhoverEfficiency = 1;
253 vd.m_VhoverTimescale = 1000;
254 vd.m_VehicleBuoyancy = 0;
255 vd.m_linearDeflectionEfficiency = 0;
256 vd.m_linearDeflectionTimescale = 1000;
257 vd.m_angularDeflectionEfficiency = 0;
258 vd.m_angularDeflectionTimescale = 1000;
259 vd.m_bankingEfficiency = 0;
260 vd.m_bankingMix = 1;
261 vd.m_bankingTimescale = 1000;
262 vd.m_verticalAttractionEfficiency = 0;
263 vd.m_verticalAttractionTimescale = 1000;
264
265 vd.m_flags = (VehicleFlag)0;
266 break;
267
268 case Vehicle.TYPE_SLED:
269 vd.m_linearFrictionTimescale = new Vector3(30, 1, 1000);
270 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
271 vd.m_linearMotorTimescale = 1000;
272 vd.m_linearMotorDecayTimescale = 120;
273 vd.m_angularMotorTimescale = 1000;
274 vd.m_angularMotorDecayTimescale = 120;
275 vd.m_VhoverHeight = 0;
276 vd.m_VhoverEfficiency = 1;
277 vd.m_VhoverTimescale = 10;
278 vd.m_VehicleBuoyancy = 0;
279 vd.m_linearDeflectionEfficiency = 1;
280 vd.m_linearDeflectionTimescale = 1;
281 vd.m_angularDeflectionEfficiency = 0;
282 vd.m_angularDeflectionTimescale = 1000;
283 vd.m_bankingEfficiency = 0;
284 vd.m_bankingMix = 1;
285 vd.m_bankingTimescale = 10;
286 vd.m_flags &=
287 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
288 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
289 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
290 break;
291 case Vehicle.TYPE_CAR:
292 vd.m_linearFrictionTimescale = new Vector3(100, 2, 1000);
293 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
294 vd.m_linearMotorTimescale = 1;
295 vd.m_linearMotorDecayTimescale = 60;
296 vd.m_angularMotorTimescale = 1;
297 vd.m_angularMotorDecayTimescale = 0.8f;
298 vd.m_VhoverHeight = 0;
299 vd.m_VhoverEfficiency = 0;
300 vd.m_VhoverTimescale = 1000;
301 vd.m_VehicleBuoyancy = 0;
302 vd.m_linearDeflectionEfficiency = 1;
303 vd.m_linearDeflectionTimescale = 2;
304 vd.m_angularDeflectionEfficiency = 0;
305 vd.m_angularDeflectionTimescale = 10;
306 vd.m_verticalAttractionEfficiency = 1f;
307 vd.m_verticalAttractionTimescale = 10f;
308 vd.m_bankingEfficiency = -0.2f;
309 vd.m_bankingMix = 1;
310 vd.m_bankingTimescale = 1;
311 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
312 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
313 VehicleFlag.LIMIT_MOTOR_UP | VehicleFlag.HOVER_UP_ONLY);
314 break;
315 case Vehicle.TYPE_BOAT:
316 vd.m_linearFrictionTimescale = new Vector3(10, 3, 2);
317 vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
318 vd.m_linearMotorTimescale = 5;
319 vd.m_linearMotorDecayTimescale = 60;
320 vd.m_angularMotorTimescale = 4;
321 vd.m_angularMotorDecayTimescale = 4;
322 vd.m_VhoverHeight = 0;
323 vd.m_VhoverEfficiency = 0.5f;
324 vd.m_VhoverTimescale = 2;
325 vd.m_VehicleBuoyancy = 1;
326 vd.m_linearDeflectionEfficiency = 0.5f;
327 vd.m_linearDeflectionTimescale = 3;
328 vd.m_angularDeflectionEfficiency = 0.5f;
329 vd.m_angularDeflectionTimescale = 5;
330 vd.m_verticalAttractionEfficiency = 0.5f;
331 vd.m_verticalAttractionTimescale = 5f;
332 vd.m_bankingEfficiency = -0.3f;
333 vd.m_bankingMix = 0.8f;
334 vd.m_bankingTimescale = 1;
335 vd.m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
336 VehicleFlag.HOVER_GLOBAL_HEIGHT |
337 VehicleFlag.HOVER_UP_ONLY |
338 VehicleFlag.LIMIT_ROLL_ONLY);
339 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
340 VehicleFlag.LIMIT_MOTOR_UP |
341 VehicleFlag.HOVER_WATER_ONLY);
342 break;
343 case Vehicle.TYPE_AIRPLANE:
344 vd.m_linearFrictionTimescale = new Vector3(200, 10, 5);
345 vd.m_angularFrictionTimescale = new Vector3(20, 20, 20);
346 vd.m_linearMotorTimescale = 2;
347 vd.m_linearMotorDecayTimescale = 60;
348 vd.m_angularMotorTimescale = 4;
349 vd.m_angularMotorDecayTimescale = 8;
350 vd.m_VhoverHeight = 0;
351 vd.m_VhoverEfficiency = 0.5f;
352 vd.m_VhoverTimescale = 1000;
353 vd.m_VehicleBuoyancy = 0;
354 vd.m_linearDeflectionEfficiency = 0.5f;
355 vd.m_linearDeflectionTimescale = 0.5f;
356 vd.m_angularDeflectionEfficiency = 1;
357 vd.m_angularDeflectionTimescale = 2;
358 vd.m_verticalAttractionEfficiency = 0.9f;
359 vd.m_verticalAttractionTimescale = 2f;
360 vd.m_bankingEfficiency = 1;
361 vd.m_bankingMix = 0.7f;
362 vd.m_bankingTimescale = 2;
363 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
364 VehicleFlag.HOVER_TERRAIN_ONLY |
365 VehicleFlag.HOVER_GLOBAL_HEIGHT |
366 VehicleFlag.HOVER_UP_ONLY |
367 VehicleFlag.NO_DEFLECTION_UP |
368 VehicleFlag.LIMIT_MOTOR_UP);
369 vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
370 break;
371 case Vehicle.TYPE_BALLOON:
372 vd.m_linearFrictionTimescale = new Vector3(5, 5, 5);
373 vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
374 vd.m_linearMotorTimescale = 5;
375 vd.m_linearMotorDecayTimescale = 60;
376 vd.m_angularMotorTimescale = 6;
377 vd.m_angularMotorDecayTimescale = 10;
378 vd.m_VhoverHeight = 5;
379 vd.m_VhoverEfficiency = 0.8f;
380 vd.m_VhoverTimescale = 10;
381 vd.m_VehicleBuoyancy = 1;
382 vd.m_linearDeflectionEfficiency = 0;
383 vd.m_linearDeflectionTimescale = 5;
384 vd.m_angularDeflectionEfficiency = 0;
385 vd.m_angularDeflectionTimescale = 5;
386 vd.m_verticalAttractionEfficiency = 0f;
387 vd.m_verticalAttractionTimescale = 1000f;
388 vd.m_bankingEfficiency = 0;
389 vd.m_bankingMix = 0.7f;
390 vd.m_bankingTimescale = 5;
391 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
392 VehicleFlag.HOVER_TERRAIN_ONLY |
393 VehicleFlag.HOVER_UP_ONLY |
394 VehicleFlag.NO_DEFLECTION_UP |
395 VehicleFlag.LIMIT_MOTOR_UP);
396 vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY |
397 VehicleFlag.HOVER_GLOBAL_HEIGHT);
398 break;
399 }
400 }
401 public void SetVehicle(PhysicsActor ph)
402 {
403 if (ph == null)
404 return;
405 ph.SetVehicle(vd);
406 }
407
408 private XmlTextWriter writer;
409
410 private void XWint(string name, int i)
411 {
412 writer.WriteElementString(name, i.ToString());
413 }
414
415 private void XWfloat(string name, float f)
416 {
417 writer.WriteElementString(name, f.ToString(Utils.EnUsCulture));
418 }
419
420 private void XWVector(string name, Vector3 vec)
421 {
422 writer.WriteStartElement(name);
423 writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture));
424 writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture));
425 writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture));
426 writer.WriteEndElement();
427 }
428
429 private void XWQuat(string name, Quaternion quat)
430 {
431 writer.WriteStartElement(name);
432 writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture));
433 writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture));
434 writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture));
435 writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture));
436 writer.WriteEndElement();
437 }
438
439 public void ToXml2(XmlTextWriter twriter)
440 {
441 writer = twriter;
442 writer.WriteStartElement("Vehicle");
443
444 XWint("TYPE", (int)vd.m_type);
445 XWint("FLAGS", (int)vd.m_flags);
446
447 // Linear properties
448 XWVector("LMDIR", vd.m_linearMotorDirection);
449 XWVector("LMFTIME", vd.m_linearFrictionTimescale);
450 XWfloat("LMDTIME", vd.m_linearMotorDecayTimescale);
451 XWfloat("LMTIME", vd.m_linearMotorTimescale);
452 XWVector("LMOFF", vd.m_linearMotorOffset);
453
454 //Angular properties
455 XWVector("AMDIR", vd.m_angularMotorDirection);
456 XWfloat("AMTIME", vd.m_angularMotorTimescale);
457 XWfloat("AMDTIME", vd.m_angularMotorDecayTimescale);
458 XWVector("AMFTIME", vd.m_angularFrictionTimescale);
459
460 //Deflection properties
461 XWfloat("ADEFF", vd.m_angularDeflectionEfficiency);
462 XWfloat("ADTIME", vd.m_angularDeflectionTimescale);
463 XWfloat("LDEFF", vd.m_linearDeflectionEfficiency);
464 XWfloat("LDTIME", vd.m_linearDeflectionTimescale);
465
466 //Banking properties
467 XWfloat("BEFF", vd.m_bankingEfficiency);
468 XWfloat("BMIX", vd.m_bankingMix);
469 XWfloat("BTIME", vd.m_bankingTimescale);
470
471 //Hover and Buoyancy properties
472 XWfloat("HHEI", vd.m_VhoverHeight);
473 XWfloat("HEFF", vd.m_VhoverEfficiency);
474 XWfloat("HTIME", vd.m_VhoverTimescale);
475 XWfloat("VBUO", vd.m_VehicleBuoyancy);
476
477 //Attractor properties
478 XWfloat("VAEFF", vd.m_verticalAttractionEfficiency);
479 XWfloat("VATIME", vd.m_verticalAttractionTimescale);
480
481 XWQuat("REF_FRAME", vd.m_referenceFrame);
482
483 writer.WriteEndElement();
484 writer = null;
485 }
486
487
488
489 XmlTextReader reader;
490
491 private int XRint()
492 {
493 return reader.ReadElementContentAsInt();
494 }
495
496 private float XRfloat()
497 {
498 return reader.ReadElementContentAsFloat();
499 }
500
501 public Vector3 XRvector()
502 {
503 Vector3 vec;
504 reader.ReadStartElement();
505 vec.X = reader.ReadElementContentAsFloat();
506 vec.Y = reader.ReadElementContentAsFloat();
507 vec.Z = reader.ReadElementContentAsFloat();
508 reader.ReadEndElement();
509 return vec;
510 }
511
512 public Quaternion XRquat()
513 {
514 Quaternion q;
515 reader.ReadStartElement();
516 q.X = reader.ReadElementContentAsFloat();
517 q.Y = reader.ReadElementContentAsFloat();
518 q.Z = reader.ReadElementContentAsFloat();
519 q.W = reader.ReadElementContentAsFloat();
520 reader.ReadEndElement();
521 return q;
522 }
523
524 public static bool EReadProcessors(
525 Dictionary<string, Action> processors,
526 XmlTextReader xtr)
527 {
528 bool errors = false;
529
530 string nodeName = string.Empty;
531 while (xtr.NodeType != XmlNodeType.EndElement)
532 {
533 nodeName = xtr.Name;
534
535 // m_log.DebugFormat("[ExternalRepresentationUtils]: Processing: {0}", nodeName);
536
537 Action p = null;
538 if (processors.TryGetValue(xtr.Name, out p))
539 {
540 // m_log.DebugFormat("[ExternalRepresentationUtils]: Found {0} processor, nodeName);
541
542 try
543 {
544 p();
545 }
546 catch (Exception e)
547 {
548 errors = true;
549 if (xtr.NodeType == XmlNodeType.EndElement)
550 xtr.Read();
551 }
552 }
553 else
554 {
555 // m_log.DebugFormat("[LandDataSerializer]: caught unknown element {0}", nodeName);
556 xtr.ReadOuterXml(); // ignore
557 }
558 }
559
560 return errors;
561 }
562
563
564
565 public void FromXml2(XmlTextReader _reader, out bool errors)
566 {
567 errors = false;
568 reader = _reader;
569
570 Dictionary<string, Action> m_VehicleXmlProcessors
571 = new Dictionary<string, Action>();
572
573 m_VehicleXmlProcessors.Add("TYPE", ProcessXR_type);
574 m_VehicleXmlProcessors.Add("FLAGS", ProcessXR_flags);
575
576 // Linear properties
577 m_VehicleXmlProcessors.Add("LMDIR", ProcessXR_linearMotorDirection);
578 m_VehicleXmlProcessors.Add("LMFTIME", ProcessXR_linearFrictionTimescale);
579 m_VehicleXmlProcessors.Add("LMDTIME", ProcessXR_linearMotorDecayTimescale);
580 m_VehicleXmlProcessors.Add("LMTIME", ProcessXR_linearMotorTimescale);
581 m_VehicleXmlProcessors.Add("LMOFF", ProcessXR_linearMotorOffset);
582
583 //Angular properties
584 m_VehicleXmlProcessors.Add("AMDIR", ProcessXR_angularMotorDirection);
585 m_VehicleXmlProcessors.Add("AMTIME", ProcessXR_angularMotorTimescale);
586 m_VehicleXmlProcessors.Add("AMDTIME", ProcessXR_angularMotorDecayTimescale);
587 m_VehicleXmlProcessors.Add("AMFTIME", ProcessXR_angularFrictionTimescale);
588
589 //Deflection properties
590 m_VehicleXmlProcessors.Add("ADEFF", ProcessXR_angularDeflectionEfficiency);
591 m_VehicleXmlProcessors.Add("ADTIME", ProcessXR_angularDeflectionTimescale);
592 m_VehicleXmlProcessors.Add("LDEFF", ProcessXR_linearDeflectionEfficiency);
593 m_VehicleXmlProcessors.Add("LDTIME", ProcessXR_linearDeflectionTimescale);
594
595 //Banking properties
596 m_VehicleXmlProcessors.Add("BEFF", ProcessXR_bankingEfficiency);
597 m_VehicleXmlProcessors.Add("BMIX", ProcessXR_bankingMix);
598 m_VehicleXmlProcessors.Add("BTIME", ProcessXR_bankingTimescale);
599
600 //Hover and Buoyancy properties
601 m_VehicleXmlProcessors.Add("HHEI", ProcessXR_VhoverHeight);
602 m_VehicleXmlProcessors.Add("HEFF", ProcessXR_VhoverEfficiency);
603 m_VehicleXmlProcessors.Add("HTIME", ProcessXR_VhoverTimescale);
604
605 m_VehicleXmlProcessors.Add("VBUO", ProcessXR_VehicleBuoyancy);
606
607 //Attractor properties
608 m_VehicleXmlProcessors.Add("VAEFF", ProcessXR_verticalAttractionEfficiency);
609 m_VehicleXmlProcessors.Add("VATIME", ProcessXR_verticalAttractionTimescale);
610
611 m_VehicleXmlProcessors.Add("REF_FRAME", ProcessXR_referenceFrame);
612
613 vd = new VehicleData();
614
615 reader.ReadStartElement("Vehicle", String.Empty);
616
617 errors = EReadProcessors(
618 m_VehicleXmlProcessors,
619 reader);
620
621 reader.ReadEndElement();
622 reader = null;
623 }
624
625 private void ProcessXR_type()
626 {
627 vd.m_type = (Vehicle)XRint();
628 }
629 private void ProcessXR_flags()
630 {
631 vd.m_flags = (VehicleFlag)XRint();
632 }
633 // Linear properties
634 private void ProcessXR_linearMotorDirection()
635 {
636 vd.m_linearMotorDirection = XRvector();
637 }
638
639 private void ProcessXR_linearFrictionTimescale()
640 {
641 vd.m_linearFrictionTimescale = XRvector();
642 }
643
644 private void ProcessXR_linearMotorDecayTimescale()
645 {
646 vd.m_linearMotorDecayTimescale = XRfloat();
647 }
648 private void ProcessXR_linearMotorTimescale()
649 {
650 vd.m_linearMotorTimescale = XRfloat();
651 }
652 private void ProcessXR_linearMotorOffset()
653 {
654 vd.m_linearMotorOffset = XRvector();
655 }
656
657
658 //Angular properties
659 private void ProcessXR_angularMotorDirection()
660 {
661 vd.m_angularMotorDirection = XRvector();
662 }
663 private void ProcessXR_angularMotorTimescale()
664 {
665 vd.m_angularMotorTimescale = XRfloat();
666 }
667 private void ProcessXR_angularMotorDecayTimescale()
668 {
669 vd.m_angularMotorDecayTimescale = XRfloat();
670 }
671 private void ProcessXR_angularFrictionTimescale()
672 {
673 vd.m_angularFrictionTimescale = XRvector();
674 }
675
676 //Deflection properties
677 private void ProcessXR_angularDeflectionEfficiency()
678 {
679 vd.m_angularDeflectionEfficiency = XRfloat();
680 }
681 private void ProcessXR_angularDeflectionTimescale()
682 {
683 vd.m_angularDeflectionTimescale = XRfloat();
684 }
685 private void ProcessXR_linearDeflectionEfficiency()
686 {
687 vd.m_linearDeflectionEfficiency = XRfloat();
688 }
689 private void ProcessXR_linearDeflectionTimescale()
690 {
691 vd.m_linearDeflectionTimescale = XRfloat();
692 }
693
694 //Banking properties
695 private void ProcessXR_bankingEfficiency()
696 {
697 vd.m_bankingEfficiency = XRfloat();
698 }
699 private void ProcessXR_bankingMix()
700 {
701 vd.m_bankingMix = XRfloat();
702 }
703 private void ProcessXR_bankingTimescale()
704 {
705 vd.m_bankingTimescale = XRfloat();
706 }
707
708 //Hover and Buoyancy properties
709 private void ProcessXR_VhoverHeight()
710 {
711 vd.m_VhoverHeight = XRfloat();
712 }
713 private void ProcessXR_VhoverEfficiency()
714 {
715 vd.m_VhoverEfficiency = XRfloat();
716 }
717 private void ProcessXR_VhoverTimescale()
718 {
719 vd.m_VhoverTimescale = XRfloat();
720 }
721
722 private void ProcessXR_VehicleBuoyancy()
723 {
724 vd.m_VehicleBuoyancy = XRfloat();
725 }
726
727 //Attractor properties
728 private void ProcessXR_verticalAttractionEfficiency()
729 {
730 vd.m_verticalAttractionEfficiency = XRfloat();
731 }
732 private void ProcessXR_verticalAttractionTimescale()
733 {
734 vd.m_verticalAttractionTimescale = XRfloat();
735 }
736
737 private void ProcessXR_referenceFrame()
738 {
739 vd.m_referenceFrame = XRquat();
740 }
741 }
742} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 9ff8467..9776a82 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -169,7 +169,7 @@ namespace OpenSim.Region.Framework.Scenes
169 return false; 169 return false;
170 } 170 }
171 } 171 }
172 172
173 if (InventoryService.AddItem(item)) 173 if (InventoryService.AddItem(item))
174 { 174 {
175 int userlevel = 0; 175 int userlevel = 0;
@@ -324,8 +324,7 @@ namespace OpenSim.Region.Framework.Scenes
324 324
325 // Update item with new asset 325 // Update item with new asset
326 item.AssetID = asset.FullID; 326 item.AssetID = asset.FullID;
327 if (group.UpdateInventoryItem(item)) 327 group.UpdateInventoryItem(item);
328 remoteClient.SendAgentAlertMessage("Script saved", false);
329 328
330 part.SendPropertiesToClient(remoteClient); 329 part.SendPropertiesToClient(remoteClient);
331 330
@@ -336,12 +335,7 @@ namespace OpenSim.Region.Framework.Scenes
336 { 335 {
337 // Needs to determine which engine was running it and use that 336 // Needs to determine which engine was running it and use that
338 // 337 //
339 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 338 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
340 errors = part.Inventory.GetScriptErrors(item.ItemID);
341 }
342 else
343 {
344 remoteClient.SendAgentAlertMessage("Script saved", false);
345 } 339 }
346 340
347 // Tell anyone managing scripts that a script has been reloaded/changed 341 // Tell anyone managing scripts that a script has been reloaded/changed
@@ -409,6 +403,7 @@ namespace OpenSim.Region.Framework.Scenes
409 403
410 if (UUID.Zero == transactionID) 404 if (UUID.Zero == transactionID)
411 { 405 {
406 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
412 item.Name = itemUpd.Name; 407 item.Name = itemUpd.Name;
413 item.Description = itemUpd.Description; 408 item.Description = itemUpd.Description;
414 409
@@ -795,6 +790,8 @@ namespace OpenSim.Region.Framework.Scenes
795 return; 790 return;
796 } 791 }
797 792
793 if (newName == null) newName = item.Name;
794
798 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 795 AssetBase asset = AssetService.Get(item.AssetID.ToString());
799 796
800 if (asset != null) 797 if (asset != null)
@@ -851,6 +848,24 @@ namespace OpenSim.Region.Framework.Scenes
851 } 848 }
852 849
853 /// <summary> 850 /// <summary>
851 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
852 /// </summary>
853 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
854 {
855 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
856 foreach (InventoryItemBase b in items)
857 {
858 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
859 InventoryItemBase n = InventoryService.GetItem(b);
860 n.Folder = destfolder;
861 moveitems.Add(n);
862 remoteClient.SendInventoryItemCreateUpdate(n, 0);
863 }
864
865 MoveInventoryItem(remoteClient, moveitems);
866 }
867
868 /// <summary>
854 /// Move an item within the agent's inventory. 869 /// Move an item within the agent's inventory.
855 /// </summary> 870 /// </summary>
856 /// <param name="remoteClient"></param> 871 /// <param name="remoteClient"></param>
@@ -1193,6 +1208,10 @@ namespace OpenSim.Region.Framework.Scenes
1193 { 1208 {
1194 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1209 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1195 1210
1211 // Can't move a null item
1212 if (itemId == UUID.Zero)
1213 return;
1214
1196 if (null == part) 1215 if (null == part)
1197 { 1216 {
1198 m_log.WarnFormat( 1217 m_log.WarnFormat(
@@ -1297,21 +1316,28 @@ namespace OpenSim.Region.Framework.Scenes
1297 return; 1316 return;
1298 } 1317 }
1299 1318
1300 if (part.OwnerID != destPart.OwnerID) 1319 // Can't transfer this
1320 //
1321 if (part.OwnerID != destPart.OwnerID && (srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1322 return;
1323
1324 bool overrideNoMod = false;
1325 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1326 overrideNoMod = true;
1327
1328 if (part.OwnerID != destPart.OwnerID && (destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1301 { 1329 {
1302 // Source must have transfer permissions 1330 // object cannot copy items to an object owned by a different owner
1303 if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) 1331 // unless llAllowInventoryDrop has been called
1304 return;
1305 1332
1306 // Object cannot copy items to an object owned by a different owner 1333 return;
1307 // unless llAllowInventoryDrop has been called on the destination
1308 if ((destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1309 return;
1310 } 1334 }
1311 1335
1312 // must have both move and modify permission to put an item in an object 1336 // must have both move and modify permission to put an item in an object
1313 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1337 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1338 {
1314 return; 1339 return;
1340 }
1315 1341
1316 TaskInventoryItem destTaskItem = new TaskInventoryItem(); 1342 TaskInventoryItem destTaskItem = new TaskInventoryItem();
1317 1343
@@ -1367,6 +1393,14 @@ namespace OpenSim.Region.Framework.Scenes
1367 1393
1368 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1394 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1369 { 1395 {
1396 SceneObjectPart destPart = GetSceneObjectPart(destID);
1397 if (destPart != null) // Move into a prim
1398 {
1399 foreach(UUID itemID in items)
1400 MoveTaskInventoryItem(destID, host, itemID);
1401 return destID; // Prim folder ID == prim ID
1402 }
1403
1370 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1404 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1371 1405
1372 UUID newFolderID = UUID.Random(); 1406 UUID newFolderID = UUID.Random();
@@ -1549,12 +1583,12 @@ namespace OpenSim.Region.Framework.Scenes
1549 AgentTransactionsModule.HandleTaskItemUpdateFromTransaction( 1583 AgentTransactionsModule.HandleTaskItemUpdateFromTransaction(
1550 remoteClient, part, transactionID, currentItem); 1584 remoteClient, part, transactionID, currentItem);
1551 1585
1552 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1586// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1553 remoteClient.SendAgentAlertMessage("Notecard saved", false); 1587// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1554 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1588// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1555 remoteClient.SendAgentAlertMessage("Script saved", false); 1589// remoteClient.SendAgentAlertMessage("Script saved", false);
1556 else 1590// else
1557 remoteClient.SendAgentAlertMessage("Item saved", false); 1591// remoteClient.SendAgentAlertMessage("Item saved", false);
1558 } 1592 }
1559 1593
1560 // Base ALWAYS has move 1594 // Base ALWAYS has move
@@ -1737,7 +1771,7 @@ namespace OpenSim.Region.Framework.Scenes
1737 } 1771 }
1738 1772
1739 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1773 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1740 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1774 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1741 agentID); 1775 agentID);
1742 AssetService.Store(asset); 1776 AssetService.Store(asset);
1743 1777
@@ -1893,23 +1927,32 @@ namespace OpenSim.Region.Framework.Scenes
1893 // build a list of eligible objects 1927 // build a list of eligible objects
1894 List<uint> deleteIDs = new List<uint>(); 1928 List<uint> deleteIDs = new List<uint>();
1895 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1929 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1896 1930 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1897 // Start with true for both, then remove the flags if objects
1898 // that we can't derez are part of the selection
1899 bool permissionToTake = true;
1900 bool permissionToTakeCopy = true;
1901 bool permissionToDelete = true;
1902 1931
1903 foreach (uint localID in localIDs) 1932 foreach (uint localID in localIDs)
1904 { 1933 {
1934 // Start with true for both, then remove the flags if objects
1935 // that we can't derez are part of the selection
1936 bool permissionToTake = true;
1937 bool permissionToTakeCopy = true;
1938 bool permissionToDelete = true;
1939
1905 // Invalid id 1940 // Invalid id
1906 SceneObjectPart part = GetSceneObjectPart(localID); 1941 SceneObjectPart part = GetSceneObjectPart(localID);
1907 if (part == null) 1942 if (part == null)
1943 {
1944 //Client still thinks the object exists, kill it
1945 deleteIDs.Add(localID);
1908 continue; 1946 continue;
1947 }
1909 1948
1910 // Already deleted by someone else 1949 // Already deleted by someone else
1911 if (part.ParentGroup.IsDeleted) 1950 if (part.ParentGroup.IsDeleted)
1951 {
1952 //Client still thinks the object exists, kill it
1953 deleteIDs.Add(localID);
1912 continue; 1954 continue;
1955 }
1913 1956
1914 // Can't delete child prims 1957 // Can't delete child prims
1915 if (part != part.ParentGroup.RootPart) 1958 if (part != part.ParentGroup.RootPart)
@@ -1917,9 +1960,6 @@ namespace OpenSim.Region.Framework.Scenes
1917 1960
1918 SceneObjectGroup grp = part.ParentGroup; 1961 SceneObjectGroup grp = part.ParentGroup;
1919 1962
1920 deleteIDs.Add(localID);
1921 deleteGroups.Add(grp);
1922
1923 if (remoteClient == null) 1963 if (remoteClient == null)
1924 { 1964 {
1925 // Autoreturn has a null client. Nothing else does. So 1965 // Autoreturn has a null client. Nothing else does. So
@@ -1936,81 +1976,193 @@ namespace OpenSim.Region.Framework.Scenes
1936 } 1976 }
1937 else 1977 else
1938 { 1978 {
1939 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1979 if (action == DeRezAction.TakeCopy)
1980 {
1981 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1982 permissionToTakeCopy = false;
1983 }
1984 else
1985 {
1940 permissionToTakeCopy = false; 1986 permissionToTakeCopy = false;
1941 1987 }
1942 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1988 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1943 permissionToTake = false; 1989 permissionToTake = false;
1944 1990
1945 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1991 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1946 permissionToDelete = false; 1992 permissionToDelete = false;
1947 } 1993 }
1948 }
1949 1994
1950 // Handle god perms 1995 // Handle god perms
1951 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1996 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1952 { 1997 {
1953 permissionToTake = true; 1998 permissionToTake = true;
1954 permissionToTakeCopy = true; 1999 permissionToTakeCopy = true;
1955 permissionToDelete = true; 2000 permissionToDelete = true;
1956 } 2001 }
1957 2002
1958 // If we're re-saving, we don't even want to delete 2003 // If we're re-saving, we don't even want to delete
1959 if (action == DeRezAction.SaveToExistingUserInventoryItem) 2004 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1960 permissionToDelete = false; 2005 permissionToDelete = false;
1961 2006
1962 // if we want to take a copy, we also don't want to delete 2007 // if we want to take a copy, we also don't want to delete
1963 // Note: after this point, the permissionToTakeCopy flag 2008 // Note: after this point, the permissionToTakeCopy flag
1964 // becomes irrelevant. It already includes the permissionToTake 2009 // becomes irrelevant. It already includes the permissionToTake
1965 // permission and after excluding no copy items here, we can 2010 // permission and after excluding no copy items here, we can
1966 // just use that. 2011 // just use that.
1967 if (action == DeRezAction.TakeCopy) 2012 if (action == DeRezAction.TakeCopy)
1968 { 2013 {
1969 // If we don't have permission, stop right here 2014 // If we don't have permission, stop right here
1970 if (!permissionToTakeCopy) 2015 if (!permissionToTakeCopy)
1971 return; 2016 return;
1972 2017
1973 permissionToTake = true; 2018 permissionToTake = true;
1974 // Don't delete 2019 // Don't delete
1975 permissionToDelete = false; 2020 permissionToDelete = false;
1976 } 2021 }
1977 2022
1978 if (action == DeRezAction.Return) 2023 if (action == DeRezAction.Return)
1979 {
1980 if (remoteClient != null)
1981 { 2024 {
1982 if (Permissions.CanReturnObjects( 2025 if (remoteClient != null)
1983 null,
1984 remoteClient.AgentId,
1985 deleteGroups))
1986 { 2026 {
1987 permissionToTake = true; 2027 if (Permissions.CanReturnObjects(
1988 permissionToDelete = true; 2028 null,
1989 2029 remoteClient.AgentId,
1990 foreach (SceneObjectGroup g in deleteGroups) 2030 deleteGroups))
1991 { 2031 {
1992 AddReturn(g.OwnerID == g.GroupID ? g.LastOwnerID : g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 2032 permissionToTake = true;
2033 permissionToDelete = true;
2034
2035 AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1993 } 2036 }
1994 } 2037 }
2038 else // Auto return passes through here with null agent
2039 {
2040 permissionToTake = true;
2041 permissionToDelete = true;
2042 }
1995 } 2043 }
1996 else // Auto return passes through here with null agent 2044
2045 if (permissionToTake && (!permissionToDelete))
2046 takeGroups.Add(grp);
2047
2048 if (permissionToDelete)
1997 { 2049 {
1998 permissionToTake = true; 2050 if (permissionToTake)
1999 permissionToDelete = true; 2051 deleteGroups.Add(grp);
2052 deleteIDs.Add(grp.LocalId);
2000 } 2053 }
2001 } 2054 }
2002 2055
2003 if (permissionToTake && (action != DeRezAction.Delete || this.m_useTrashOnDelete)) 2056 SendKillObject(deleteIDs);
2057
2058 if (deleteGroups.Count > 0)
2004 { 2059 {
2060 foreach (SceneObjectGroup g in deleteGroups)
2061 deleteIDs.Remove(g.LocalId);
2062
2005 m_asyncSceneObjectDeleter.DeleteToInventory( 2063 m_asyncSceneObjectDeleter.DeleteToInventory(
2006 action, destinationID, deleteGroups, remoteClient, 2064 action, destinationID, deleteGroups, remoteClient,
2007 permissionToDelete); 2065 true);
2008 } 2066 }
2009 else if (permissionToDelete) 2067 if (takeGroups.Count > 0)
2068 {
2069 m_asyncSceneObjectDeleter.DeleteToInventory(
2070 action, destinationID, takeGroups, remoteClient,
2071 false);
2072 }
2073 if (deleteIDs.Count > 0)
2010 { 2074 {
2011 foreach (SceneObjectGroup g in deleteGroups) 2075 foreach (SceneObjectGroup g in deleteGroups)
2012 DeleteSceneObject(g, false); 2076 DeleteSceneObject(g, true);
2077 }
2078 }
2079
2080 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
2081 {
2082 itemID = UUID.Zero;
2083 if (grp != null)
2084 {
2085 Vector3 inventoryStoredPosition = new Vector3
2086 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
2087 ? 250
2088 : grp.AbsolutePosition.X)
2089 ,
2090 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
2091 ? 250
2092 : grp.AbsolutePosition.X,
2093 grp.AbsolutePosition.Z);
2094
2095 Vector3 originalPosition = grp.AbsolutePosition;
2096
2097 grp.AbsolutePosition = inventoryStoredPosition;
2098
2099 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
2100
2101 grp.AbsolutePosition = originalPosition;
2102
2103 AssetBase asset = CreateAsset(
2104 grp.GetPartName(grp.LocalId),
2105 grp.GetPartDescription(grp.LocalId),
2106 (sbyte)AssetType.Object,
2107 Utils.StringToBytes(sceneObjectXml),
2108 remoteClient.AgentId);
2109 AssetService.Store(asset);
2110
2111 InventoryItemBase item = new InventoryItemBase();
2112 item.CreatorId = grp.RootPart.CreatorID.ToString();
2113 item.CreatorData = grp.RootPart.CreatorData;
2114 item.Owner = remoteClient.AgentId;
2115 item.ID = UUID.Random();
2116 item.AssetID = asset.FullID;
2117 item.Description = asset.Description;
2118 item.Name = asset.Name;
2119 item.AssetType = asset.Type;
2120 item.InvType = (int)InventoryType.Object;
2121
2122 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
2123 if (folder != null)
2124 item.Folder = folder.ID;
2125 else // oopsies
2126 item.Folder = UUID.Zero;
2127
2128 // Set up base perms properly
2129 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
2130 permsBase &= grp.RootPart.BaseMask;
2131 permsBase |= (uint)PermissionMask.Move;
2132
2133 // Make sure we don't lock it
2134 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
2135
2136 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2137 {
2138 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2139 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2140 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2141 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2142 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2143 }
2144 else
2145 {
2146 item.BasePermissions = permsBase;
2147 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2148 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2149 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2150 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2151 }
2152 item.CreationDate = Util.UnixTimeSinceEpoch();
2153
2154 // sets itemID so client can show item as 'attached' in inventory
2155 grp.FromItemID = item.ID;
2156
2157 if (AddInventoryItem(item))
2158 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2159 else
2160 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2161
2162 itemID = item.ID;
2163 return item.AssetID;
2013 } 2164 }
2165 return UUID.Zero;
2014 } 2166 }
2015 2167
2016 /// <summary> 2168 /// <summary>
@@ -2139,6 +2291,9 @@ namespace OpenSim.Region.Framework.Scenes
2139 2291
2140 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2292 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2141 { 2293 {
2294 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2295 return;
2296
2142 SceneObjectPart part = GetSceneObjectPart(objectID); 2297 SceneObjectPart part = GetSceneObjectPart(objectID);
2143 if (part == null) 2298 if (part == null)
2144 return; 2299 return;
@@ -2209,7 +2364,10 @@ namespace OpenSim.Region.Framework.Scenes
2209 } 2364 }
2210 else 2365 else
2211 { 2366 {
2212 if (!Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)) 2367 if (!Permissions.IsGod(remoteClient.AgentId) && sog.OwnerID != remoteClient.AgentId)
2368 continue;
2369
2370 if (!Permissions.CanTransferObject(sog.UUID, groupID))
2213 continue; 2371 continue;
2214 2372
2215 if (sog.GroupID != groupID) 2373 if (sog.GroupID != groupID)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 2701d6e..431b903 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -38,9 +38,8 @@ namespace OpenSim.Region.Framework.Scenes
38{ 38{
39 public partial class Scene 39 public partial class Scene
40 { 40 {
41 41 public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
42 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, 42 UUID fromID, bool fromAgent, bool broadcast, UUID destination)
43 UUID fromID, UUID targetID, bool fromAgent, bool broadcast)
44 { 43 {
45 OSChatMessage args = new OSChatMessage(); 44 OSChatMessage args = new OSChatMessage();
46 45
@@ -50,6 +49,7 @@ namespace OpenSim.Region.Framework.Scenes
50 args.Position = fromPos; 49 args.Position = fromPos;
51 args.SenderUUID = fromID; 50 args.SenderUUID = fromID;
52 args.Scene = this; 51 args.Scene = this;
52 args.Destination = destination;
53 53
54 if (fromAgent) 54 if (fromAgent)
55 { 55 {
@@ -64,18 +64,18 @@ namespace OpenSim.Region.Framework.Scenes
64 } 64 }
65 65
66 args.From = fromName; 66 args.From = fromName;
67 args.TargetUUID = targetID; 67 //args.
68 68
69 if (broadcast) 69 if (broadcast)
70 EventManager.TriggerOnChatBroadcast(this, args); 70 EventManager.TriggerOnChatBroadcast(this, args);
71 else 71 else
72 EventManager.TriggerOnChatFromWorld(this, args); 72 EventManager.TriggerOnChatFromWorld(this, args);
73 } 73 }
74 74
75 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, 75 protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName,
76 UUID fromID, bool fromAgent, bool broadcast) 76 UUID fromID, bool fromAgent, bool broadcast)
77 { 77 {
78 SimChat(message, type, channel, fromPos, fromName, fromID, UUID.Zero, fromAgent, broadcast); 78 SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, broadcast, UUID.Zero);
79 } 79 }
80 80
81 /// <summary> 81 /// <summary>
@@ -115,19 +115,6 @@ namespace OpenSim.Region.Framework.Scenes
115 { 115 {
116 SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, true); 116 SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, true);
117 } 117 }
118 /// <summary>
119 ///
120 /// </summary>
121 /// <param name="message"></param>
122 /// <param name="type"></param>
123 /// <param name="fromPos"></param>
124 /// <param name="fromName"></param>
125 /// <param name="fromAgentID"></param>
126 /// <param name="targetID"></param>
127 public void SimChatToAgent(UUID targetID, byte[] message, Vector3 fromPos, string fromName, UUID fromID, bool fromAgent)
128 {
129 SimChat(message, ChatTypeEnum.Say, 0, fromPos, fromName, fromID, targetID, fromAgent, false);
130 }
131 118
132 /// <summary> 119 /// <summary>
133 /// Invoked when the client requests a prim. 120 /// Invoked when the client requests a prim.
@@ -149,27 +136,47 @@ namespace OpenSim.Region.Framework.Scenes
149 /// <param name="remoteClient"></param> 136 /// <param name="remoteClient"></param>
150 public void SelectPrim(uint primLocalID, IClientAPI remoteClient) 137 public void SelectPrim(uint primLocalID, IClientAPI remoteClient)
151 { 138 {
139 /*
140 SceneObjectPart part = GetSceneObjectPart(primLocalID);
141
142 if (null == part)
143 return;
144
145 if (part.IsRoot)
146 {
147 SceneObjectGroup sog = part.ParentGroup;
148 sog.SendPropertiesToClient(remoteClient);
149
150 // A prim is only tainted if it's allowed to be edited by the person clicking it.
151 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
152 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
153 {
154 sog.IsSelected = true;
155 EventManager.TriggerParcelPrimCountTainted();
156 }
157 }
158 else
159 {
160 part.SendPropertiesToClient(remoteClient);
161 }
162 */
152 SceneObjectPart part = GetSceneObjectPart(primLocalID); 163 SceneObjectPart part = GetSceneObjectPart(primLocalID);
153 164
154 if (null == part) 165 if (null == part)
155 return; 166 return;
156 167
157 if (part.IsRoot) 168 SceneObjectGroup sog = part.ParentGroup;
158 { 169 if (sog == null)
159 SceneObjectGroup sog = part.ParentGroup; 170 return;
160 sog.SendPropertiesToClient(remoteClient);
161 sog.IsSelected = true;
162 171
163 // A prim is only tainted if it's allowed to be edited by the person clicking it. 172 part.SendPropertiesToClient(remoteClient);
164 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId) 173
165 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId)) 174 // A prim is only tainted if it's allowed to be edited by the person clicking it.
166 { 175 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
167 EventManager.TriggerParcelPrimCountTainted(); 176 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
168 }
169 }
170 else
171 { 177 {
172 part.SendPropertiesToClient(remoteClient); 178 part.IsSelected = true;
179 EventManager.TriggerParcelPrimCountTainted();
173 } 180 }
174 } 181 }
175 182
@@ -222,7 +229,7 @@ namespace OpenSim.Region.Framework.Scenes
222 SceneObjectPart part = GetSceneObjectPart(primLocalID); 229 SceneObjectPart part = GetSceneObjectPart(primLocalID);
223 if (part == null) 230 if (part == null)
224 return; 231 return;
225 232 /*
226 // A deselect packet contains all the local prims being deselected. However, since selection is still 233 // A deselect packet contains all the local prims being deselected. However, since selection is still
227 // group based we only want the root prim to trigger a full update - otherwise on objects with many prims 234 // group based we only want the root prim to trigger a full update - otherwise on objects with many prims
228 // we end up sending many duplicate ObjectUpdates 235 // we end up sending many duplicate ObjectUpdates
@@ -235,7 +242,9 @@ namespace OpenSim.Region.Framework.Scenes
235 // handled by group, but by prim. Legacy cruft. 242 // handled by group, but by prim. Legacy cruft.
236 // TODO: Make selection flagging per prim! 243 // TODO: Make selection flagging per prim!
237 // 244 //
238 part.ParentGroup.IsSelected = false; 245 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
246 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
247 part.ParentGroup.IsSelected = false;
239 248
240 if (part.ParentGroup.IsAttachment) 249 if (part.ParentGroup.IsAttachment)
241 isAttachment = true; 250 isAttachment = true;
@@ -255,6 +264,22 @@ namespace OpenSim.Region.Framework.Scenes
255 part.UUID, remoteClient.AgentId)) 264 part.UUID, remoteClient.AgentId))
256 EventManager.TriggerParcelPrimCountTainted(); 265 EventManager.TriggerParcelPrimCountTainted();
257 } 266 }
267 */
268
269 bool oldgprSelect = part.ParentGroup.IsSelected;
270
271 // This is wrong, wrong, wrong. Selection should not be
272 // handled by group, but by prim. Legacy cruft.
273 // TODO: Make selection flagging per prim!
274 //
275 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
276 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
277 {
278 part.IsSelected = false;
279 if (!part.ParentGroup.IsAttachment && oldgprSelect != part.ParentGroup.IsSelected)
280 EventManager.TriggerParcelPrimCountTainted();
281 }
282
258 } 283 }
259 284
260 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount, 285 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount,
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 36d39ea..a63ed13 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -127,6 +127,7 @@ namespace OpenSim.Region.Framework.Scenes
127 // TODO: need to figure out how allow client agents but deny 127 // TODO: need to figure out how allow client agents but deny
128 // root agents when ACL denies access to root agent 128 // root agents when ACL denies access to root agent
129 public bool m_strictAccessControl = true; 129 public bool m_strictAccessControl = true;
130 public bool m_seeIntoBannedRegion = false;
130 public int MaxUndoCount = 5; 131 public int MaxUndoCount = 5;
131 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 132 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
132 public bool LoginLock = false; 133 public bool LoginLock = false;
@@ -142,12 +143,14 @@ namespace OpenSim.Region.Framework.Scenes
142 143
143 protected int m_splitRegionID; 144 protected int m_splitRegionID;
144 protected Timer m_restartWaitTimer = new Timer(); 145 protected Timer m_restartWaitTimer = new Timer();
146 protected Timer m_timerWatchdog = new Timer();
145 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 147 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
146 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 148 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
147 protected string m_simulatorVersion = "OpenSimulator Server"; 149 protected string m_simulatorVersion = "OpenSimulator Server";
148 protected ModuleLoader m_moduleLoader; 150 protected ModuleLoader m_moduleLoader;
149 protected AgentCircuitManager m_authenticateHandler; 151 protected AgentCircuitManager m_authenticateHandler;
150 protected SceneCommunicationService m_sceneGridService; 152 protected SceneCommunicationService m_sceneGridService;
153 protected ISnmpModule m_snmpService = null;
151 154
152 protected ISimulationDataService m_SimulationDataService; 155 protected ISimulationDataService m_SimulationDataService;
153 protected IEstateDataService m_EstateDataService; 156 protected IEstateDataService m_EstateDataService;
@@ -209,7 +212,7 @@ namespace OpenSim.Region.Framework.Scenes
209 private int m_update_events = 1; 212 private int m_update_events = 1;
210 private int m_update_backup = 200; 213 private int m_update_backup = 200;
211 private int m_update_terrain = 50; 214 private int m_update_terrain = 50;
212// private int m_update_land = 1; 215 private int m_update_land = 10;
213 private int m_update_coarse_locations = 50; 216 private int m_update_coarse_locations = 50;
214 217
215 private int agentMS; 218 private int agentMS;
@@ -229,6 +232,7 @@ namespace OpenSim.Region.Framework.Scenes
229 /// </summary> 232 /// </summary>
230 private int m_lastFrameTick; 233 private int m_lastFrameTick;
231 234
235 public bool CombineRegions = false;
232 /// <summary> 236 /// <summary>
233 /// Tick at which the last maintenance run occurred. 237 /// Tick at which the last maintenance run occurred.
234 /// </summary> 238 /// </summary>
@@ -259,6 +263,11 @@ namespace OpenSim.Region.Framework.Scenes
259 /// </summary> 263 /// </summary>
260 private int m_LastLogin; 264 private int m_LastLogin;
261 265
266 private int m_lastIncoming;
267 private int m_lastOutgoing;
268 private int m_hbRestarts = 0;
269
270
262 /// <summary> 271 /// <summary>
263 /// Thread that runs the scene loop. 272 /// Thread that runs the scene loop.
264 /// </summary> 273 /// </summary>
@@ -274,7 +283,7 @@ namespace OpenSim.Region.Framework.Scenes
274 private volatile bool m_shuttingDown; 283 private volatile bool m_shuttingDown;
275 284
276// private int m_lastUpdate; 285// private int m_lastUpdate;
277// private bool m_firstHeartbeat = true; 286 private bool m_firstHeartbeat = true;
278 287
279 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time; 288 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time;
280 private bool m_reprioritizationEnabled = true; 289 private bool m_reprioritizationEnabled = true;
@@ -319,6 +328,19 @@ namespace OpenSim.Region.Framework.Scenes
319 get { return m_sceneGridService; } 328 get { return m_sceneGridService; }
320 } 329 }
321 330
331 public ISnmpModule SnmpService
332 {
333 get
334 {
335 if (m_snmpService == null)
336 {
337 m_snmpService = RequestModuleInterface<ISnmpModule>();
338 }
339
340 return m_snmpService;
341 }
342 }
343
322 public ISimulationDataService SimulationDataService 344 public ISimulationDataService SimulationDataService
323 { 345 {
324 get 346 get
@@ -617,7 +639,9 @@ namespace OpenSim.Region.Framework.Scenes
617 m_sceneGridService = sceneGridService; 639 m_sceneGridService = sceneGridService;
618 m_SimulationDataService = simDataService; 640 m_SimulationDataService = simDataService;
619 m_EstateDataService = estateDataService; 641 m_EstateDataService = estateDataService;
620 m_regionHandle = RegionInfo.RegionHandle; 642 m_regionHandle = m_regInfo.RegionHandle;
643 m_lastIncoming = 0;
644 m_lastOutgoing = 0;
621 645
622 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 646 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
623 m_asyncSceneObjectDeleter.Enabled = true; 647 m_asyncSceneObjectDeleter.Enabled = true;
@@ -698,120 +722,129 @@ namespace OpenSim.Region.Framework.Scenes
698 722
699 // Region config overrides global config 723 // Region config overrides global config
700 // 724 //
701 if (m_config.Configs["Startup"] != null) 725 try
702 { 726 {
703 IConfig startupConfig = m_config.Configs["Startup"]; 727 if (m_config.Configs["Startup"] != null)
704
705 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance);
706 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
707 if (!m_useBackup)
708 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
709
710 //Animation states
711 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
712
713 PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims);
714 CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims);
715
716 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
717 if (RegionInfo.NonphysPrimMax > 0)
718 { 728 {
719 m_maxNonphys = RegionInfo.NonphysPrimMax; 729 IConfig startupConfig = m_config.Configs["Startup"];
720 }
721 730
722 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 731 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance);
723 732 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
724 if (RegionInfo.PhysPrimMax > 0) 733 if (!m_useBackup)
725 { 734 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
726 m_maxPhys = RegionInfo.PhysPrimMax; 735
727 } 736 //Animation states
728 737 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
729 // Here, if clamping is requested in either global or
730 // local config, it will be used
731 //
732 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize);
733 if (RegionInfo.ClampPrimSize)
734 {
735 m_clampPrimSize = true;
736 }
737 738
738 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete); 739 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
739 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 740 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
740 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
741 m_dontPersistBefore =
742 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
743 m_dontPersistBefore *= 10000000;
744 m_persistAfter =
745 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
746 m_persistAfter *= 10000000;
747 741
748 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 742 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
743 if (RegionInfo.NonphysPrimMax > 0)
744 {
745 m_maxNonphys = RegionInfo.NonphysPrimMax;
746 }
749 747
750 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); 748 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
751 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
752 749
753 IConfig packetConfig = m_config.Configs["PacketPool"]; 750 if (RegionInfo.PhysPrimMax > 0)
754 if (packetConfig != null) 751 {
755 { 752 m_maxPhys = RegionInfo.PhysPrimMax;
756 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); 753 }
757 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
758 }
759 754
760 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 755 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
756 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
761 757
762 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 758 // Here, if clamping is requested in either global or
763 if (m_generateMaptiles) 759 // local config, it will be used
764 { 760 //
765 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0); 761 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize);
766 if (maptileRefresh != 0) 762 if (RegionInfo.ClampPrimSize)
767 { 763 {
768 m_mapGenerationTimer.Interval = maptileRefresh * 1000; 764 m_clampPrimSize = true;
769 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister;
770 m_mapGenerationTimer.AutoReset = true;
771 m_mapGenerationTimer.Start();
772 } 765 }
773 }
774 else
775 {
776 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
777 UUID tileID;
778 766
779 if (UUID.TryParse(tile, out tileID)) 767 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete);
768 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
769 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
770 m_dontPersistBefore =
771 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
772 m_dontPersistBefore *= 10000000;
773 m_persistAfter =
774 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
775 m_persistAfter *= 10000000;
776
777 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
778 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
779
780 IConfig packetConfig = m_config.Configs["PacketPool"];
781 if (packetConfig != null)
780 { 782 {
781 RegionInfo.RegionSettings.TerrainImageID = tileID; 783 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
784 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
782 } 785 }
783 }
784 786
785 string grant = startupConfig.GetString("AllowedViewerList", String.Empty); 787 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
786 if (grant.Length > 0) 788 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
787 { 789 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
788 foreach (string viewer in grant.Split(',')) 790
791 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
792 if (m_generateMaptiles)
789 { 793 {
790 m_AllowedViewers.Add(viewer.Trim().ToLower()); 794 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0);
795 if (maptileRefresh != 0)
796 {
797 m_mapGenerationTimer.Interval = maptileRefresh * 1000;
798 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister;
799 m_mapGenerationTimer.AutoReset = true;
800 m_mapGenerationTimer.Start();
801 }
791 } 802 }
792 } 803 else
804 {
805 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
806 UUID tileID;
793 807
794 grant = startupConfig.GetString("BannedViewerList", String.Empty); 808 if (UUID.TryParse(tile, out tileID))
795 if (grant.Length > 0) 809 {
796 { 810 RegionInfo.RegionSettings.TerrainImageID = tileID;
797 foreach (string viewer in grant.Split(',')) 811 }
812 }
813
814 string grant = startupConfig.GetString("AllowedViewerList", String.Empty);
815 if (grant.Length > 0)
798 { 816 {
799 m_BannedViewers.Add(viewer.Trim().ToLower()); 817 foreach (string viewer in grant.Split(','))
818 {
819 m_AllowedViewers.Add(viewer.Trim().ToLower());
820 }
800 } 821 }
801 }
802 822
803 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime); 823 grant = startupConfig.GetString("BannedViewerList", String.Empty);
804 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup); 824 if (grant.Length > 0)
805 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 825 {
806 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement); 826 foreach (string viewer in grant.Split(','))
807 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events); 827 {
808 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects); 828 m_BannedViewers.Add(viewer.Trim().ToLower());
809 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics); 829 }
810 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences); 830 }
811 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
812 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
813 831
814 SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates); 832 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime);
833 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup);
834 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
835 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement);
836 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events);
837 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects);
838 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics);
839 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
840 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
841 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
842 SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates);
843 }
844 }
845 catch (Exception e)
846 {
847 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
815 } 848 }
816 849
817 #endregion Region Config 850 #endregion Region Config
@@ -1237,7 +1270,22 @@ namespace OpenSim.Region.Framework.Scenes
1237 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1270 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1238 if (m_heartbeatThread != null) 1271 if (m_heartbeatThread != null)
1239 { 1272 {
1273 m_hbRestarts++;
1274 if(m_hbRestarts > 10)
1275 Environment.Exit(1);
1276 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1277
1278//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1279//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1280//proc.EnableRaisingEvents=false;
1281//proc.StartInfo.FileName = "/bin/kill";
1282//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1283//proc.Start();
1284//proc.WaitForExit();
1285//Thread.Sleep(1000);
1286//Environment.Exit(1);
1240 m_heartbeatThread.Abort(); 1287 m_heartbeatThread.Abort();
1288 Watchdog.AbortThread(m_heartbeatThread.ManagedThreadId);
1241 m_heartbeatThread = null; 1289 m_heartbeatThread = null;
1242 } 1290 }
1243// m_lastUpdate = Util.EnvironmentTickCount(); 1291// m_lastUpdate = Util.EnvironmentTickCount();
@@ -1528,6 +1576,8 @@ namespace OpenSim.Region.Framework.Scenes
1528 tmpMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc); 1576 tmpMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc);
1529 tmpMS = (int)(MinFrameTime * 1000) - tmpMS; 1577 tmpMS = (int)(MinFrameTime * 1000) - tmpMS;
1530 1578
1579 m_firstHeartbeat = false;
1580
1531 if (tmpMS > 0) 1581 if (tmpMS > 0)
1532 { 1582 {
1533 Thread.Sleep(tmpMS); 1583 Thread.Sleep(tmpMS);
@@ -1578,9 +1628,9 @@ namespace OpenSim.Region.Framework.Scenes
1578 1628
1579 private void CheckAtTargets() 1629 private void CheckAtTargets()
1580 { 1630 {
1581 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1631 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1582 lock (m_groupsWithTargets) 1632 lock (m_groupsWithTargets)
1583 objs = m_groupsWithTargets.Values; 1633 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1584 1634
1585 foreach (SceneObjectGroup entry in objs) 1635 foreach (SceneObjectGroup entry in objs)
1586 entry.checkAtTargets(); 1636 entry.checkAtTargets();
@@ -1661,7 +1711,7 @@ namespace OpenSim.Region.Framework.Scenes
1661 msg.fromAgentName = "Server"; 1711 msg.fromAgentName = "Server";
1662 msg.dialog = (byte)19; // Object msg 1712 msg.dialog = (byte)19; // Object msg
1663 msg.fromGroup = false; 1713 msg.fromGroup = false;
1664 msg.offline = (byte)0; 1714 msg.offline = (byte)1;
1665 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1715 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1666 msg.Position = Vector3.Zero; 1716 msg.Position = Vector3.Zero;
1667 msg.RegionID = RegionInfo.RegionID.Guid; 1717 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1883,6 +1933,19 @@ namespace OpenSim.Region.Framework.Scenes
1883 EventManager.TriggerPrimsLoaded(this); 1933 EventManager.TriggerPrimsLoaded(this);
1884 } 1934 }
1885 1935
1936 public bool SuportsRayCastFiltered()
1937 {
1938 if (PhysicsScene == null)
1939 return false;
1940 return PhysicsScene.SuportsRaycastWorldFiltered();
1941 }
1942
1943 public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter)
1944 {
1945 if (PhysicsScene == null)
1946 return null;
1947 return PhysicsScene.RaycastWorld(position, direction, length, Count,filter);
1948 }
1886 1949
1887 /// <summary> 1950 /// <summary>
1888 /// Gets a new rez location based on the raycast and the size of the object that is being rezzed. 1951 /// Gets a new rez location based on the raycast and the size of the object that is being rezzed.
@@ -1899,14 +1962,24 @@ namespace OpenSim.Region.Framework.Scenes
1899 /// <returns></returns> 1962 /// <returns></returns>
1900 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1963 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1901 { 1964 {
1965
1966 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1967 Vector3 wpos = Vector3.Zero;
1968 // Check for water surface intersection from above
1969 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1970 {
1971 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1972 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1973 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1974 wpos.Z = wheight;
1975 }
1976
1902 Vector3 pos = Vector3.Zero; 1977 Vector3 pos = Vector3.Zero;
1903 if (RayEndIsIntersection == (byte)1) 1978 if (RayEndIsIntersection == (byte)1)
1904 { 1979 {
1905 pos = RayEnd; 1980 pos = RayEnd;
1906 return pos;
1907 } 1981 }
1908 1982 else if (RayTargetID != UUID.Zero)
1909 if (RayTargetID != UUID.Zero)
1910 { 1983 {
1911 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1984 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1912 1985
@@ -1928,7 +2001,7 @@ namespace OpenSim.Region.Framework.Scenes
1928 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 2001 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1929 2002
1930 // Un-comment out the following line to Get Raytrace results printed to the console. 2003 // Un-comment out the following line to Get Raytrace results printed to the console.
1931 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 2004 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1932 float ScaleOffset = 0.5f; 2005 float ScaleOffset = 0.5f;
1933 2006
1934 // If we hit something 2007 // If we hit something
@@ -1951,13 +2024,10 @@ namespace OpenSim.Region.Framework.Scenes
1951 //pos.Z -= 0.25F; 2024 //pos.Z -= 0.25F;
1952 2025
1953 } 2026 }
1954
1955 return pos;
1956 } 2027 }
1957 else 2028 else
1958 { 2029 {
1959 // We don't have a target here, so we're going to raytrace all the objects in the scene. 2030 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1960
1961 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 2031 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1962 2032
1963 // Un-comment the following line to print the raytrace results to the console. 2033 // Un-comment the following line to print the raytrace results to the console.
@@ -1966,13 +2036,12 @@ namespace OpenSim.Region.Framework.Scenes
1966 if (ei.HitTF) 2036 if (ei.HitTF)
1967 { 2037 {
1968 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 2038 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1969 } else 2039 }
2040 else
1970 { 2041 {
1971 // fall back to our stupid functionality 2042 // fall back to our stupid functionality
1972 pos = RayEnd; 2043 pos = RayEnd;
1973 } 2044 }
1974
1975 return pos;
1976 } 2045 }
1977 } 2046 }
1978 else 2047 else
@@ -1983,8 +2052,12 @@ namespace OpenSim.Region.Framework.Scenes
1983 //increase height so its above the ground. 2052 //increase height so its above the ground.
1984 //should be getting the normal of the ground at the rez point and using that? 2053 //should be getting the normal of the ground at the rez point and using that?
1985 pos.Z += scale.Z / 2f; 2054 pos.Z += scale.Z / 2f;
1986 return pos; 2055// return pos;
1987 } 2056 }
2057
2058 // check against posible water intercept
2059 if (wpos.Z > pos.Z) pos = wpos;
2060 return pos;
1988 } 2061 }
1989 2062
1990 2063
@@ -2073,7 +2146,10 @@ namespace OpenSim.Region.Framework.Scenes
2073 public bool AddRestoredSceneObject( 2146 public bool AddRestoredSceneObject(
2074 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 2147 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
2075 { 2148 {
2076 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 2149 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
2150 if (result)
2151 sceneObject.IsDeleted = false;
2152 return result;
2077 } 2153 }
2078 2154
2079 /// <summary> 2155 /// <summary>
@@ -2165,6 +2241,15 @@ namespace OpenSim.Region.Framework.Scenes
2165 /// </summary> 2241 /// </summary>
2166 public void DeleteAllSceneObjects() 2242 public void DeleteAllSceneObjects()
2167 { 2243 {
2244 DeleteAllSceneObjects(false);
2245 }
2246
2247 /// <summary>
2248 /// Delete every object from the scene. This does not include attachments worn by avatars.
2249 /// </summary>
2250 public void DeleteAllSceneObjects(bool exceptNoCopy)
2251 {
2252 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2168 lock (Entities) 2253 lock (Entities)
2169 { 2254 {
2170 EntityBase[] entities = Entities.GetEntities(); 2255 EntityBase[] entities = Entities.GetEntities();
@@ -2173,11 +2258,24 @@ namespace OpenSim.Region.Framework.Scenes
2173 if (e is SceneObjectGroup) 2258 if (e is SceneObjectGroup)
2174 { 2259 {
2175 SceneObjectGroup sog = (SceneObjectGroup)e; 2260 SceneObjectGroup sog = (SceneObjectGroup)e;
2176 if (!sog.IsAttachment) 2261 if (sog != null && !sog.IsAttachment)
2177 DeleteSceneObject((SceneObjectGroup)e, false); 2262 {
2263 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2264 {
2265 DeleteSceneObject((SceneObjectGroup)e, false);
2266 }
2267 else
2268 {
2269 toReturn.Add((SceneObjectGroup)e);
2270 }
2271 }
2178 } 2272 }
2179 } 2273 }
2180 } 2274 }
2275 if (toReturn.Count > 0)
2276 {
2277 returnObjects(toReturn.ToArray(), UUID.Zero);
2278 }
2181 } 2279 }
2182 2280
2183 /// <summary> 2281 /// <summary>
@@ -2212,6 +2310,8 @@ namespace OpenSim.Region.Framework.Scenes
2212 } 2310 }
2213 2311
2214 group.DeleteGroupFromScene(silent); 2312 group.DeleteGroupFromScene(silent);
2313 if (!silent)
2314 SendKillObject(new List<uint>() { group.LocalId });
2215 2315
2216// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2316// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2217 } 2317 }
@@ -2501,6 +2601,8 @@ namespace OpenSim.Region.Framework.Scenes
2501 2601
2502 if (newPosition != Vector3.Zero) 2602 if (newPosition != Vector3.Zero)
2503 newObject.RootPart.GroupPosition = newPosition; 2603 newObject.RootPart.GroupPosition = newPosition;
2604 if (newObject.RootPart.KeyframeMotion != null)
2605 newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
2504 2606
2505 if (!AddSceneObject(newObject)) 2607 if (!AddSceneObject(newObject))
2506 { 2608 {
@@ -2531,10 +2633,17 @@ namespace OpenSim.Region.Framework.Scenes
2531 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2633 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2532 public bool AddSceneObject(SceneObjectGroup sceneObject) 2634 public bool AddSceneObject(SceneObjectGroup sceneObject)
2533 { 2635 {
2636 if (sceneObject.OwnerID == UUID.Zero)
2637 {
2638 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2639 return false;
2640 }
2641
2534 // If the user is banned, we won't let any of their objects 2642 // If the user is banned, we won't let any of their objects
2535 // enter. Period. 2643 // enter. Period.
2536 // 2644 //
2537 if (RegionInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2645 int flags = GetUserFlags(sceneObject.OwnerID);
2646 if (RegionInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2538 { 2647 {
2539 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2648 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2540 2649
@@ -2576,16 +2685,27 @@ namespace OpenSim.Region.Framework.Scenes
2576 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2685 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2577 2686
2578 if (AttachmentsModule != null) 2687 if (AttachmentsModule != null)
2579 AttachmentsModule.AttachObject(sp, grp, 0, false); 2688 AttachmentsModule.AttachObject(sp, grp, 0, false, false);
2580 } 2689 }
2581 else 2690 else
2582 { 2691 {
2692 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2583 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2693 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2584 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2694 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2585 } 2695 }
2696 if (sceneObject.OwnerID == UUID.Zero)
2697 {
2698 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2699 return false;
2700 }
2586 } 2701 }
2587 else 2702 else
2588 { 2703 {
2704 if (sceneObject.OwnerID == UUID.Zero)
2705 {
2706 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2707 return false;
2708 }
2589 AddRestoredSceneObject(sceneObject, true, false); 2709 AddRestoredSceneObject(sceneObject, true, false);
2590 2710
2591 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2711 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2614,6 +2734,24 @@ namespace OpenSim.Region.Framework.Scenes
2614 return 2; // StateSource.PrimCrossing 2734 return 2; // StateSource.PrimCrossing
2615 } 2735 }
2616 2736
2737 public int GetUserFlags(UUID user)
2738 {
2739 //Unfortunately the SP approach means that the value is cached until region is restarted
2740 /*
2741 ScenePresence sp;
2742 if (TryGetScenePresence(user, out sp))
2743 {
2744 return sp.UserFlags;
2745 }
2746 else
2747 {
2748 */
2749 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2750 if (uac == null)
2751 return 0;
2752 return uac.UserFlags;
2753 //}
2754 }
2617 #endregion 2755 #endregion
2618 2756
2619 #region Add/Remove Avatar Methods 2757 #region Add/Remove Avatar Methods
@@ -2627,7 +2765,7 @@ namespace OpenSim.Region.Framework.Scenes
2627 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 2765 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2628 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2766 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2629 2767
2630// CheckHeartbeat(); 2768 CheckHeartbeat();
2631 2769
2632 ScenePresence sp = GetScenePresence(client.AgentId); 2770 ScenePresence sp = GetScenePresence(client.AgentId);
2633 2771
@@ -2681,7 +2819,13 @@ namespace OpenSim.Region.Framework.Scenes
2681 2819
2682 EventManager.TriggerOnNewClient(client); 2820 EventManager.TriggerOnNewClient(client);
2683 if (vialogin) 2821 if (vialogin)
2822 {
2684 EventManager.TriggerOnClientLogin(client); 2823 EventManager.TriggerOnClientLogin(client);
2824 // Send initial parcel data
2825 Vector3 pos = sp.AbsolutePosition;
2826 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2827 land.SendLandUpdateToClient(client);
2828 }
2685 2829
2686 return sp; 2830 return sp;
2687 } 2831 }
@@ -2770,19 +2914,12 @@ namespace OpenSim.Region.Framework.Scenes
2770 // and the scene presence and the client, if they exist 2914 // and the scene presence and the client, if they exist
2771 try 2915 try
2772 { 2916 {
2773 // We need to wait for the client to make UDP contact first. 2917 ScenePresence sp = GetScenePresence(agentID);
2774 // It's the UDP contact that creates the scene presence 2918 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2775 ScenePresence sp = WaitGetScenePresence(agentID); 2919
2776 if (sp != null) 2920 if (sp != null)
2777 {
2778 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2779
2780 sp.ControllingClient.Close(); 2921 sp.ControllingClient.Close();
2781 } 2922
2782 else
2783 {
2784 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2785 }
2786 // BANG! SLASH! 2923 // BANG! SLASH!
2787 m_authenticateHandler.RemoveCircuit(agentID); 2924 m_authenticateHandler.RemoveCircuit(agentID);
2788 2925
@@ -2827,6 +2964,8 @@ namespace OpenSim.Region.Framework.Scenes
2827 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; 2964 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition;
2828 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; 2965 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
2829 2966
2967 client.onClientChangeObject += m_sceneGraph.ClientChangeObject;
2968
2830 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; 2969 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation;
2831 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; 2970 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation;
2832 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; 2971 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
@@ -2883,6 +3022,7 @@ namespace OpenSim.Region.Framework.Scenes
2883 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 3022 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2884 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 3023 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2885 client.OnCopyInventoryItem += CopyInventoryItem; 3024 client.OnCopyInventoryItem += CopyInventoryItem;
3025 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2886 client.OnMoveInventoryItem += MoveInventoryItem; 3026 client.OnMoveInventoryItem += MoveInventoryItem;
2887 client.OnRemoveInventoryItem += RemoveInventoryItem; 3027 client.OnRemoveInventoryItem += RemoveInventoryItem;
2888 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 3028 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2954,6 +3094,8 @@ namespace OpenSim.Region.Framework.Scenes
2954 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; 3094 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition;
2955 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; 3095 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition;
2956 3096
3097 client.onClientChangeObject -= m_sceneGraph.ClientChangeObject;
3098
2957 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3099 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation;
2958 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3100 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation;
2959 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; 3101 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation;
@@ -3056,7 +3198,7 @@ namespace OpenSim.Region.Framework.Scenes
3056 /// </summary> 3198 /// </summary>
3057 /// <param name="agentId">The avatar's Unique ID</param> 3199 /// <param name="agentId">The avatar's Unique ID</param>
3058 /// <param name="client">The IClientAPI for the client</param> 3200 /// <param name="client">The IClientAPI for the client</param>
3059 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3201 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
3060 { 3202 {
3061 if (EntityTransferModule != null) 3203 if (EntityTransferModule != null)
3062 { 3204 {
@@ -3067,6 +3209,7 @@ namespace OpenSim.Region.Framework.Scenes
3067 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3209 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
3068 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3210 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
3069 } 3211 }
3212 return false;
3070 } 3213 }
3071 3214
3072 /// <summary> 3215 /// <summary>
@@ -3176,6 +3319,16 @@ namespace OpenSim.Region.Framework.Scenes
3176 /// <param name="flags"></param> 3319 /// <param name="flags"></param>
3177 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3320 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3178 { 3321 {
3322 //Add half the avatar's height so that the user doesn't fall through prims
3323 ScenePresence presence;
3324 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3325 {
3326 if (presence.Appearance != null)
3327 {
3328 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3329 }
3330 }
3331
3179 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3332 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3180 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3333 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3181 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3334 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3304,6 +3457,7 @@ namespace OpenSim.Region.Framework.Scenes
3304 avatar.Close(); 3457 avatar.Close();
3305 3458
3306 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3459 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3460 m_log.Debug("[Scene] The avatar has left the building");
3307 } 3461 }
3308 catch (Exception e) 3462 catch (Exception e)
3309 { 3463 {
@@ -3497,13 +3651,16 @@ namespace OpenSim.Region.Framework.Scenes
3497 sp = null; 3651 sp = null;
3498 } 3652 }
3499 3653
3500 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3501 3654
3502 //On login test land permisions 3655 //On login test land permisions
3503 if (vialogin) 3656 if (vialogin)
3504 { 3657 {
3505 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3658 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3659 if (cache != null)
3660 cache.Remove(agent.firstname + " " + agent.lastname);
3661 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3506 { 3662 {
3663 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3507 return false; 3664 return false;
3508 } 3665 }
3509 } 3666 }
@@ -3526,9 +3683,15 @@ namespace OpenSim.Region.Framework.Scenes
3526 3683
3527 try 3684 try
3528 { 3685 {
3529 if (!AuthorizeUser(agent, out reason)) 3686 // Always check estate if this is a login. Always
3530 return false; 3687 // check if banned regions are to be blacked out.
3531 } catch (Exception e) 3688 if (vialogin || (!m_seeIntoBannedRegion))
3689 {
3690 if (!AuthorizeUser(agent, out reason))
3691 return false;
3692 }
3693 }
3694 catch (Exception e)
3532 { 3695 {
3533 m_log.ErrorFormat( 3696 m_log.ErrorFormat(
3534 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 3697 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
@@ -3659,6 +3822,8 @@ namespace OpenSim.Region.Framework.Scenes
3659 } 3822 }
3660 3823
3661 // Honor parcel landing type and position. 3824 // Honor parcel landing type and position.
3825 /*
3826 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3662 if (land != null) 3827 if (land != null)
3663 { 3828 {
3664 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3829 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3666,25 +3831,34 @@ namespace OpenSim.Region.Framework.Scenes
3666 agent.startpos = land.LandData.UserLocation; 3831 agent.startpos = land.LandData.UserLocation;
3667 } 3832 }
3668 } 3833 }
3834 */// This is now handled properly in ScenePresence.MakeRootAgent
3669 } 3835 }
3670 3836
3671 return true; 3837 return true;
3672 } 3838 }
3673 3839
3674 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3840 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3675 { 3841 {
3676 bool banned = land.IsBannedFromLand(agent.AgentID); 3842 reason = String.Empty;
3677 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3843 if (Permissions.IsGod(agentID))
3844 return true;
3845
3846 ILandObject land = LandChannel.GetLandObject(posX, posY);
3847 if (land == null)
3848 return false;
3849
3850 bool banned = land.IsBannedFromLand(agentID);
3851 bool restricted = land.IsRestrictedFromLand(agentID);
3678 3852
3679 if (banned || restricted) 3853 if (banned || restricted)
3680 { 3854 {
3681 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3855 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3682 if (nearestParcel != null) 3856 if (nearestParcel != null)
3683 { 3857 {
3684 //Move agent to nearest allowed 3858 //Move agent to nearest allowed
3685 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3859 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3686 agent.startpos.X = newPosition.X; 3860 posX = newPosition.X;
3687 agent.startpos.Y = newPosition.Y; 3861 posY = newPosition.Y;
3688 } 3862 }
3689 else 3863 else
3690 { 3864 {
@@ -3746,7 +3920,7 @@ namespace OpenSim.Region.Framework.Scenes
3746 3920
3747 if (!m_strictAccessControl) return true; 3921 if (!m_strictAccessControl) return true;
3748 if (Permissions.IsGod(agent.AgentID)) return true; 3922 if (Permissions.IsGod(agent.AgentID)) return true;
3749 3923
3750 if (AuthorizationService != null) 3924 if (AuthorizationService != null)
3751 { 3925 {
3752 if (!AuthorizationService.IsAuthorizedForRegion( 3926 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3761,7 +3935,7 @@ namespace OpenSim.Region.Framework.Scenes
3761 3935
3762 if (RegionInfo.EstateSettings != null) 3936 if (RegionInfo.EstateSettings != null)
3763 { 3937 {
3764 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID)) 3938 if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, 0))
3765 { 3939 {
3766 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3940 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3767 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3941 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3951,6 +4125,15 @@ namespace OpenSim.Region.Framework.Scenes
3951 4125
3952 // XPTO: if this agent is not allowed here as root, always return false 4126 // XPTO: if this agent is not allowed here as root, always return false
3953 4127
4128 // We have to wait until the viewer contacts this region after receiving EAC.
4129 // That calls AddNewClient, which finally creates the ScenePresence
4130 int flags = GetUserFlags(cAgentData.AgentID);
4131 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
4132 {
4133 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
4134 return false;
4135 }
4136
3954 // TODO: This check should probably be in QueryAccess(). 4137 // TODO: This check should probably be in QueryAccess().
3955 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4138 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3956 if (nearestParcel == null) 4139 if (nearestParcel == null)
@@ -4044,12 +4227,22 @@ namespace OpenSim.Region.Framework.Scenes
4044 return false; 4227 return false;
4045 } 4228 }
4046 4229
4230 public bool IncomingCloseAgent(UUID agentID)
4231 {
4232 return IncomingCloseAgent(agentID, false);
4233 }
4234
4235 public bool IncomingCloseChildAgent(UUID agentID)
4236 {
4237 return IncomingCloseAgent(agentID, true);
4238 }
4239
4047 /// <summary> 4240 /// <summary>
4048 /// Tell a single agent to disconnect from the region. 4241 /// Tell a single agent to disconnect from the region.
4049 /// </summary> 4242 /// </summary>
4050 /// <param name="regionHandle"></param>
4051 /// <param name="agentID"></param> 4243 /// <param name="agentID"></param>
4052 public bool IncomingCloseAgent(UUID agentID) 4244 /// <param name="childOnly"></param>
4245 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
4053 { 4246 {
4054 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4247 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
4055 4248
@@ -4642,35 +4835,81 @@ namespace OpenSim.Region.Framework.Scenes
4642 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID); 4835 SimulationDataService.RemoveObject(uuid, RegionInfo.RegionID);
4643 } 4836 }
4644 4837
4645 public int GetHealth() 4838 public int GetHealth(out int flags, out string message)
4646 { 4839 {
4647 // Returns: 4840 // Returns:
4648 // 1 = sim is up and accepting http requests. The heartbeat has 4841 // 1 = sim is up and accepting http requests. The heartbeat has
4649 // stopped and the sim is probably locked up, but a remote 4842 // stopped and the sim is probably locked up, but a remote
4650 // admin restart may succeed 4843 // admin restart may succeed
4651 // 4844 //
4652 // 2 = Sim is up and the heartbeat is running. The sim is likely 4845 // 2 = Sim is up and the heartbeat is running. The sim is likely
4653 // usable for people within and logins _may_ work 4846 // usable for people within
4654 // 4847 //
4655 // 3 = We have seen a new user enter within the past 4 minutes 4848 // 3 = Sim is up and one packet thread is running. Sim is
4849 // unstable and will not accept new logins
4850 //
4851 // 4 = Sim is up and both packet threads are running. Sim is
4852 // likely usable
4853 //
4854 // 5 = We have seen a new user enter within the past 4 minutes
4656 // which can be seen as positive confirmation of sim health 4855 // which can be seen as positive confirmation of sim health
4657 // 4856 //
4857
4858 flags = 0;
4859 message = String.Empty;
4860
4861 CheckHeartbeat();
4862
4863 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4864 {
4865 // We're still starting
4866 // 0 means "in startup", it can't happen another way, since
4867 // to get here, we must be able to accept http connections
4868 return 0;
4869 }
4870
4658 int health=1; // Start at 1, means we're up 4871 int health=1; // Start at 1, means we're up
4659 4872
4660 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) 4873 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000)
4661 health += 1; 4874 {
4875 health+=1;
4876 flags |= 1;
4877 }
4878
4879 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4880 {
4881 health+=1;
4882 flags |= 2;
4883 }
4884
4885 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4886 {
4887 health+=1;
4888 flags |= 4;
4889 }
4662 else 4890 else
4891 {
4892int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4893System.Diagnostics.Process proc = new System.Diagnostics.Process();
4894proc.EnableRaisingEvents=false;
4895proc.StartInfo.FileName = "/bin/kill";
4896proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4897proc.Start();
4898proc.WaitForExit();
4899Thread.Sleep(1000);
4900Environment.Exit(1);
4901 }
4902
4903 if (flags != 7)
4663 return health; 4904 return health;
4664 4905
4665 // A login in the last 4 mins? We can't be doing too badly 4906 // A login in the last 4 mins? We can't be doing too badly
4666 // 4907 //
4667 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4908 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4668 health++; 4909 health++;
4669 else 4910 else
4670 return health; 4911 return health;
4671 4912
4672// CheckHeartbeat();
4673
4674 return health; 4913 return health;
4675 } 4914 }
4676 4915
@@ -4758,7 +4997,7 @@ namespace OpenSim.Region.Framework.Scenes
4758 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); 4997 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
4759 if (wasUsingPhysics) 4998 if (wasUsingPhysics)
4760 { 4999 {
4761 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 5000 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
4762 } 5001 }
4763 } 5002 }
4764 5003
@@ -4857,14 +5096,14 @@ namespace OpenSim.Region.Framework.Scenes
4857 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; 5096 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z;
4858 } 5097 }
4859 5098
4860// private void CheckHeartbeat() 5099 private void CheckHeartbeat()
4861// { 5100 {
4862// if (m_firstHeartbeat) 5101 if (m_firstHeartbeat)
4863// return; 5102 return;
4864// 5103
4865// if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) 5104 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) > 5000)
4866// StartTimer(); 5105 Start();
4867// } 5106 }
4868 5107
4869 public override ISceneObject DeserializeObject(string representation) 5108 public override ISceneObject DeserializeObject(string representation)
4870 { 5109 {
@@ -4876,9 +5115,14 @@ namespace OpenSim.Region.Framework.Scenes
4876 get { return m_allowScriptCrossings; } 5115 get { return m_allowScriptCrossings; }
4877 } 5116 }
4878 5117
4879 public Vector3? GetNearestAllowedPosition(ScenePresence avatar) 5118 public Vector3 GetNearestAllowedPosition(ScenePresence avatar)
5119 {
5120 return GetNearestAllowedPosition(avatar, null);
5121 }
5122
5123 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
4880 { 5124 {
4881 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 5125 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel);
4882 5126
4883 if (nearestParcel != null) 5127 if (nearestParcel != null)
4884 { 5128 {
@@ -4887,10 +5131,7 @@ namespace OpenSim.Region.Framework.Scenes
4887 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5131 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4888 if (nearestPoint != null) 5132 if (nearestPoint != null)
4889 { 5133 {
4890// m_log.DebugFormat( 5134 Debug.WriteLine("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString());
4891// "[SCENE]: Found a sane previous position based on velocity for {0}, sending them to {1} in {2}",
4892// avatar.Name, nearestPoint, nearestParcel.LandData.Name);
4893
4894 return nearestPoint.Value; 5135 return nearestPoint.Value;
4895 } 5136 }
4896 5137
@@ -4900,17 +5141,20 @@ namespace OpenSim.Region.Framework.Scenes
4900 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5141 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4901 if (nearestPoint != null) 5142 if (nearestPoint != null)
4902 { 5143 {
4903// m_log.DebugFormat( 5144 Debug.WriteLine("They had a zero velocity, sending them to: " + nearestPoint.ToString());
4904// "[SCENE]: {0} had a zero velocity, sending them to {1}", avatar.Name, nearestPoint);
4905
4906 return nearestPoint.Value; 5145 return nearestPoint.Value;
4907 } 5146 }
4908 5147
4909 //Ultimate backup if we have no idea where they are 5148 ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y);
4910// m_log.DebugFormat( 5149 if (dest != excludeParcel)
4911// "[SCENE]: No idea where {0} is, sending them to {1}", avatar.Name, avatar.lastKnownAllowedPosition); 5150 {
5151 // Ultimate backup if we have no idea where they are and
5152 // the last allowed position was in another parcel
5153 Debug.WriteLine("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString());
5154 return avatar.lastKnownAllowedPosition;
5155 }
4912 5156
4913 return avatar.lastKnownAllowedPosition; 5157 // else fall through to region edge
4914 } 5158 }
4915 5159
4916 //Go to the edge, this happens in teleporting to a region with no available parcels 5160 //Go to the edge, this happens in teleporting to a region with no available parcels
@@ -4944,13 +5188,18 @@ namespace OpenSim.Region.Framework.Scenes
4944 5188
4945 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) 5189 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
4946 { 5190 {
5191 return GetNearestAllowedParcel(avatarId, x, y, null);
5192 }
5193
5194 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
5195 {
4947 List<ILandObject> all = AllParcels(); 5196 List<ILandObject> all = AllParcels();
4948 float minParcelDistance = float.MaxValue; 5197 float minParcelDistance = float.MaxValue;
4949 ILandObject nearestParcel = null; 5198 ILandObject nearestParcel = null;
4950 5199
4951 foreach (var parcel in all) 5200 foreach (var parcel in all)
4952 { 5201 {
4953 if (!parcel.IsEitherBannedOrRestricted(avatarId)) 5202 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel)
4954 { 5203 {
4955 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 5204 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
4956 if (parcelDistance < minParcelDistance) 5205 if (parcelDistance < minParcelDistance)
@@ -5192,7 +5441,55 @@ namespace OpenSim.Region.Framework.Scenes
5192 mapModule.GenerateMaptile(); 5441 mapModule.GenerateMaptile();
5193 } 5442 }
5194 5443
5195 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5444// public void CleanDroppedAttachments()
5445// {
5446// List<SceneObjectGroup> objectsToDelete =
5447// new List<SceneObjectGroup>();
5448//
5449// lock (m_cleaningAttachments)
5450// {
5451// ForEachSOG(delegate (SceneObjectGroup grp)
5452// {
5453// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5454// {
5455// UUID agentID = grp.OwnerID;
5456// if (agentID == UUID.Zero)
5457// {
5458// objectsToDelete.Add(grp);
5459// return;
5460// }
5461//
5462// ScenePresence sp = GetScenePresence(agentID);
5463// if (sp == null)
5464// {
5465// objectsToDelete.Add(grp);
5466// return;
5467// }
5468// }
5469// });
5470// }
5471//
5472// foreach (SceneObjectGroup grp in objectsToDelete)
5473// {
5474// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5475// DeleteSceneObject(grp, true);
5476// }
5477// }
5478
5479 public void ThreadAlive(int threadCode)
5480 {
5481 switch(threadCode)
5482 {
5483 case 1: // Incoming
5484 m_lastIncoming = Util.EnvironmentTickCount();
5485 break;
5486 case 2: // Incoming
5487 m_lastOutgoing = Util.EnvironmentTickCount();
5488 break;
5489 }
5490 }
5491
5492 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5196 { 5493 {
5197 RegenerateMaptile(); 5494 RegenerateMaptile();
5198 5495
@@ -5220,6 +5517,8 @@ namespace OpenSim.Region.Framework.Scenes
5220 /// <returns></returns> 5517 /// <returns></returns>
5221 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5518 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5222 { 5519 {
5520 reason = "You are banned from the region";
5521
5223 if (EntityTransferModule.IsInTransit(agentID)) 5522 if (EntityTransferModule.IsInTransit(agentID))
5224 { 5523 {
5225 reason = "Agent is still in transit from this region"; 5524 reason = "Agent is still in transit from this region";
@@ -5231,6 +5530,12 @@ namespace OpenSim.Region.Framework.Scenes
5231 return false; 5530 return false;
5232 } 5531 }
5233 5532
5533 if (Permissions.IsGod(agentID))
5534 {
5535 reason = String.Empty;
5536 return true;
5537 }
5538
5234 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. 5539 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check.
5235 // However, the long term fix is to make sure root agent count is always accurate. 5540 // However, the long term fix is to make sure root agent count is always accurate.
5236 m_sceneGraph.RecalculateStats(); 5541 m_sceneGraph.RecalculateStats();
@@ -5251,6 +5556,41 @@ namespace OpenSim.Region.Framework.Scenes
5251 } 5556 }
5252 } 5557 }
5253 5558
5559 ScenePresence presence = GetScenePresence(agentID);
5560 IClientAPI client = null;
5561 AgentCircuitData aCircuit = null;
5562
5563 if (presence != null)
5564 {
5565 client = presence.ControllingClient;
5566 if (client != null)
5567 aCircuit = client.RequestClientInfo();
5568 }
5569
5570 // We may be called before there is a presence or a client.
5571 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5572 if (client == null)
5573 {
5574 aCircuit = new AgentCircuitData();
5575 aCircuit.AgentID = agentID;
5576 aCircuit.firstname = String.Empty;
5577 aCircuit.lastname = String.Empty;
5578 }
5579
5580 try
5581 {
5582 if (!AuthorizeUser(aCircuit, out reason))
5583 {
5584 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5585 return false;
5586 }
5587 }
5588 catch (Exception e)
5589 {
5590 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5591 return false;
5592 }
5593
5254 if (position == Vector3.Zero) // Teleport 5594 if (position == Vector3.Zero) // Teleport
5255 { 5595 {
5256 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5596 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
@@ -5279,13 +5619,46 @@ namespace OpenSim.Region.Framework.Scenes
5279 } 5619 }
5280 } 5620 }
5281 } 5621 }
5622
5623 float posX = 128.0f;
5624 float posY = 128.0f;
5625
5626 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5627 {
5628 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5629 return false;
5630 }
5631 }
5632 else // Walking
5633 {
5634 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5635 if (land == null)
5636 return false;
5637
5638 bool banned = land.IsBannedFromLand(agentID);
5639 bool restricted = land.IsRestrictedFromLand(agentID);
5640
5641 if (banned || restricted)
5642 return false;
5282 } 5643 }
5283 5644
5284 reason = String.Empty; 5645 reason = String.Empty;
5285 return true; 5646 return true;
5286 } 5647 }
5287 5648
5288 /// <summary> 5649 public void StartTimerWatchdog()
5650 {
5651 m_timerWatchdog.Interval = 1000;
5652 m_timerWatchdog.Elapsed += TimerWatchdog;
5653 m_timerWatchdog.AutoReset = true;
5654 m_timerWatchdog.Start();
5655 }
5656
5657 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5658 {
5659 CheckHeartbeat();
5660 }
5661
5289 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5662 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5290 /// autopilot that moves an avatar to a sit target!. 5663 /// autopilot that moves an avatar to a sit target!.
5291 /// </summary> 5664 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index f50fbfc..e8134cd 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -138,6 +138,8 @@ namespace OpenSim.Region.Framework.Scenes
138 get { return m_permissions; } 138 get { return m_permissions; }
139 } 139 }
140 140
141 protected string m_datastore;
142
141 /* Used by the loadbalancer plugin on GForge */ 143 /* Used by the loadbalancer plugin on GForge */
142 protected RegionStatus m_regStatus; 144 protected RegionStatus m_regStatus;
143 public RegionStatus RegionStatus 145 public RegionStatus RegionStatus
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index eff635b..c1414ee 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -182,10 +182,13 @@ namespace OpenSim.Region.Framework.Scenes
182 } 182 }
183 } 183 }
184 184
185 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
186
185 /// <summary> 187 /// <summary>
186 /// Closes a child agent on a given region 188 /// This Closes child agents on neighboring regions
189 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
187 /// </summary> 190 /// </summary>
188 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 191 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
189 { 192 {
190 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 193 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
191 194
@@ -194,30 +197,29 @@ namespace OpenSim.Region.Framework.Scenes
194 Utils.LongToUInts(regionHandle, out x, out y); 197 Utils.LongToUInts(regionHandle, out x, out y);
195 198
196 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 199 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
200 m_scene.SimulationService.CloseChildAgent(destination, agentID);
201 }
197 202
198 m_log.DebugFormat( 203 private void SendCloseChildAgentCompleted(IAsyncResult iar)
199 "[SCENE COMMUNICATION SERVICE]: Sending close agent ID {0} to {1}", agentID, destination.RegionName); 204 {
200 205 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
201 m_scene.SimulationService.CloseAgent(destination, agentID); 206 icon.EndInvoke(iar);
202 } 207 }
203 208
204 /// <summary>
205 /// Closes a child agents in a collection of regions. Does so asynchronously
206 /// so that the caller doesn't wait.
207 /// </summary>
208 /// <param name="agentID"></param>
209 /// <param name="regionslst"></param>
210 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 209 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
211 { 210 {
212 foreach (ulong handle in regionslst) 211 foreach (ulong handle in regionslst)
213 { 212 {
214 SendCloseChildAgent(agentID, handle); 213 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
214 d.BeginInvoke(agentID, handle,
215 SendCloseChildAgentCompleted,
216 d);
215 } 217 }
216 } 218 }
217 219
218 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 220 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
219 { 221 {
220 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 222 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
221 } 223 }
222 } 224 }
223} \ No newline at end of file 225}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index a59758f..4c12496 100644
--- 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
@@ -127,13 +137,18 @@ namespace OpenSim.Region.Framework.Scenes
127 137
128 protected internal void Close() 138 protected internal void Close()
129 { 139 {
130 lock (m_presenceLock) 140 m_scenePresencesLock.EnterWriteLock();
141 try
131 { 142 {
132 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 143 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
133 List<ScenePresence> newlist = new List<ScenePresence>(); 144 List<ScenePresence> newlist = new List<ScenePresence>();
134 m_scenePresenceMap = newmap; 145 m_scenePresenceMap = newmap;
135 m_scenePresenceArray = newlist; 146 m_scenePresenceArray = newlist;
136 } 147 }
148 finally
149 {
150 m_scenePresencesLock.ExitWriteLock();
151 }
137 152
138 lock (SceneObjectGroupsByFullID) 153 lock (SceneObjectGroupsByFullID)
139 SceneObjectGroupsByFullID.Clear(); 154 SceneObjectGroupsByFullID.Clear();
@@ -254,6 +269,33 @@ namespace OpenSim.Region.Framework.Scenes
254 protected internal bool AddRestoredSceneObject( 269 protected internal bool AddRestoredSceneObject(
255 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 270 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
256 { 271 {
272 if (!m_parentScene.CombineRegions)
273 {
274 // KF: Check for out-of-region, move inside and make static.
275 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
276 sceneObject.RootPart.GroupPosition.Y,
277 sceneObject.RootPart.GroupPosition.Z);
278 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 ||
279 npos.X > Constants.RegionSize ||
280 npos.Y > Constants.RegionSize))
281 {
282 if (npos.X < 0.0) npos.X = 1.0f;
283 if (npos.Y < 0.0) npos.Y = 1.0f;
284 if (npos.Z < 0.0) npos.Z = 0.0f;
285 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
286 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
287
288 foreach (SceneObjectPart part in sceneObject.Parts)
289 {
290 part.GroupPosition = npos;
291 }
292 sceneObject.RootPart.Velocity = Vector3.Zero;
293 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
294 sceneObject.RootPart.Acceleration = Vector3.Zero;
295 sceneObject.RootPart.Velocity = Vector3.Zero;
296 }
297 }
298
257 if (attachToBackup && (!alreadyPersisted)) 299 if (attachToBackup && (!alreadyPersisted))
258 { 300 {
259 sceneObject.ForceInventoryPersistence(); 301 sceneObject.ForceInventoryPersistence();
@@ -317,9 +359,8 @@ namespace OpenSim.Region.Framework.Scenes
317 if (pa != null && pa.IsPhysical && vel != Vector3.Zero) 359 if (pa != null && pa.IsPhysical && vel != Vector3.Zero)
318 { 360 {
319 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); 361 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false);
320 sceneObject.Velocity = vel;
321 } 362 }
322 363
323 return true; 364 return true;
324 } 365 }
325 366
@@ -344,6 +385,11 @@ namespace OpenSim.Region.Framework.Scenes
344 /// </returns> 385 /// </returns>
345 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 386 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
346 { 387 {
388 if (sceneObject == null)
389 {
390 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
391 return false;
392 }
347 if (sceneObject.UUID == UUID.Zero) 393 if (sceneObject.UUID == UUID.Zero)
348 { 394 {
349 m_log.ErrorFormat( 395 m_log.ErrorFormat(
@@ -478,6 +524,30 @@ namespace OpenSim.Region.Framework.Scenes
478 m_updateList[obj.UUID] = obj; 524 m_updateList[obj.UUID] = obj;
479 } 525 }
480 526
527 public void FireAttachToBackup(SceneObjectGroup obj)
528 {
529 if (OnAttachToBackup != null)
530 {
531 OnAttachToBackup(obj);
532 }
533 }
534
535 public void FireDetachFromBackup(SceneObjectGroup obj)
536 {
537 if (OnDetachFromBackup != null)
538 {
539 OnDetachFromBackup(obj);
540 }
541 }
542
543 public void FireChangeBackup(SceneObjectGroup obj)
544 {
545 if (OnChangeBackup != null)
546 {
547 OnChangeBackup(obj);
548 }
549 }
550
481 /// <summary> 551 /// <summary>
482 /// Process all pending updates 552 /// Process all pending updates
483 /// </summary> 553 /// </summary>
@@ -595,7 +665,8 @@ namespace OpenSim.Region.Framework.Scenes
595 665
596 Entities[presence.UUID] = presence; 666 Entities[presence.UUID] = presence;
597 667
598 lock (m_presenceLock) 668 m_scenePresencesLock.EnterWriteLock();
669 try
599 { 670 {
600 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 671 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
601 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 672 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -619,6 +690,10 @@ namespace OpenSim.Region.Framework.Scenes
619 m_scenePresenceMap = newmap; 690 m_scenePresenceMap = newmap;
620 m_scenePresenceArray = newlist; 691 m_scenePresenceArray = newlist;
621 } 692 }
693 finally
694 {
695 m_scenePresencesLock.ExitWriteLock();
696 }
622 } 697 }
623 698
624 /// <summary> 699 /// <summary>
@@ -633,7 +708,8 @@ namespace OpenSim.Region.Framework.Scenes
633 agentID); 708 agentID);
634 } 709 }
635 710
636 lock (m_presenceLock) 711 m_scenePresencesLock.EnterWriteLock();
712 try
637 { 713 {
638 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 714 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
639 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 715 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -655,6 +731,10 @@ namespace OpenSim.Region.Framework.Scenes
655 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 731 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
656 } 732 }
657 } 733 }
734 finally
735 {
736 m_scenePresencesLock.ExitWriteLock();
737 }
658 } 738 }
659 739
660 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 740 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1176,6 +1256,52 @@ namespace OpenSim.Region.Framework.Scenes
1176 1256
1177 #region Client Event handlers 1257 #region Client Event handlers
1178 1258
1259 protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
1260 {
1261 SceneObjectPart part = GetSceneObjectPart(localID);
1262 ObjectChangeData data = (ObjectChangeData)odata;
1263
1264 if (part != null)
1265 {
1266 SceneObjectGroup grp = part.ParentGroup;
1267 if (grp != null)
1268 {
1269 if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId))
1270 {
1271 // These two are exceptions SL makes in the interpretation
1272 // of the change flags. Must check them here because otherwise
1273 // the group flag (see below) would be lost
1274 if (data.change == ObjectChangeType.groupS)
1275 data.change = ObjectChangeType.primS;
1276 if (data.change == ObjectChangeType.groupPS)
1277 data.change = ObjectChangeType.primPS;
1278 part.StoreUndoState(data.change); // lets test only saving what we changed
1279 grp.doChangeObject(part, (ObjectChangeData)data);
1280 }
1281 else
1282 {
1283 // Is this any kind of group operation?
1284 if ((data.change & ObjectChangeType.Group) != 0)
1285 {
1286 // Is a move and/or rotation requested?
1287 if ((data.change & (ObjectChangeType.Position | ObjectChangeType.Rotation)) != 0)
1288 {
1289 // Are we allowed to move it?
1290 if (m_parentScene.Permissions.CanMoveObject(grp.UUID, remoteClient.AgentId))
1291 {
1292 // Strip all but move and rotation from request
1293 data.change &= (ObjectChangeType.Group | ObjectChangeType.Position | ObjectChangeType.Rotation);
1294
1295 part.StoreUndoState(data.change);
1296 grp.doChangeObject(part, (ObjectChangeData)data);
1297 }
1298 }
1299 }
1300 }
1301 }
1302 }
1303 }
1304
1179 /// <summary> 1305 /// <summary>
1180 /// Update the scale of an individual prim. 1306 /// Update the scale of an individual prim.
1181 /// </summary> 1307 /// </summary>
@@ -1190,7 +1316,17 @@ namespace OpenSim.Region.Framework.Scenes
1190 { 1316 {
1191 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) 1317 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId))
1192 { 1318 {
1319 bool physbuild = false;
1320 if (part.ParentGroup.RootPart.PhysActor != null)
1321 {
1322 part.ParentGroup.RootPart.PhysActor.Building = true;
1323 physbuild = true;
1324 }
1325
1193 part.Resize(scale); 1326 part.Resize(scale);
1327
1328 if (physbuild)
1329 part.ParentGroup.RootPart.PhysActor.Building = false;
1194 } 1330 }
1195 } 1331 }
1196 } 1332 }
@@ -1202,7 +1338,17 @@ namespace OpenSim.Region.Framework.Scenes
1202 { 1338 {
1203 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1339 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1204 { 1340 {
1341 bool physbuild = false;
1342 if (group.RootPart.PhysActor != null)
1343 {
1344 group.RootPart.PhysActor.Building = true;
1345 physbuild = true;
1346 }
1347
1205 group.GroupResize(scale); 1348 group.GroupResize(scale);
1349
1350 if (physbuild)
1351 group.RootPart.PhysActor.Building = false;
1206 } 1352 }
1207 } 1353 }
1208 } 1354 }
@@ -1330,8 +1476,13 @@ namespace OpenSim.Region.Framework.Scenes
1330 { 1476 {
1331 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1477 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1332 { 1478 {
1333 if (m_parentScene.AttachmentsModule != null) 1479 // Set the new attachment point data in the object
1334 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1480 byte attachmentPoint = group.GetAttachmentPoint();
1481 group.UpdateGroupPosition(pos);
1482 group.IsAttachment = false;
1483 group.AbsolutePosition = group.RootPart.AttachedPos;
1484 group.AttachmentPoint = attachmentPoint;
1485 group.HasGroupChanged = true;
1335 } 1486 }
1336 else 1487 else
1337 { 1488 {
@@ -1379,7 +1530,7 @@ namespace OpenSim.Region.Framework.Scenes
1379 /// <param name="SetPhantom"></param> 1530 /// <param name="SetPhantom"></param>
1380 /// <param name="remoteClient"></param> 1531 /// <param name="remoteClient"></param>
1381 protected internal void UpdatePrimFlags( 1532 protected internal void UpdatePrimFlags(
1382 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, IClientAPI remoteClient) 1533 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient)
1383 { 1534 {
1384 SceneObjectGroup group = GetGroupByPrim(localID); 1535 SceneObjectGroup group = GetGroupByPrim(localID);
1385 if (group != null) 1536 if (group != null)
@@ -1387,7 +1538,28 @@ namespace OpenSim.Region.Framework.Scenes
1387 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1538 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1388 { 1539 {
1389 // VolumeDetect can't be set via UI and will always be off when a change is made there 1540 // VolumeDetect can't be set via UI and will always be off when a change is made there
1390 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false); 1541 // now only change volume dtc if phantom off
1542
1543 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data
1544 {
1545 bool vdtc;
1546 if (SetPhantom) // if phantom keep volumedtc
1547 vdtc = group.RootPart.VolumeDetectActive;
1548 else // else turn it off
1549 vdtc = false;
1550
1551 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, vdtc);
1552 }
1553 else
1554 {
1555 SceneObjectPart part = GetSceneObjectPart(localID);
1556 if (part != null)
1557 {
1558 part.UpdateExtraPhysics(PhysData);
1559 if (part.UpdatePhysRequired)
1560 remoteClient.SendPartPhysicsProprieties(part);
1561 }
1562 }
1391 } 1563 }
1392 } 1564 }
1393 } 1565 }
@@ -1531,6 +1703,7 @@ namespace OpenSim.Region.Framework.Scenes
1531 { 1703 {
1532 part.Material = Convert.ToByte(material); 1704 part.Material = Convert.ToByte(material);
1533 group.HasGroupChanged = true; 1705 group.HasGroupChanged = true;
1706 remoteClient.SendPartPhysicsProprieties(part);
1534 } 1707 }
1535 } 1708 }
1536 } 1709 }
@@ -1595,6 +1768,12 @@ namespace OpenSim.Region.Framework.Scenes
1595 /// <param name="childPrims"></param> 1768 /// <param name="childPrims"></param>
1596 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1769 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1597 { 1770 {
1771 if (root.KeyframeMotion != null)
1772 {
1773 root.KeyframeMotion.Stop();
1774 root.KeyframeMotion = null;
1775 }
1776
1598 SceneObjectGroup parentGroup = root.ParentGroup; 1777 SceneObjectGroup parentGroup = root.ParentGroup;
1599 if (parentGroup == null) return; 1778 if (parentGroup == null) return;
1600 1779
@@ -1603,8 +1782,11 @@ namespace OpenSim.Region.Framework.Scenes
1603 return; 1782 return;
1604 1783
1605 Monitor.Enter(m_updateLock); 1784 Monitor.Enter(m_updateLock);
1785
1606 try 1786 try
1607 { 1787 {
1788 parentGroup.areUpdatesSuspended = true;
1789
1608 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1790 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1609 1791
1610 // We do this in reverse to get the link order of the prims correct 1792 // We do this in reverse to get the link order of the prims correct
@@ -1619,9 +1801,13 @@ namespace OpenSim.Region.Framework.Scenes
1619 // Make sure no child prim is set for sale 1801 // Make sure no child prim is set for sale
1620 // So that, on delink, no prims are unwittingly 1802 // So that, on delink, no prims are unwittingly
1621 // left for sale and sold off 1803 // left for sale and sold off
1622 child.RootPart.ObjectSaleType = 0; 1804
1623 child.RootPart.SalePrice = 10; 1805 if (child != null)
1624 childGroups.Add(child); 1806 {
1807 child.RootPart.ObjectSaleType = 0;
1808 child.RootPart.SalePrice = 10;
1809 childGroups.Add(child);
1810 }
1625 } 1811 }
1626 1812
1627 foreach (SceneObjectGroup child in childGroups) 1813 foreach (SceneObjectGroup child in childGroups)
@@ -1648,6 +1834,16 @@ namespace OpenSim.Region.Framework.Scenes
1648 } 1834 }
1649 finally 1835 finally
1650 { 1836 {
1837 lock (SceneObjectGroupsByLocalPartID)
1838 {
1839 foreach (SceneObjectPart part in parentGroup.Parts)
1840 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1841 }
1842
1843 parentGroup.areUpdatesSuspended = false;
1844 parentGroup.HasGroupChanged = true;
1845 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1846 parentGroup.ScheduleGroupForFullUpdate();
1651 Monitor.Exit(m_updateLock); 1847 Monitor.Exit(m_updateLock);
1652 } 1848 }
1653 } 1849 }
@@ -1670,6 +1866,11 @@ namespace OpenSim.Region.Framework.Scenes
1670 { 1866 {
1671 if (part != null) 1867 if (part != null)
1672 { 1868 {
1869 if (part.KeyframeMotion != null)
1870 {
1871 part.KeyframeMotion.Stop();
1872 part.KeyframeMotion = null;
1873 }
1673 if (part.ParentGroup.PrimCount != 1) // Skip single 1874 if (part.ParentGroup.PrimCount != 1) // Skip single
1674 { 1875 {
1675 if (part.LinkNum < 2) // Root 1876 if (part.LinkNum < 2) // Root
@@ -1684,21 +1885,24 @@ namespace OpenSim.Region.Framework.Scenes
1684 1885
1685 SceneObjectGroup group = part.ParentGroup; 1886 SceneObjectGroup group = part.ParentGroup;
1686 if (!affectedGroups.Contains(group)) 1887 if (!affectedGroups.Contains(group))
1888 {
1889 group.areUpdatesSuspended = true;
1687 affectedGroups.Add(group); 1890 affectedGroups.Add(group);
1891 }
1688 } 1892 }
1689 } 1893 }
1690 } 1894 }
1691 1895
1692 foreach (SceneObjectPart child in childParts) 1896 if (childParts.Count > 0)
1693 { 1897 {
1694 // Unlink all child parts from their groups 1898 foreach (SceneObjectPart child in childParts)
1695 // 1899 {
1696 child.ParentGroup.DelinkFromGroup(child, true); 1900 // Unlink all child parts from their groups
1697 1901 //
1698 // These are not in affected groups and will not be 1902 child.ParentGroup.DelinkFromGroup(child, true);
1699 // handled further. Do the honors here. 1903 child.ParentGroup.HasGroupChanged = true;
1700 child.ParentGroup.HasGroupChanged = true; 1904 child.ParentGroup.ScheduleGroupForFullUpdate();
1701 child.ParentGroup.ScheduleGroupForFullUpdate(); 1905 }
1702 } 1906 }
1703 1907
1704 foreach (SceneObjectPart root in rootParts) 1908 foreach (SceneObjectPart root in rootParts)
@@ -1708,56 +1912,68 @@ namespace OpenSim.Region.Framework.Scenes
1708 // However, editing linked parts and unlinking may be different 1912 // However, editing linked parts and unlinking may be different
1709 // 1913 //
1710 SceneObjectGroup group = root.ParentGroup; 1914 SceneObjectGroup group = root.ParentGroup;
1915 group.areUpdatesSuspended = true;
1711 1916
1712 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1917 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1713 int numChildren = newSet.Count; 1918 int numChildren = newSet.Count;
1714 1919
1920 if (numChildren == 1)
1921 break;
1922
1715 // If there are prims left in a link set, but the root is 1923 // If there are prims left in a link set, but the root is
1716 // slated for unlink, we need to do this 1924 // slated for unlink, we need to do this
1925 // Unlink the remaining set
1717 // 1926 //
1718 if (numChildren != 1) 1927 bool sendEventsToRemainder = true;
1719 { 1928 if (numChildren > 1)
1720 // Unlink the remaining set 1929 sendEventsToRemainder = false;
1721 //
1722 bool sendEventsToRemainder = true;
1723 if (numChildren > 1)
1724 sendEventsToRemainder = false;
1725 1930
1726 foreach (SceneObjectPart p in newSet) 1931 foreach (SceneObjectPart p in newSet)
1932 {
1933 if (p != group.RootPart)
1727 { 1934 {
1728 if (p != group.RootPart) 1935 group.DelinkFromGroup(p, sendEventsToRemainder);
1729 group.DelinkFromGroup(p, sendEventsToRemainder); 1936 if (numChildren > 2)
1937 {
1938 p.ParentGroup.areUpdatesSuspended = true;
1939 }
1940 else
1941 {
1942 p.ParentGroup.HasGroupChanged = true;
1943 p.ParentGroup.ScheduleGroupForFullUpdate();
1944 }
1730 } 1945 }
1946 }
1947
1948 // If there is more than one prim remaining, we
1949 // need to re-link
1950 //
1951 if (numChildren > 2)
1952 {
1953 // Remove old root
1954 //
1955 if (newSet.Contains(root))
1956 newSet.Remove(root);
1731 1957
1732 // If there is more than one prim remaining, we 1958 // Preserve link ordering
1733 // need to re-link
1734 // 1959 //
1735 if (numChildren > 2) 1960 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1736 { 1961 {
1737 // Remove old root 1962 return a.LinkNum.CompareTo(b.LinkNum);
1738 // 1963 });
1739 if (newSet.Contains(root))
1740 newSet.Remove(root);
1741
1742 // Preserve link ordering
1743 //
1744 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1745 {
1746 return a.LinkNum.CompareTo(b.LinkNum);
1747 });
1748 1964
1749 // Determine new root 1965 // Determine new root
1750 // 1966 //
1751 SceneObjectPart newRoot = newSet[0]; 1967 SceneObjectPart newRoot = newSet[0];
1752 newSet.RemoveAt(0); 1968 newSet.RemoveAt(0);
1753 1969
1754 foreach (SceneObjectPart newChild in newSet) 1970 foreach (SceneObjectPart newChild in newSet)
1755 newChild.ClearUpdateSchedule(); 1971 newChild.ClearUpdateSchedule();
1756 1972
1757 LinkObjects(newRoot, newSet); 1973 newRoot.ParentGroup.areUpdatesSuspended = true;
1758 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1974 LinkObjects(newRoot, newSet);
1759 affectedGroups.Add(newRoot.ParentGroup); 1975 if (!affectedGroups.Contains(newRoot.ParentGroup))
1760 } 1976 affectedGroups.Add(newRoot.ParentGroup);
1761 } 1977 }
1762 } 1978 }
1763 1979
@@ -1765,8 +1981,14 @@ namespace OpenSim.Region.Framework.Scenes
1765 // 1981 //
1766 foreach (SceneObjectGroup g in affectedGroups) 1982 foreach (SceneObjectGroup g in affectedGroups)
1767 { 1983 {
1984 // Child prims that have been unlinked and deleted will
1985 // return unless the root is deleted. This will remove them
1986 // from the database. They will be rewritten immediately,
1987 // minus the rows for the unlinked child prims.
1988 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1768 g.TriggerScriptChangedEvent(Changed.LINK); 1989 g.TriggerScriptChangedEvent(Changed.LINK);
1769 g.HasGroupChanged = true; // Persist 1990 g.HasGroupChanged = true; // Persist
1991 g.areUpdatesSuspended = false;
1770 g.ScheduleGroupForFullUpdate(); 1992 g.ScheduleGroupForFullUpdate();
1771 } 1993 }
1772 } 1994 }
@@ -1838,108 +2060,96 @@ namespace OpenSim.Region.Framework.Scenes
1838 /// <param name="GroupID"></param> 2060 /// <param name="GroupID"></param>
1839 /// <param name="rot"></param> 2061 /// <param name="rot"></param>
1840 /// <returns>null if duplication fails, otherwise the duplicated object</returns> 2062 /// <returns>null if duplication fails, otherwise the duplicated object</returns>
1841 public SceneObjectGroup DuplicateObject( 2063 /// <summary>
1842 uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) 2064 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
1843 { 2065 {
1844 Monitor.Enter(m_updateLock); 2066// m_log.DebugFormat(
2067// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
2068// originalPrimID, offset, AgentID);
1845 2069
1846 try 2070 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
2071 if (original != null)
1847 { 2072 {
1848 // m_log.DebugFormat( 2073 if (m_parentScene.Permissions.CanDuplicateObject(
1849 // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", 2074 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1850 // originalPrimID, offset, AgentID);
1851
1852 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1853 if (original == null)
1854 { 2075 {
1855 m_log.WarnFormat( 2076 SceneObjectGroup copy = original.Copy(true);
1856 "[SCENEGRAPH]: Attempt to duplicate nonexistant prim id {0} by {1}", originalPrimID, AgentID); 2077 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1857 2078
1858 return null; 2079 if (original.OwnerID != AgentID)
1859 } 2080 {
2081 copy.SetOwnerId(AgentID);
2082 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1860 2083
1861 if (!m_parentScene.Permissions.CanDuplicateObject( 2084 SceneObjectPart[] partList = copy.Parts;
1862 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1863 return null;
1864 2085
1865 SceneObjectGroup copy = original.Copy(true); 2086 if (m_parentScene.Permissions.PropagatePermissions())
1866 copy.AbsolutePosition = copy.AbsolutePosition + offset; 2087 {
2088 foreach (SceneObjectPart child in partList)
2089 {
2090 child.Inventory.ChangeInventoryOwner(AgentID);
2091 child.TriggerScriptChangedEvent(Changed.OWNER);
2092 child.ApplyNextOwnerPermissions();
2093 }
2094 }
2095 }
1867 2096
1868 if (original.OwnerID != AgentID) 2097 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
1869 { 2098 Entities.Add(copy);
1870 copy.SetOwnerId(AgentID);
1871 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1872 2099
1873 SceneObjectPart[] partList = copy.Parts; 2100 lock (SceneObjectGroupsByFullID)
2101 SceneObjectGroupsByFullID[copy.UUID] = copy;
1874 2102
1875 if (m_parentScene.Permissions.PropagatePermissions()) 2103 SceneObjectPart[] children = copy.Parts;
2104
2105 lock (SceneObjectGroupsByFullPartID)
1876 { 2106 {
1877 foreach (SceneObjectPart child in partList) 2107 SceneObjectGroupsByFullPartID[copy.UUID] = copy;
1878 { 2108 foreach (SceneObjectPart part in children)
1879 child.Inventory.ChangeInventoryOwner(AgentID); 2109 SceneObjectGroupsByFullPartID[part.UUID] = copy;
1880 child.TriggerScriptChangedEvent(Changed.OWNER);
1881 child.ApplyNextOwnerPermissions();
1882 }
1883 } 2110 }
1884 2111
1885 copy.RootPart.ObjectSaleType = 0; 2112 lock (SceneObjectGroupsByLocalPartID)
1886 copy.RootPart.SalePrice = 10; 2113 {
1887 } 2114 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
2115 foreach (SceneObjectPart part in children)
2116 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
2117 }
2118 // PROBABLE END OF FIXME
1888 2119
1889 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2120 // Since we copy from a source group that is in selected
1890 Entities.Add(copy); 2121 // state, but the copy is shown deselected in the viewer,
1891 2122 // We need to clear the selection flag here, else that
1892 lock (SceneObjectGroupsByFullID) 2123 // prim never gets persisted at all. The client doesn't
1893 SceneObjectGroupsByFullID[copy.UUID] = copy; 2124 // think it's selected, so it will never send a deselect...
1894 2125 copy.IsSelected = false;
1895 SceneObjectPart[] children = copy.Parts; 2126
1896 2127 m_numPrim += copy.Parts.Length;
1897 lock (SceneObjectGroupsByFullPartID) 2128
1898 { 2129 if (rot != Quaternion.Identity)
1899 SceneObjectGroupsByFullPartID[copy.UUID] = copy; 2130 {
1900 foreach (SceneObjectPart part in children) 2131 copy.UpdateGroupRotationR(rot);
1901 SceneObjectGroupsByFullPartID[part.UUID] = copy; 2132 }
1902 }
1903
1904 lock (SceneObjectGroupsByLocalPartID)
1905 {
1906 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
1907 foreach (SceneObjectPart part in children)
1908 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
1909 }
1910 // PROBABLE END OF FIXME
1911
1912 // Since we copy from a source group that is in selected
1913 // state, but the copy is shown deselected in the viewer,
1914 // We need to clear the selection flag here, else that
1915 // prim never gets persisted at all. The client doesn't
1916 // think it's selected, so it will never send a deselect...
1917 copy.IsSelected = false;
1918
1919 m_numPrim += copy.Parts.Length;
1920
1921 if (rot != Quaternion.Identity)
1922 {
1923 copy.UpdateGroupRotationR(rot);
1924 }
1925 2133
1926 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); 2134 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
1927 copy.HasGroupChanged = true; 2135 copy.HasGroupChanged = true;
1928 copy.ScheduleGroupForFullUpdate(); 2136 copy.ScheduleGroupForFullUpdate();
1929 copy.ResumeScripts(); 2137 copy.ResumeScripts();
1930 2138
1931 // required for physics to update it's position 2139 // required for physics to update it's position
1932 copy.AbsolutePosition = copy.AbsolutePosition; 2140 copy.AbsolutePosition = copy.AbsolutePosition;
1933 2141
1934 return copy; 2142 return copy;
2143 }
1935 } 2144 }
1936 finally 2145 else
1937 { 2146 {
1938 Monitor.Exit(m_updateLock); 2147 m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID);
1939 } 2148 }
2149
2150 return null;
1940 } 2151 }
1941 2152
1942 /// <summary>
1943 /// Calculates the distance between two Vector3s 2153 /// Calculates the distance between two Vector3s
1944 /// </summary> 2154 /// </summary>
1945 /// <param name="v1"></param> 2155 /// <param name="v1"></param>
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index d73a959..e3fed49 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -53,12 +53,12 @@ namespace OpenSim.Region.Framework.Scenes
53 get { return m_instance; } 53 get { return m_instance; }
54 } 54 }
55 55
56 private readonly List<Scene> m_localScenes = new List<Scene>(); 56 private readonly DoubleDictionary<UUID, string, Scene> m_localScenes = new DoubleDictionary<UUID, string, Scene>();
57 private Scene m_currentScene = null; 57 private Scene m_currentScene = null;
58 58
59 public List<Scene> Scenes 59 public List<Scene> Scenes
60 { 60 {
61 get { return new List<Scene>(m_localScenes); } 61 get { return new List<Scene>(m_localScenes.FindAll(delegate(Scene s) { return true; })); }
62 } 62 }
63 63
64 public Scene CurrentScene 64 public Scene CurrentScene
@@ -72,13 +72,10 @@ namespace OpenSim.Region.Framework.Scenes
72 { 72 {
73 if (m_currentScene == null) 73 if (m_currentScene == null)
74 { 74 {
75 lock (m_localScenes) 75 List<Scene> sceneList = Scenes;
76 { 76 if (sceneList.Count == 0)
77 if (m_localScenes.Count > 0) 77 return null;
78 return m_localScenes[0]; 78 return sceneList[0];
79 else
80 return null;
81 }
82 } 79 }
83 else 80 else
84 { 81 {
@@ -90,7 +87,7 @@ namespace OpenSim.Region.Framework.Scenes
90 public SceneManager() 87 public SceneManager()
91 { 88 {
92 m_instance = this; 89 m_instance = this;
93 m_localScenes = new List<Scene>(); 90 m_localScenes = new DoubleDictionary<UUID, string, Scene>();
94 } 91 }
95 92
96 public void Close() 93 public void Close()
@@ -98,20 +95,18 @@ namespace OpenSim.Region.Framework.Scenes
98 // collect known shared modules in sharedModules 95 // collect known shared modules in sharedModules
99 Dictionary<string, IRegionModule> sharedModules = new Dictionary<string, IRegionModule>(); 96 Dictionary<string, IRegionModule> sharedModules = new Dictionary<string, IRegionModule>();
100 97
101 lock (m_localScenes) 98 List<Scene> sceneList = Scenes;
99 for (int i = 0; i < sceneList.Count; i++)
102 { 100 {
103 for (int i = 0; i < m_localScenes.Count; i++) 101 // extract known shared modules from scene
102 foreach (string k in sceneList[i].Modules.Keys)
104 { 103 {
105 // extract known shared modules from scene 104 if (sceneList[i].Modules[k].IsSharedModule &&
106 foreach (string k in m_localScenes[i].Modules.Keys) 105 !sharedModules.ContainsKey(k))
107 { 106 sharedModules[k] = sceneList[i].Modules[k];
108 if (m_localScenes[i].Modules[k].IsSharedModule &&
109 !sharedModules.ContainsKey(k))
110 sharedModules[k] = m_localScenes[i].Modules[k];
111 }
112 // close scene/region
113 m_localScenes[i].Close();
114 } 107 }
108 // close scene/region
109 sceneList[i].Close();
115 } 110 }
116 111
117 // all regions/scenes are now closed, we can now safely 112 // all regions/scenes are now closed, we can now safely
@@ -120,31 +115,22 @@ namespace OpenSim.Region.Framework.Scenes
120 { 115 {
121 mod.Close(); 116 mod.Close();
122 } 117 }
118
119 m_localScenes.Clear();
123 } 120 }
124 121
125 public void Close(Scene cscene) 122 public void Close(Scene cscene)
126 { 123 {
127 lock (m_localScenes) 124 if (!m_localScenes.ContainsKey(cscene.RegionInfo.RegionID))
128 { 125 return;
129 if (m_localScenes.Contains(cscene)) 126 cscene.Close();
130 {
131 for (int i = 0; i < m_localScenes.Count; i++)
132 {
133 if (m_localScenes[i].Equals(cscene))
134 {
135 m_localScenes[i].Close();
136 }
137 }
138 }
139 }
140 } 127 }
141 128
142 public void Add(Scene scene) 129 public void Add(Scene scene)
143 { 130 {
144 scene.OnRestart += HandleRestart; 131 scene.OnRestart += HandleRestart;
145 132
146 lock (m_localScenes) 133 m_localScenes.Add(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, scene);
147 m_localScenes.Add(scene);
148 } 134 }
149 135
150 public void HandleRestart(RegionInfo rdata) 136 public void HandleRestart(RegionInfo rdata)
@@ -152,24 +138,7 @@ namespace OpenSim.Region.Framework.Scenes
152 m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main"); 138 m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main");
153 int RegionSceneElement = -1; 139 int RegionSceneElement = -1;
154 140
155 lock (m_localScenes) 141 m_localScenes.Remove(rdata.RegionID);
156 {
157 for (int i = 0; i < m_localScenes.Count; i++)
158 {
159 if (rdata.RegionName == m_localScenes[i].RegionInfo.RegionName)
160 {
161 RegionSceneElement = i;
162 }
163 }
164
165 // Now we make sure the region is no longer known about by the SceneManager
166 // Prevents duplicates.
167
168 if (RegionSceneElement >= 0)
169 {
170 m_localScenes.RemoveAt(RegionSceneElement);
171 }
172 }
173 142
174 // Send signal to main that we're restarting this sim. 143 // Send signal to main that we're restarting this sim.
175 OnRestartSim(rdata); 144 OnRestartSim(rdata);
@@ -179,32 +148,29 @@ namespace OpenSim.Region.Framework.Scenes
179 { 148 {
180 RegionInfo Result = null; 149 RegionInfo Result = null;
181 150
182 lock (m_localScenes) 151 Scene s = m_localScenes.FindValue(delegate(Scene x)
183 {
184 for (int i = 0; i < m_localScenes.Count; i++)
185 {
186 if (m_localScenes[i].RegionInfo.RegionHandle == regionHandle)
187 { 152 {
188 // Inform other regions to tell their avatar about me 153 if (x.RegionInfo.RegionHandle == regionHandle)
189 Result = m_localScenes[i].RegionInfo; 154 return true;
190 } 155 return false;
191 } 156 });
192 157
193 if (Result != null) 158 if (s != null)
159 {
160 List<Scene> sceneList = Scenes;
161
162 for (int i = 0; i < sceneList.Count; i++)
194 { 163 {
195 for (int i = 0; i < m_localScenes.Count; i++) 164 if (sceneList[i]!= s)
196 { 165 {
197 if (m_localScenes[i].RegionInfo.RegionHandle != regionHandle) 166 // Inform other regions to tell their avatar about me
198 { 167 //sceneList[i].OtherRegionUp(Result);
199 // Inform other regions to tell their avatar about me
200 //m_localScenes[i].OtherRegionUp(Result);
201 }
202 } 168 }
203 } 169 }
204 else 170 }
205 { 171 else
206 m_log.Error("[REGION]: Unable to notify Other regions of this Region coming up"); 172 {
207 } 173 m_log.Error("[REGION]: Unable to notify Other regions of this Region coming up");
208 } 174 }
209 } 175 }
210 176
@@ -308,8 +274,8 @@ namespace OpenSim.Region.Framework.Scenes
308 { 274 {
309 if (m_currentScene == null) 275 if (m_currentScene == null)
310 { 276 {
311 lock (m_localScenes) 277 List<Scene> sceneList = Scenes;
312 m_localScenes.ForEach(func); 278 sceneList.ForEach(func);
313 } 279 }
314 else 280 else
315 { 281 {
@@ -338,16 +304,12 @@ namespace OpenSim.Region.Framework.Scenes
338 } 304 }
339 else 305 else
340 { 306 {
341 lock (m_localScenes) 307 Scene s;
308
309 if (m_localScenes.TryGetValue(regionName, out s))
342 { 310 {
343 foreach (Scene scene in m_localScenes) 311 m_currentScene = s;
344 { 312 return true;
345 if (String.Compare(scene.RegionInfo.RegionName, regionName, true) == 0)
346 {
347 m_currentScene = scene;
348 return true;
349 }
350 }
351 } 313 }
352 314
353 return false; 315 return false;
@@ -356,18 +318,14 @@ namespace OpenSim.Region.Framework.Scenes
356 318
357 public bool TrySetCurrentScene(UUID regionID) 319 public bool TrySetCurrentScene(UUID regionID)
358 { 320 {
359 m_log.Debug("Searching for Region: '" + regionID + "'"); 321// m_log.Debug("Searching for Region: '" + regionID + "'");
360 322
361 lock (m_localScenes) 323 Scene s;
324
325 if (m_localScenes.TryGetValue(regionID, out s))
362 { 326 {
363 foreach (Scene scene in m_localScenes) 327 m_currentScene = s;
364 { 328 return true;
365 if (scene.RegionInfo.RegionID == regionID)
366 {
367 m_currentScene = scene;
368 return true;
369 }
370 }
371 } 329 }
372 330
373 return false; 331 return false;
@@ -375,52 +333,24 @@ namespace OpenSim.Region.Framework.Scenes
375 333
376 public bool TryGetScene(string regionName, out Scene scene) 334 public bool TryGetScene(string regionName, out Scene scene)
377 { 335 {
378 lock (m_localScenes) 336 return m_localScenes.TryGetValue(regionName, out scene);
379 {
380 foreach (Scene mscene in m_localScenes)
381 {
382 if (String.Compare(mscene.RegionInfo.RegionName, regionName, true) == 0)
383 {
384 scene = mscene;
385 return true;
386 }
387 }
388 }
389
390 scene = null;
391 return false;
392 } 337 }
393 338
394 public bool TryGetScene(UUID regionID, out Scene scene) 339 public bool TryGetScene(UUID regionID, out Scene scene)
395 { 340 {
396 lock (m_localScenes) 341 return m_localScenes.TryGetValue(regionID, out scene);
397 {
398 foreach (Scene mscene in m_localScenes)
399 {
400 if (mscene.RegionInfo.RegionID == regionID)
401 {
402 scene = mscene;
403 return true;
404 }
405 }
406 }
407
408 scene = null;
409 return false;
410 } 342 }
411 343
412 public bool TryGetScene(uint locX, uint locY, out Scene scene) 344 public bool TryGetScene(uint locX, uint locY, out Scene scene)
413 { 345 {
414 lock (m_localScenes) 346 List<Scene> sceneList = Scenes;
347 foreach (Scene mscene in sceneList)
415 { 348 {
416 foreach (Scene mscene in m_localScenes) 349 if (mscene.RegionInfo.RegionLocX == locX &&
350 mscene.RegionInfo.RegionLocY == locY)
417 { 351 {
418 if (mscene.RegionInfo.RegionLocX == locX && 352 scene = mscene;
419 mscene.RegionInfo.RegionLocY == locY) 353 return true;
420 {
421 scene = mscene;
422 return true;
423 }
424 } 354 }
425 } 355 }
426 356
@@ -430,16 +360,14 @@ namespace OpenSim.Region.Framework.Scenes
430 360
431 public bool TryGetScene(IPEndPoint ipEndPoint, out Scene scene) 361 public bool TryGetScene(IPEndPoint ipEndPoint, out Scene scene)
432 { 362 {
433 lock (m_localScenes) 363 List<Scene> sceneList = Scenes;
364 foreach (Scene mscene in sceneList)
434 { 365 {
435 foreach (Scene mscene in m_localScenes) 366 if ((mscene.RegionInfo.InternalEndPoint.Equals(ipEndPoint.Address)) &&
367 (mscene.RegionInfo.InternalEndPoint.Port == ipEndPoint.Port))
436 { 368 {
437 if ((mscene.RegionInfo.InternalEndPoint.Equals(ipEndPoint.Address)) && 369 scene = mscene;
438 (mscene.RegionInfo.InternalEndPoint.Port == ipEndPoint.Port)) 370 return true;
439 {
440 scene = mscene;
441 return true;
442 }
443 } 371 }
444 } 372 }
445 373
@@ -504,15 +432,10 @@ namespace OpenSim.Region.Framework.Scenes
504 432
505 public RegionInfo GetRegionInfo(UUID regionID) 433 public RegionInfo GetRegionInfo(UUID regionID)
506 { 434 {
507 lock (m_localScenes) 435 Scene s;
436 if (m_localScenes.TryGetValue(regionID, out s))
508 { 437 {
509 foreach (Scene scene in m_localScenes) 438 return s.RegionInfo;
510 {
511 if (scene.RegionInfo.RegionID == regionID)
512 {
513 return scene.RegionInfo;
514 }
515 }
516 } 439 }
517 440
518 return null; 441 return null;
@@ -530,14 +453,12 @@ namespace OpenSim.Region.Framework.Scenes
530 453
531 public bool TryGetScenePresence(UUID avatarId, out ScenePresence avatar) 454 public bool TryGetScenePresence(UUID avatarId, out ScenePresence avatar)
532 { 455 {
533 lock (m_localScenes) 456 List<Scene> sceneList = Scenes;
457 foreach (Scene scene in sceneList)
534 { 458 {
535 foreach (Scene scene in m_localScenes) 459 if (scene.TryGetScenePresence(avatarId, out avatar))
536 { 460 {
537 if (scene.TryGetScenePresence(avatarId, out avatar)) 461 return true;
538 {
539 return true;
540 }
541 } 462 }
542 } 463 }
543 464
@@ -547,15 +468,13 @@ namespace OpenSim.Region.Framework.Scenes
547 468
548 public bool TryGetRootScenePresence(UUID avatarId, out ScenePresence avatar) 469 public bool TryGetRootScenePresence(UUID avatarId, out ScenePresence avatar)
549 { 470 {
550 lock (m_localScenes) 471 List<Scene> sceneList = Scenes;
472 foreach (Scene scene in sceneList)
551 { 473 {
552 foreach (Scene scene in m_localScenes) 474 avatar = scene.GetScenePresence(avatarId);
553 {
554 avatar = scene.GetScenePresence(avatarId);
555 475
556 if (avatar != null && !avatar.IsChildAgent) 476 if (avatar != null && !avatar.IsChildAgent)
557 return true; 477 return true;
558 }
559 } 478 }
560 479
561 avatar = null; 480 avatar = null;
@@ -564,22 +483,19 @@ namespace OpenSim.Region.Framework.Scenes
564 483
565 public void CloseScene(Scene scene) 484 public void CloseScene(Scene scene)
566 { 485 {
567 lock (m_localScenes) 486 m_localScenes.Remove(scene.RegionInfo.RegionID);
568 m_localScenes.Remove(scene);
569 487
570 scene.Close(); 488 scene.Close();
571 } 489 }
572 490
573 public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) 491 public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar)
574 { 492 {
575 lock (m_localScenes) 493 List<Scene> sceneList = Scenes;
494 foreach (Scene scene in sceneList)
576 { 495 {
577 foreach (Scene scene in m_localScenes) 496 if (scene.TryGetAvatarByName(avatarName, out avatar))
578 { 497 {
579 if (scene.TryGetAvatarByName(avatarName, out avatar)) 498 return true;
580 {
581 return true;
582 }
583 } 499 }
584 } 500 }
585 501
@@ -589,14 +505,12 @@ namespace OpenSim.Region.Framework.Scenes
589 505
590 public bool TryGetRootScenePresenceByName(string firstName, string lastName, out ScenePresence sp) 506 public bool TryGetRootScenePresenceByName(string firstName, string lastName, out ScenePresence sp)
591 { 507 {
592 lock (m_localScenes) 508 List<Scene> sceneList = Scenes;
509 foreach (Scene scene in sceneList)
593 { 510 {
594 foreach (Scene scene in m_localScenes) 511 sp = scene.GetScenePresence(firstName, lastName);
595 { 512 if (sp != null && !sp.IsChildAgent)
596 sp = scene.GetScenePresence(firstName, lastName); 513 return true;
597 if (sp != null && !sp.IsChildAgent)
598 return true;
599 }
600 } 514 }
601 515
602 sp = null; 516 sp = null;
@@ -605,8 +519,8 @@ namespace OpenSim.Region.Framework.Scenes
605 519
606 public void ForEachScene(Action<Scene> action) 520 public void ForEachScene(Action<Scene> action)
607 { 521 {
608 lock (m_localScenes) 522 List<Scene> sceneList = Scenes;
609 m_localScenes.ForEach(action); 523 sceneList.ForEach(action);
610 } 524 }
611 } 525 }
612} 526}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 2866b54..1038111 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -81,10 +81,6 @@ namespace OpenSim.Region.Framework.Scenes
81 /// <summary> 81 /// <summary>
82 /// Stop the scripts contained in all the prims in this group 82 /// Stop the scripts contained in all the prims in this group
83 /// </summary> 83 /// </summary>
84 /// <param name="sceneObjectBeingDeleted">
85 /// Should be true if these scripts are being removed because the scene
86 /// object is being deleted. This will prevent spurious updates to the client.
87 /// </param>
88 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 84 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
89 { 85 {
90 SceneObjectPart[] parts = m_parts.GetArray(); 86 SceneObjectPart[] parts = m_parts.GetArray();
@@ -239,6 +235,11 @@ namespace OpenSim.Region.Framework.Scenes
239 235
240 public uint GetEffectivePermissions() 236 public uint GetEffectivePermissions()
241 { 237 {
238 return GetEffectivePermissions(false);
239 }
240
241 public uint GetEffectivePermissions(bool useBase)
242 {
242 uint perms=(uint)(PermissionMask.Modify | 243 uint perms=(uint)(PermissionMask.Modify |
243 PermissionMask.Copy | 244 PermissionMask.Copy |
244 PermissionMask.Move | 245 PermissionMask.Move |
@@ -250,7 +251,10 @@ namespace OpenSim.Region.Framework.Scenes
250 for (int i = 0; i < parts.Length; i++) 251 for (int i = 0; i < parts.Length; i++)
251 { 252 {
252 SceneObjectPart part = parts[i]; 253 SceneObjectPart part = parts[i];
253 ownerMask &= part.OwnerMask; 254 if (useBase)
255 ownerMask &= part.BaseMask;
256 else
257 ownerMask &= part.OwnerMask;
254 perms &= part.Inventory.MaskEffectivePermissions(); 258 perms &= part.Inventory.MaskEffectivePermissions();
255 } 259 }
256 260
@@ -392,6 +396,9 @@ namespace OpenSim.Region.Framework.Scenes
392 396
393 public void ResumeScripts() 397 public void ResumeScripts()
394 { 398 {
399 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
400 return;
401
395 SceneObjectPart[] parts = m_parts.GetArray(); 402 SceneObjectPart[] parts = m_parts.GetArray();
396 for (int i = 0; i < parts.Length; i++) 403 for (int i = 0; i < parts.Length; i++)
397 parts[i].Inventory.ResumeScripts(); 404 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 96cc376..3db6710 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -24,11 +24,12 @@
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.Collections.Generic; 29using System.Collections.Generic;
30using System.Drawing; 30using System.Drawing;
31using System.IO; 31using System.IO;
32using System.Diagnostics;
32using System.Linq; 33using System.Linq;
33using System.Threading; 34using System.Threading;
34using System.Xml; 35using System.Xml;
@@ -42,6 +43,7 @@ using OpenSim.Region.Framework.Scenes.Serialization;
42 43
43namespace OpenSim.Region.Framework.Scenes 44namespace OpenSim.Region.Framework.Scenes
44{ 45{
46
45 [Flags] 47 [Flags]
46 public enum scriptEvents 48 public enum scriptEvents
47 { 49 {
@@ -105,8 +107,29 @@ namespace OpenSim.Region.Framework.Scenes
105 /// since the group's last persistent backup 107 /// since the group's last persistent backup
106 /// </summary> 108 /// </summary>
107 private bool m_hasGroupChanged = false; 109 private bool m_hasGroupChanged = false;
108 private long timeFirstChanged; 110 private long timeFirstChanged = 0;
109 private long timeLastChanged; 111 private long timeLastChanged = 0;
112 private long m_maxPersistTime = 0;
113 private long m_minPersistTime = 0;
114 private Random m_rand;
115 private bool m_suspendUpdates;
116 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
117
118 public bool areUpdatesSuspended
119 {
120 get
121 {
122 return m_suspendUpdates;
123 }
124 set
125 {
126 m_suspendUpdates = value;
127 if (!value)
128 {
129 QueueForUpdateCheck();
130 }
131 }
132 }
110 133
111 /// <summary> 134 /// <summary>
112 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage 135 /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage
@@ -123,9 +146,39 @@ namespace OpenSim.Region.Framework.Scenes
123 { 146 {
124 if (value) 147 if (value)
125 { 148 {
149 if (m_isBackedUp)
150 {
151 m_scene.SceneGraph.FireChangeBackup(this);
152 }
126 timeLastChanged = DateTime.Now.Ticks; 153 timeLastChanged = DateTime.Now.Ticks;
127 if (!m_hasGroupChanged) 154 if (!m_hasGroupChanged)
128 timeFirstChanged = DateTime.Now.Ticks; 155 timeFirstChanged = DateTime.Now.Ticks;
156 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
157 {
158 if (m_rand == null)
159 {
160 byte[] val = new byte[16];
161 m_rootPart.UUID.ToBytes(val, 0);
162 m_rand = new Random(BitConverter.ToInt32(val, 0));
163 }
164
165 if (m_scene.GetRootAgentCount() == 0)
166 {
167 //If the region is empty, this change has been made by an automated process
168 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
169
170 float factor = 1.5f + (float)(m_rand.NextDouble());
171 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
172 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
173 }
174 else
175 {
176 //If the region is not empty, we want to obey the minimum and maximum persist times
177 //but add a random factor so we stagger the object persistance a little
178 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
179 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
180 }
181 }
129 } 182 }
130 m_hasGroupChanged = value; 183 m_hasGroupChanged = value;
131 184
@@ -140,7 +193,7 @@ namespace OpenSim.Region.Framework.Scenes
140 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since 193 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since
141 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation. 194 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation.
142 /// </summary> 195 /// </summary>
143 public bool HasGroupChangedDueToDelink { get; private set; } 196 public bool HasGroupChangedDueToDelink { get; set; }
144 197
145 private bool isTimeToPersist() 198 private bool isTimeToPersist()
146 { 199 {
@@ -150,8 +203,19 @@ namespace OpenSim.Region.Framework.Scenes
150 return false; 203 return false;
151 if (m_scene.ShuttingDown) 204 if (m_scene.ShuttingDown)
152 return true; 205 return true;
206
207 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
208 {
209 m_maxPersistTime = m_scene.m_persistAfter;
210 m_minPersistTime = m_scene.m_dontPersistBefore;
211 }
212
153 long currentTime = DateTime.Now.Ticks; 213 long currentTime = DateTime.Now.Ticks;
154 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 214
215 if (timeLastChanged == 0) timeLastChanged = currentTime;
216 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
217
218 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
155 return true; 219 return true;
156 return false; 220 return false;
157 } 221 }
@@ -270,10 +334,10 @@ namespace OpenSim.Region.Framework.Scenes
270 334
271 private bool m_scriptListens_atTarget; 335 private bool m_scriptListens_atTarget;
272 private bool m_scriptListens_notAtTarget; 336 private bool m_scriptListens_notAtTarget;
273
274 private bool m_scriptListens_atRotTarget; 337 private bool m_scriptListens_atRotTarget;
275 private bool m_scriptListens_notAtRotTarget; 338 private bool m_scriptListens_notAtRotTarget;
276 339
340 public bool m_dupeInProgress = false;
277 internal Dictionary<UUID, string> m_savedScriptState; 341 internal Dictionary<UUID, string> m_savedScriptState;
278 342
279 #region Properties 343 #region Properties
@@ -310,6 +374,16 @@ namespace OpenSim.Region.Framework.Scenes
310 get { return m_parts.Count; } 374 get { return m_parts.Count; }
311 } 375 }
312 376
377// protected Quaternion m_rotation = Quaternion.Identity;
378//
379// public virtual Quaternion Rotation
380// {
381// get { return m_rotation; }
382// set {
383// m_rotation = value;
384// }
385// }
386
313 public Quaternion GroupRotation 387 public Quaternion GroupRotation
314 { 388 {
315 get { return m_rootPart.RotationOffset; } 389 get { return m_rootPart.RotationOffset; }
@@ -416,7 +490,15 @@ namespace OpenSim.Region.Framework.Scenes
416 { 490 {
417 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); 491 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
418 } 492 }
419 493
494
495
496 private struct avtocrossInfo
497 {
498 public ScenePresence av;
499 public uint ParentID;
500 }
501
420 /// <summary> 502 /// <summary>
421 /// The absolute position of this scene object in the scene 503 /// The absolute position of this scene object in the scene
422 /// </summary> 504 /// </summary>
@@ -429,14 +511,128 @@ namespace OpenSim.Region.Framework.Scenes
429 511
430 if (Scene != null) 512 if (Scene != null)
431 { 513 {
432 if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) 514 // if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
433 || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) 515 // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
516 // && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
517 if ((Scene.TestBorderCross(val, Cardinals.E) || Scene.TestBorderCross(val, Cardinals.W)
518 || Scene.TestBorderCross(val, Cardinals.N) || Scene.TestBorderCross(val, Cardinals.S))
434 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 519 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
435 { 520 {
436 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 521 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
522 uint x = 0;
523 uint y = 0;
524 string version = String.Empty;
525 Vector3 newpos = Vector3.Zero;
526 OpenSim.Services.Interfaces.GridRegion destination = null;
527
528 bool canCross = true;
529 foreach (ScenePresence av in m_linkedAvatars)
530 {
531 // We need to cross these agents. First, let's find
532 // out if any of them can't cross for some reason.
533 // We have to deny the crossing entirely if any
534 // of them are banned. Alternatively, we could
535 // unsit banned agents....
536
537
538 // We set the avatar position as being the object
539 // position to get the region to send to
540 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null)
541 {
542 canCross = false;
543 break;
544 }
545
546 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
547 }
548
549 if (canCross)
550 {
551 // We unparent the SP quietly so that it won't
552 // be made to stand up
553
554 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
555
556 foreach (ScenePresence av in m_linkedAvatars)
557 {
558 avtocrossInfo avinfo = new avtocrossInfo();
559 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
560 if (parentPart != null)
561 av.ParentUUID = parentPart.UUID;
562
563 avinfo.av = av;
564 avinfo.ParentID = av.ParentID;
565 avsToCross.Add(avinfo);
566
567 av.ParentID = 0;
568 }
569
570// m_linkedAvatars.Clear();
571 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
572
573 // Normalize
574 if (val.X >= Constants.RegionSize)
575 val.X -= Constants.RegionSize;
576 if (val.Y >= Constants.RegionSize)
577 val.Y -= Constants.RegionSize;
578 if (val.X < 0)
579 val.X += Constants.RegionSize;
580 if (val.Y < 0)
581 val.Y += Constants.RegionSize;
582
583 // If it's deleted, crossing was successful
584 if (IsDeleted)
585 {
586 // foreach (ScenePresence av in m_linkedAvatars)
587 foreach (avtocrossInfo avinfo in avsToCross)
588 {
589 ScenePresence av = avinfo.av;
590 if (!av.IsInTransit) // just in case...
591 {
592 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
593
594 av.IsInTransit = true;
595
596 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
597 d.BeginInvoke(av, val, x, y, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
598 }
599 else
600 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val);
601 }
602 avsToCross.Clear();
603 return;
604 }
605 else // cross failed, put avas back ??
606 {
607 foreach (avtocrossInfo avinfo in avsToCross)
608 {
609 ScenePresence av = avinfo.av;
610 av.ParentUUID = UUID.Zero;
611 av.ParentID = avinfo.ParentID;
612// m_linkedAvatars.Add(av);
613 }
614 }
615 avsToCross.Clear();
616
617 }
618 else if (RootPart.PhysActor != null)
619 {
620 RootPart.PhysActor.CrossingFailure();
621 }
622
623 Vector3 oldp = AbsolutePosition;
624 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
625 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
626 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
437 } 627 }
438 } 628 }
439 629
630/* don't see the need but worse don't see where is restored to false if things stay in
631 foreach (SceneObjectPart part in m_parts.GetArray())
632 {
633 part.IgnoreUndoUpdate = true;
634 }
635 */
440 if (RootPart.GetStatusSandbox()) 636 if (RootPart.GetStatusSandbox())
441 { 637 {
442 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 638 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -450,10 +646,30 @@ namespace OpenSim.Region.Framework.Scenes
450 return; 646 return;
451 } 647 }
452 } 648 }
453
454 SceneObjectPart[] parts = m_parts.GetArray(); 649 SceneObjectPart[] parts = m_parts.GetArray();
455 for (int i = 0; i < parts.Length; i++) 650 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
456 parts[i].GroupPosition = val; 651 if (m_dupeInProgress)
652 triggerScriptEvent = false;
653 foreach (SceneObjectPart part in parts)
654 {
655 part.GroupPosition = val;
656 if (triggerScriptEvent)
657 part.TriggerScriptChangedEvent(Changed.POSITION);
658 }
659 if (!m_dupeInProgress)
660 {
661 foreach (ScenePresence av in m_linkedAvatars)
662 {
663 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
664 if (p != null && m_parts.TryGetValue(p.UUID, out p))
665 {
666 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
667 av.AbsolutePosition += offset;
668 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
669 av.SendAvatarDataToAllAgents();
670 }
671 }
672 }
457 673
458 //if (m_rootPart.PhysActor != null) 674 //if (m_rootPart.PhysActor != null)
459 //{ 675 //{
@@ -468,6 +684,40 @@ namespace OpenSim.Region.Framework.Scenes
468 } 684 }
469 } 685 }
470 686
687 public override Vector3 Velocity
688 {
689 get { return RootPart.Velocity; }
690 set { RootPart.Velocity = value; }
691 }
692
693 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
694 {
695 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
696 ScenePresence agent = icon.EndInvoke(iar);
697
698 //// If the cross was successful, this agent is a child agent
699 if (agent.IsChildAgent)
700 {
701 if (agent.ParentUUID != UUID.Zero)
702 {
703 agent.ParentPart = null;
704 agent.ParentPosition = Vector3.Zero;
705 // agent.ParentUUID = UUID.Zero;
706 }
707 }
708
709 agent.ParentUUID = UUID.Zero;
710
711// agent.Reset();
712// else // Not successful
713// agent.RestoreInCurrentScene();
714
715 // In any case
716 agent.IsInTransit = false;
717
718 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
719 }
720
471 public override uint LocalId 721 public override uint LocalId
472 { 722 {
473 get { return m_rootPart.LocalId; } 723 get { return m_rootPart.LocalId; }
@@ -538,6 +788,11 @@ namespace OpenSim.Region.Framework.Scenes
538 m_isSelected = value; 788 m_isSelected = value;
539 // Tell physics engine that group is selected 789 // Tell physics engine that group is selected
540 790
791 // this is not right
792 // but ode engines should only really need to know about root part
793 // so they can put entire object simulation on hold and not colliding
794 // keep as was for now
795
541 PhysicsActor pa = m_rootPart.PhysActor; 796 PhysicsActor pa = m_rootPart.PhysActor;
542 if (pa != null) 797 if (pa != null)
543 { 798 {
@@ -554,6 +809,42 @@ namespace OpenSim.Region.Framework.Scenes
554 childPa.Selected = value; 809 childPa.Selected = value;
555 } 810 }
556 } 811 }
812 if (RootPart.KeyframeMotion != null)
813 RootPart.KeyframeMotion.Selected = value;
814 }
815 }
816
817 public void PartSelectChanged(bool partSelect)
818 {
819 // any part selected makes group selected
820 if (m_isSelected == partSelect)
821 return;
822
823 if (partSelect)
824 {
825 IsSelected = partSelect;
826// if (!IsAttachment)
827// ScheduleGroupForFullUpdate();
828 }
829 else
830 {
831 // bad bad bad 2 heavy for large linksets
832 // since viewer does send lot of (un)selects
833 // this needs to be replaced by a specific list or count ?
834 // but that will require extra code in several places
835
836 SceneObjectPart[] parts = m_parts.GetArray();
837 for (int i = 0; i < parts.Length; i++)
838 {
839 SceneObjectPart part = parts[i];
840 if (part.IsSelected)
841 return;
842 }
843 IsSelected = partSelect;
844 if (!IsAttachment)
845 {
846 ScheduleGroupForFullUpdate();
847 }
557 } 848 }
558 } 849 }
559 850
@@ -631,6 +922,7 @@ namespace OpenSim.Region.Framework.Scenes
631 /// </summary> 922 /// </summary>
632 public SceneObjectGroup() 923 public SceneObjectGroup()
633 { 924 {
925
634 } 926 }
635 927
636 /// <summary> 928 /// <summary>
@@ -647,7 +939,7 @@ namespace OpenSim.Region.Framework.Scenes
647 /// Constructor. This object is added to the scene later via AttachToScene() 939 /// Constructor. This object is added to the scene later via AttachToScene()
648 /// </summary> 940 /// </summary>
649 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 941 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
650 { 942 {
651 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 943 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
652 } 944 }
653 945
@@ -683,6 +975,9 @@ namespace OpenSim.Region.Framework.Scenes
683 /// </summary> 975 /// </summary>
684 public virtual void AttachToBackup() 976 public virtual void AttachToBackup()
685 { 977 {
978 if (IsAttachment) return;
979 m_scene.SceneGraph.FireAttachToBackup(this);
980
686 if (InSceneBackup) 981 if (InSceneBackup)
687 { 982 {
688 //m_log.DebugFormat( 983 //m_log.DebugFormat(
@@ -725,6 +1020,13 @@ namespace OpenSim.Region.Framework.Scenes
725 1020
726 ApplyPhysics(); 1021 ApplyPhysics();
727 1022
1023 if (RootPart.PhysActor != null)
1024 RootPart.Force = RootPart.Force;
1025 if (RootPart.PhysActor != null)
1026 RootPart.Torque = RootPart.Torque;
1027 if (RootPart.PhysActor != null)
1028 RootPart.Buoyancy = RootPart.Buoyancy;
1029
728 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 1030 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
729 // for the same object with very different properties. The caller must schedule the update. 1031 // for the same object with very different properties. The caller must schedule the update.
730 //ScheduleGroupForFullUpdate(); 1032 //ScheduleGroupForFullUpdate();
@@ -740,6 +1042,10 @@ namespace OpenSim.Region.Framework.Scenes
740 EntityIntersection result = new EntityIntersection(); 1042 EntityIntersection result = new EntityIntersection();
741 1043
742 SceneObjectPart[] parts = m_parts.GetArray(); 1044 SceneObjectPart[] parts = m_parts.GetArray();
1045
1046 // Find closest hit here
1047 float idist = float.MaxValue;
1048
743 for (int i = 0; i < parts.Length; i++) 1049 for (int i = 0; i < parts.Length; i++)
744 { 1050 {
745 SceneObjectPart part = parts[i]; 1051 SceneObjectPart part = parts[i];
@@ -754,11 +1060,6 @@ namespace OpenSim.Region.Framework.Scenes
754 1060
755 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 1061 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
756 1062
757 // This may need to be updated to the maximum draw distance possible..
758 // We might (and probably will) be checking for prim creation from other sims
759 // when the camera crosses the border.
760 float idist = Constants.RegionSize;
761
762 if (inter.HitTF) 1063 if (inter.HitTF)
763 { 1064 {
764 // We need to find the closest prim to return to the testcaller along the ray 1065 // We need to find the closest prim to return to the testcaller along the ray
@@ -769,10 +1070,11 @@ namespace OpenSim.Region.Framework.Scenes
769 result.obj = part; 1070 result.obj = part;
770 result.normal = inter.normal; 1071 result.normal = inter.normal;
771 result.distance = inter.distance; 1072 result.distance = inter.distance;
1073
1074 idist = inter.distance;
772 } 1075 }
773 } 1076 }
774 } 1077 }
775
776 return result; 1078 return result;
777 } 1079 }
778 1080
@@ -784,25 +1086,27 @@ namespace OpenSim.Region.Framework.Scenes
784 /// <returns></returns> 1086 /// <returns></returns>
785 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 1087 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
786 { 1088 {
787 maxX = -256f; 1089 maxX = float.MinValue;
788 maxY = -256f; 1090 maxY = float.MinValue;
789 maxZ = -256f; 1091 maxZ = float.MinValue;
790 minX = 256f; 1092 minX = float.MaxValue;
791 minY = 256f; 1093 minY = float.MaxValue;
792 minZ = 8192f; 1094 minZ = float.MaxValue;
793 1095
794 SceneObjectPart[] parts = m_parts.GetArray(); 1096 SceneObjectPart[] parts = m_parts.GetArray();
795 for (int i = 0; i < parts.Length; i++) 1097 foreach (SceneObjectPart part in parts)
796 { 1098 {
797 SceneObjectPart part = parts[i];
798
799 Vector3 worldPos = part.GetWorldPosition(); 1099 Vector3 worldPos = part.GetWorldPosition();
800 Vector3 offset = worldPos - AbsolutePosition; 1100 Vector3 offset = worldPos - AbsolutePosition;
801 Quaternion worldRot; 1101 Quaternion worldRot;
802 if (part.ParentID == 0) 1102 if (part.ParentID == 0)
1103 {
803 worldRot = part.RotationOffset; 1104 worldRot = part.RotationOffset;
1105 }
804 else 1106 else
1107 {
805 worldRot = part.GetWorldRotation(); 1108 worldRot = part.GetWorldRotation();
1109 }
806 1110
807 Vector3 frontTopLeft; 1111 Vector3 frontTopLeft;
808 Vector3 frontTopRight; 1112 Vector3 frontTopRight;
@@ -814,6 +1118,8 @@ namespace OpenSim.Region.Framework.Scenes
814 Vector3 backBottomLeft; 1118 Vector3 backBottomLeft;
815 Vector3 backBottomRight; 1119 Vector3 backBottomRight;
816 1120
1121 // Vector3[] corners = new Vector3[8];
1122
817 Vector3 orig = Vector3.Zero; 1123 Vector3 orig = Vector3.Zero;
818 1124
819 frontTopLeft.X = orig.X - (part.Scale.X / 2); 1125 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -848,6 +1154,38 @@ namespace OpenSim.Region.Framework.Scenes
848 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1154 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
849 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1155 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
850 1156
1157
1158
1159 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1160 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1161 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1162 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1163 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1164 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1165 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1166 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1167
1168 //for (int i = 0; i < 8; i++)
1169 //{
1170 // corners[i] = corners[i] * worldRot;
1171 // corners[i] += offset;
1172
1173 // if (corners[i].X > maxX)
1174 // maxX = corners[i].X;
1175 // if (corners[i].X < minX)
1176 // minX = corners[i].X;
1177
1178 // if (corners[i].Y > maxY)
1179 // maxY = corners[i].Y;
1180 // if (corners[i].Y < minY)
1181 // minY = corners[i].Y;
1182
1183 // if (corners[i].Z > maxZ)
1184 // maxZ = corners[i].Y;
1185 // if (corners[i].Z < minZ)
1186 // minZ = corners[i].Z;
1187 //}
1188
851 frontTopLeft = frontTopLeft * worldRot; 1189 frontTopLeft = frontTopLeft * worldRot;
852 frontTopRight = frontTopRight * worldRot; 1190 frontTopRight = frontTopRight * worldRot;
853 frontBottomLeft = frontBottomLeft * worldRot; 1191 frontBottomLeft = frontBottomLeft * worldRot;
@@ -869,6 +1207,15 @@ namespace OpenSim.Region.Framework.Scenes
869 backTopLeft += offset; 1207 backTopLeft += offset;
870 backTopRight += offset; 1208 backTopRight += offset;
871 1209
1210 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1211 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1212 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1213 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1214 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1215 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1216 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1217 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1218
872 if (frontTopRight.X > maxX) 1219 if (frontTopRight.X > maxX)
873 maxX = frontTopRight.X; 1220 maxX = frontTopRight.X;
874 if (frontTopLeft.X > maxX) 1221 if (frontTopLeft.X > maxX)
@@ -1012,17 +1359,118 @@ namespace OpenSim.Region.Framework.Scenes
1012 1359
1013 #endregion 1360 #endregion
1014 1361
1362 public void GetResourcesCosts(SceneObjectPart apart,
1363 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost)
1364 {
1365 // this information may need to be cached
1366
1367 float cost;
1368 float tmpcost;
1369
1370 bool ComplexCost = false;
1371
1372 SceneObjectPart p;
1373 SceneObjectPart[] parts;
1374
1375 lock (m_parts)
1376 {
1377 parts = m_parts.GetArray();
1378 }
1379
1380 int nparts = parts.Length;
1381
1382
1383 for (int i = 0; i < nparts; i++)
1384 {
1385 p = parts[i];
1386
1387 if (p.UsesComplexCost)
1388 {
1389 ComplexCost = true;
1390 break;
1391 }
1392 }
1393
1394 if (ComplexCost)
1395 {
1396 linksetResCost = 0;
1397 linksetPhysCost = 0;
1398 partCost = 0;
1399 partPhysCost = 0;
1400
1401 for (int i = 0; i < nparts; i++)
1402 {
1403 p = parts[i];
1404
1405 cost = p.StreamingCost;
1406 tmpcost = p.SimulationCost;
1407 if (tmpcost > cost)
1408 cost = tmpcost;
1409 tmpcost = p.PhysicsCost;
1410 if (tmpcost > cost)
1411 cost = tmpcost;
1412
1413 linksetPhysCost += tmpcost;
1414 linksetResCost += cost;
1415
1416 if (p == apart)
1417 {
1418 partCost = cost;
1419 partPhysCost = tmpcost;
1420 }
1421 }
1422 }
1423 else
1424 {
1425 partPhysCost = 1.0f;
1426 partCost = 1.0f;
1427 linksetResCost = (float)nparts;
1428 linksetPhysCost = linksetResCost;
1429 }
1430 }
1431
1432 public void GetSelectedCosts(out float PhysCost, out float StreamCost, out float SimulCost)
1433 {
1434 SceneObjectPart p;
1435 SceneObjectPart[] parts;
1436
1437 lock (m_parts)
1438 {
1439 parts = m_parts.GetArray();
1440 }
1441
1442 int nparts = parts.Length;
1443
1444 PhysCost = 0;
1445 StreamCost = 0;
1446 SimulCost = 0;
1447
1448 for (int i = 0; i < nparts; i++)
1449 {
1450 p = parts[i];
1451
1452 StreamCost += p.StreamingCost;
1453 SimulCost += p.SimulationCost;
1454 PhysCost += p.PhysicsCost;
1455 }
1456 }
1457
1015 public void SaveScriptedState(XmlTextWriter writer) 1458 public void SaveScriptedState(XmlTextWriter writer)
1016 { 1459 {
1460 SaveScriptedState(writer, false);
1461 }
1462
1463 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1464 {
1017 XmlDocument doc = new XmlDocument(); 1465 XmlDocument doc = new XmlDocument();
1018 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1466 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
1019 1467
1020 SceneObjectPart[] parts = m_parts.GetArray(); 1468 SceneObjectPart[] parts = m_parts.GetArray();
1021 for (int i = 0; i < parts.Length; i++) 1469 for (int i = 0; i < parts.Length; i++)
1022 { 1470 {
1023 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1471 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
1024 foreach (KeyValuePair<UUID, string> kvp in pstates) 1472 foreach (KeyValuePair<UUID, string> kvp in pstates)
1025 states.Add(kvp.Key, kvp.Value); 1473 states[kvp.Key] = kvp.Value;
1026 } 1474 }
1027 1475
1028 if (states.Count > 0) 1476 if (states.Count > 0)
@@ -1042,6 +1490,169 @@ namespace OpenSim.Region.Framework.Scenes
1042 } 1490 }
1043 1491
1044 /// <summary> 1492 /// <summary>
1493 /// Add the avatar to this linkset (avatar is sat).
1494 /// </summary>
1495 /// <param name="agentID"></param>
1496 public void AddAvatar(UUID agentID)
1497 {
1498 ScenePresence presence;
1499 if (m_scene.TryGetScenePresence(agentID, out presence))
1500 {
1501 if (!m_linkedAvatars.Contains(presence))
1502 {
1503 m_linkedAvatars.Add(presence);
1504 }
1505 }
1506 }
1507
1508 /// <summary>
1509 /// Delete the avatar from this linkset (avatar is unsat).
1510 /// </summary>
1511 /// <param name="agentID"></param>
1512 public void DeleteAvatar(UUID agentID)
1513 {
1514 ScenePresence presence;
1515 if (m_scene.TryGetScenePresence(agentID, out presence))
1516 {
1517 if (m_linkedAvatars.Contains(presence))
1518 {
1519 m_linkedAvatars.Remove(presence);
1520 }
1521 }
1522 }
1523
1524 /// <summary>
1525 /// Returns the list of linked presences (avatars sat on this group)
1526 /// </summary>
1527 /// <param name="agentID"></param>
1528 public List<ScenePresence> GetLinkedAvatars()
1529 {
1530 return m_linkedAvatars;
1531 }
1532
1533 /// <summary>
1534 /// Attach this scene object to the given avatar.
1535 /// </summary>
1536 /// <param name="agentID"></param>
1537 /// <param name="attachmentpoint"></param>
1538 /// <param name="AttachOffset"></param>
1539 private void AttachToAgent(
1540 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1541 {
1542 if (avatar != null)
1543 {
1544 // don't attach attachments to child agents
1545 if (avatar.IsChildAgent) return;
1546
1547 // Remove from database and parcel prim count
1548 m_scene.DeleteFromStorage(so.UUID);
1549 m_scene.EventManager.TriggerParcelPrimCountTainted();
1550
1551 so.AttachedAvatar = avatar.UUID;
1552
1553 if (so.RootPart.PhysActor != null)
1554 {
1555 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1556 so.RootPart.PhysActor = null;
1557 }
1558
1559 so.AbsolutePosition = attachOffset;
1560 so.RootPart.AttachedPos = attachOffset;
1561 so.IsAttachment = true;
1562 so.RootPart.SetParentLocalId(avatar.LocalId);
1563 so.AttachmentPoint = attachmentpoint;
1564
1565 avatar.AddAttachment(this);
1566
1567 if (!silent)
1568 {
1569 // Killing it here will cause the client to deselect it
1570 // It then reappears on the avatar, deselected
1571 // through the full update below
1572 //
1573 if (IsSelected)
1574 {
1575 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1576 }
1577
1578 IsSelected = false; // fudge....
1579 ScheduleGroupForFullUpdate();
1580 }
1581 }
1582 else
1583 {
1584 m_log.WarnFormat(
1585 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1586 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1587 }
1588 }
1589
1590 public byte GetAttachmentPoint()
1591 {
1592 return m_rootPart.Shape.State;
1593 }
1594
1595 public void DetachToGround()
1596 {
1597 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1598 if (avatar == null)
1599 return;
1600
1601 avatar.RemoveAttachment(this);
1602
1603 Vector3 detachedpos = new Vector3(127f,127f,127f);
1604 if (avatar == null)
1605 return;
1606
1607 detachedpos = avatar.AbsolutePosition;
1608 FromItemID = UUID.Zero;
1609
1610 AbsolutePosition = detachedpos;
1611 AttachedAvatar = UUID.Zero;
1612
1613 //SceneObjectPart[] parts = m_parts.GetArray();
1614 //for (int i = 0; i < parts.Length; i++)
1615 // parts[i].AttachedAvatar = UUID.Zero;
1616
1617 m_rootPart.SetParentLocalId(0);
1618 AttachmentPoint = (byte)0;
1619 // must check if buildind should be true or false here
1620 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1621 HasGroupChanged = true;
1622 RootPart.Rezzed = DateTime.Now;
1623 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1624 AttachToBackup();
1625 m_scene.EventManager.TriggerParcelPrimCountTainted();
1626 m_rootPart.ScheduleFullUpdate();
1627 m_rootPart.ClearUndoState();
1628 }
1629
1630 public void DetachToInventoryPrep()
1631 {
1632 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1633 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1634 if (avatar != null)
1635 {
1636 //detachedpos = avatar.AbsolutePosition;
1637 avatar.RemoveAttachment(this);
1638 }
1639
1640 AttachedAvatar = UUID.Zero;
1641
1642 /*SceneObjectPart[] parts = m_parts.GetArray();
1643 for (int i = 0; i < parts.Length; i++)
1644 parts[i].AttachedAvatar = UUID.Zero;*/
1645
1646 m_rootPart.SetParentLocalId(0);
1647 //m_rootPart.SetAttachmentPoint((byte)0);
1648 IsAttachment = false;
1649 AbsolutePosition = m_rootPart.AttachedPos;
1650 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1651 //AttachToBackup();
1652 //m_rootPart.ScheduleFullUpdate();
1653 }
1654
1655 /// <summary>
1045 /// 1656 ///
1046 /// </summary> 1657 /// </summary>
1047 /// <param name="part"></param> 1658 /// <param name="part"></param>
@@ -1091,7 +1702,10 @@ namespace OpenSim.Region.Framework.Scenes
1091 public void AddPart(SceneObjectPart part) 1702 public void AddPart(SceneObjectPart part)
1092 { 1703 {
1093 part.SetParent(this); 1704 part.SetParent(this);
1094 part.LinkNum = m_parts.Add(part.UUID, part); 1705 m_parts.Add(part.UUID, part);
1706
1707 part.LinkNum = m_parts.Count;
1708
1095 if (part.LinkNum == 2) 1709 if (part.LinkNum == 2)
1096 RootPart.LinkNum = 1; 1710 RootPart.LinkNum = 1;
1097 } 1711 }
@@ -1179,7 +1793,7 @@ namespace OpenSim.Region.Framework.Scenes
1179// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 1793// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1180// remoteClient.Name, part.Name, part.LocalId, offsetPos); 1794// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1181 1795
1182 part.StoreUndoState(); 1796// part.StoreUndoState();
1183 part.OnGrab(offsetPos, remoteClient); 1797 part.OnGrab(offsetPos, remoteClient);
1184 } 1798 }
1185 1799
@@ -1199,6 +1813,11 @@ namespace OpenSim.Region.Framework.Scenes
1199 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1813 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1200 public void DeleteGroupFromScene(bool silent) 1814 public void DeleteGroupFromScene(bool silent)
1201 { 1815 {
1816 // We need to keep track of this state in case this group is still queued for backup.
1817 IsDeleted = true;
1818
1819 DetachFromBackup();
1820
1202 SceneObjectPart[] parts = m_parts.GetArray(); 1821 SceneObjectPart[] parts = m_parts.GetArray();
1203 for (int i = 0; i < parts.Length; i++) 1822 for (int i = 0; i < parts.Length; i++)
1204 { 1823 {
@@ -1222,6 +1841,7 @@ namespace OpenSim.Region.Framework.Scenes
1222 } 1841 }
1223 }); 1842 });
1224 } 1843 }
1844
1225 } 1845 }
1226 1846
1227 public void AddScriptLPS(int count) 1847 public void AddScriptLPS(int count)
@@ -1291,28 +1911,43 @@ namespace OpenSim.Region.Framework.Scenes
1291 /// </summary> 1911 /// </summary>
1292 public void ApplyPhysics() 1912 public void ApplyPhysics()
1293 { 1913 {
1294 // Apply physics to the root prim
1295 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1296
1297 // Apply physics to child prims
1298 SceneObjectPart[] parts = m_parts.GetArray(); 1914 SceneObjectPart[] parts = m_parts.GetArray();
1299 if (parts.Length > 1) 1915 if (parts.Length > 1)
1300 { 1916 {
1917 ResetChildPrimPhysicsPositions();
1918
1919 // Apply physics to the root prim
1920 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
1921
1922
1301 for (int i = 0; i < parts.Length; i++) 1923 for (int i = 0; i < parts.Length; i++)
1302 { 1924 {
1303 SceneObjectPart part = parts[i]; 1925 SceneObjectPart part = parts[i];
1304 if (part.LocalId != m_rootPart.LocalId) 1926 if (part.LocalId != m_rootPart.LocalId)
1305 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 1927 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1306 } 1928 }
1307
1308 // Hack to get the physics scene geometries in the right spot 1929 // Hack to get the physics scene geometries in the right spot
1309 ResetChildPrimPhysicsPositions(); 1930// ResetChildPrimPhysicsPositions();
1931 if (m_rootPart.PhysActor != null)
1932 {
1933 m_rootPart.PhysActor.Building = false;
1934 }
1935 }
1936 else
1937 {
1938 // Apply physics to the root prim
1939 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1310 } 1940 }
1311 } 1941 }
1312 1942
1313 public void SetOwnerId(UUID userId) 1943 public void SetOwnerId(UUID userId)
1314 { 1944 {
1315 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1945 ForEachPart(delegate(SceneObjectPart part)
1946 {
1947
1948 part.OwnerID = userId;
1949
1950 });
1316 } 1951 }
1317 1952
1318 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1953 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1344,11 +1979,17 @@ namespace OpenSim.Region.Framework.Scenes
1344 return; 1979 return;
1345 } 1980 }
1346 1981
1982 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1983 return;
1984
1347 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1985 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1348 // any exception propogate upwards. 1986 // any exception propogate upwards.
1349 try 1987 try
1350 { 1988 {
1351 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1989 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1990 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1991 m_scene.LoadingPrims) // Land may not be valid yet
1992
1352 { 1993 {
1353 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1994 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1354 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1995 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1375,6 +2016,7 @@ namespace OpenSim.Region.Framework.Scenes
1375 } 2016 }
1376 } 2017 }
1377 } 2018 }
2019
1378 } 2020 }
1379 2021
1380 if (m_scene.UseBackup && HasGroupChanged) 2022 if (m_scene.UseBackup && HasGroupChanged)
@@ -1382,10 +2024,30 @@ namespace OpenSim.Region.Framework.Scenes
1382 // don't backup while it's selected or you're asking for changes mid stream. 2024 // don't backup while it's selected or you're asking for changes mid stream.
1383 if (isTimeToPersist() || forcedBackup) 2025 if (isTimeToPersist() || forcedBackup)
1384 { 2026 {
2027 if (m_rootPart.PhysActor != null &&
2028 (!m_rootPart.PhysActor.IsPhysical))
2029 {
2030 // Possible ghost prim
2031 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
2032 {
2033 foreach (SceneObjectPart part in m_parts.GetArray())
2034 {
2035 // Re-set physics actor positions and
2036 // orientations
2037 part.GroupPosition = m_rootPart.GroupPosition;
2038 }
2039 }
2040 }
1385// m_log.DebugFormat( 2041// m_log.DebugFormat(
1386// "[SCENE]: Storing {0}, {1} in {2}", 2042// "[SCENE]: Storing {0}, {1} in {2}",
1387// Name, UUID, m_scene.RegionInfo.RegionName); 2043// Name, UUID, m_scene.RegionInfo.RegionName);
1388 2044
2045 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
2046 {
2047 RootPart.Shape.State = 0;
2048 ScheduleGroupForFullUpdate();
2049 }
2050
1389 SceneObjectGroup backup_group = Copy(false); 2051 SceneObjectGroup backup_group = Copy(false);
1390 backup_group.RootPart.Velocity = RootPart.Velocity; 2052 backup_group.RootPart.Velocity = RootPart.Velocity;
1391 backup_group.RootPart.Acceleration = RootPart.Acceleration; 2053 backup_group.RootPart.Acceleration = RootPart.Acceleration;
@@ -1399,6 +2061,11 @@ namespace OpenSim.Region.Framework.Scenes
1399 2061
1400 backup_group.ForEachPart(delegate(SceneObjectPart part) 2062 backup_group.ForEachPart(delegate(SceneObjectPart part)
1401 { 2063 {
2064 if (part.KeyframeMotion != null)
2065 {
2066 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize());
2067 part.KeyframeMotion.UpdateSceneObject(this);
2068 }
1402 part.Inventory.ProcessInventoryBackup(datastore); 2069 part.Inventory.ProcessInventoryBackup(datastore);
1403 }); 2070 });
1404 2071
@@ -1451,10 +2118,14 @@ namespace OpenSim.Region.Framework.Scenes
1451 /// <returns></returns> 2118 /// <returns></returns>
1452 public SceneObjectGroup Copy(bool userExposed) 2119 public SceneObjectGroup Copy(bool userExposed)
1453 { 2120 {
2121 m_dupeInProgress = true;
1454 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 2122 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1455 dupe.m_isBackedUp = false; 2123 dupe.m_isBackedUp = false;
1456 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 2124 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1457 2125
2126 // new group as no sitting avatars
2127 dupe.m_linkedAvatars = new List<ScenePresence>();
2128
1458 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 2129 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1459 // attachments do not bordercross while they're being duplicated. This is hacktastic! 2130 // attachments do not bordercross while they're being duplicated. This is hacktastic!
1460 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! 2131 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
@@ -1465,7 +2136,7 @@ namespace OpenSim.Region.Framework.Scenes
1465 // This is only necessary when userExposed is false! 2136 // This is only necessary when userExposed is false!
1466 2137
1467 bool previousAttachmentStatus = dupe.IsAttachment; 2138 bool previousAttachmentStatus = dupe.IsAttachment;
1468 2139
1469 if (!userExposed) 2140 if (!userExposed)
1470 dupe.IsAttachment = true; 2141 dupe.IsAttachment = true;
1471 2142
@@ -1483,11 +2154,11 @@ namespace OpenSim.Region.Framework.Scenes
1483 dupe.m_rootPart.TrimPermissions(); 2154 dupe.m_rootPart.TrimPermissions();
1484 2155
1485 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 2156 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1486 2157
1487 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 2158 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1488 { 2159 {
1489 return p1.LinkNum.CompareTo(p2.LinkNum); 2160 return p1.LinkNum.CompareTo(p2.LinkNum);
1490 } 2161 }
1491 ); 2162 );
1492 2163
1493 foreach (SceneObjectPart part in partList) 2164 foreach (SceneObjectPart part in partList)
@@ -1497,41 +2168,53 @@ namespace OpenSim.Region.Framework.Scenes
1497 { 2168 {
1498 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2169 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1499 newPart.LinkNum = part.LinkNum; 2170 newPart.LinkNum = part.LinkNum;
1500 } 2171 if (userExposed)
2172 newPart.ParentID = dupe.m_rootPart.LocalId;
2173 }
1501 else 2174 else
1502 { 2175 {
1503 newPart = dupe.m_rootPart; 2176 newPart = dupe.m_rootPart;
1504 } 2177 }
2178/*
2179 bool isphys = ((newPart.Flags & PrimFlags.Physics) != 0);
2180 bool isphan = ((newPart.Flags & PrimFlags.Phantom) != 0);
1505 2181
1506 // Need to duplicate the physics actor as well 2182 // Need to duplicate the physics actor as well
1507 PhysicsActor originalPartPa = part.PhysActor; 2183 if (userExposed && (isphys || !isphan || newPart.VolumeDetectActive))
1508 if (originalPartPa != null && userExposed)
1509 { 2184 {
1510 PrimitiveBaseShape pbs = newPart.Shape; 2185 PrimitiveBaseShape pbs = newPart.Shape;
1511
1512 newPart.PhysActor 2186 newPart.PhysActor
1513 = m_scene.PhysicsScene.AddPrimShape( 2187 = m_scene.PhysicsScene.AddPrimShape(
1514 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 2188 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1515 pbs, 2189 pbs,
1516 newPart.AbsolutePosition, 2190 newPart.AbsolutePosition,
1517 newPart.Scale, 2191 newPart.Scale,
1518 newPart.RotationOffset, 2192 newPart.GetWorldRotation(),
1519 originalPartPa.IsPhysical, 2193 isphys,
2194 isphan,
1520 newPart.LocalId); 2195 newPart.LocalId);
1521 2196
1522 newPart.DoPhysicsPropertyUpdate(originalPartPa.IsPhysical, true); 2197 newPart.DoPhysicsPropertyUpdate(isphys, true);
1523 } 2198 */
2199 if (userExposed)
2200 newPart.ApplyPhysics((uint)newPart.Flags,newPart.VolumeDetectActive,true);
2201// }
1524 } 2202 }
1525 2203
1526 if (userExposed) 2204 if (userExposed)
1527 { 2205 {
1528 dupe.UpdateParentIDs(); 2206// done above dupe.UpdateParentIDs();
2207
2208 if (dupe.m_rootPart.PhysActor != null)
2209 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
2210
1529 dupe.HasGroupChanged = true; 2211 dupe.HasGroupChanged = true;
1530 dupe.AttachToBackup(); 2212 dupe.AttachToBackup();
1531 2213
1532 ScheduleGroupForFullUpdate(); 2214 ScheduleGroupForFullUpdate();
1533 } 2215 }
1534 2216
2217 m_dupeInProgress = false;
1535 return dupe; 2218 return dupe;
1536 } 2219 }
1537 2220
@@ -1543,11 +2226,24 @@ namespace OpenSim.Region.Framework.Scenes
1543 /// <param name="cGroupID"></param> 2226 /// <param name="cGroupID"></param>
1544 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2227 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1545 { 2228 {
1546 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2229 // SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed));
2230 // give newpart a new local ID lettng old part keep same
2231 SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2232 newpart.LocalId = m_scene.AllocateLocalId();
2233
2234 SetRootPart(newpart);
2235 if (userExposed)
2236 RootPart.Velocity = Vector3.Zero; // In case source is moving
1547 } 2237 }
1548 2238
1549 public void ScriptSetPhysicsStatus(bool usePhysics) 2239 public void ScriptSetPhysicsStatus(bool usePhysics)
1550 { 2240 {
2241 if (usePhysics)
2242 {
2243 if (RootPart.KeyframeMotion != null)
2244 RootPart.KeyframeMotion.Stop();
2245 RootPart.KeyframeMotion = null;
2246 }
1551 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2247 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1552 } 2248 }
1553 2249
@@ -1595,13 +2291,14 @@ namespace OpenSim.Region.Framework.Scenes
1595 2291
1596 if (pa != null) 2292 if (pa != null)
1597 { 2293 {
1598 pa.AddForce(impulse, true); 2294 // false to be applied as a impulse
2295 pa.AddForce(impulse, false);
1599 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2296 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1600 } 2297 }
1601 } 2298 }
1602 } 2299 }
1603 2300
1604 public void applyAngularImpulse(Vector3 impulse) 2301 public void ApplyAngularImpulse(Vector3 impulse)
1605 { 2302 {
1606 PhysicsActor pa = RootPart.PhysActor; 2303 PhysicsActor pa = RootPart.PhysActor;
1607 2304
@@ -1609,21 +2306,8 @@ namespace OpenSim.Region.Framework.Scenes
1609 { 2306 {
1610 if (!IsAttachment) 2307 if (!IsAttachment)
1611 { 2308 {
1612 pa.AddAngularForce(impulse, true); 2309 // false to be applied as a impulse
1613 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2310 pa.AddAngularForce(impulse, false);
1614 }
1615 }
1616 }
1617
1618 public void setAngularImpulse(Vector3 impulse)
1619 {
1620 PhysicsActor pa = RootPart.PhysActor;
1621
1622 if (pa != null)
1623 {
1624 if (!IsAttachment)
1625 {
1626 pa.Torque = impulse;
1627 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2311 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1628 } 2312 }
1629 } 2313 }
@@ -1631,20 +2315,10 @@ namespace OpenSim.Region.Framework.Scenes
1631 2315
1632 public Vector3 GetTorque() 2316 public Vector3 GetTorque()
1633 { 2317 {
1634 PhysicsActor pa = RootPart.PhysActor; 2318 return RootPart.Torque;
1635
1636 if (pa != null)
1637 {
1638 if (!IsAttachment)
1639 {
1640 Vector3 torque = pa.Torque;
1641 return torque;
1642 }
1643 }
1644
1645 return Vector3.Zero;
1646 } 2319 }
1647 2320
2321 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1648 public void moveToTarget(Vector3 target, float tau) 2322 public void moveToTarget(Vector3 target, float tau)
1649 { 2323 {
1650 if (IsAttachment) 2324 if (IsAttachment)
@@ -1676,6 +2350,46 @@ namespace OpenSim.Region.Framework.Scenes
1676 pa.PIDActive = false; 2350 pa.PIDActive = false;
1677 } 2351 }
1678 2352
2353 public void rotLookAt(Quaternion target, float strength, float damping)
2354 {
2355 SceneObjectPart rootpart = m_rootPart;
2356 if (rootpart != null)
2357 {
2358 if (IsAttachment)
2359 {
2360 /*
2361 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2362 if (avatar != null)
2363 {
2364 Rotate the Av?
2365 } */
2366 }
2367 else
2368 {
2369 if (rootpart.PhysActor != null)
2370 { // APID must be implemented in your physics system for this to function.
2371 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2372 rootpart.PhysActor.APIDStrength = strength;
2373 rootpart.PhysActor.APIDDamping = damping;
2374 rootpart.PhysActor.APIDActive = true;
2375 }
2376 }
2377 }
2378 }
2379
2380 public void stopLookAt()
2381 {
2382 SceneObjectPart rootpart = m_rootPart;
2383 if (rootpart != null)
2384 {
2385 if (rootpart.PhysActor != null)
2386 { // APID must be implemented in your physics system for this to function.
2387 rootpart.PhysActor.APIDActive = false;
2388 }
2389 }
2390
2391 }
2392
1679 /// <summary> 2393 /// <summary>
1680 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2394 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1681 /// </summary> 2395 /// </summary>
@@ -1692,7 +2406,7 @@ namespace OpenSim.Region.Framework.Scenes
1692 { 2406 {
1693 pa.PIDHoverHeight = height; 2407 pa.PIDHoverHeight = height;
1694 pa.PIDHoverType = hoverType; 2408 pa.PIDHoverType = hoverType;
1695 pa.PIDTau = tau; 2409 pa.PIDHoverTau = tau;
1696 pa.PIDHoverActive = true; 2410 pa.PIDHoverActive = true;
1697 } 2411 }
1698 else 2412 else
@@ -1732,7 +2446,12 @@ namespace OpenSim.Region.Framework.Scenes
1732 /// <param name="cGroupID"></param> 2446 /// <param name="cGroupID"></param>
1733 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2447 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1734 { 2448 {
1735 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2449 // give new ID to the new part, letting old keep original
2450 // SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2451 SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2452 newPart.LocalId = m_scene.AllocateLocalId();
2453 newPart.SetParent(this);
2454
1736 AddPart(newPart); 2455 AddPart(newPart);
1737 2456
1738 SetPartAsNonRoot(newPart); 2457 SetPartAsNonRoot(newPart);
@@ -1871,11 +2590,11 @@ namespace OpenSim.Region.Framework.Scenes
1871 /// Immediately send a full update for this scene object. 2590 /// Immediately send a full update for this scene object.
1872 /// </summary> 2591 /// </summary>
1873 public void SendGroupFullUpdate() 2592 public void SendGroupFullUpdate()
1874 { 2593 {
1875 if (IsDeleted) 2594 if (IsDeleted)
1876 return; 2595 return;
1877 2596
1878// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2597// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1879 2598
1880 RootPart.SendFullUpdateToAllClients(); 2599 RootPart.SendFullUpdateToAllClients();
1881 2600
@@ -2009,6 +2728,11 @@ namespace OpenSim.Region.Framework.Scenes
2009 2728
2010 SceneObjectPart linkPart = objectGroup.m_rootPart; 2729 SceneObjectPart linkPart = objectGroup.m_rootPart;
2011 2730
2731 if (m_rootPart.PhysActor != null)
2732 m_rootPart.PhysActor.Building = true;
2733 if (linkPart.PhysActor != null)
2734 linkPart.PhysActor.Building = true;
2735
2012 // physics flags from group to be applied to linked parts 2736 // physics flags from group to be applied to linked parts
2013 bool grpusephys = UsesPhysics; 2737 bool grpusephys = UsesPhysics;
2014 bool grptemporary = IsTemporary; 2738 bool grptemporary = IsTemporary;
@@ -2017,19 +2741,21 @@ namespace OpenSim.Region.Framework.Scenes
2017 Quaternion oldRootRotation = linkPart.RotationOffset; 2741 Quaternion oldRootRotation = linkPart.RotationOffset;
2018 2742
2019 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; 2743 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition;
2744
2020 linkPart.ParentID = m_rootPart.LocalId; 2745 linkPart.ParentID = m_rootPart.LocalId;
2021 linkPart.GroupPosition = AbsolutePosition; 2746
2022 Vector3 axPos = linkPart.OffsetPosition; 2747 linkPart.GroupPosition = AbsolutePosition;
2023 2748
2749 Vector3 axPos = linkPart.OffsetPosition;
2024 Quaternion parentRot = m_rootPart.RotationOffset; 2750 Quaternion parentRot = m_rootPart.RotationOffset;
2025 axPos *= Quaternion.Inverse(parentRot); 2751 axPos *= Quaternion.Conjugate(parentRot);
2026
2027 linkPart.OffsetPosition = axPos; 2752 linkPart.OffsetPosition = axPos;
2753
2028 Quaternion oldRot = linkPart.RotationOffset; 2754 Quaternion oldRot = linkPart.RotationOffset;
2029 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2755 Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot;
2030 linkPart.RotationOffset = newRot; 2756 linkPart.RotationOffset = newRot;
2031 2757
2032 linkPart.ParentID = m_rootPart.LocalId; 2758// linkPart.ParentID = m_rootPart.LocalId; done above
2033 2759
2034 if (m_rootPart.LinkNum == 0) 2760 if (m_rootPart.LinkNum == 0)
2035 m_rootPart.LinkNum = 1; 2761 m_rootPart.LinkNum = 1;
@@ -2057,7 +2783,7 @@ namespace OpenSim.Region.Framework.Scenes
2057 linkPart.CreateSelected = true; 2783 linkPart.CreateSelected = true;
2058 2784
2059 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now 2785 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
2060 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive); 2786 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true);
2061 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 2787 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2062 { 2788 {
2063 linkPart.PhysActor.link(m_rootPart.PhysActor); 2789 linkPart.PhysActor.link(m_rootPart.PhysActor);
@@ -2065,6 +2791,7 @@ namespace OpenSim.Region.Framework.Scenes
2065 } 2791 }
2066 2792
2067 linkPart.LinkNum = linkNum++; 2793 linkPart.LinkNum = linkNum++;
2794 linkPart.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2068 2795
2069 SceneObjectPart[] ogParts = objectGroup.Parts; 2796 SceneObjectPart[] ogParts = objectGroup.Parts;
2070 Array.Sort(ogParts, delegate(SceneObjectPart a, SceneObjectPart b) 2797 Array.Sort(ogParts, delegate(SceneObjectPart a, SceneObjectPart b)
@@ -2079,7 +2806,7 @@ namespace OpenSim.Region.Framework.Scenes
2079 { 2806 {
2080 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); 2807 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2081 // let physics know 2808 // let physics know
2082 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive); 2809 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true);
2083 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 2810 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2084 { 2811 {
2085 part.PhysActor.link(m_rootPart.PhysActor); 2812 part.PhysActor.link(m_rootPart.PhysActor);
@@ -2094,7 +2821,7 @@ namespace OpenSim.Region.Framework.Scenes
2094 objectGroup.IsDeleted = true; 2821 objectGroup.IsDeleted = true;
2095 2822
2096 objectGroup.m_parts.Clear(); 2823 objectGroup.m_parts.Clear();
2097 2824
2098 // Can't do this yet since backup still makes use of the root part without any synchronization 2825 // Can't do this yet since backup still makes use of the root part without any synchronization
2099// objectGroup.m_rootPart = null; 2826// objectGroup.m_rootPart = null;
2100 2827
@@ -2105,6 +2832,9 @@ namespace OpenSim.Region.Framework.Scenes
2105 // unmoved prims! 2832 // unmoved prims!
2106 ResetChildPrimPhysicsPositions(); 2833 ResetChildPrimPhysicsPositions();
2107 2834
2835 if (m_rootPart.PhysActor != null)
2836 m_rootPart.PhysActor.Building = false;
2837
2108 //HasGroupChanged = true; 2838 //HasGroupChanged = true;
2109 //ScheduleGroupForFullUpdate(); 2839 //ScheduleGroupForFullUpdate();
2110 } 2840 }
@@ -2172,7 +2902,10 @@ namespace OpenSim.Region.Framework.Scenes
2172// m_log.DebugFormat( 2902// m_log.DebugFormat(
2173// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", 2903// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2174// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); 2904// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2175 2905
2906 if (m_rootPart.PhysActor != null)
2907 m_rootPart.PhysActor.Building = true;
2908
2176 linkPart.ClearUndoState(); 2909 linkPart.ClearUndoState();
2177 2910
2178 Quaternion worldRot = linkPart.GetWorldRotation(); 2911 Quaternion worldRot = linkPart.GetWorldRotation();
@@ -2232,6 +2965,14 @@ namespace OpenSim.Region.Framework.Scenes
2232 2965
2233 // When we delete a group, we currently have to force persist to the database if the object id has changed 2966 // When we delete a group, we currently have to force persist to the database if the object id has changed
2234 // (since delete works by deleting all rows which have a given object id) 2967 // (since delete works by deleting all rows which have a given object id)
2968
2969 // this is as it seems to be in sl now
2970 if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none)
2971 linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now
2972
2973 if (m_rootPart.PhysActor != null)
2974 m_rootPart.PhysActor.Building = false;
2975
2235 objectGroup.HasGroupChangedDueToDelink = true; 2976 objectGroup.HasGroupChangedDueToDelink = true;
2236 2977
2237 return objectGroup; 2978 return objectGroup;
@@ -2243,6 +2984,7 @@ namespace OpenSim.Region.Framework.Scenes
2243 /// <param name="objectGroup"></param> 2984 /// <param name="objectGroup"></param>
2244 public virtual void DetachFromBackup() 2985 public virtual void DetachFromBackup()
2245 { 2986 {
2987 m_scene.SceneGraph.FireDetachFromBackup(this);
2246 if (m_isBackedUp && Scene != null) 2988 if (m_isBackedUp && Scene != null)
2247 m_scene.EventManager.OnBackup -= ProcessBackup; 2989 m_scene.EventManager.OnBackup -= ProcessBackup;
2248 2990
@@ -2261,7 +3003,8 @@ namespace OpenSim.Region.Framework.Scenes
2261 3003
2262 axPos *= parentRot; 3004 axPos *= parentRot;
2263 part.OffsetPosition = axPos; 3005 part.OffsetPosition = axPos;
2264 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 3006 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
3007 part.GroupPosition = newPos;
2265 part.OffsetPosition = Vector3.Zero; 3008 part.OffsetPosition = Vector3.Zero;
2266 part.RotationOffset = worldRot; 3009 part.RotationOffset = worldRot;
2267 3010
@@ -2272,20 +3015,20 @@ namespace OpenSim.Region.Framework.Scenes
2272 3015
2273 part.LinkNum = linkNum; 3016 part.LinkNum = linkNum;
2274 3017
2275 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 3018 part.OffsetPosition = newPos - AbsolutePosition;
2276 3019
2277 Quaternion rootRotation = m_rootPart.RotationOffset; 3020 Quaternion rootRotation = m_rootPart.RotationOffset;
2278 3021
2279 Vector3 pos = part.OffsetPosition; 3022 Vector3 pos = part.OffsetPosition;
2280 pos *= Quaternion.Inverse(rootRotation); 3023 pos *= Quaternion.Conjugate(rootRotation);
2281 part.OffsetPosition = pos; 3024 part.OffsetPosition = pos;
2282 3025
2283 parentRot = m_rootPart.RotationOffset; 3026 parentRot = m_rootPart.RotationOffset;
2284 oldRot = part.RotationOffset; 3027 oldRot = part.RotationOffset;
2285 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 3028 Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot;
2286 part.RotationOffset = newRot; 3029 part.RotationOffset = newRot;
2287 3030
2288 part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3031 part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2289 } 3032 }
2290 3033
2291 /// <summary> 3034 /// <summary>
@@ -2307,10 +3050,14 @@ namespace OpenSim.Region.Framework.Scenes
2307 { 3050 {
2308 if (!m_rootPart.BlockGrab) 3051 if (!m_rootPart.BlockGrab)
2309 { 3052 {
2310 Vector3 llmoveforce = pos - AbsolutePosition; 3053/* Vector3 llmoveforce = pos - AbsolutePosition;
2311 Vector3 grabforce = llmoveforce; 3054 Vector3 grabforce = llmoveforce;
2312 grabforce = (grabforce / 10) * pa.Mass; 3055 grabforce = (grabforce / 10) * pa.Mass;
2313 pa.AddForce(grabforce, true); 3056 */
3057 // empirically convert distance diference to a impulse
3058 Vector3 grabforce = pos - AbsolutePosition;
3059 grabforce = grabforce * (pa.Mass/ 10.0f);
3060 pa.AddForce(grabforce, false);
2314 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 3061 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
2315 } 3062 }
2316 } 3063 }
@@ -2536,8 +3283,22 @@ namespace OpenSim.Region.Framework.Scenes
2536 } 3283 }
2537 } 3284 }
2538 3285
2539 for (int i = 0; i < parts.Length; i++) 3286 if (parts.Length > 1)
2540 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 3287 {
3288 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3289
3290 for (int i = 0; i < parts.Length; i++)
3291 {
3292
3293 if (parts[i].UUID != m_rootPart.UUID)
3294 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3295 }
3296
3297 if (m_rootPart.PhysActor != null)
3298 m_rootPart.PhysActor.Building = false;
3299 }
3300 else
3301 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
2541 } 3302 }
2542 } 3303 }
2543 3304
@@ -2550,6 +3311,17 @@ namespace OpenSim.Region.Framework.Scenes
2550 } 3311 }
2551 } 3312 }
2552 3313
3314
3315
3316 /// <summary>
3317 /// Gets the number of parts
3318 /// </summary>
3319 /// <returns></returns>
3320 public int GetPartCount()
3321 {
3322 return Parts.Count();
3323 }
3324
2553 /// <summary> 3325 /// <summary>
2554 /// Update the texture entry for this part 3326 /// Update the texture entry for this part
2555 /// </summary> 3327 /// </summary>
@@ -2611,11 +3383,6 @@ namespace OpenSim.Region.Framework.Scenes
2611 /// <param name="scale"></param> 3383 /// <param name="scale"></param>
2612 public void GroupResize(Vector3 scale) 3384 public void GroupResize(Vector3 scale)
2613 { 3385 {
2614// m_log.DebugFormat(
2615// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2616
2617 RootPart.StoreUndoState(true);
2618
2619 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3386 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
2620 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); 3387 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
2621 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); 3388 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
@@ -2642,7 +3409,6 @@ namespace OpenSim.Region.Framework.Scenes
2642 SceneObjectPart obPart = parts[i]; 3409 SceneObjectPart obPart = parts[i];
2643 if (obPart.UUID != m_rootPart.UUID) 3410 if (obPart.UUID != m_rootPart.UUID)
2644 { 3411 {
2645// obPart.IgnoreUndoUpdate = true;
2646 Vector3 oldSize = new Vector3(obPart.Scale); 3412 Vector3 oldSize = new Vector3(obPart.Scale);
2647 3413
2648 float f = 1.0f; 3414 float f = 1.0f;
@@ -2706,8 +3472,6 @@ namespace OpenSim.Region.Framework.Scenes
2706 z *= a; 3472 z *= a;
2707 } 3473 }
2708 } 3474 }
2709
2710// obPart.IgnoreUndoUpdate = false;
2711 } 3475 }
2712 } 3476 }
2713 } 3477 }
@@ -2717,9 +3481,7 @@ namespace OpenSim.Region.Framework.Scenes
2717 prevScale.Y *= y; 3481 prevScale.Y *= y;
2718 prevScale.Z *= z; 3482 prevScale.Z *= z;
2719 3483
2720// RootPart.IgnoreUndoUpdate = true;
2721 RootPart.Resize(prevScale); 3484 RootPart.Resize(prevScale);
2722// RootPart.IgnoreUndoUpdate = false;
2723 3485
2724 parts = m_parts.GetArray(); 3486 parts = m_parts.GetArray();
2725 for (int i = 0; i < parts.Length; i++) 3487 for (int i = 0; i < parts.Length; i++)
@@ -2728,8 +3490,6 @@ namespace OpenSim.Region.Framework.Scenes
2728 3490
2729 if (obPart.UUID != m_rootPart.UUID) 3491 if (obPart.UUID != m_rootPart.UUID)
2730 { 3492 {
2731 obPart.IgnoreUndoUpdate = true;
2732
2733 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3493 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2734 currentpos.X *= x; 3494 currentpos.X *= x;
2735 currentpos.Y *= y; 3495 currentpos.Y *= y;
@@ -2742,16 +3502,12 @@ namespace OpenSim.Region.Framework.Scenes
2742 3502
2743 obPart.Resize(newSize); 3503 obPart.Resize(newSize);
2744 obPart.UpdateOffSet(currentpos); 3504 obPart.UpdateOffSet(currentpos);
2745
2746 obPart.IgnoreUndoUpdate = false;
2747 } 3505 }
2748 3506
2749// obPart.IgnoreUndoUpdate = false; 3507 HasGroupChanged = true;
2750// obPart.StoreUndoState(); 3508 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3509 ScheduleGroupForTerseUpdate();
2751 } 3510 }
2752
2753// m_log.DebugFormat(
2754// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale);
2755 } 3511 }
2756 3512
2757 #endregion 3513 #endregion
@@ -2764,14 +3520,6 @@ namespace OpenSim.Region.Framework.Scenes
2764 /// <param name="pos"></param> 3520 /// <param name="pos"></param>
2765 public void UpdateGroupPosition(Vector3 pos) 3521 public void UpdateGroupPosition(Vector3 pos)
2766 { 3522 {
2767// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
2768
2769 RootPart.StoreUndoState(true);
2770
2771// SceneObjectPart[] parts = m_parts.GetArray();
2772// for (int i = 0; i < parts.Length; i++)
2773// parts[i].StoreUndoState();
2774
2775 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3523 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2776 { 3524 {
2777 if (IsAttachment) 3525 if (IsAttachment)
@@ -2804,21 +3552,17 @@ namespace OpenSim.Region.Framework.Scenes
2804 /// </summary> 3552 /// </summary>
2805 /// <param name="pos"></param> 3553 /// <param name="pos"></param>
2806 /// <param name="localID"></param> 3554 /// <param name="localID"></param>
3555 ///
3556
2807 public void UpdateSinglePosition(Vector3 pos, uint localID) 3557 public void UpdateSinglePosition(Vector3 pos, uint localID)
2808 { 3558 {
2809 SceneObjectPart part = GetPart(localID); 3559 SceneObjectPart part = GetPart(localID);
2810 3560
2811// SceneObjectPart[] parts = m_parts.GetArray();
2812// for (int i = 0; i < parts.Length; i++)
2813// parts[i].StoreUndoState();
2814
2815 if (part != null) 3561 if (part != null)
2816 { 3562 {
2817// m_log.DebugFormat( 3563// unlock parts position change
2818// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); 3564 if (m_rootPart.PhysActor != null)
2819 3565 m_rootPart.PhysActor.Building = true;
2820 part.StoreUndoState(false);
2821 part.IgnoreUndoUpdate = true;
2822 3566
2823 if (part.UUID == m_rootPart.UUID) 3567 if (part.UUID == m_rootPart.UUID)
2824 { 3568 {
@@ -2829,8 +3573,10 @@ namespace OpenSim.Region.Framework.Scenes
2829 part.UpdateOffSet(pos); 3573 part.UpdateOffSet(pos);
2830 } 3574 }
2831 3575
3576 if (m_rootPart.PhysActor != null)
3577 m_rootPart.PhysActor.Building = false;
3578
2832 HasGroupChanged = true; 3579 HasGroupChanged = true;
2833 part.IgnoreUndoUpdate = false;
2834 } 3580 }
2835 } 3581 }
2836 3582
@@ -2840,13 +3586,7 @@ namespace OpenSim.Region.Framework.Scenes
2840 /// <param name="pos"></param> 3586 /// <param name="pos"></param>
2841 public void UpdateRootPosition(Vector3 pos) 3587 public void UpdateRootPosition(Vector3 pos)
2842 { 3588 {
2843// m_log.DebugFormat( 3589 // needs to be called with phys building true
2844// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
2845
2846// SceneObjectPart[] parts = m_parts.GetArray();
2847// for (int i = 0; i < parts.Length; i++)
2848// parts[i].StoreUndoState();
2849
2850 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3590 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2851 Vector3 oldPos = 3591 Vector3 oldPos =
2852 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3592 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
@@ -2869,7 +3609,14 @@ namespace OpenSim.Region.Framework.Scenes
2869 AbsolutePosition = newPos; 3609 AbsolutePosition = newPos;
2870 3610
2871 HasGroupChanged = true; 3611 HasGroupChanged = true;
2872 ScheduleGroupForTerseUpdate(); 3612 if (m_rootPart.Undoing)
3613 {
3614 ScheduleGroupForFullUpdate();
3615 }
3616 else
3617 {
3618 ScheduleGroupForTerseUpdate();
3619 }
2873 } 3620 }
2874 3621
2875 #endregion 3622 #endregion
@@ -2882,24 +3629,16 @@ namespace OpenSim.Region.Framework.Scenes
2882 /// <param name="rot"></param> 3629 /// <param name="rot"></param>
2883 public void UpdateGroupRotationR(Quaternion rot) 3630 public void UpdateGroupRotationR(Quaternion rot)
2884 { 3631 {
2885// m_log.DebugFormat(
2886// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
2887
2888// SceneObjectPart[] parts = m_parts.GetArray();
2889// for (int i = 0; i < parts.Length; i++)
2890// parts[i].StoreUndoState();
2891
2892 m_rootPart.StoreUndoState(true);
2893
2894 m_rootPart.UpdateRotation(rot); 3632 m_rootPart.UpdateRotation(rot);
2895 3633
3634/* this is done by rootpart RotationOffset set called by UpdateRotation
2896 PhysicsActor actor = m_rootPart.PhysActor; 3635 PhysicsActor actor = m_rootPart.PhysActor;
2897 if (actor != null) 3636 if (actor != null)
2898 { 3637 {
2899 actor.Orientation = m_rootPart.RotationOffset; 3638 actor.Orientation = m_rootPart.RotationOffset;
2900 m_scene.PhysicsScene.AddPhysicsActorTaint(actor); 3639 m_scene.PhysicsScene.AddPhysicsActorTaint(actor);
2901 } 3640 }
2902 3641*/
2903 HasGroupChanged = true; 3642 HasGroupChanged = true;
2904 ScheduleGroupForTerseUpdate(); 3643 ScheduleGroupForTerseUpdate();
2905 } 3644 }
@@ -2911,16 +3650,6 @@ namespace OpenSim.Region.Framework.Scenes
2911 /// <param name="rot"></param> 3650 /// <param name="rot"></param>
2912 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 3651 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
2913 { 3652 {
2914// m_log.DebugFormat(
2915// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
2916
2917// SceneObjectPart[] parts = m_parts.GetArray();
2918// for (int i = 0; i < parts.Length; i++)
2919// parts[i].StoreUndoState();
2920
2921 RootPart.StoreUndoState(true);
2922 RootPart.IgnoreUndoUpdate = true;
2923
2924 m_rootPart.UpdateRotation(rot); 3653 m_rootPart.UpdateRotation(rot);
2925 3654
2926 PhysicsActor actor = m_rootPart.PhysActor; 3655 PhysicsActor actor = m_rootPart.PhysActor;
@@ -2939,8 +3668,6 @@ namespace OpenSim.Region.Framework.Scenes
2939 3668
2940 HasGroupChanged = true; 3669 HasGroupChanged = true;
2941 ScheduleGroupForTerseUpdate(); 3670 ScheduleGroupForTerseUpdate();
2942
2943 RootPart.IgnoreUndoUpdate = false;
2944 } 3671 }
2945 3672
2946 /// <summary> 3673 /// <summary>
@@ -2953,13 +3680,11 @@ namespace OpenSim.Region.Framework.Scenes
2953 SceneObjectPart part = GetPart(localID); 3680 SceneObjectPart part = GetPart(localID);
2954 3681
2955 SceneObjectPart[] parts = m_parts.GetArray(); 3682 SceneObjectPart[] parts = m_parts.GetArray();
2956 for (int i = 0; i < parts.Length; i++)
2957 parts[i].StoreUndoState();
2958 3683
2959 if (part != null) 3684 if (part != null)
2960 { 3685 {
2961// m_log.DebugFormat( 3686 if (m_rootPart.PhysActor != null)
2962// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); 3687 m_rootPart.PhysActor.Building = true;
2963 3688
2964 if (part.UUID == m_rootPart.UUID) 3689 if (part.UUID == m_rootPart.UUID)
2965 { 3690 {
@@ -2969,6 +3694,9 @@ namespace OpenSim.Region.Framework.Scenes
2969 { 3694 {
2970 part.UpdateRotation(rot); 3695 part.UpdateRotation(rot);
2971 } 3696 }
3697
3698 if (m_rootPart.PhysActor != null)
3699 m_rootPart.PhysActor.Building = false;
2972 } 3700 }
2973 } 3701 }
2974 3702
@@ -2982,12 +3710,8 @@ namespace OpenSim.Region.Framework.Scenes
2982 SceneObjectPart part = GetPart(localID); 3710 SceneObjectPart part = GetPart(localID);
2983 if (part != null) 3711 if (part != null)
2984 { 3712 {
2985// m_log.DebugFormat( 3713 if (m_rootPart.PhysActor != null)
2986// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", 3714 m_rootPart.PhysActor.Building = true;
2987// part.Name, part.LocalId, rot);
2988
2989 part.StoreUndoState();
2990 part.IgnoreUndoUpdate = true;
2991 3715
2992 if (part.UUID == m_rootPart.UUID) 3716 if (part.UUID == m_rootPart.UUID)
2993 { 3717 {
@@ -3000,7 +3724,8 @@ namespace OpenSim.Region.Framework.Scenes
3000 part.OffsetPosition = pos; 3724 part.OffsetPosition = pos;
3001 } 3725 }
3002 3726
3003 part.IgnoreUndoUpdate = false; 3727 if (m_rootPart.PhysActor != null)
3728 m_rootPart.PhysActor.Building = false;
3004 } 3729 }
3005 } 3730 }
3006 3731
@@ -3010,15 +3735,12 @@ namespace OpenSim.Region.Framework.Scenes
3010 /// <param name="rot"></param> 3735 /// <param name="rot"></param>
3011 public void UpdateRootRotation(Quaternion rot) 3736 public void UpdateRootRotation(Quaternion rot)
3012 { 3737 {
3013// m_log.DebugFormat( 3738 // needs to be called with phys building true
3014// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
3015// Name, LocalId, rot);
3016
3017 Quaternion axRot = rot; 3739 Quaternion axRot = rot;
3018 Quaternion oldParentRot = m_rootPart.RotationOffset; 3740 Quaternion oldParentRot = m_rootPart.RotationOffset;
3019 3741
3020 m_rootPart.StoreUndoState(); 3742 //Don't use UpdateRotation because it schedules an update prematurely
3021 m_rootPart.UpdateRotation(rot); 3743 m_rootPart.RotationOffset = rot;
3022 3744
3023 PhysicsActor pa = m_rootPart.PhysActor; 3745 PhysicsActor pa = m_rootPart.PhysActor;
3024 3746
@@ -3034,35 +3756,145 @@ namespace OpenSim.Region.Framework.Scenes
3034 SceneObjectPart prim = parts[i]; 3756 SceneObjectPart prim = parts[i];
3035 if (prim.UUID != m_rootPart.UUID) 3757 if (prim.UUID != m_rootPart.UUID)
3036 { 3758 {
3037 prim.IgnoreUndoUpdate = true; 3759 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3760 NewRot = Quaternion.Inverse(axRot) * NewRot;
3761 prim.RotationOffset = NewRot;
3762
3038 Vector3 axPos = prim.OffsetPosition; 3763 Vector3 axPos = prim.OffsetPosition;
3764
3039 axPos *= oldParentRot; 3765 axPos *= oldParentRot;
3040 axPos *= Quaternion.Inverse(axRot); 3766 axPos *= Quaternion.Inverse(axRot);
3041 prim.OffsetPosition = axPos; 3767 prim.OffsetPosition = axPos;
3042 Quaternion primsRot = prim.RotationOffset; 3768 }
3043 Quaternion newRot = oldParentRot * primsRot; 3769 }
3044 newRot = Quaternion.Inverse(axRot) * newRot; 3770
3045 prim.RotationOffset = newRot; 3771 HasGroupChanged = true;
3046 prim.ScheduleTerseUpdate(); 3772 ScheduleGroupForFullUpdate();
3047 prim.IgnoreUndoUpdate = false; 3773 }
3048 }
3049 }
3050
3051// for (int i = 0; i < parts.Length; i++)
3052// {
3053// SceneObjectPart childpart = parts[i];
3054// if (childpart != m_rootPart)
3055// {
3056//// childpart.IgnoreUndoUpdate = false;
3057//// childpart.StoreUndoState();
3058// }
3059// }
3060 3774
3061 m_rootPart.ScheduleTerseUpdate(); 3775 private enum updatetype :int
3776 {
3777 none = 0,
3778 partterse = 1,
3779 partfull = 2,
3780 groupterse = 3,
3781 groupfull = 4
3782 }
3062 3783
3063// m_log.DebugFormat( 3784 public void doChangeObject(SceneObjectPart part, ObjectChangeData data)
3064// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3785 {
3065// Name, LocalId, rot); 3786 // TODO this still as excessive *.Schedule*Update()s
3787
3788 if (part != null && part.ParentGroup != null)
3789 {
3790 ObjectChangeType change = data.change;
3791 bool togroup = ((change & ObjectChangeType.Group) != 0);
3792 // bool uniform = ((what & ObjectChangeType.UniformScale) != 0); not in use
3793
3794 SceneObjectGroup group = part.ParentGroup;
3795 PhysicsActor pha = group.RootPart.PhysActor;
3796
3797 updatetype updateType = updatetype.none;
3798
3799 if (togroup)
3800 {
3801 // related to group
3802 if ((change & (ObjectChangeType.Rotation | ObjectChangeType.Position)) != 0)
3803 {
3804 if ((change & ObjectChangeType.Rotation) != 0)
3805 {
3806 group.RootPart.UpdateRotation(data.rotation);
3807 updateType = updatetype.none;
3808 }
3809 if ((change & ObjectChangeType.Position) != 0)
3810 {
3811 if (IsAttachment || m_scene.Permissions.CanObjectEntry(group.UUID, false, data.position))
3812 UpdateGroupPosition(data.position);
3813 updateType = updatetype.groupterse;
3814 }
3815 else
3816 // ugly rotation update of all parts
3817 {
3818 group.AbsolutePosition = AbsolutePosition;
3819 }
3820
3821 }
3822 if ((change & ObjectChangeType.Scale) != 0)
3823 {
3824 if (pha != null)
3825 pha.Building = true;
3826
3827 group.GroupResize(data.scale);
3828 updateType = updatetype.none;
3829
3830 if (pha != null)
3831 pha.Building = false;
3832 }
3833 }
3834 else
3835 {
3836 // related to single prim in a link-set ( ie group)
3837 if (pha != null)
3838 pha.Building = true;
3839
3840 // root part is special
3841 // parts offset positions or rotations need to change also
3842
3843 if (part == group.RootPart)
3844 {
3845 if ((change & ObjectChangeType.Rotation) != 0)
3846 group.UpdateRootRotation(data.rotation);
3847 if ((change & ObjectChangeType.Position) != 0)
3848 group.UpdateRootPosition(data.position);
3849 if ((change & ObjectChangeType.Scale) != 0)
3850 part.Resize(data.scale);
3851 }
3852 else
3853 {
3854 if ((change & ObjectChangeType.Position) != 0)
3855 {
3856 part.OffsetPosition = data.position;
3857 updateType = updatetype.partterse;
3858 }
3859 if ((change & ObjectChangeType.Rotation) != 0)
3860 {
3861 part.UpdateRotation(data.rotation);
3862 updateType = updatetype.none;
3863 }
3864 if ((change & ObjectChangeType.Scale) != 0)
3865 {
3866 part.Resize(data.scale);
3867 updateType = updatetype.none;
3868 }
3869 }
3870
3871 if (pha != null)
3872 pha.Building = false;
3873 }
3874
3875 if (updateType != updatetype.none)
3876 {
3877 group.HasGroupChanged = true;
3878
3879 switch (updateType)
3880 {
3881 case updatetype.partterse:
3882 part.ScheduleTerseUpdate();
3883 break;
3884 case updatetype.partfull:
3885 part.ScheduleFullUpdate();
3886 break;
3887 case updatetype.groupterse:
3888 group.ScheduleGroupForTerseUpdate();
3889 break;
3890 case updatetype.groupfull:
3891 group.ScheduleGroupForFullUpdate();
3892 break;
3893 default:
3894 break;
3895 }
3896 }
3897 }
3066 } 3898 }
3067 3899
3068 #endregion 3900 #endregion
@@ -3161,10 +3993,11 @@ namespace OpenSim.Region.Framework.Scenes
3161 scriptPosTarget target = m_targets[idx]; 3993 scriptPosTarget target = m_targets[idx];
3162 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance) 3994 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance)
3163 { 3995 {
3996 at_target = true;
3997
3164 // trigger at_target 3998 // trigger at_target
3165 if (m_scriptListens_atTarget) 3999 if (m_scriptListens_atTarget)
3166 { 4000 {
3167 at_target = true;
3168 scriptPosTarget att = new scriptPosTarget(); 4001 scriptPosTarget att = new scriptPosTarget();
3169 att.targetPos = target.targetPos; 4002 att.targetPos = target.targetPos;
3170 att.tolerance = target.tolerance; 4003 att.tolerance = target.tolerance;
@@ -3282,11 +4115,50 @@ namespace OpenSim.Region.Framework.Scenes
3282 } 4115 }
3283 } 4116 }
3284 } 4117 }
3285 4118
4119 public Vector3 GetGeometricCenter()
4120 {
4121 // this is not real geometric center but a average of positions relative to root prim acording to
4122 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
4123 // ignoring tortured prims details since sl also seems to ignore
4124 // so no real use in doing it on physics
4125
4126 Vector3 gc = Vector3.Zero;
4127
4128 int nparts = m_parts.Count;
4129 if (nparts <= 1)
4130 return gc;
4131
4132 SceneObjectPart[] parts = m_parts.GetArray();
4133 nparts = parts.Length; // just in case it changed
4134 if (nparts <= 1)
4135 return gc;
4136
4137 Quaternion parentRot = RootPart.RotationOffset;
4138 Vector3 pPos;
4139
4140 // average all parts positions
4141 for (int i = 0; i < nparts; i++)
4142 {
4143 // do it directly
4144 // gc += parts[i].GetWorldPosition();
4145 if (parts[i] != RootPart)
4146 {
4147 pPos = parts[i].OffsetPosition;
4148 gc += pPos;
4149 }
4150
4151 }
4152 gc /= nparts;
4153
4154 // relative to root:
4155// gc -= AbsolutePosition;
4156 return gc;
4157 }
4158
3286 public float GetMass() 4159 public float GetMass()
3287 { 4160 {
3288 float retmass = 0f; 4161 float retmass = 0f;
3289
3290 SceneObjectPart[] parts = m_parts.GetArray(); 4162 SceneObjectPart[] parts = m_parts.GetArray();
3291 for (int i = 0; i < parts.Length; i++) 4163 for (int i = 0; i < parts.Length; i++)
3292 retmass += parts[i].GetMass(); 4164 retmass += parts[i].GetMass();
@@ -3294,6 +4166,39 @@ namespace OpenSim.Region.Framework.Scenes
3294 return retmass; 4166 return retmass;
3295 } 4167 }
3296 4168
4169 // center of mass of full object
4170 public Vector3 GetCenterOfMass()
4171 {
4172 PhysicsActor pa = RootPart.PhysActor;
4173
4174 if(((RootPart.Flags & PrimFlags.Physics) !=0) && pa !=null)
4175 {
4176 // physics knows better about center of mass of physical prims
4177 Vector3 tmp = pa.CenterOfMass;
4178 return tmp;
4179 }
4180
4181 Vector3 Ptot = Vector3.Zero;
4182 float totmass = 0f;
4183 float m;
4184
4185 SceneObjectPart[] parts = m_parts.GetArray();
4186 for (int i = 0; i < parts.Length; i++)
4187 {
4188 m = parts[i].GetMass();
4189 Ptot += parts[i].GetPartCenterOfMass() * m;
4190 totmass += m;
4191 }
4192
4193 if (totmass == 0)
4194 totmass = 0;
4195 else
4196 totmass = 1 / totmass;
4197 Ptot *= totmass;
4198
4199 return Ptot;
4200 }
4201
3297 /// <summary> 4202 /// <summary>
3298 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that 4203 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that
3299 /// the physics engine can use it. 4204 /// the physics engine can use it.
@@ -3447,6 +4352,14 @@ namespace OpenSim.Region.Framework.Scenes
3447 FromItemID = uuid; 4352 FromItemID = uuid;
3448 } 4353 }
3449 4354
4355 public void ResetOwnerChangeFlag()
4356 {
4357 ForEachPart(delegate(SceneObjectPart part)
4358 {
4359 part.ResetOwnerChangeFlag();
4360 });
4361 }
4362
3450 #endregion 4363 #endregion
3451 } 4364 }
3452} 4365}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 3d81358..f1e781c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -62,7 +62,8 @@ namespace OpenSim.Region.Framework.Scenes
62 TELEPORT = 512, 62 TELEPORT = 512,
63 REGION_RESTART = 1024, 63 REGION_RESTART = 1024,
64 MEDIA = 2048, 64 MEDIA = 2048,
65 ANIMATION = 16384 65 ANIMATION = 16384,
66 POSITION = 32768
66 } 67 }
67 68
68 // I don't really know where to put this except here. 69 // I don't really know where to put this except here.
@@ -121,7 +122,18 @@ namespace OpenSim.Region.Framework.Scenes
121 /// Denote all sides of the prim 122 /// Denote all sides of the prim
122 /// </value> 123 /// </value>
123 public const int ALL_SIDES = -1; 124 public const int ALL_SIDES = -1;
124 125
126 private const scriptEvents PhysicsNeededSubsEvents = (
127 scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end |
128 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
129 );
130 private const scriptEvents PhyscicsPhantonSubsEvents = (
131 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
132 );
133 private const scriptEvents PhyscicsVolumeDtcSubsEvents = (
134 scriptEvents.collision_start | scriptEvents.collision_end
135 );
136
125 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 137 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
126 138
127 /// <value> 139 /// <value>
@@ -176,12 +188,25 @@ namespace OpenSim.Region.Framework.Scenes
176 188
177 public double SoundRadius; 189 public double SoundRadius;
178 190
191
179 public uint TimeStampFull; 192 public uint TimeStampFull;
180 193
181 public uint TimeStampLastActivity; // Will be used for AutoReturn 194 public uint TimeStampLastActivity; // Will be used for AutoReturn
182 195
183 public uint TimeStampTerse; 196 public uint TimeStampTerse;
184 197
198 // The following two are to hold the attachment data
199 // while an object is inworld
200 [XmlIgnore]
201 public byte AttachPoint = 0;
202
203 [XmlIgnore]
204 public Vector3 AttachOffset = Vector3.Zero;
205
206 [XmlIgnore]
207 public Quaternion AttachRotation = Quaternion.Identity;
208
209 [XmlIgnore]
185 public int STATUS_ROTATE_X; 210 public int STATUS_ROTATE_X;
186 211
187 public int STATUS_ROTATE_Y; 212 public int STATUS_ROTATE_Y;
@@ -208,8 +233,7 @@ namespace OpenSim.Region.Framework.Scenes
208 233
209 public Vector3 RotationAxis = Vector3.One; 234 public Vector3 RotationAxis = Vector3.One;
210 235
211 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 236 public bool VolumeDetectActive;
212 // Certainly this must be a persistant setting finally
213 237
214 public bool IsWaitingForFirstSpinUpdatePacket; 238 public bool IsWaitingForFirstSpinUpdatePacket;
215 239
@@ -249,10 +273,10 @@ namespace OpenSim.Region.Framework.Scenes
249 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 273 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
250 private Vector3 m_sitTargetPosition; 274 private Vector3 m_sitTargetPosition;
251 private string m_sitAnimation = "SIT"; 275 private string m_sitAnimation = "SIT";
276 private bool m_occupied; // KF if any av is sitting on this prim
252 private string m_text = String.Empty; 277 private string m_text = String.Empty;
253 private string m_touchName = String.Empty; 278 private string m_touchName = String.Empty;
254 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 279 private UndoRedoState m_UndoRedo = null;
255 private readonly Stack<UndoState> m_redo = new Stack<UndoState>(5);
256 280
257 private bool m_passTouches = false; 281 private bool m_passTouches = false;
258 private bool m_passCollisions = false; 282 private bool m_passCollisions = false;
@@ -281,7 +305,19 @@ namespace OpenSim.Region.Framework.Scenes
281 protected Vector3 m_lastAcceleration; 305 protected Vector3 m_lastAcceleration;
282 protected Vector3 m_lastAngularVelocity; 306 protected Vector3 m_lastAngularVelocity;
283 protected int m_lastTerseSent; 307 protected int m_lastTerseSent;
284 308 protected float m_buoyancy = 0.0f;
309 protected Vector3 m_force;
310 protected Vector3 m_torque;
311
312 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
313 protected float m_density = 1000.0f; // in kg/m^3
314 protected float m_gravitymod = 1.0f;
315 protected float m_friction = 0.6f; // wood
316 protected float m_bounce = 0.5f; // wood
317
318
319 protected bool m_isSelected = false;
320
285 /// <summary> 321 /// <summary>
286 /// Stores media texture data 322 /// Stores media texture data
287 /// </summary> 323 /// </summary>
@@ -293,10 +329,25 @@ namespace OpenSim.Region.Framework.Scenes
293 private Vector3 m_cameraAtOffset; 329 private Vector3 m_cameraAtOffset;
294 private bool m_forceMouselook; 330 private bool m_forceMouselook;
295 331
296 // TODO: Collision sound should have default. 332
333 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
334 private sbyte m_collisionSoundType;
297 private UUID m_collisionSound; 335 private UUID m_collisionSound;
298 private float m_collisionSoundVolume; 336 private float m_collisionSoundVolume;
299 337
338 private int LastColSoundSentTime;
339
340
341 private SOPVehicle m_vehicle = null;
342
343 private KeyframeMotion m_keyframeMotion = null;
344
345 public KeyframeMotion KeyframeMotion
346 {
347 get; set;
348 }
349
350
300 #endregion Fields 351 #endregion Fields
301 352
302// ~SceneObjectPart() 353// ~SceneObjectPart()
@@ -325,6 +376,7 @@ namespace OpenSim.Region.Framework.Scenes
325 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from 376 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
326 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log 377 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
327 m_inventory = new SceneObjectPartInventory(this); 378 m_inventory = new SceneObjectPartInventory(this);
379 LastColSoundSentTime = Util.EnvironmentTickCount();
328 } 380 }
329 381
330 /// <summary> 382 /// <summary>
@@ -339,7 +391,7 @@ namespace OpenSim.Region.Framework.Scenes
339 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 391 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
340 Quaternion rotationOffset, Vector3 offsetPosition) : this() 392 Quaternion rotationOffset, Vector3 offsetPosition) : this()
341 { 393 {
342 m_name = "Primitive"; 394 m_name = "Object";
343 395
344 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 396 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
345 LastOwnerID = CreatorID = OwnerID = ownerID; 397 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -379,7 +431,7 @@ namespace OpenSim.Region.Framework.Scenes
379 private uint _ownerMask = (uint)PermissionMask.All; 431 private uint _ownerMask = (uint)PermissionMask.All;
380 private uint _groupMask = (uint)PermissionMask.None; 432 private uint _groupMask = (uint)PermissionMask.None;
381 private uint _everyoneMask = (uint)PermissionMask.None; 433 private uint _everyoneMask = (uint)PermissionMask.None;
382 private uint _nextOwnerMask = (uint)PermissionMask.All; 434 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
383 private PrimFlags _flags = PrimFlags.None; 435 private PrimFlags _flags = PrimFlags.None;
384 private DateTime m_expires; 436 private DateTime m_expires;
385 private DateTime m_rezzed; 437 private DateTime m_rezzed;
@@ -473,12 +525,16 @@ namespace OpenSim.Region.Framework.Scenes
473 } 525 }
474 526
475 /// <value> 527 /// <value>
476 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 528 /// Get the inventory list
477 /// </value> 529 /// </value>
478 public TaskInventoryDictionary TaskInventory 530 public TaskInventoryDictionary TaskInventory
479 { 531 {
480 get { return m_inventory.Items; } 532 get {
481 set { m_inventory.Items = value; } 533 return m_inventory.Items;
534 }
535 set {
536 m_inventory.Items = value;
537 }
482 } 538 }
483 539
484 /// <summary> 540 /// <summary>
@@ -528,20 +584,6 @@ namespace OpenSim.Region.Framework.Scenes
528 } 584 }
529 } 585 }
530 586
531 public byte Material
532 {
533 get { return (byte) m_material; }
534 set
535 {
536 m_material = (Material)value;
537
538 PhysicsActor pa = PhysActor;
539
540 if (pa != null)
541 pa.SetMaterial((int)value);
542 }
543 }
544
545 [XmlIgnore] 587 [XmlIgnore]
546 public bool PassTouches 588 public bool PassTouches
547 { 589 {
@@ -567,6 +609,18 @@ namespace OpenSim.Region.Framework.Scenes
567 } 609 }
568 } 610 }
569 611
612 public bool IsSelected
613 {
614 get { return m_isSelected; }
615 set
616 {
617 m_isSelected = value;
618 if (ParentGroup != null)
619 ParentGroup.PartSelectChanged(value);
620 }
621 }
622
623
570 public Dictionary<int, string> CollisionFilter 624 public Dictionary<int, string> CollisionFilter
571 { 625 {
572 get { return m_CollisionFilter; } 626 get { return m_CollisionFilter; }
@@ -635,14 +689,12 @@ namespace OpenSim.Region.Framework.Scenes
635 set { m_LoopSoundSlavePrims = value; } 689 set { m_LoopSoundSlavePrims = value; }
636 } 690 }
637 691
638
639 public Byte[] TextureAnimation 692 public Byte[] TextureAnimation
640 { 693 {
641 get { return m_TextureAnimation; } 694 get { return m_TextureAnimation; }
642 set { m_TextureAnimation = value; } 695 set { m_TextureAnimation = value; }
643 } 696 }
644 697
645
646 public Byte[] ParticleSystem 698 public Byte[] ParticleSystem
647 { 699 {
648 get { return m_particleSystem; } 700 get { return m_particleSystem; }
@@ -679,8 +731,12 @@ namespace OpenSim.Region.Framework.Scenes
679 { 731 {
680 // If this is a linkset, we don't want the physics engine mucking up our group position here. 732 // If this is a linkset, we don't want the physics engine mucking up our group position here.
681 PhysicsActor actor = PhysActor; 733 PhysicsActor actor = PhysActor;
682 if (actor != null && ParentID == 0) 734 if (ParentID == 0)
683 m_groupPosition = actor.Position; 735 {
736 if (actor != null)
737 m_groupPosition = actor.Position;
738 return m_groupPosition;
739 }
684 740
685 if (ParentGroup.IsAttachment) 741 if (ParentGroup.IsAttachment)
686 { 742 {
@@ -689,12 +745,14 @@ namespace OpenSim.Region.Framework.Scenes
689 return sp.AbsolutePosition; 745 return sp.AbsolutePosition;
690 } 746 }
691 747
748 // use root prim's group position. Physics may have updated it
749 if (ParentGroup.RootPart != this)
750 m_groupPosition = ParentGroup.RootPart.GroupPosition;
692 return m_groupPosition; 751 return m_groupPosition;
693 } 752 }
694 set 753 set
695 { 754 {
696 m_groupPosition = value; 755 m_groupPosition = value;
697
698 PhysicsActor actor = PhysActor; 756 PhysicsActor actor = PhysActor;
699 if (actor != null) 757 if (actor != null)
700 { 758 {
@@ -720,16 +778,6 @@ namespace OpenSim.Region.Framework.Scenes
720 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 778 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
721 } 779 }
722 } 780 }
723
724 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
725 if (SitTargetAvatar != UUID.Zero)
726 {
727 ScenePresence avatar;
728 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
729 {
730 avatar.ParentPosition = GetWorldPosition();
731 }
732 }
733 } 781 }
734 } 782 }
735 783
@@ -738,7 +786,7 @@ namespace OpenSim.Region.Framework.Scenes
738 get { return m_offsetPosition; } 786 get { return m_offsetPosition; }
739 set 787 set
740 { 788 {
741// StoreUndoState(); 789 Vector3 oldpos = m_offsetPosition;
742 m_offsetPosition = value; 790 m_offsetPosition = value;
743 791
744 if (ParentGroup != null && !ParentGroup.IsDeleted) 792 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -753,7 +801,22 @@ namespace OpenSim.Region.Framework.Scenes
753 if (ParentGroup.Scene != null) 801 if (ParentGroup.Scene != null)
754 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 802 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
755 } 803 }
804
805 if (!m_parentGroup.m_dupeInProgress)
806 {
807 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
808 foreach (ScenePresence av in avs)
809 {
810 if (av.ParentID == m_localId)
811 {
812 Vector3 offset = (m_offsetPosition - oldpos);
813 av.AbsolutePosition += offset;
814 av.SendAvatarDataToAllAgents();
815 }
816 }
817 }
756 } 818 }
819 TriggerScriptChangedEvent(Changed.POSITION);
757 } 820 }
758 } 821 }
759 822
@@ -802,7 +865,7 @@ namespace OpenSim.Region.Framework.Scenes
802 865
803 set 866 set
804 { 867 {
805 StoreUndoState(); 868// StoreUndoState();
806 m_rotationOffset = value; 869 m_rotationOffset = value;
807 870
808 PhysicsActor actor = PhysActor; 871 PhysicsActor actor = PhysActor;
@@ -890,7 +953,7 @@ namespace OpenSim.Region.Framework.Scenes
890 get 953 get
891 { 954 {
892 PhysicsActor actor = PhysActor; 955 PhysicsActor actor = PhysActor;
893 if ((actor != null) && actor.IsPhysical) 956 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
894 { 957 {
895 m_angularVelocity = actor.RotationalVelocity; 958 m_angularVelocity = actor.RotationalVelocity;
896 } 959 }
@@ -902,7 +965,16 @@ namespace OpenSim.Region.Framework.Scenes
902 /// <summary></summary> 965 /// <summary></summary>
903 public Vector3 Acceleration 966 public Vector3 Acceleration
904 { 967 {
905 get { return m_acceleration; } 968 get
969 {
970 PhysicsActor actor = PhysActor;
971 if (actor != null)
972 {
973 m_acceleration = actor.Acceleration;
974 }
975 return m_acceleration;
976 }
977
906 set { m_acceleration = value; } 978 set { m_acceleration = value; }
907 } 979 }
908 980
@@ -970,7 +1042,10 @@ namespace OpenSim.Region.Framework.Scenes
970 public PrimitiveBaseShape Shape 1042 public PrimitiveBaseShape Shape
971 { 1043 {
972 get { return m_shape; } 1044 get { return m_shape; }
973 set { m_shape = value;} 1045 set
1046 {
1047 m_shape = value;
1048 }
974 } 1049 }
975 1050
976 /// <summary> 1051 /// <summary>
@@ -983,7 +1058,6 @@ namespace OpenSim.Region.Framework.Scenes
983 { 1058 {
984 if (m_shape != null) 1059 if (m_shape != null)
985 { 1060 {
986 StoreUndoState();
987 1061
988 m_shape.Scale = value; 1062 m_shape.Scale = value;
989 1063
@@ -1010,6 +1084,7 @@ namespace OpenSim.Region.Framework.Scenes
1010 } 1084 }
1011 1085
1012 public UpdateRequired UpdateFlag { get; set; } 1086 public UpdateRequired UpdateFlag { get; set; }
1087 public bool UpdatePhysRequired { get; set; }
1013 1088
1014 /// <summary> 1089 /// <summary>
1015 /// Used for media on a prim. 1090 /// Used for media on a prim.
@@ -1050,10 +1125,7 @@ namespace OpenSim.Region.Framework.Scenes
1050 { 1125 {
1051 get 1126 get
1052 { 1127 {
1053 if (ParentGroup.IsAttachment) 1128 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1054 return GroupPosition;
1055
1056 return m_offsetPosition + m_groupPosition;
1057 } 1129 }
1058 } 1130 }
1059 1131
@@ -1231,6 +1303,13 @@ namespace OpenSim.Region.Framework.Scenes
1231 _flags = value; 1303 _flags = value;
1232 } 1304 }
1233 } 1305 }
1306
1307 [XmlIgnore]
1308 public bool IsOccupied // KF If an av is sittingon this prim
1309 {
1310 get { return m_occupied; }
1311 set { m_occupied = value; }
1312 }
1234 1313
1235 /// <summary> 1314 /// <summary>
1236 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1315 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1274,12 +1353,41 @@ namespace OpenSim.Region.Framework.Scenes
1274 set { m_sitAnimation = value; } 1353 set { m_sitAnimation = value; }
1275 } 1354 }
1276 1355
1356 public UUID invalidCollisionSoundUUID = new UUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
1357
1358 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
1359 // runtime thing.. do not persist
1360 [XmlIgnore]
1361 public sbyte CollisionSoundType
1362 {
1363 get
1364 {
1365 return m_collisionSoundType;
1366 }
1367 set
1368 {
1369 m_collisionSoundType = value;
1370 if (value == -1)
1371 m_collisionSound = invalidCollisionSoundUUID;
1372 else if (value == 0)
1373 m_collisionSound = UUID.Zero;
1374 }
1375 }
1376
1277 public UUID CollisionSound 1377 public UUID CollisionSound
1278 { 1378 {
1279 get { return m_collisionSound; } 1379 get { return m_collisionSound; }
1280 set 1380 set
1281 { 1381 {
1282 m_collisionSound = value; 1382 m_collisionSound = value;
1383
1384 if (value == invalidCollisionSoundUUID)
1385 m_collisionSoundType = -1;
1386 else if (value == UUID.Zero)
1387 m_collisionSoundType = 0;
1388 else
1389 m_collisionSoundType = 1;
1390
1283 aggregateScriptEvents(); 1391 aggregateScriptEvents();
1284 } 1392 }
1285 } 1393 }
@@ -1290,6 +1398,319 @@ namespace OpenSim.Region.Framework.Scenes
1290 set { m_collisionSoundVolume = value; } 1398 set { m_collisionSoundVolume = value; }
1291 } 1399 }
1292 1400
1401 public float Buoyancy
1402 {
1403 get
1404 {
1405 if (ParentGroup.RootPart == this)
1406 return m_buoyancy;
1407
1408 return ParentGroup.RootPart.Buoyancy;
1409 }
1410 set
1411 {
1412 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1413 {
1414 ParentGroup.RootPart.Buoyancy = value;
1415 return;
1416 }
1417 m_buoyancy = value;
1418 if (PhysActor != null)
1419 PhysActor.Buoyancy = value;
1420 }
1421 }
1422
1423 public Vector3 Force
1424 {
1425 get
1426 {
1427 if (ParentGroup.RootPart == this)
1428 return m_force;
1429
1430 return ParentGroup.RootPart.Force;
1431 }
1432
1433 set
1434 {
1435 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1436 {
1437 ParentGroup.RootPart.Force = value;
1438 return;
1439 }
1440 m_force = value;
1441 if (PhysActor != null)
1442 PhysActor.Force = value;
1443 }
1444 }
1445
1446 public Vector3 Torque
1447 {
1448 get
1449 {
1450 if (ParentGroup.RootPart == this)
1451 return m_torque;
1452
1453 return ParentGroup.RootPart.Torque;
1454 }
1455
1456 set
1457 {
1458 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1459 {
1460 ParentGroup.RootPart.Torque = value;
1461 return;
1462 }
1463 m_torque = value;
1464 if (PhysActor != null)
1465 PhysActor.Torque = value;
1466 }
1467 }
1468
1469 public byte Material
1470 {
1471 get { return (byte)m_material; }
1472 set
1473 {
1474 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1475 {
1476 bool update = false;
1477
1478 if (m_material != (Material)value)
1479 {
1480 update = true;
1481 m_material = (Material)value;
1482 }
1483
1484 if (m_friction != SOPMaterialData.friction(m_material))
1485 {
1486 update = true;
1487 m_friction = SOPMaterialData.friction(m_material);
1488 }
1489
1490 if (m_bounce != SOPMaterialData.bounce(m_material))
1491 {
1492 update = true;
1493 m_bounce = SOPMaterialData.bounce(m_material);
1494 }
1495
1496 if (update)
1497 {
1498 if (PhysActor != null)
1499 {
1500 PhysActor.SetMaterial((int)value);
1501 }
1502 if(ParentGroup != null)
1503 ParentGroup.HasGroupChanged = true;
1504 ScheduleFullUpdateIfNone();
1505 UpdatePhysRequired = true;
1506 }
1507 }
1508 }
1509 }
1510
1511 // not a propriety to move to methods place later
1512 private bool HasMesh()
1513 {
1514 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1515 return true;
1516 return false;
1517 }
1518
1519 // not a propriety to move to methods place later
1520 public byte DefaultPhysicsShapeType()
1521 {
1522 byte type;
1523
1524 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1525 type = (byte)PhysShapeType.convex;
1526 else
1527 type = (byte)PhysShapeType.prim;
1528
1529 return type;
1530 }
1531
1532 [XmlIgnore]
1533 public bool UsesComplexCost
1534 {
1535 get
1536 {
1537 byte pst = PhysicsShapeType;
1538 if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh())
1539 return true;
1540 return false;
1541 }
1542 }
1543
1544 [XmlIgnore]
1545 public float PhysicsCost
1546 {
1547 get
1548 {
1549 if(PhysicsShapeType == (byte)PhysShapeType.none)
1550 return 0;
1551
1552 float cost = 0.1f;
1553 if (PhysActor != null)
1554// cost += PhysActor.Cost;
1555
1556 if ((Flags & PrimFlags.Physics) != 0)
1557 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1558 return cost;
1559 }
1560 }
1561
1562 [XmlIgnore]
1563 public float StreamingCost
1564 {
1565 get
1566 {
1567
1568
1569 return 0.1f;
1570 }
1571 }
1572
1573 [XmlIgnore]
1574 public float SimulationCost
1575 {
1576 get
1577 {
1578 // ignoring scripts. Don't like considering them for this
1579 if((Flags & PrimFlags.Physics) != 0)
1580 return 1.0f;
1581
1582 return 0.5f;
1583 }
1584 }
1585
1586 public byte PhysicsShapeType
1587 {
1588 get { return m_physicsShapeType; }
1589 set
1590 {
1591 byte oldv = m_physicsShapeType;
1592
1593 if (value >= 0 && value <= (byte)PhysShapeType.convex)
1594 {
1595 if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this)
1596 m_physicsShapeType = DefaultPhysicsShapeType();
1597 else
1598 m_physicsShapeType = value;
1599 }
1600 else
1601 m_physicsShapeType = DefaultPhysicsShapeType();
1602
1603 if (m_physicsShapeType != oldv && ParentGroup != null)
1604 {
1605 if (m_physicsShapeType == (byte)PhysShapeType.none)
1606 {
1607 if (PhysActor != null)
1608 {
1609 Velocity = new Vector3(0, 0, 0);
1610 Acceleration = new Vector3(0, 0, 0);
1611 if (ParentGroup.RootPart == this)
1612 AngularVelocity = new Vector3(0, 0, 0);
1613 ParentGroup.Scene.RemovePhysicalPrim(1);
1614 RemoveFromPhysics();
1615 }
1616 }
1617 else if (PhysActor == null)
1618 {
1619 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1620 UpdatePhysicsSubscribedEvents();
1621 }
1622 else
1623 {
1624 PhysActor.PhysicsShapeType = m_physicsShapeType;
1625 if (Shape.SculptEntry)
1626 CheckSculptAndLoad();
1627 }
1628
1629 if (ParentGroup != null)
1630 ParentGroup.HasGroupChanged = true;
1631 }
1632
1633 if (m_physicsShapeType != value)
1634 {
1635 UpdatePhysRequired = true;
1636 }
1637 }
1638 }
1639
1640 public float Density // in kg/m^3
1641 {
1642 get { return m_density; }
1643 set
1644 {
1645 if (value >=1 && value <= 22587.0)
1646 {
1647 m_density = value;
1648 UpdatePhysRequired = true;
1649 }
1650
1651 ScheduleFullUpdateIfNone();
1652
1653 if (ParentGroup != null)
1654 ParentGroup.HasGroupChanged = true;
1655 }
1656 }
1657
1658 public float GravityModifier
1659 {
1660 get { return m_gravitymod; }
1661 set
1662 {
1663 if( value >= -1 && value <=28.0f)
1664 {
1665 m_gravitymod = value;
1666 UpdatePhysRequired = true;
1667 }
1668
1669 ScheduleFullUpdateIfNone();
1670
1671 if (ParentGroup != null)
1672 ParentGroup.HasGroupChanged = true;
1673
1674 }
1675 }
1676
1677 public float Friction
1678 {
1679 get { return m_friction; }
1680 set
1681 {
1682 if (value >= 0 && value <= 255.0f)
1683 {
1684 m_friction = value;
1685 UpdatePhysRequired = true;
1686 }
1687
1688 ScheduleFullUpdateIfNone();
1689
1690 if (ParentGroup != null)
1691 ParentGroup.HasGroupChanged = true;
1692 }
1693 }
1694
1695 public float Bounciness
1696 {
1697 get { return m_bounce; }
1698 set
1699 {
1700 if (value >= 0 && value <= 1.0f)
1701 {
1702 m_bounce = value;
1703 UpdatePhysRequired = true;
1704 }
1705
1706 ScheduleFullUpdateIfNone();
1707
1708 if (ParentGroup != null)
1709 ParentGroup.HasGroupChanged = true;
1710 }
1711 }
1712
1713
1293 #endregion Public Properties with only Get 1714 #endregion Public Properties with only Get
1294 1715
1295 private uint ApplyMask(uint val, bool set, uint mask) 1716 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1455,7 +1876,7 @@ namespace OpenSim.Region.Framework.Scenes
1455 impulse = newimpulse; 1876 impulse = newimpulse;
1456 } 1877 }
1457 1878
1458 ParentGroup.applyAngularImpulse(impulse); 1879 ParentGroup.ApplyAngularImpulse(impulse);
1459 } 1880 }
1460 1881
1461 /// <summary> 1882 /// <summary>
@@ -1465,20 +1886,24 @@ namespace OpenSim.Region.Framework.Scenes
1465 /// </summary> 1886 /// </summary>
1466 /// <param name="impulsei">Vector force</param> 1887 /// <param name="impulsei">Vector force</param>
1467 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 1888 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1468 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 1889
1890 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
1891 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1469 { 1892 {
1470 Vector3 impulse = impulsei; 1893 Vector3 torque = torquei;
1471 1894
1472 if (localGlobalTF) 1895 if (localGlobalTF)
1473 { 1896 {
1897/*
1474 Quaternion grot = GetWorldRotation(); 1898 Quaternion grot = GetWorldRotation();
1475 Quaternion AXgrot = grot; 1899 Quaternion AXgrot = grot;
1476 Vector3 AXimpulsei = impulsei; 1900 Vector3 AXimpulsei = impulsei;
1477 Vector3 newimpulse = AXimpulsei * AXgrot; 1901 Vector3 newimpulse = AXimpulsei * AXgrot;
1478 impulse = newimpulse; 1902 */
1903 torque *= GetWorldRotation();
1479 } 1904 }
1480 1905
1481 ParentGroup.setAngularImpulse(impulse); 1906 Torque = torque;
1482 } 1907 }
1483 1908
1484 /// <summary> 1909 /// <summary>
@@ -1486,17 +1911,23 @@ namespace OpenSim.Region.Framework.Scenes
1486 /// </summary> 1911 /// </summary>
1487 /// <param name="rootObjectFlags"></param> 1912 /// <param name="rootObjectFlags"></param>
1488 /// <param name="VolumeDetectActive"></param> 1913 /// <param name="VolumeDetectActive"></param>
1489 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) 1914 /// <param name="building"></param>
1915
1916 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1490 { 1917 {
1918 VolumeDetectActive = _VolumeDetectActive;
1919
1491 if (!ParentGroup.Scene.CollidablePrims) 1920 if (!ParentGroup.Scene.CollidablePrims)
1492 return; 1921 return;
1493 1922
1494// m_log.DebugFormat( 1923 if (PhysicsShapeType == (byte)PhysShapeType.none)
1495// "[SCENE OBJECT PART]: Applying physics to {0} {1}, m_physicalPrim {2}", 1924 return;
1496// Name, LocalId, UUID, m_physicalPrim); 1925
1926 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
1927 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
1497 1928
1498 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 1929 if (_VolumeDetectActive)
1499 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 1930 isPhantom = true;
1500 1931
1501 if (IsJoint()) 1932 if (IsJoint())
1502 { 1933 {
@@ -1504,22 +1935,14 @@ namespace OpenSim.Region.Framework.Scenes
1504 } 1935 }
1505 else 1936 else
1506 { 1937 {
1507 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored 1938 if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment
1508 if (VolumeDetectActive) 1939 && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1509 isPhantom = false;
1510
1511 // The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition
1512 // or flexible
1513 if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1514 { 1940 {
1515 // Added clarification.. since A rigid body is an object that you can kick around, etc. 1941 AddToPhysics(isPhysical, isPhantom, building, isPhysical);
1516 bool rigidBody = isPhysical && !isPhantom; 1942 UpdatePhysicsSubscribedEvents(); // not sure if appliable here
1517
1518 PhysicsActor pa = AddToPhysics(rigidBody);
1519
1520 if (pa != null)
1521 pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1522 } 1943 }
1944 else
1945 PhysActor = null; // just to be sure
1523 } 1946 }
1524 } 1947 }
1525 1948
@@ -1571,6 +1994,12 @@ namespace OpenSim.Region.Framework.Scenes
1571 dupe.Category = Category; 1994 dupe.Category = Category;
1572 dupe.m_rezzed = m_rezzed; 1995 dupe.m_rezzed = m_rezzed;
1573 1996
1997 dupe.m_UndoRedo = null;
1998 dupe.m_isSelected = false;
1999
2000 dupe.IgnoreUndoUpdate = false;
2001 dupe.Undoing = false;
2002
1574 dupe.m_inventory = new SceneObjectPartInventory(dupe); 2003 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1575 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 2004 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1576 2005
@@ -1586,6 +2015,7 @@ namespace OpenSim.Region.Framework.Scenes
1586 2015
1587 // Move afterwards ResetIDs as it clears the localID 2016 // Move afterwards ResetIDs as it clears the localID
1588 dupe.LocalId = localID; 2017 dupe.LocalId = localID;
2018
1589 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 2019 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1590 dupe.LastOwnerID = OwnerID; 2020 dupe.LastOwnerID = OwnerID;
1591 2021
@@ -1603,8 +2033,12 @@ namespace OpenSim.Region.Framework.Scenes
1603 2033
1604 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 2034 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
1605 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 2035 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
2036// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
1606 } 2037 }
1607 2038
2039 if (dupe.PhysActor != null)
2040 dupe.PhysActor.LocalID = localID;
2041
1608 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2042 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1609 2043
1610// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 2044// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1724,6 +2158,7 @@ namespace OpenSim.Region.Framework.Scenes
1724 2158
1725 /// <summary> 2159 /// <summary>
1726 /// Do a physics propery update for this part. 2160 /// Do a physics propery update for this part.
2161 /// now also updates phantom and volume detector
1727 /// </summary> 2162 /// </summary>
1728 /// <param name="UsePhysics"></param> 2163 /// <param name="UsePhysics"></param>
1729 /// <param name="isNew"></param> 2164 /// <param name="isNew"></param>
@@ -1749,61 +2184,69 @@ namespace OpenSim.Region.Framework.Scenes
1749 { 2184 {
1750 if (pa.IsPhysical) // implies UsePhysics==false for this block 2185 if (pa.IsPhysical) // implies UsePhysics==false for this block
1751 { 2186 {
1752 if (!isNew) 2187 if (!isNew) // implies UsePhysics==false for this block
2188 {
1753 ParentGroup.Scene.RemovePhysicalPrim(1); 2189 ParentGroup.Scene.RemovePhysicalPrim(1);
1754 2190
1755 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2191 Velocity = new Vector3(0, 0, 0);
1756 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2192 Acceleration = new Vector3(0, 0, 0);
1757 pa.delink(); 2193 if (ParentGroup.RootPart == this)
2194 AngularVelocity = new Vector3(0, 0, 0);
1758 2195
1759 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2196 if (pa.Phantom && !VolumeDetectActive)
1760 { 2197 {
1761 // destroy all joints connected to this now deactivated body 2198 RemoveFromPhysics();
1762 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2199 return;
1763 } 2200 }
1764 2201
1765 // stop client-side interpolation of all joint proxy objects that have just been deleted 2202 pa.IsPhysical = UsePhysics;
1766 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2203 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1767 // which stops client-side interpolation of deactivated joint proxy objects. 2204 pa.OnOutOfBounds -= PhysicsOutOfBounds;
2205 pa.delink();
2206 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2207 {
2208 // destroy all joints connected to this now deactivated body
2209 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
2210 }
2211 }
1768 } 2212 }
1769 2213
1770 if (!UsePhysics && !isNew) 2214 if (pa.IsPhysical != UsePhysics)
1771 { 2215 pa.IsPhysical = UsePhysics;
1772 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
1773 // prim still has velocity and continues to interpolate its position along the old
1774 // velocity-vector.
1775 Velocity = new Vector3(0, 0, 0);
1776 Acceleration = new Vector3(0, 0, 0);
1777 AngularVelocity = new Vector3(0, 0, 0);
1778 //RotationalVelocity = new Vector3(0, 0, 0);
1779 }
1780 2216
1781 pa.IsPhysical = UsePhysics; 2217 if (UsePhysics)
2218 {
2219 if (ParentGroup.RootPart.KeyframeMotion != null)
2220 ParentGroup.RootPart.KeyframeMotion.Stop();
2221 ParentGroup.RootPart.KeyframeMotion = null;
2222 ParentGroup.Scene.AddPhysicalPrim(1);
1782 2223
1783 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2224 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1784 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2225 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1785 /// that's not wholesome. Had to make Scene public
1786 //PhysActor = null;
1787 2226
1788 if ((Flags & PrimFlags.Phantom) == 0) 2227 if (ParentID != 0 && ParentID != LocalId)
1789 {
1790 if (UsePhysics)
1791 { 2228 {
1792 ParentGroup.Scene.AddPhysicalPrim(1); 2229 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
1793 2230
1794 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 2231 if (parentPa != null)
1795 pa.OnOutOfBounds += PhysicsOutOfBounds;
1796 if (ParentID != 0 && ParentID != LocalId)
1797 { 2232 {
1798 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; 2233 pa.link(parentPa);
1799
1800 if (parentPa != null)
1801 {
1802 pa.link(parentPa);
1803 }
1804 } 2234 }
1805 } 2235 }
1806 } 2236 }
2237 }
2238
2239 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2240 if (pa.Phantom != phan)
2241 pa.Phantom = phan;
2242
2243// some engines dont' have this check still
2244// if (VolumeDetectActive != pa.IsVolumeDtc)
2245 {
2246 if (VolumeDetectActive)
2247 pa.SetVolumeDetect(1);
2248 else
2249 pa.SetVolumeDetect(0);
1807 } 2250 }
1808 2251
1809 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2252 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
@@ -1922,12 +2365,26 @@ namespace OpenSim.Region.Framework.Scenes
1922 2365
1923 public Vector3 GetGeometricCenter() 2366 public Vector3 GetGeometricCenter()
1924 { 2367 {
1925 PhysicsActor pa = PhysActor; 2368 // this is not real geometric center but a average of positions relative to root prim acording to
1926 2369 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
1927 if (pa != null) 2370 // ignoring tortured prims details since sl also seems to ignore
1928 return new Vector3(pa.CenterOfMass.X, pa.CenterOfMass.Y, pa.CenterOfMass.Z); 2371 // so no real use in doing it on physics
1929 else 2372 if (ParentGroup.IsDeleted)
1930 return new Vector3(0, 0, 0); 2373 return new Vector3(0, 0, 0);
2374
2375 return ParentGroup.GetGeometricCenter();
2376
2377 /*
2378 PhysicsActor pa = PhysActor;
2379
2380 if (pa != null)
2381 {
2382 Vector3 vtmp = pa.CenterOfMass;
2383 return vtmp;
2384 }
2385 else
2386 return new Vector3(0, 0, 0);
2387 */
1931 } 2388 }
1932 2389
1933 public float GetMass() 2390 public float GetMass()
@@ -1940,14 +2397,43 @@ namespace OpenSim.Region.Framework.Scenes
1940 return 0; 2397 return 0;
1941 } 2398 }
1942 2399
1943 public Vector3 GetForce() 2400 public Vector3 GetCenterOfMass()
2401 {
2402 if (ParentGroup.RootPart == this)
2403 {
2404 if (ParentGroup.IsDeleted)
2405 return AbsolutePosition;
2406 return ParentGroup.GetCenterOfMass();
2407 }
2408
2409 PhysicsActor pa = PhysActor;
2410
2411 if (pa != null)
2412 {
2413 Vector3 tmp = pa.CenterOfMass;
2414 return tmp;
2415 }
2416 else
2417 return AbsolutePosition;
2418 }
2419
2420 public Vector3 GetPartCenterOfMass()
1944 { 2421 {
1945 PhysicsActor pa = PhysActor; 2422 PhysicsActor pa = PhysActor;
1946 2423
1947 if (pa != null) 2424 if (pa != null)
1948 return pa.Force; 2425 {
2426 Vector3 tmp = pa.CenterOfMass;
2427 return tmp;
2428 }
1949 else 2429 else
1950 return Vector3.Zero; 2430 return AbsolutePosition;
2431 }
2432
2433
2434 public Vector3 GetForce()
2435 {
2436 return Force;
1951 } 2437 }
1952 2438
1953 /// <summary> 2439 /// <summary>
@@ -2154,15 +2640,25 @@ namespace OpenSim.Region.Framework.Scenes
2154 2640
2155 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify) 2641 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify)
2156 { 2642 {
2157 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0) 2643 bool sendToRoot = true;
2158 {
2159 ColliderArgs LandCollidingMessage = new ColliderArgs();
2160 List<DetectedObject> colliding = new List<DetectedObject>();
2161
2162 colliding.Add(CreateDetObjectForGround());
2163 LandCollidingMessage.Colliders = colliding;
2164 2644
2645 ColliderArgs LandCollidingMessage = new ColliderArgs();
2646 List<DetectedObject> colliding = new List<DetectedObject>();
2647
2648 colliding.Add(CreateDetObjectForGround());
2649 LandCollidingMessage.Colliders = colliding;
2650
2651 if (Inventory.ContainsScripts())
2652 {
2653 if (!PassCollisions)
2654 sendToRoot = false;
2655 }
2656 if ((ScriptEvents & ev) != 0)
2165 notify(LocalId, LandCollidingMessage); 2657 notify(LocalId, LandCollidingMessage);
2658
2659 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0 && sendToRoot)
2660 {
2661 notify(ParentGroup.RootPart.LocalId, LandCollidingMessage);
2166 } 2662 }
2167 } 2663 }
2168 2664
@@ -2178,45 +2674,87 @@ namespace OpenSim.Region.Framework.Scenes
2178 List<uint> endedColliders = new List<uint>(); 2674 List<uint> endedColliders = new List<uint>();
2179 List<uint> startedColliders = new List<uint>(); 2675 List<uint> startedColliders = new List<uint>();
2180 2676
2181 // calculate things that started colliding this time 2677 if (collissionswith.Count == 0)
2182 // and build up list of colliders this time
2183 foreach (uint localid in collissionswith.Keys)
2184 { 2678 {
2185 thisHitColliders.Add(localid); 2679 if (m_lastColliders.Count == 0)
2186 if (!m_lastColliders.Contains(localid)) 2680 return; // nothing to do
2187 startedColliders.Add(localid);
2188 }
2189 2681
2190 // calculate things that ended colliding 2682 foreach (uint localID in m_lastColliders)
2191 foreach (uint localID in m_lastColliders) 2683 {
2192 {
2193 if (!thisHitColliders.Contains(localID))
2194 endedColliders.Add(localID); 2684 endedColliders.Add(localID);
2685 }
2686 m_lastColliders.Clear();
2195 } 2687 }
2196 2688
2197 //add the items that started colliding this time to the last colliders list. 2689 else
2198 foreach (uint localID in startedColliders) 2690 {
2199 m_lastColliders.Add(localID); 2691 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
2692
2693 // calculate things that started colliding this time
2694 // and build up list of colliders this time
2695 if (!VolumeDetectActive && CollisionSoundType >= 0)
2696 {
2697 CollisionForSoundInfo soundinfo;
2698 ContactPoint curcontact;
2699
2700 foreach (uint id in collissionswith.Keys)
2701 {
2702 thisHitColliders.Add(id);
2703 if (!m_lastColliders.Contains(id))
2704 {
2705 startedColliders.Add(id);
2706
2707 curcontact = collissionswith[id];
2708 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2709 {
2710 soundinfo = new CollisionForSoundInfo();
2711 soundinfo.colliderID = id;
2712 soundinfo.position = curcontact.Position;
2713 soundinfo.relativeVel = curcontact.RelativeSpeed;
2714 soundinfolist.Add(soundinfo);
2715 }
2716 }
2717 }
2718 }
2719 else
2720 {
2721 foreach (uint id in collissionswith.Keys)
2722 {
2723 thisHitColliders.Add(id);
2724 if (!m_lastColliders.Contains(id))
2725 startedColliders.Add(id);
2726 }
2727 }
2728
2729 // calculate things that ended colliding
2730 foreach (uint localID in m_lastColliders)
2731 {
2732 if (!thisHitColliders.Contains(localID))
2733 endedColliders.Add(localID);
2734 }
2735
2736 //add the items that started colliding this time to the last colliders list.
2737 foreach (uint localID in startedColliders)
2738 m_lastColliders.Add(localID);
2200 2739
2201 // remove things that ended colliding from the last colliders list 2740 // remove things that ended colliding from the last colliders list
2202 foreach (uint localID in endedColliders) 2741 foreach (uint localID in endedColliders)
2203 m_lastColliders.Remove(localID); 2742 m_lastColliders.Remove(localID);
2204 2743
2205 // play the sound. 2744 // play sounds.
2206 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) 2745 if (soundinfolist.Count > 0)
2207 SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, (byte)0, 0, false, false); 2746 CollisionSounds.PartCollisionSound(this, soundinfolist);
2747 }
2208 2748
2209 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); 2749 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart);
2210 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); 2750 if (!VolumeDetectActive)
2751 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
2211 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 2752 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
2212 2753
2213 if (startedColliders.Contains(0)) 2754 if (startedColliders.Contains(0))
2214 { 2755 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2215 if (m_lastColliders.Contains(0)) 2756 if (m_lastColliders.Contains(0))
2216 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding); 2757 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding);
2217 else
2218 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2219 }
2220 if (endedColliders.Contains(0)) 2758 if (endedColliders.Contains(0))
2221 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2759 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2222 } 2760 }
@@ -2239,9 +2777,9 @@ namespace OpenSim.Region.Framework.Scenes
2239 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); 2777 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
2240 2778
2241 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2779 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2242 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) 2780 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2243 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) 2781 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2244 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) 2782 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2245 { 2783 {
2246 ParentGroup.AbsolutePosition = newpos; 2784 ParentGroup.AbsolutePosition = newpos;
2247 return; 2785 return;
@@ -2263,17 +2801,18 @@ namespace OpenSim.Region.Framework.Scenes
2263 //Trys to fetch sound id from prim's inventory. 2801 //Trys to fetch sound id from prim's inventory.
2264 //Prim's inventory doesn't support non script items yet 2802 //Prim's inventory doesn't support non script items yet
2265 2803
2266 lock (TaskInventory) 2804 TaskInventory.LockItemsForRead(true);
2805
2806 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2267 { 2807 {
2268 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2808 if (item.Value.Name == sound)
2269 { 2809 {
2270 if (item.Value.Name == sound) 2810 soundID = item.Value.ItemID;
2271 { 2811 break;
2272 soundID = item.Value.ItemID;
2273 break;
2274 }
2275 } 2812 }
2276 } 2813 }
2814
2815 TaskInventory.LockItemsForRead(false);
2277 } 2816 }
2278 2817
2279 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2818 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2396,6 +2935,19 @@ namespace OpenSim.Region.Framework.Scenes
2396 APIDTarget = Quaternion.Identity; 2935 APIDTarget = Quaternion.Identity;
2397 } 2936 }
2398 2937
2938
2939
2940 public void ScheduleFullUpdateIfNone()
2941 {
2942 if (ParentGroup == null)
2943 return;
2944
2945// ??? ParentGroup.HasGroupChanged = true;
2946
2947 if (UpdateFlag != UpdateRequired.FULL)
2948 ScheduleFullUpdate();
2949 }
2950
2399 /// <summary> 2951 /// <summary>
2400 /// Schedules this prim for a full update 2952 /// Schedules this prim for a full update
2401 /// </summary> 2953 /// </summary>
@@ -2598,8 +3150,8 @@ namespace OpenSim.Region.Framework.Scenes
2598 { 3150 {
2599 const float ROTATION_TOLERANCE = 0.01f; 3151 const float ROTATION_TOLERANCE = 0.01f;
2600 const float VELOCITY_TOLERANCE = 0.001f; 3152 const float VELOCITY_TOLERANCE = 0.001f;
2601 const float POSITION_TOLERANCE = 0.05f; 3153 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2602 const int TIME_MS_TOLERANCE = 3000; 3154 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2603 3155
2604 switch (UpdateFlag) 3156 switch (UpdateFlag)
2605 { 3157 {
@@ -2661,17 +3213,16 @@ namespace OpenSim.Region.Framework.Scenes
2661 if (!UUID.TryParse(sound, out soundID)) 3213 if (!UUID.TryParse(sound, out soundID))
2662 { 3214 {
2663 // search sound file from inventory 3215 // search sound file from inventory
2664 lock (TaskInventory) 3216 TaskInventory.LockItemsForRead(true);
3217 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2665 { 3218 {
2666 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3219 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2667 { 3220 {
2668 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3221 soundID = item.Value.ItemID;
2669 { 3222 break;
2670 soundID = item.Value.ItemID;
2671 break;
2672 }
2673 } 3223 }
2674 } 3224 }
3225 TaskInventory.LockItemsForRead(false);
2675 } 3226 }
2676 3227
2677 if (soundID == UUID.Zero) 3228 if (soundID == UUID.Zero)
@@ -2728,6 +3279,35 @@ namespace OpenSim.Region.Framework.Scenes
2728 } 3279 }
2729 } 3280 }
2730 3281
3282 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
3283 {
3284 if (soundID == UUID.Zero)
3285 return;
3286
3287 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
3288 if (soundModule == null)
3289 return;
3290
3291 if (volume > 1)
3292 volume = 1;
3293 if (volume < 0)
3294 volume = 0;
3295
3296 int now = Util.EnvironmentTickCount();
3297 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
3298 return;
3299
3300 LastColSoundSentTime = now;
3301
3302 UUID ownerID = OwnerID;
3303 UUID objectID = ParentGroup.RootPart.UUID;
3304 UUID parentID = ParentGroup.UUID;
3305 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
3306
3307 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
3308 }
3309
3310
2731 /// <summary> 3311 /// <summary>
2732 /// Send a terse update to all clients 3312 /// Send a terse update to all clients
2733 /// </summary> 3313 /// </summary>
@@ -2756,10 +3336,13 @@ namespace OpenSim.Region.Framework.Scenes
2756 3336
2757 public void SetBuoyancy(float fvalue) 3337 public void SetBuoyancy(float fvalue)
2758 { 3338 {
2759 PhysicsActor pa = PhysActor; 3339 Buoyancy = fvalue;
2760 3340/*
2761 if (pa != null) 3341 if (PhysActor != null)
2762 pa.Buoyancy = fvalue; 3342 {
3343 PhysActor.Buoyancy = fvalue;
3344 }
3345 */
2763 } 3346 }
2764 3347
2765 public void SetDieAtEdge(bool p) 3348 public void SetDieAtEdge(bool p)
@@ -2775,47 +3358,111 @@ namespace OpenSim.Region.Framework.Scenes
2775 PhysicsActor pa = PhysActor; 3358 PhysicsActor pa = PhysActor;
2776 3359
2777 if (pa != null) 3360 if (pa != null)
2778 pa.FloatOnWater = floatYN == 1; 3361 pa.FloatOnWater = (floatYN == 1);
2779 } 3362 }
2780 3363
2781 public void SetForce(Vector3 force) 3364 public void SetForce(Vector3 force)
2782 { 3365 {
2783 PhysicsActor pa = PhysActor; 3366 Force = force;
3367 }
2784 3368
2785 if (pa != null) 3369 public SOPVehicle sopVehicle
2786 pa.Force = force; 3370 {
3371 get
3372 {
3373 return m_vehicle;
3374 }
3375 set
3376 {
3377 m_vehicle = value;
3378 }
3379 }
3380
3381
3382 public int VehicleType
3383 {
3384 get
3385 {
3386 if (m_vehicle == null)
3387 return (int)Vehicle.TYPE_NONE;
3388 else
3389 return (int)m_vehicle.Type;
3390 }
3391 set
3392 {
3393 SetVehicleType(value);
3394 }
2787 } 3395 }
2788 3396
2789 public void SetVehicleType(int type) 3397 public void SetVehicleType(int type)
2790 { 3398 {
2791 PhysicsActor pa = PhysActor; 3399 m_vehicle = null;
3400
3401 if (type == (int)Vehicle.TYPE_NONE)
3402 {
3403 if (_parentID ==0 && PhysActor != null)
3404 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3405 return;
3406 }
3407 m_vehicle = new SOPVehicle();
3408 m_vehicle.ProcessTypeChange((Vehicle)type);
3409 {
3410 if (_parentID ==0 && PhysActor != null)
3411 PhysActor.VehicleType = type;
3412 return;
3413 }
3414 }
2792 3415
2793 if (pa != null) 3416 public void SetVehicleFlags(int param, bool remove)
2794 pa.VehicleType = type; 3417 {
3418 if (m_vehicle == null)
3419 return;
3420
3421 m_vehicle.ProcessVehicleFlags(param, remove);
3422
3423 if (_parentID ==0 && PhysActor != null)
3424 {
3425 PhysActor.VehicleFlags(param, remove);
3426 }
2795 } 3427 }
2796 3428
2797 public void SetVehicleFloatParam(int param, float value) 3429 public void SetVehicleFloatParam(int param, float value)
2798 { 3430 {
2799 PhysicsActor pa = PhysActor; 3431 if (m_vehicle == null)
3432 return;
2800 3433
2801 if (pa != null) 3434 m_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
2802 pa.VehicleFloatParam(param, value); 3435
3436 if (_parentID == 0 && PhysActor != null)
3437 {
3438 PhysActor.VehicleFloatParam(param, value);
3439 }
2803 } 3440 }
2804 3441
2805 public void SetVehicleVectorParam(int param, Vector3 value) 3442 public void SetVehicleVectorParam(int param, Vector3 value)
2806 { 3443 {
2807 PhysicsActor pa = PhysActor; 3444 if (m_vehicle == null)
3445 return;
2808 3446
2809 if (pa != null) 3447 m_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
2810 pa.VehicleVectorParam(param, value); 3448
3449 if (_parentID == 0 && PhysActor != null)
3450 {
3451 PhysActor.VehicleVectorParam(param, value);
3452 }
2811 } 3453 }
2812 3454
2813 public void SetVehicleRotationParam(int param, Quaternion rotation) 3455 public void SetVehicleRotationParam(int param, Quaternion rotation)
2814 { 3456 {
2815 PhysicsActor pa = PhysActor; 3457 if (m_vehicle == null)
3458 return;
2816 3459
2817 if (pa != null) 3460 m_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
2818 pa.VehicleRotationParam(param, rotation); 3461
3462 if (_parentID == 0 && PhysActor != null)
3463 {
3464 PhysActor.VehicleRotationParam(param, rotation);
3465 }
2819 } 3466 }
2820 3467
2821 /// <summary> 3468 /// <summary>
@@ -2999,14 +3646,6 @@ namespace OpenSim.Region.Framework.Scenes
2999 hasProfileCut = hasDimple; // is it the same thing? 3646 hasProfileCut = hasDimple; // is it the same thing?
3000 } 3647 }
3001 3648
3002 public void SetVehicleFlags(int param, bool remove)
3003 {
3004 PhysicsActor pa = PhysActor;
3005
3006 if (pa != null)
3007 pa.VehicleFlags(param, remove);
3008 }
3009
3010 public void SetGroup(UUID groupID, IClientAPI client) 3649 public void SetGroup(UUID groupID, IClientAPI client)
3011 { 3650 {
3012 // Scene.AddNewPrims() calls with client == null so can't use this. 3651 // Scene.AddNewPrims() calls with client == null so can't use this.
@@ -3110,68 +3749,18 @@ namespace OpenSim.Region.Framework.Scenes
3110 //ParentGroup.ScheduleGroupForFullUpdate(); 3749 //ParentGroup.ScheduleGroupForFullUpdate();
3111 } 3750 }
3112 3751
3113 public void StoreUndoState() 3752 public void StoreUndoState(ObjectChangeType change)
3114 { 3753 {
3115 StoreUndoState(false); 3754 if (m_UndoRedo == null)
3116 } 3755 m_UndoRedo = new UndoRedoState(5);
3117 3756
3118 public void StoreUndoState(bool forGroup) 3757 lock (m_UndoRedo)
3119 {
3120 if (!Undoing)
3121 { 3758 {
3122 if (!IgnoreUndoUpdate) 3759 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3123 { 3760 {
3124 if (ParentGroup != null) 3761 m_UndoRedo.StoreUndo(this, change);
3125 {
3126 lock (m_undo)
3127 {
3128 if (m_undo.Count > 0)
3129 {
3130 UndoState last = m_undo.Peek();
3131 if (last != null)
3132 {
3133 // TODO: May need to fix for group comparison
3134 if (last.Compare(this))
3135 {
3136 // m_log.DebugFormat(
3137 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3138 // Name, LocalId, m_undo.Count);
3139
3140 return;
3141 }
3142 }
3143 }
3144
3145 // m_log.DebugFormat(
3146 // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3147 // Name, LocalId, forGroup, m_undo.Count);
3148
3149 if (ParentGroup.GetSceneMaxUndo() > 0)
3150 {
3151 UndoState nUndo = new UndoState(this, forGroup);
3152
3153 m_undo.Push(nUndo);
3154
3155 if (m_redo.Count > 0)
3156 m_redo.Clear();
3157
3158 // m_log.DebugFormat(
3159 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3160 // Name, LocalId, forGroup, m_undo.Count);
3161 }
3162 }
3163 }
3164 } 3762 }
3165// else
3166// {
3167// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3168// }
3169 } 3763 }
3170// else
3171// {
3172// m_log.DebugFormat(
3173// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3174// }
3175 } 3764 }
3176 3765
3177 /// <summary> 3766 /// <summary>
@@ -3181,84 +3770,46 @@ namespace OpenSim.Region.Framework.Scenes
3181 { 3770 {
3182 get 3771 get
3183 { 3772 {
3184 lock (m_undo) 3773 if (m_UndoRedo == null)
3185 return m_undo.Count; 3774 return 0;
3775 return m_UndoRedo.Count;
3186 } 3776 }
3187 } 3777 }
3188 3778
3189 public void Undo() 3779 public void Undo()
3190 { 3780 {
3191 lock (m_undo) 3781 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3192 { 3782 return;
3193// m_log.DebugFormat(
3194// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3195// Name, LocalId, m_undo.Count);
3196
3197 if (m_undo.Count > 0)
3198 {
3199 UndoState goback = m_undo.Pop();
3200
3201 if (goback != null)
3202 {
3203 UndoState nUndo = null;
3204
3205 if (ParentGroup.GetSceneMaxUndo() > 0)
3206 {
3207 nUndo = new UndoState(this, goback.ForGroup);
3208 }
3209
3210 goback.PlaybackState(this);
3211
3212 if (nUndo != null)
3213 m_redo.Push(nUndo);
3214 }
3215 }
3216 3783
3217// m_log.DebugFormat( 3784 lock (m_UndoRedo)
3218// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3785 {
3219// Name, LocalId, m_undo.Count); 3786 Undoing = true;
3787 m_UndoRedo.Undo(this);
3788 Undoing = false;
3220 } 3789 }
3221 } 3790 }
3222 3791
3223 public void Redo() 3792 public void Redo()
3224 { 3793 {
3225 lock (m_undo) 3794 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3226 { 3795 return;
3227// m_log.DebugFormat(
3228// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3229// Name, LocalId, m_redo.Count);
3230
3231 if (m_redo.Count > 0)
3232 {
3233 UndoState gofwd = m_redo.Pop();
3234
3235 if (gofwd != null)
3236 {
3237 if (ParentGroup.GetSceneMaxUndo() > 0)
3238 {
3239 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3240
3241 m_undo.Push(nUndo);
3242 }
3243
3244 gofwd.PlayfwdState(this);
3245 }
3246 3796
3247// m_log.DebugFormat( 3797 lock (m_UndoRedo)
3248// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3798 {
3249// Name, LocalId, m_redo.Count); 3799 Undoing = true;
3250 } 3800 m_UndoRedo.Redo(this);
3801 Undoing = false;
3251 } 3802 }
3252 } 3803 }
3253 3804
3254 public void ClearUndoState() 3805 public void ClearUndoState()
3255 { 3806 {
3256// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3807 if (m_UndoRedo == null || Undoing)
3808 return;
3257 3809
3258 lock (m_undo) 3810 lock (m_UndoRedo)
3259 { 3811 {
3260 m_undo.Clear(); 3812 m_UndoRedo.Clear();
3261 m_redo.Clear();
3262 } 3813 }
3263 } 3814 }
3264 3815
@@ -3888,6 +4439,27 @@ namespace OpenSim.Region.Framework.Scenes
3888 } 4439 }
3889 } 4440 }
3890 4441
4442
4443 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4444 {
4445 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
4446 return;
4447
4448 if (PhysicsShapeType != (byte)physdata.PhysShapeType)
4449 {
4450 PhysicsShapeType = (byte)physdata.PhysShapeType;
4451
4452 }
4453
4454 if(Density != physdata.Density)
4455 Density = physdata.Density;
4456 if(GravityModifier != physdata.GravitationModifier)
4457 GravityModifier = physdata.GravitationModifier;
4458 if(Friction != physdata.Friction)
4459 Friction = physdata.Friction;
4460 if(Bounciness != physdata.Bounce)
4461 Bounciness = physdata.Bounce;
4462 }
3891 /// <summary> 4463 /// <summary>
3892 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. 4464 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
3893 /// </summary> 4465 /// </summary>
@@ -3895,7 +4467,7 @@ namespace OpenSim.Region.Framework.Scenes
3895 /// <param name="SetTemporary"></param> 4467 /// <param name="SetTemporary"></param>
3896 /// <param name="SetPhantom"></param> 4468 /// <param name="SetPhantom"></param>
3897 /// <param name="SetVD"></param> 4469 /// <param name="SetVD"></param>
3898 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4470 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
3899 { 4471 {
3900 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4472 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
3901 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4473 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -3905,237 +4477,230 @@ namespace OpenSim.Region.Framework.Scenes
3905 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4477 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
3906 return; 4478 return;
3907 4479
3908 PhysicsActor pa = PhysActor; 4480 VolumeDetectActive = SetVD;
3909
3910 // Special cases for VD. VD can only be called from a script
3911 // and can't be combined with changes to other states. So we can rely
3912 // that...
3913 // ... if VD is changed, all others are not.
3914 // ... if one of the others is changed, VD is not.
3915 if (SetVD) // VD is active, special logic applies
3916 {
3917 // State machine logic for VolumeDetect
3918 // More logic below
3919 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
3920
3921 if (phanReset) // Phantom changes from on to off switch VD off too
3922 {
3923 SetVD = false; // Switch it of for the course of this routine
3924 VolumeDetectActive = false; // and also permanently
3925
3926 if (pa != null)
3927 pa.SetVolumeDetect(0); // Let physics know about it too
3928 }
3929 else
3930 {
3931 // If volumedetect is active we don't want phantom to be applied.
3932 // If this is a new call to VD out of the state "phantom"
3933 // this will also cause the prim to be visible to physics
3934 SetPhantom = false;
3935 }
3936 }
3937 4481
3938 if (UsePhysics && IsJoint()) 4482 // volume detector implies phantom
3939 { 4483 if (VolumeDetectActive)
3940 SetPhantom = true; 4484 SetPhantom = true;
3941 }
3942 4485
3943 if (UsePhysics) 4486 if (UsePhysics)
3944 {
3945 AddFlag(PrimFlags.Physics); 4487 AddFlag(PrimFlags.Physics);
3946 if (!wasUsingPhysics)
3947 {
3948 DoPhysicsPropertyUpdate(UsePhysics, false);
3949
3950 if (!ParentGroup.IsDeleted)
3951 {
3952 if (LocalId == ParentGroup.RootPart.LocalId)
3953 {
3954 ParentGroup.CheckSculptAndLoad();
3955 }
3956 }
3957 }
3958 }
3959 else 4488 else
3960 {
3961 RemFlag(PrimFlags.Physics); 4489 RemFlag(PrimFlags.Physics);
3962 if (wasUsingPhysics)
3963 {
3964 DoPhysicsPropertyUpdate(UsePhysics, false);
3965 }
3966 }
3967 4490
3968 if (SetPhantom 4491 if (SetPhantom)
3969 || ParentGroup.IsAttachment
3970 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
3971 {
3972 AddFlag(PrimFlags.Phantom); 4492 AddFlag(PrimFlags.Phantom);
3973 4493 else
3974 if (PhysActor != null)
3975 {
3976 RemoveFromPhysics();
3977 pa = null;
3978 }
3979 }
3980 else // Not phantom
3981 {
3982 RemFlag(PrimFlags.Phantom); 4494 RemFlag(PrimFlags.Phantom);
3983 4495
3984 if (ParentGroup.Scene == null) 4496 if (SetTemporary)
3985 return; 4497 AddFlag(PrimFlags.TemporaryOnRez);
4498 else
4499 RemFlag(PrimFlags.TemporaryOnRez);
3986 4500
3987 if (ParentGroup.Scene.CollidablePrims && pa == null)
3988 {
3989 pa = AddToPhysics(UsePhysics);
3990 4501
3991 if (pa != null) 4502 if (ParentGroup.Scene == null)
3992 { 4503 return;
3993 pa.SetMaterial(Material);
3994 DoPhysicsPropertyUpdate(UsePhysics, true);
3995
3996 if (!ParentGroup.IsDeleted)
3997 {
3998 if (LocalId == ParentGroup.RootPart.LocalId)
3999 {
4000 ParentGroup.CheckSculptAndLoad();
4001 }
4002 }
4003
4004 if (
4005 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4006 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4007 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4008 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4009 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4010 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4011 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4012 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4013 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4014 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4015 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4016 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4017 (CollisionSound != UUID.Zero)
4018 )
4019 {
4020 pa.OnCollisionUpdate += PhysicsCollision;
4021 pa.SubscribeEvents(1000);
4022 }
4023 }
4024 }
4025 else // it already has a physical representation
4026 {
4027 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4028 4504
4029 if (!ParentGroup.IsDeleted) 4505 PhysicsActor pa = PhysActor;
4030 {
4031 if (LocalId == ParentGroup.RootPart.LocalId)
4032 {
4033 ParentGroup.CheckSculptAndLoad();
4034 }
4035 }
4036 }
4037 }
4038 4506
4039 if (SetVD) 4507 if (pa != null && building && pa.Building != building)
4508 pa.Building = building;
4509
4510 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4511 || (Shape.PathCurve == (byte)Extrusion.Flexible))
4040 { 4512 {
4041 // If the above logic worked (this is urgent candidate to unit tests!)
4042 // we now have a physicsactor.
4043 // Defensive programming calls for a check here.
4044 // Better would be throwing an exception that could be catched by a unit test as the internal
4045 // logic should make sure, this Physactor is always here.
4046 if (pa != null) 4513 if (pa != null)
4047 { 4514 {
4048 pa.SetVolumeDetect(1); 4515 ParentGroup.Scene.RemovePhysicalPrim(1);
4049 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4516 RemoveFromPhysics();
4050 VolumeDetectActive = true;
4051 } 4517 }
4518
4519 Velocity = new Vector3(0, 0, 0);
4520 Acceleration = new Vector3(0, 0, 0);
4521 if (ParentGroup.RootPart == this)
4522 AngularVelocity = new Vector3(0, 0, 0);
4052 } 4523 }
4053 else 4524 else
4054 { 4525 {
4055 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like 4526 if (ParentGroup.Scene.CollidablePrims)
4056 // (mumbles, well, at least if you have infinte CPU powers :-)) 4527 {
4057 if (pa != null) 4528 if (pa == null)
4058 pa.SetVolumeDetect(0); 4529 {
4530 AddToPhysics(UsePhysics, SetPhantom, building, false);
4531 pa = PhysActor;
4532 /*
4533 if (pa != null)
4534 {
4535 if (
4536 // ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4537 // ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4538 // ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4539 // ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4540 // ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4541 // ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4542 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4543 ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4544 (CollisionSound != UUID.Zero)
4545 )
4546 {
4547 pa.OnCollisionUpdate += PhysicsCollision;
4548 pa.SubscribeEvents(1000);
4549 }
4550 }
4551 */
4552 }
4553 else // it already has a physical representation
4554 {
4555 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4556 /* moved into DoPhysicsPropertyUpdate
4557 if(VolumeDetectActive)
4558 pa.SetVolumeDetect(1);
4559 else
4560 pa.SetVolumeDetect(0);
4561 */
4059 4562
4060 VolumeDetectActive = false;
4061 }
4062 4563
4063 if (SetTemporary) 4564 if (pa.Building != building)
4064 { 4565 pa.Building = building;
4065 AddFlag(PrimFlags.TemporaryOnRez); 4566 }
4066 } 4567
4067 else 4568 UpdatePhysicsSubscribedEvents();
4068 { 4569 }
4069 RemFlag(PrimFlags.TemporaryOnRez); 4570 }
4070 }
4071 4571
4072 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4572 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4073 4573
4574 // and last in case we have a new actor and not building
4575
4074 if (ParentGroup != null) 4576 if (ParentGroup != null)
4075 { 4577 {
4076 ParentGroup.HasGroupChanged = true; 4578 ParentGroup.HasGroupChanged = true;
4077 ScheduleFullUpdate(); 4579 ScheduleFullUpdate();
4078 } 4580 }
4079 4581
4080// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4582// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4081 } 4583 }
4082 4584
4083 /// <summary> 4585 /// <summary>
4084 /// Adds this part to the physics scene. 4586 /// Adds this part to the physics scene.
4587 /// and sets the PhysActor property
4085 /// </summary> 4588 /// </summary>
4086 /// <remarks>This method also sets the PhysActor property.</remarks> 4589 /// <param name="isPhysical">Add this prim as physical.</param>
4087 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4590 /// <param name="isPhantom">Add this prim as phantom.</param>
4088 /// <returns> 4591 /// <param name="building">tells physics to delay full construction of object</param>
4089 /// The physics actor. null if there was a failure. 4592 /// <param name="applyDynamics">applies velocities, force and torque</param>
4090 /// </returns> 4593 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4091 private PhysicsActor AddToPhysics(bool rigidBody) 4594 {
4092 {
4093 PhysicsActor pa; 4595 PhysicsActor pa;
4094 4596
4597 Vector3 velocity = Velocity;
4598 Vector3 rotationalVelocity = AngularVelocity;;
4599
4095 try 4600 try
4096 { 4601 {
4097 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4602 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4098 string.Format("{0}/{1}", Name, UUID), 4603 string.Format("{0}/{1}", Name, UUID),
4099 Shape, 4604 Shape,
4100 AbsolutePosition, 4605 AbsolutePosition,
4101 Scale, 4606 Scale,
4102 RotationOffset, 4607 GetWorldRotation(),
4103 rigidBody, 4608 isPhysical,
4104 m_localId); 4609 isPhantom,
4610 PhysicsShapeType,
4611 m_localId);
4105 } 4612 }
4106 catch 4613 catch (Exception ex)
4107 { 4614 {
4108 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); 4615 m_log.ErrorFormat("[SCENE]: AddToPhysics object {0} failed: {1}", m_uuid, ex.Message);
4109 pa = null; 4616 pa = null;
4110 } 4617 }
4111 4618
4112 // FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical
4113 // properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor
4114 // being set.
4115 PhysActor = pa;
4116
4117 // Basic Physics can also return null as well as an exception catch.
4118 if (pa != null) 4619 if (pa != null)
4119 { 4620 {
4120 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4621 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
4121 pa.SetMaterial(Material); 4622 pa.SetMaterial(Material);
4122 DoPhysicsPropertyUpdate(rigidBody, true); 4623
4624 if (VolumeDetectActive) // change if not the default only
4625 pa.SetVolumeDetect(1);
4626
4627 if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
4628 m_vehicle.SetVehicle(pa);
4629
4630 // we are going to tell rest of code about physics so better have this here
4631 PhysActor = pa;
4632
4633 // DoPhysicsPropertyUpdate(isPhysical, true);
4634 // lets expand it here just with what it really needs to do
4635
4636 if (isPhysical)
4637 {
4638 if (ParentGroup.RootPart.KeyframeMotion != null)
4639 ParentGroup.RootPart.KeyframeMotion.Stop();
4640 ParentGroup.RootPart.KeyframeMotion = null;
4641 ParentGroup.Scene.AddPhysicalPrim(1);
4642
4643 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
4644 pa.OnOutOfBounds += PhysicsOutOfBounds;
4645
4646 if (ParentID != 0 && ParentID != LocalId)
4647 {
4648 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
4649
4650 if (parentPa != null)
4651 {
4652 pa.link(parentPa);
4653 }
4654 }
4655 }
4656
4657 if (applyDynamics)
4658 // do independent of isphysical so parameters get setted (at least some)
4659 {
4660 Velocity = velocity;
4661 AngularVelocity = rotationalVelocity;
4662// pa.Velocity = velocity;
4663 pa.RotationalVelocity = rotationalVelocity;
4664
4665 // if not vehicle and root part apply force and torque
4666 if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE)
4667 && LocalId == ParentGroup.RootPart.LocalId)
4668 {
4669 pa.Force = Force;
4670 pa.Torque = Torque;
4671 }
4672 }
4673
4674 if (Shape.SculptEntry)
4675 CheckSculptAndLoad();
4676 else
4677 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4678
4679 if (!building)
4680 pa.Building = false;
4123 } 4681 }
4124 4682
4125 return pa; 4683 PhysActor = pa;
4126 } 4684 }
4127 4685
4128 /// <summary> 4686 /// <summary>
4129 /// This removes the part from the physics scene. 4687 /// This removes the part from the physics scene.
4130 /// </summary> 4688 /// </summary>
4131 /// <remarks> 4689 /// <remarks>
4132 /// This isn't the same as turning off physical, since even without being physical the prim has a physics 4690 /// This isn't the same as turning off physical, since even without being physical the prim has a physics
4133 /// representation for collision detection. Rather, this would be used in situations such as making a prim 4691 /// representation for collision detection.
4134 /// phantom.
4135 /// </remarks> 4692 /// </remarks>
4136 public void RemoveFromPhysics() 4693 public void RemoveFromPhysics()
4137 { 4694 {
4138 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 4695 PhysicsActor pa = PhysActor;
4696 if (pa != null)
4697 {
4698 pa.OnCollisionUpdate -= PhysicsCollision;
4699 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
4700 pa.OnOutOfBounds -= PhysicsOutOfBounds;
4701
4702 ParentGroup.Scene.PhysicsScene.RemovePrim(pa);
4703 }
4139 PhysActor = null; 4704 PhysActor = null;
4140 } 4705 }
4141 4706
@@ -4295,6 +4860,44 @@ namespace OpenSim.Region.Framework.Scenes
4295 ScheduleFullUpdate(); 4860 ScheduleFullUpdate();
4296 } 4861 }
4297 4862
4863
4864 private void UpdatePhysicsSubscribedEvents()
4865 {
4866 PhysicsActor pa = PhysActor;
4867 if (pa == null)
4868 return;
4869
4870 pa.OnCollisionUpdate -= PhysicsCollision;
4871
4872 bool hassound = (CollisionSoundType >= 0 && !VolumeDetectActive);
4873
4874 scriptEvents CombinedEvents = AggregateScriptEvents;
4875
4876 // merge with root part
4877 if (ParentGroup != null && ParentGroup.RootPart != null)
4878 CombinedEvents |= ParentGroup.RootPart.AggregateScriptEvents;
4879
4880 // submit to this part case
4881 if (VolumeDetectActive)
4882 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
4883 else if ((Flags & PrimFlags.Phantom) != 0)
4884 CombinedEvents &= PhyscicsPhantonSubsEvents;
4885 else
4886 CombinedEvents &= PhysicsNeededSubsEvents;
4887
4888 if (hassound || CombinedEvents != 0)
4889 {
4890 // subscribe to physics updates.
4891 pa.OnCollisionUpdate += PhysicsCollision;
4892 pa.SubscribeEvents(50); // 20 reports per second
4893 }
4894 else
4895 {
4896 pa.UnSubscribeEvents();
4897 }
4898 }
4899
4900
4298 public void aggregateScriptEvents() 4901 public void aggregateScriptEvents()
4299 { 4902 {
4300 if (ParentGroup == null || ParentGroup.RootPart == null) 4903 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4331,40 +4934,32 @@ namespace OpenSim.Region.Framework.Scenes
4331 { 4934 {
4332 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 4935 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4333 } 4936 }
4334 4937/*
4335 PhysicsActor pa = PhysActor; 4938 PhysicsActor pa = PhysActor;
4336 4939 if (pa != null)
4337 if (
4338 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4339 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4340 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4341 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4342 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4343 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4344 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4345 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4346 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4347 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4348 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4349 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4350 (CollisionSound != UUID.Zero)
4351 )
4352 { 4940 {
4353 // subscribe to physics updates. 4941 if (
4354 if (pa != null) 4942// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4943// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4944// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4945// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4946// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4947// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4948 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
4949 )
4355 { 4950 {
4951 // subscribe to physics updates.
4356 pa.OnCollisionUpdate += PhysicsCollision; 4952 pa.OnCollisionUpdate += PhysicsCollision;
4357 pa.SubscribeEvents(1000); 4953 pa.SubscribeEvents(1000);
4358 } 4954 }
4359 } 4955 else
4360 else
4361 {
4362 if (pa != null)
4363 { 4956 {
4364 pa.UnSubscribeEvents(); 4957 pa.UnSubscribeEvents();
4365 pa.OnCollisionUpdate -= PhysicsCollision; 4958 pa.OnCollisionUpdate -= PhysicsCollision;
4366 } 4959 }
4367 } 4960 }
4961 */
4962 UpdatePhysicsSubscribedEvents();
4368 4963
4369 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 4964 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4370 //{ 4965 //{
@@ -4493,5 +5088,17 @@ namespace OpenSim.Region.Framework.Scenes
4493 Color color = Color; 5088 Color color = Color;
4494 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5089 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4495 } 5090 }
5091
5092 public void ResetOwnerChangeFlag()
5093 {
5094 List<UUID> inv = Inventory.GetInventoryList();
5095
5096 foreach (UUID itemID in inv)
5097 {
5098 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5099 item.OwnerChanged = false;
5100 Inventory.UpdateInventoryItem(item, false, false);
5101 }
5102 }
4496 } 5103 }
4497} 5104}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 866311a..1dff088 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -48,6 +48,9 @@ namespace OpenSim.Region.Framework.Scenes
48 private string m_inventoryFileName = String.Empty; 48 private string m_inventoryFileName = String.Empty;
49 private byte[] m_inventoryFileData = new byte[0]; 49 private byte[] m_inventoryFileData = new byte[0];
50 private uint m_inventoryFileNameSerial = 0; 50 private uint m_inventoryFileNameSerial = 0;
51 private bool m_inventoryPrivileged = false;
52
53 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
51 54
52 /// <value> 55 /// <value>
53 /// The part to which the inventory belongs. 56 /// The part to which the inventory belongs.
@@ -84,7 +87,9 @@ namespace OpenSim.Region.Framework.Scenes
84 /// </value> 87 /// </value>
85 protected internal TaskInventoryDictionary Items 88 protected internal TaskInventoryDictionary Items
86 { 89 {
87 get { return m_items; } 90 get {
91 return m_items;
92 }
88 set 93 set
89 { 94 {
90 m_items = value; 95 m_items = value;
@@ -124,38 +129,45 @@ namespace OpenSim.Region.Framework.Scenes
124 public void ResetInventoryIDs() 129 public void ResetInventoryIDs()
125 { 130 {
126 if (null == m_part) 131 if (null == m_part)
127 return; 132 m_items.LockItemsForWrite(true);
128 133
129 lock (m_items) 134 if (Items.Count == 0)
130 { 135 {
131 if (0 == m_items.Count) 136 m_items.LockItemsForWrite(false);
132 return; 137 return;
138 }
133 139
134 IList<TaskInventoryItem> items = GetInventoryItems(); 140 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
135 m_items.Clear(); 141 Items.Clear();
136 142
137 foreach (TaskInventoryItem item in items) 143 foreach (TaskInventoryItem item in items)
138 { 144 {
139 item.ResetIDs(m_part.UUID); 145 item.ResetIDs(m_part.UUID);
140 m_items.Add(item.ItemID, item); 146 Items.Add(item.ItemID, item);
141 }
142 } 147 }
148 m_items.LockItemsForWrite(false);
143 } 149 }
144 150
145 public void ResetObjectID() 151 public void ResetObjectID()
146 { 152 {
147 lock (Items) 153 m_items.LockItemsForWrite(true);
154
155 if (Items.Count == 0)
148 { 156 {
149 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 157 m_items.LockItemsForWrite(false);
150 Items.Clear(); 158 return;
151
152 foreach (TaskInventoryItem item in items)
153 {
154 item.ParentPartID = m_part.UUID;
155 item.ParentID = m_part.UUID;
156 Items.Add(item.ItemID, item);
157 }
158 } 159 }
160
161 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
162 Items.Clear();
163
164 foreach (TaskInventoryItem item in items)
165 {
166 item.ParentPartID = m_part.UUID;
167 item.ParentID = m_part.UUID;
168 Items.Add(item.ItemID, item);
169 }
170 m_items.LockItemsForWrite(false);
159 } 171 }
160 172
161 /// <summary> 173 /// <summary>
@@ -164,17 +176,14 @@ namespace OpenSim.Region.Framework.Scenes
164 /// <param name="ownerId"></param> 176 /// <param name="ownerId"></param>
165 public void ChangeInventoryOwner(UUID ownerId) 177 public void ChangeInventoryOwner(UUID ownerId)
166 { 178 {
167 lock (Items) 179 List<TaskInventoryItem> items = GetInventoryItems();
168 { 180
169 if (0 == Items.Count) 181 if (items.Count == 0)
170 { 182 return;
171 return;
172 }
173 }
174 183
184 m_items.LockItemsForWrite(true);
175 HasInventoryChanged = true; 185 HasInventoryChanged = true;
176 m_part.ParentGroup.HasGroupChanged = true; 186 m_part.ParentGroup.HasGroupChanged = true;
177 List<TaskInventoryItem> items = GetInventoryItems();
178 foreach (TaskInventoryItem item in items) 187 foreach (TaskInventoryItem item in items)
179 { 188 {
180 if (ownerId != item.OwnerID) 189 if (ownerId != item.OwnerID)
@@ -185,6 +194,7 @@ namespace OpenSim.Region.Framework.Scenes
185 item.PermsGranter = UUID.Zero; 194 item.PermsGranter = UUID.Zero;
186 item.OwnerChanged = true; 195 item.OwnerChanged = true;
187 } 196 }
197 m_items.LockItemsForWrite(false);
188 } 198 }
189 199
190 /// <summary> 200 /// <summary>
@@ -193,12 +203,11 @@ namespace OpenSim.Region.Framework.Scenes
193 /// <param name="groupID"></param> 203 /// <param name="groupID"></param>
194 public void ChangeInventoryGroup(UUID groupID) 204 public void ChangeInventoryGroup(UUID groupID)
195 { 205 {
196 lock (Items) 206 m_items.LockItemsForWrite(true);
207 if (0 == Items.Count)
197 { 208 {
198 if (0 == Items.Count) 209 m_items.LockItemsForWrite(false);
199 { 210 return;
200 return;
201 }
202 } 211 }
203 212
204 // Don't let this set the HasGroupChanged flag for attachments 213 // Don't let this set the HasGroupChanged flag for attachments
@@ -210,12 +219,15 @@ namespace OpenSim.Region.Framework.Scenes
210 m_part.ParentGroup.HasGroupChanged = true; 219 m_part.ParentGroup.HasGroupChanged = true;
211 } 220 }
212 221
213 List<TaskInventoryItem> items = GetInventoryItems(); 222 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
214 foreach (TaskInventoryItem item in items) 223 foreach (TaskInventoryItem item in items)
215 { 224 {
216 if (groupID != item.GroupID) 225 if (groupID != item.GroupID)
226 {
217 item.GroupID = groupID; 227 item.GroupID = groupID;
228 }
218 } 229 }
230 m_items.LockItemsForWrite(false);
219 } 231 }
220 232
221 private void QueryScriptStates() 233 private void QueryScriptStates()
@@ -227,25 +239,25 @@ namespace OpenSim.Region.Framework.Scenes
227 if (engines == null) // No engine at all 239 if (engines == null) // No engine at all
228 return; 240 return;
229 241
230 lock (Items) 242 Items.LockItemsForRead(true);
243 foreach (TaskInventoryItem item in Items.Values)
231 { 244 {
232 foreach (TaskInventoryItem item in Items.Values) 245 if (item.InvType == (int)InventoryType.LSL)
233 { 246 {
234 if (item.InvType == (int)InventoryType.LSL) 247 foreach (IScriptModule e in engines)
235 { 248 {
236 foreach (IScriptModule e in engines) 249 bool running;
237 {
238 bool running;
239 250
240 if (e.HasScript(item.ItemID, out running)) 251 if (e.HasScript(item.ItemID, out running))
241 { 252 {
242 item.ScriptRunning = running; 253 item.ScriptRunning = running;
243 break; 254 break;
244 }
245 } 255 }
246 } 256 }
247 } 257 }
248 } 258 }
259
260 Items.LockItemsForRead(false);
249 } 261 }
250 262
251 public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 263 public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
@@ -290,7 +302,10 @@ namespace OpenSim.Region.Framework.Scenes
290 { 302 {
291 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL); 303 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
292 foreach (TaskInventoryItem item in scripts) 304 foreach (TaskInventoryItem item in scripts)
305 {
293 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 306 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
307 m_part.RemoveScriptEvents(item.ItemID);
308 }
294 } 309 }
295 310
296 /// <summary> 311 /// <summary>
@@ -304,7 +319,10 @@ namespace OpenSim.Region.Framework.Scenes
304// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName); 319// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName);
305 320
306 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 321 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
322 {
323 StoreScriptError(item.ItemID, "no permission");
307 return false; 324 return false;
325 }
308 326
309 m_part.AddFlag(PrimFlags.Scripted); 327 m_part.AddFlag(PrimFlags.Scripted);
310 328
@@ -314,14 +332,13 @@ namespace OpenSim.Region.Framework.Scenes
314 if (stateSource == 2 && // Prim crossing 332 if (stateSource == 2 && // Prim crossing
315 m_part.ParentGroup.Scene.m_trustBinaries) 333 m_part.ParentGroup.Scene.m_trustBinaries)
316 { 334 {
317 lock (m_items) 335 m_items.LockItemsForWrite(true);
318 { 336 m_items[item.ItemID].PermsMask = 0;
319 m_items[item.ItemID].PermsMask = 0; 337 m_items[item.ItemID].PermsGranter = UUID.Zero;
320 m_items[item.ItemID].PermsGranter = UUID.Zero; 338 m_items.LockItemsForWrite(false);
321 }
322
323 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 339 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
324 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 340 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
341 StoreScriptErrors(item.ItemID, null);
325 m_part.ParentGroup.AddActiveScriptCount(1); 342 m_part.ParentGroup.AddActiveScriptCount(1);
326 m_part.ScheduleFullUpdate(); 343 m_part.ScheduleFullUpdate();
327 return true; 344 return true;
@@ -342,16 +359,25 @@ namespace OpenSim.Region.Framework.Scenes
342 if (m_part.ParentGroup.m_savedScriptState != null) 359 if (m_part.ParentGroup.m_savedScriptState != null)
343 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); 360 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
344 361
345 lock (m_items) 362 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
346 { 363 StoreScriptError(item.ItemID, msg);
347 m_items[item.ItemID].OldItemID = item.OldItemID; 364 m_log.ErrorFormat(
348 m_items[item.ItemID].PermsMask = 0; 365 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
349 m_items[item.ItemID].PermsGranter = UUID.Zero; 366 item.Name, item.ItemID, m_part.AbsolutePosition,
350 } 367 m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID);
368
369 m_items.LockItemsForWrite(true);
351 370
371 m_items[item.ItemID].OldItemID = item.OldItemID;
372 m_items[item.ItemID].PermsMask = 0;
373 m_items[item.ItemID].PermsGranter = UUID.Zero;
374
375 m_items.LockItemsForWrite(false);
376
352 string script = Utils.BytesToString(asset.Data); 377 string script = Utils.BytesToString(asset.Data);
353 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 378 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
354 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 379 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
380 StoreScriptErrors(item.ItemID, null);
355 if (!item.ScriptRunning) 381 if (!item.ScriptRunning)
356 m_part.ParentGroup.Scene.EventManager.TriggerStopScript( 382 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
357 m_part.LocalId, item.ItemID); 383 m_part.LocalId, item.ItemID);
@@ -424,22 +450,149 @@ namespace OpenSim.Region.Framework.Scenes
424 return stateID; 450 return stateID;
425 } 451 }
426 452
453 /// <summary>
454 /// Start a script which is in this prim's inventory.
455 /// Some processing may occur in the background, but this routine returns asap.
456 /// </summary>
457 /// <param name="itemId">
458 /// A <see cref="UUID"/>
459 /// </param>
427 public bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 460 public bool CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
428 { 461 {
429 TaskInventoryItem item = GetInventoryItem(itemId); 462 lock (m_scriptErrors)
430 if (item != null)
431 { 463 {
432 return CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 464 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
465 m_scriptErrors.Remove(itemId);
466 }
467 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
468 return true;
469 }
470
471 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
472 {
473 m_items.LockItemsForRead(true);
474 if (m_items.ContainsKey(itemId))
475 {
476 if (m_items.ContainsKey(itemId))
477 {
478 m_items.LockItemsForRead(false);
479 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
480 }
481 else
482 {
483 m_items.LockItemsForRead(false);
484 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
485 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
486 StoreScriptError(itemId, msg);
487 m_log.ErrorFormat(
488 "[PRIM INVENTORY]: " +
489 "Couldn't start script with ID {0} since it {1}", itemId, msg);
490 }
433 } 491 }
434 else 492 else
435 { 493 {
494 m_items.LockItemsForRead(false);
495 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
496 StoreScriptError(itemId, msg);
436 m_log.ErrorFormat( 497 m_log.ErrorFormat(
437 "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 498 "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
438 itemId, m_part.Name, m_part.UUID, 499 itemId, m_part.Name, m_part.UUID,
439 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 500 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
501 }
502
503 }
440 504
441 return false; 505 /// <summary>
506 /// Start a script which is in this prim's inventory and return any compilation error messages.
507 /// </summary>
508 /// <param name="itemId">
509 /// A <see cref="UUID"/>
510 /// </param>
511 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
512 {
513 ArrayList errors;
514
515 // Indicate to CreateScriptInstanceInternal() we want it to
516 // post any compilation/loading error messages
517 lock (m_scriptErrors)
518 {
519 m_scriptErrors[itemId] = null;
520 }
521
522 // Perform compilation/loading
523 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
524
525 // Wait for and retrieve any errors
526 lock (m_scriptErrors)
527 {
528 while ((errors = m_scriptErrors[itemId]) == null)
529 {
530 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
531 {
532 m_log.ErrorFormat(
533 "[PRIM INVENTORY]: " +
534 "timedout waiting for script {0} errors", itemId);
535 errors = m_scriptErrors[itemId];
536 if (errors == null)
537 {
538 errors = new ArrayList(1);
539 errors.Add("timedout waiting for errors");
540 }
541 break;
542 }
543 }
544 m_scriptErrors.Remove(itemId);
545 }
546 return errors;
547 }
548
549 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
550 private void StoreScriptErrors(UUID itemId, ArrayList errors)
551 {
552 lock (m_scriptErrors)
553 {
554 // If compilation/loading initiated via CreateScriptInstance(),
555 // it does not want the errors, so just get out
556 if (!m_scriptErrors.ContainsKey(itemId))
557 {
558 return;
559 }
560
561 // Initiated via CreateScriptInstanceEr(), if we know what the
562 // errors are, save them and wake CreateScriptInstanceEr().
563 if (errors != null)
564 {
565 m_scriptErrors[itemId] = errors;
566 System.Threading.Monitor.PulseAll(m_scriptErrors);
567 return;
568 }
442 } 569 }
570
571 // Initiated via CreateScriptInstanceEr() but we don't know what
572 // the errors are yet, so retrieve them from the script engine.
573 // This may involve some waiting internal to GetScriptErrors().
574 errors = GetScriptErrors(itemId);
575
576 // Get a default non-null value to indicate success.
577 if (errors == null)
578 {
579 errors = new ArrayList();
580 }
581
582 // Post to CreateScriptInstanceEr() and wake it up
583 lock (m_scriptErrors)
584 {
585 m_scriptErrors[itemId] = errors;
586 System.Threading.Monitor.PulseAll(m_scriptErrors);
587 }
588 }
589
590 // Like StoreScriptErrors(), but just posts a single string message
591 private void StoreScriptError(UUID itemId, string message)
592 {
593 ArrayList errors = new ArrayList(1);
594 errors.Add(message);
595 StoreScriptErrors(itemId, errors);
443 } 596 }
444 597
445 /// <summary> 598 /// <summary>
@@ -452,15 +605,7 @@ namespace OpenSim.Region.Framework.Scenes
452 /// </param> 605 /// </param>
453 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 606 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
454 { 607 {
455 bool scriptPresent = false; 608 if (m_items.ContainsKey(itemId))
456
457 lock (m_items)
458 {
459 if (m_items.ContainsKey(itemId))
460 scriptPresent = true;
461 }
462
463 if (scriptPresent)
464 { 609 {
465 if (!sceneObjectBeingDeleted) 610 if (!sceneObjectBeingDeleted)
466 m_part.RemoveScriptEvents(itemId); 611 m_part.RemoveScriptEvents(itemId);
@@ -485,14 +630,16 @@ namespace OpenSim.Region.Framework.Scenes
485 /// <returns></returns> 630 /// <returns></returns>
486 private bool InventoryContainsName(string name) 631 private bool InventoryContainsName(string name)
487 { 632 {
488 lock (m_items) 633 m_items.LockItemsForRead(true);
634 foreach (TaskInventoryItem item in m_items.Values)
489 { 635 {
490 foreach (TaskInventoryItem item in m_items.Values) 636 if (item.Name == name)
491 { 637 {
492 if (item.Name == name) 638 m_items.LockItemsForRead(false);
493 return true; 639 return true;
494 } 640 }
495 } 641 }
642 m_items.LockItemsForRead(false);
496 return false; 643 return false;
497 } 644 }
498 645
@@ -534,8 +681,9 @@ namespace OpenSim.Region.Framework.Scenes
534 /// <param name="item"></param> 681 /// <param name="item"></param>
535 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 682 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
536 { 683 {
537 List<TaskInventoryItem> il = GetInventoryItems(); 684 m_items.LockItemsForRead(true);
538 685 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
686 m_items.LockItemsForRead(false);
539 foreach (TaskInventoryItem i in il) 687 foreach (TaskInventoryItem i in il)
540 { 688 {
541 if (i.Name == item.Name) 689 if (i.Name == item.Name)
@@ -573,14 +721,14 @@ namespace OpenSim.Region.Framework.Scenes
573 item.Name = name; 721 item.Name = name;
574 item.GroupID = m_part.GroupID; 722 item.GroupID = m_part.GroupID;
575 723
576 lock (m_items) 724 m_items.LockItemsForWrite(true);
577 m_items.Add(item.ItemID, item); 725 m_items.Add(item.ItemID, item);
578 726 m_items.LockItemsForWrite(false);
579 if (allowedDrop) 727 if (allowedDrop)
580 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 728 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
581 else 729 else
582 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 730 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
583 731
584 m_inventorySerial++; 732 m_inventorySerial++;
585 //m_inventorySerial += 2; 733 //m_inventorySerial += 2;
586 HasInventoryChanged = true; 734 HasInventoryChanged = true;
@@ -596,15 +744,15 @@ namespace OpenSim.Region.Framework.Scenes
596 /// <param name="items"></param> 744 /// <param name="items"></param>
597 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 745 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
598 { 746 {
599 lock (m_items) 747 m_items.LockItemsForWrite(true);
748 foreach (TaskInventoryItem item in items)
600 { 749 {
601 foreach (TaskInventoryItem item in items) 750 m_items.Add(item.ItemID, item);
602 { 751// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
603 m_items.Add(item.ItemID, item);
604// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
605 }
606 m_inventorySerial++;
607 } 752 }
753 m_items.LockItemsForWrite(false);
754
755 m_inventorySerial++;
608 } 756 }
609 757
610 /// <summary> 758 /// <summary>
@@ -615,23 +763,24 @@ namespace OpenSim.Region.Framework.Scenes
615 public TaskInventoryItem GetInventoryItem(UUID itemId) 763 public TaskInventoryItem GetInventoryItem(UUID itemId)
616 { 764 {
617 TaskInventoryItem item; 765 TaskInventoryItem item;
618 766 m_items.LockItemsForRead(true);
619 lock (m_items) 767 m_items.TryGetValue(itemId, out item);
620 m_items.TryGetValue(itemId, out item); 768 m_items.LockItemsForRead(false);
621
622 return item; 769 return item;
623 } 770 }
624 771
625 public TaskInventoryItem GetInventoryItem(string name) 772 public TaskInventoryItem GetInventoryItem(string name)
626 { 773 {
627 lock (m_items) 774 m_items.LockItemsForRead(true);
775 foreach (TaskInventoryItem item in m_items.Values)
628 { 776 {
629 foreach (TaskInventoryItem item in m_items.Values) 777 if (item.Name == name)
630 { 778 {
631 if (item.Name == name) 779 m_items.LockItemsForRead(false);
632 return item; 780 return item;
633 } 781 }
634 } 782 }
783 m_items.LockItemsForRead(false);
635 784
636 return null; 785 return null;
637 } 786 }
@@ -640,15 +789,16 @@ namespace OpenSim.Region.Framework.Scenes
640 { 789 {
641 List<TaskInventoryItem> items = new List<TaskInventoryItem>(); 790 List<TaskInventoryItem> items = new List<TaskInventoryItem>();
642 791
643 lock (m_items) 792 m_items.LockItemsForRead(true);
793
794 foreach (TaskInventoryItem item in m_items.Values)
644 { 795 {
645 foreach (TaskInventoryItem item in m_items.Values) 796 if (item.Name == name)
646 { 797 items.Add(item);
647 if (item.Name == name)
648 items.Add(item);
649 }
650 } 798 }
651 799
800 m_items.LockItemsForRead(false);
801
652 return items; 802 return items;
653 } 803 }
654 804
@@ -667,6 +817,10 @@ namespace OpenSim.Region.Framework.Scenes
667 string xmlData = Utils.BytesToString(rezAsset.Data); 817 string xmlData = Utils.BytesToString(rezAsset.Data);
668 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 818 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
669 819
820 group.RootPart.AttachPoint = group.RootPart.Shape.State;
821 group.RootPart.AttachOffset = group.AbsolutePosition;
822 group.RootPart.AttachRotation = group.GroupRotation;
823
670 group.ResetIDs(); 824 group.ResetIDs();
671 825
672 SceneObjectPart rootPart = group.GetPart(group.UUID); 826 SceneObjectPart rootPart = group.GetPart(group.UUID);
@@ -741,8 +895,9 @@ namespace OpenSim.Region.Framework.Scenes
741 895
742 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 896 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
743 { 897 {
744 TaskInventoryItem it = GetInventoryItem(item.ItemID); 898 m_items.LockItemsForWrite(true);
745 if (it != null) 899
900 if (m_items.ContainsKey(item.ItemID))
746 { 901 {
747// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 902// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
748 903
@@ -755,14 +910,10 @@ namespace OpenSim.Region.Framework.Scenes
755 item.GroupID = m_part.GroupID; 910 item.GroupID = m_part.GroupID;
756 911
757 if (item.AssetID == UUID.Zero) 912 if (item.AssetID == UUID.Zero)
758 item.AssetID = it.AssetID; 913 item.AssetID = m_items[item.ItemID].AssetID;
759 914
760 lock (m_items) 915 m_items[item.ItemID] = item;
761 { 916 m_inventorySerial++;
762 m_items[item.ItemID] = item;
763 m_inventorySerial++;
764 }
765
766 if (fireScriptEvents) 917 if (fireScriptEvents)
767 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 918 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
768 919
@@ -771,7 +922,7 @@ namespace OpenSim.Region.Framework.Scenes
771 HasInventoryChanged = true; 922 HasInventoryChanged = true;
772 m_part.ParentGroup.HasGroupChanged = true; 923 m_part.ParentGroup.HasGroupChanged = true;
773 } 924 }
774 925 m_items.LockItemsForWrite(false);
775 return true; 926 return true;
776 } 927 }
777 else 928 else
@@ -782,8 +933,9 @@ namespace OpenSim.Region.Framework.Scenes
782 item.ItemID, m_part.Name, m_part.UUID, 933 item.ItemID, m_part.Name, m_part.UUID,
783 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 934 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
784 } 935 }
785 return false; 936 m_items.LockItemsForWrite(false);
786 937
938 return false;
787 } 939 }
788 940
789 /// <summary> 941 /// <summary>
@@ -794,43 +946,59 @@ namespace OpenSim.Region.Framework.Scenes
794 /// in this prim's inventory.</returns> 946 /// in this prim's inventory.</returns>
795 public int RemoveInventoryItem(UUID itemID) 947 public int RemoveInventoryItem(UUID itemID)
796 { 948 {
797 TaskInventoryItem item = GetInventoryItem(itemID); 949 m_items.LockItemsForRead(true);
798 if (item != null) 950
951 if (m_items.ContainsKey(itemID))
799 { 952 {
800 int type = m_items[itemID].InvType; 953 int type = m_items[itemID].InvType;
954 m_items.LockItemsForRead(false);
801 if (type == 10) // Script 955 if (type == 10) // Script
802 { 956 {
803 m_part.RemoveScriptEvents(itemID);
804 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 957 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
805 } 958 }
959 m_items.LockItemsForWrite(true);
806 m_items.Remove(itemID); 960 m_items.Remove(itemID);
961 m_items.LockItemsForWrite(false);
807 m_inventorySerial++; 962 m_inventorySerial++;
808 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 963 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
809 964
810 HasInventoryChanged = true; 965 HasInventoryChanged = true;
811 m_part.ParentGroup.HasGroupChanged = true; 966 m_part.ParentGroup.HasGroupChanged = true;
812 967
813 if (!ContainsScripts()) 968 int scriptcount = 0;
969 m_items.LockItemsForRead(true);
970 foreach (TaskInventoryItem item in m_items.Values)
971 {
972 if (item.Type == 10)
973 {
974 scriptcount++;
975 }
976 }
977 m_items.LockItemsForRead(false);
978
979
980 if (scriptcount <= 0)
981 {
814 m_part.RemFlag(PrimFlags.Scripted); 982 m_part.RemFlag(PrimFlags.Scripted);
983 }
815 984
816 m_part.ScheduleFullUpdate(); 985 m_part.ScheduleFullUpdate();
817 986
818 return type; 987 return type;
819
820 } 988 }
821 else 989 else
822 { 990 {
991 m_items.LockItemsForRead(false);
823 m_log.ErrorFormat( 992 m_log.ErrorFormat(
824 "[PRIM INVENTORY]: " + 993 "[PRIM INVENTORY]: " +
825 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 994 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
826 itemID, m_part.Name, m_part.UUID, 995 itemID, m_part.Name, m_part.UUID);
827 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
828 } 996 }
829 997
830 return -1; 998 return -1;
831 } 999 }
832 1000
833 private bool CreateInventoryFile() 1001 private bool CreateInventoryFileName()
834 { 1002 {
835// m_log.DebugFormat( 1003// m_log.DebugFormat(
836// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", 1004// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
@@ -839,70 +1007,12 @@ namespace OpenSim.Region.Framework.Scenes
839 if (m_inventoryFileName == String.Empty || 1007 if (m_inventoryFileName == String.Empty ||
840 m_inventoryFileNameSerial < m_inventorySerial) 1008 m_inventoryFileNameSerial < m_inventorySerial)
841 { 1009 {
842 // Something changed, we need to create a new file
843 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 1010 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
844 m_inventoryFileNameSerial = m_inventorySerial; 1011 m_inventoryFileNameSerial = m_inventorySerial;
845 1012
846 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
847
848 lock (m_items)
849 {
850 foreach (TaskInventoryItem item in m_items.Values)
851 {
852// m_log.DebugFormat(
853// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}",
854// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
855
856 UUID ownerID = item.OwnerID;
857 uint everyoneMask = 0;
858 uint baseMask = item.BasePermissions;
859 uint ownerMask = item.CurrentPermissions;
860 uint groupMask = item.GroupPermissions;
861
862 invString.AddItemStart();
863 invString.AddNameValueLine("item_id", item.ItemID.ToString());
864 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
865
866 invString.AddPermissionsStart();
867
868 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
869 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
870 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
871 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
872 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
873
874 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
875 invString.AddNameValueLine("owner_id", ownerID.ToString());
876
877 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
878
879 invString.AddNameValueLine("group_id", item.GroupID.ToString());
880 invString.AddSectionEnd();
881
882 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
883 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
884 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
885 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
886
887 invString.AddSaleStart();
888 invString.AddNameValueLine("sale_type", "not");
889 invString.AddNameValueLine("sale_price", "0");
890 invString.AddSectionEnd();
891
892 invString.AddNameValueLine("name", item.Name + "|");
893 invString.AddNameValueLine("desc", item.Description + "|");
894
895 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
896 invString.AddSectionEnd();
897 }
898 }
899
900 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
901
902 return true; 1013 return true;
903 } 1014 }
904 1015
905 // No need to recreate, the existing file is fine
906 return false; 1016 return false;
907 } 1017 }
908 1018
@@ -912,43 +1022,110 @@ namespace OpenSim.Region.Framework.Scenes
912 /// <param name="xferManager"></param> 1022 /// <param name="xferManager"></param>
913 public void RequestInventoryFile(IClientAPI client, IXfer xferManager) 1023 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
914 { 1024 {
915 lock (m_items) 1025 bool changed = CreateInventoryFileName();
916 {
917 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
918 // a new script if any previous deletion has left the prim inventory empty.
919 if (m_items.Count == 0) // No inventory
920 {
921// m_log.DebugFormat(
922// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items",
923// m_part.Name, m_part.LocalId, m_part.UUID, client.Name);
924 1026
925 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1027 bool includeAssets = false;
926 return; 1028 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
927 } 1029 includeAssets = true;
1030
1031 if (m_inventoryPrivileged != includeAssets)
1032 changed = true;
1033
1034 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1035
1036 Items.LockItemsForRead(true);
1037
1038 if (m_inventorySerial == 0) // No inventory
1039 {
1040 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1041 Items.LockItemsForRead(false);
1042 return;
1043 }
928 1044
929 CreateInventoryFile(); 1045 if (m_items.Count == 0) // No inventory
1046 {
1047 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1048 Items.LockItemsForRead(false);
1049 return;
1050 }
930 1051
931 // In principle, we should only do the rest if the inventory changed; 1052 if (!changed)
932 // by sending m_inventorySerial to the client, it ought to know 1053 {
933 // that nothing changed and that it doesn't need to request the file.
934 // Unfortunately, it doesn't look like the client optimizes this;
935 // the client seems to always come back and request the Xfer,
936 // no matter what value m_inventorySerial has.
937 // FIXME: Could probably be > 0 here rather than > 2
938 if (m_inventoryFileData.Length > 2) 1054 if (m_inventoryFileData.Length > 2)
939 { 1055 {
940 // Add the file for Xfer 1056 xferManager.AddNewFile(m_inventoryFileName,
941 // m_log.DebugFormat( 1057 m_inventoryFileData);
942 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}", 1058 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
943 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId); 1059 Util.StringToBytes256(m_inventoryFileName));
944 1060
945 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); 1061 Items.LockItemsForRead(false);
1062 return;
946 } 1063 }
947
948 // Tell the client we're ready to Xfer the file
949 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
950 Util.StringToBytes256(m_inventoryFileName));
951 } 1064 }
1065
1066 m_inventoryPrivileged = includeAssets;
1067
1068 foreach (TaskInventoryItem item in m_items.Values)
1069 {
1070 UUID ownerID = item.OwnerID;
1071 uint everyoneMask = 0;
1072 uint baseMask = item.BasePermissions;
1073 uint ownerMask = item.CurrentPermissions;
1074 uint groupMask = item.GroupPermissions;
1075
1076 invString.AddItemStart();
1077 invString.AddNameValueLine("item_id", item.ItemID.ToString());
1078 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
1079
1080 invString.AddPermissionsStart();
1081
1082 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1083 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1084 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1085 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1086 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
1087
1088 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
1089 invString.AddNameValueLine("owner_id", ownerID.ToString());
1090
1091 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
1092
1093 invString.AddNameValueLine("group_id", item.GroupID.ToString());
1094 invString.AddSectionEnd();
1095
1096 if (includeAssets)
1097 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1098 else
1099 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1100 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1101 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1102 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
1103
1104 invString.AddSaleStart();
1105 invString.AddNameValueLine("sale_type", "not");
1106 invString.AddNameValueLine("sale_price", "0");
1107 invString.AddSectionEnd();
1108
1109 invString.AddNameValueLine("name", item.Name + "|");
1110 invString.AddNameValueLine("desc", item.Description + "|");
1111
1112 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1113 invString.AddSectionEnd();
1114 }
1115
1116 Items.LockItemsForRead(false);
1117
1118 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
1119
1120 if (m_inventoryFileData.Length > 2)
1121 {
1122 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
1123 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
1124 Util.StringToBytes256(m_inventoryFileName));
1125 return;
1126 }
1127
1128 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
952 } 1129 }
953 1130
954 /// <summary> 1131 /// <summary>
@@ -957,13 +1134,19 @@ namespace OpenSim.Region.Framework.Scenes
957 /// <param name="datastore"></param> 1134 /// <param name="datastore"></param>
958 public void ProcessInventoryBackup(ISimulationDataService datastore) 1135 public void ProcessInventoryBackup(ISimulationDataService datastore)
959 { 1136 {
960 if (HasInventoryChanged) 1137// Removed this because linking will cause an immediate delete of the new
961 { 1138// child prim from the database and the subsequent storing of the prim sees
962 HasInventoryChanged = false; 1139// the inventory of it as unchanged and doesn't store it at all. The overhead
963 List<TaskInventoryItem> items = GetInventoryItems(); 1140// of storing prim inventory needlessly is much less than the aggravation
964 datastore.StorePrimInventory(m_part.UUID, items); 1141// of prim inventory loss.
1142// if (HasInventoryChanged)
1143// {
1144 Items.LockItemsForRead(true);
1145 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1146 Items.LockItemsForRead(false);
965 1147
966 } 1148 HasInventoryChanged = false;
1149// }
967 } 1150 }
968 1151
969 public class InventoryStringBuilder 1152 public class InventoryStringBuilder
@@ -1029,87 +1212,63 @@ namespace OpenSim.Region.Framework.Scenes
1029 { 1212 {
1030 uint mask=0x7fffffff; 1213 uint mask=0x7fffffff;
1031 1214
1032 lock (m_items) 1215 foreach (TaskInventoryItem item in m_items.Values)
1033 { 1216 {
1034 foreach (TaskInventoryItem item in m_items.Values) 1217 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1218 mask &= ~((uint)PermissionMask.Copy >> 13);
1219 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1220 mask &= ~((uint)PermissionMask.Transfer >> 13);
1221 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1222 mask &= ~((uint)PermissionMask.Modify >> 13);
1223
1224 if (item.InvType == (int)InventoryType.Object)
1035 { 1225 {
1036 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1226 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1037 mask &= ~((uint)PermissionMask.Copy >> 13); 1227 mask &= ~((uint)PermissionMask.Copy >> 13);
1038 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1228 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1039 mask &= ~((uint)PermissionMask.Transfer >> 13); 1229 mask &= ~((uint)PermissionMask.Transfer >> 13);
1040 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1230 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1041 mask &= ~((uint)PermissionMask.Modify >> 13); 1231 mask &= ~((uint)PermissionMask.Modify >> 13);
1042
1043 if (item.InvType != (int)InventoryType.Object)
1044 {
1045 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1046 mask &= ~((uint)PermissionMask.Copy >> 13);
1047 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1048 mask &= ~((uint)PermissionMask.Transfer >> 13);
1049 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1050 mask &= ~((uint)PermissionMask.Modify >> 13);
1051 }
1052 else
1053 {
1054 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1055 mask &= ~((uint)PermissionMask.Copy >> 13);
1056 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1057 mask &= ~((uint)PermissionMask.Transfer >> 13);
1058 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1059 mask &= ~((uint)PermissionMask.Modify >> 13);
1060 }
1061
1062 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1063 mask &= ~(uint)PermissionMask.Copy;
1064 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1065 mask &= ~(uint)PermissionMask.Transfer;
1066 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1067 mask &= ~(uint)PermissionMask.Modify;
1068 } 1232 }
1233
1234 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1235 mask &= ~(uint)PermissionMask.Copy;
1236 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1237 mask &= ~(uint)PermissionMask.Transfer;
1238 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1239 mask &= ~(uint)PermissionMask.Modify;
1069 } 1240 }
1070
1071 return mask; 1241 return mask;
1072 } 1242 }
1073 1243
1074 public void ApplyNextOwnerPermissions() 1244 public void ApplyNextOwnerPermissions()
1075 { 1245 {
1076 lock (m_items) 1246 foreach (TaskInventoryItem item in m_items.Values)
1077 { 1247 {
1078 foreach (TaskInventoryItem item in m_items.Values) 1248 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1079 { 1249 {
1080// m_log.DebugFormat ( 1250 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1081// "[SCENE OBJECT PART INVENTORY]: Applying next permissions {0} to {1} in {2} with current {3}, base {4}, everyone {5}", 1251 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1082// item.NextPermissions, item.Name, m_part.Name, item.CurrentPermissions, item.BasePermissions, item.EveryonePermissions); 1252 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1083 1253 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1084 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1254 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1085 { 1255 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1086 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1087 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1088 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1089 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1090 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1091 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1092 }
1093
1094 item.CurrentPermissions &= item.NextPermissions;
1095 item.BasePermissions &= item.NextPermissions;
1096 item.EveryonePermissions &= item.NextPermissions;
1097 item.OwnerChanged = true;
1098 item.PermsMask = 0;
1099 item.PermsGranter = UUID.Zero;
1100 } 1256 }
1257 item.CurrentPermissions &= item.NextPermissions;
1258 item.BasePermissions &= item.NextPermissions;
1259 item.EveryonePermissions &= item.NextPermissions;
1260 item.OwnerChanged = true;
1261 item.PermsMask = 0;
1262 item.PermsGranter = UUID.Zero;
1101 } 1263 }
1102 } 1264 }
1103 1265
1104 public void ApplyGodPermissions(uint perms) 1266 public void ApplyGodPermissions(uint perms)
1105 { 1267 {
1106 lock (m_items) 1268 foreach (TaskInventoryItem item in m_items.Values)
1107 { 1269 {
1108 foreach (TaskInventoryItem item in m_items.Values) 1270 item.CurrentPermissions = perms;
1109 { 1271 item.BasePermissions = perms;
1110 item.CurrentPermissions = perms;
1111 item.BasePermissions = perms;
1112 }
1113 } 1272 }
1114 1273
1115 m_inventorySerial++; 1274 m_inventorySerial++;
@@ -1122,14 +1281,11 @@ namespace OpenSim.Region.Framework.Scenes
1122 /// <returns></returns> 1281 /// <returns></returns>
1123 public bool ContainsScripts() 1282 public bool ContainsScripts()
1124 { 1283 {
1125 lock (m_items) 1284 foreach (TaskInventoryItem item in m_items.Values)
1126 { 1285 {
1127 foreach (TaskInventoryItem item in m_items.Values) 1286 if (item.InvType == (int)InventoryType.LSL)
1128 { 1287 {
1129 if (item.InvType == (int)InventoryType.LSL) 1288 return true;
1130 {
1131 return true;
1132 }
1133 } 1289 }
1134 } 1290 }
1135 1291
@@ -1143,17 +1299,15 @@ namespace OpenSim.Region.Framework.Scenes
1143 public int ScriptCount() 1299 public int ScriptCount()
1144 { 1300 {
1145 int count = 0; 1301 int count = 0;
1146 lock (m_items) 1302 Items.LockItemsForRead(true);
1303 foreach (TaskInventoryItem item in m_items.Values)
1147 { 1304 {
1148 foreach (TaskInventoryItem item in m_items.Values) 1305 if (item.InvType == (int)InventoryType.LSL)
1149 { 1306 {
1150 if (item.InvType == (int)InventoryType.LSL) 1307 count++;
1151 {
1152 count++;
1153 }
1154 } 1308 }
1155 } 1309 }
1156 1310 Items.LockItemsForRead(false);
1157 return count; 1311 return count;
1158 } 1312 }
1159 /// <summary> 1313 /// <summary>
@@ -1189,11 +1343,8 @@ namespace OpenSim.Region.Framework.Scenes
1189 { 1343 {
1190 List<UUID> ret = new List<UUID>(); 1344 List<UUID> ret = new List<UUID>();
1191 1345
1192 lock (m_items) 1346 foreach (TaskInventoryItem item in m_items.Values)
1193 { 1347 ret.Add(item.ItemID);
1194 foreach (TaskInventoryItem item in m_items.Values)
1195 ret.Add(item.ItemID);
1196 }
1197 1348
1198 return ret; 1349 return ret;
1199 } 1350 }
@@ -1202,8 +1353,9 @@ namespace OpenSim.Region.Framework.Scenes
1202 { 1353 {
1203 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1354 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1204 1355
1205 lock (m_items) 1356 Items.LockItemsForRead(true);
1206 ret = new List<TaskInventoryItem>(m_items.Values); 1357 ret = new List<TaskInventoryItem>(m_items.Values);
1358 Items.LockItemsForRead(false);
1207 1359
1208 return ret; 1360 return ret;
1209 } 1361 }
@@ -1212,18 +1364,24 @@ namespace OpenSim.Region.Framework.Scenes
1212 { 1364 {
1213 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1365 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1214 1366
1215 lock (m_items) 1367 Items.LockItemsForRead(true);
1216 { 1368
1217 foreach (TaskInventoryItem item in m_items.Values) 1369 foreach (TaskInventoryItem item in m_items.Values)
1218 if (item.InvType == (int)type) 1370 if (item.InvType == (int)type)
1219 ret.Add(item); 1371 ret.Add(item);
1220 } 1372
1373 Items.LockItemsForRead(false);
1221 1374
1222 return ret; 1375 return ret;
1223 } 1376 }
1224 1377
1225 public Dictionary<UUID, string> GetScriptStates() 1378 public Dictionary<UUID, string> GetScriptStates()
1226 { 1379 {
1380 return GetScriptStates(false);
1381 }
1382
1383 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1384 {
1227 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1385 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1228 1386
1229 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1387 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1245,14 +1403,21 @@ namespace OpenSim.Region.Framework.Scenes
1245 string n = e.GetXMLState(item.ItemID); 1403 string n = e.GetXMLState(item.ItemID);
1246 if (n != String.Empty) 1404 if (n != String.Empty)
1247 { 1405 {
1248 if (!ret.ContainsKey(item.ItemID)) 1406 if (oldIDs)
1249 ret[item.ItemID] = n; 1407 {
1408 if (!ret.ContainsKey(item.OldItemID))
1409 ret[item.OldItemID] = n;
1410 }
1411 else
1412 {
1413 if (!ret.ContainsKey(item.ItemID))
1414 ret[item.ItemID] = n;
1415 }
1250 break; 1416 break;
1251 } 1417 }
1252 } 1418 }
1253 } 1419 }
1254 } 1420 }
1255
1256 return ret; 1421 return ret;
1257 } 1422 }
1258 1423
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index c7a670f..159a92a 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -63,6 +63,7 @@ namespace OpenSim.Region.Framework.Scenes
63 63
64 struct ScriptControllers 64 struct ScriptControllers
65 { 65 {
66 public UUID objectID;
66 public UUID itemID; 67 public UUID itemID;
67 public ScriptControlled ignoreControls; 68 public ScriptControlled ignoreControls;
68 public ScriptControlled eventControls; 69 public ScriptControlled eventControls;
@@ -98,7 +99,7 @@ namespace OpenSim.Region.Framework.Scenes
98 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 99 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
99 /// issue #1716 100 /// issue #1716
100 /// </summary> 101 /// </summary>
101 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); 102 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f);
102 103
103 /// <summary> 104 /// <summary>
104 /// Movement updates for agents in neighboring regions are sent directly to clients. 105 /// Movement updates for agents in neighboring regions are sent directly to clients.
@@ -175,6 +176,7 @@ namespace OpenSim.Region.Framework.Scenes
175// private int m_lastColCount = -1; //KF: Look for Collision chnages 176// private int m_lastColCount = -1; //KF: Look for Collision chnages
176// private int m_updateCount = 0; //KF: Update Anims for a while 177// private int m_updateCount = 0; //KF: Update Anims for a while
177// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 178// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
179 private List<uint> m_lastColliders = new List<uint>();
178 180
179 private TeleportFlags m_teleportFlags; 181 private TeleportFlags m_teleportFlags;
180 public TeleportFlags TeleportFlags 182 public TeleportFlags TeleportFlags
@@ -236,6 +238,13 @@ namespace OpenSim.Region.Framework.Scenes
236 //private int m_moveToPositionStateStatus; 238 //private int m_moveToPositionStateStatus;
237 //***************************************************** 239 //*****************************************************
238 240
241 private bool m_collisionEventFlag = false;
242 private object m_collisionEventLock = new Object();
243
244 private int m_movementAnimationUpdateCounter = 0;
245
246 private Vector3 m_prevSitOffset;
247
239 protected AvatarAppearance m_appearance; 248 protected AvatarAppearance m_appearance;
240 249
241 public AvatarAppearance Appearance 250 public AvatarAppearance Appearance
@@ -577,6 +586,13 @@ namespace OpenSim.Region.Framework.Scenes
577 /// </summary> 586 /// </summary>
578 public uint ParentID { get; set; } 587 public uint ParentID { get; set; }
579 588
589 public UUID ParentUUID
590 {
591 get { return m_parentUUID; }
592 set { m_parentUUID = value; }
593 }
594 private UUID m_parentUUID = UUID.Zero;
595
580 /// <summary> 596 /// <summary>
581 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null. 597 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null.
582 /// </summary> 598 /// </summary>
@@ -737,6 +753,33 @@ namespace OpenSim.Region.Framework.Scenes
737 Appearance = appearance; 753 Appearance = appearance;
738 } 754 }
739 755
756 private void RegionHeartbeatEnd(Scene scene)
757 {
758 if (IsChildAgent)
759 return;
760
761 m_movementAnimationUpdateCounter ++;
762 if (m_movementAnimationUpdateCounter >= 2)
763 {
764 m_movementAnimationUpdateCounter = 0;
765 if (Animator != null)
766 {
767 // If the parentID == 0 we are not sitting
768 // if !SitGournd then we are not sitting on the ground
769 // Fairly straightforward, now here comes the twist
770 // if ParentUUID is NOT UUID.Zero, we are looking to
771 // be sat on an object that isn't there yet. Should
772 // be treated as if sat.
773 if(ParentID == 0 && !SitGround && ParentUUID == UUID.Zero) // skip it if sitting
774 Animator.UpdateMovementAnimations();
775 }
776 else
777 {
778 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
779 }
780 }
781 }
782
740 public void RegisterToEvents() 783 public void RegisterToEvents()
741 { 784 {
742 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 785 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
@@ -746,6 +789,7 @@ namespace OpenSim.Region.Framework.Scenes
746 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 789 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
747 ControllingClient.OnStartAnim += HandleStartAnim; 790 ControllingClient.OnStartAnim += HandleStartAnim;
748 ControllingClient.OnStopAnim += HandleStopAnim; 791 ControllingClient.OnStopAnim += HandleStopAnim;
792 ControllingClient.OnChangeAnim += avnHandleChangeAnim;
749 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls; 793 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls;
750 ControllingClient.OnAutoPilotGo += MoveToTarget; 794 ControllingClient.OnAutoPilotGo += MoveToTarget;
751 795
@@ -806,10 +850,38 @@ namespace OpenSim.Region.Framework.Scenes
806 "[SCENE]: Upgrading child to root agent for {0} in {1}", 850 "[SCENE]: Upgrading child to root agent for {0} in {1}",
807 Name, m_scene.RegionInfo.RegionName); 851 Name, m_scene.RegionInfo.RegionName);
808 852
809 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
810
811 bool wasChild = IsChildAgent; 853 bool wasChild = IsChildAgent;
812 IsChildAgent = false; 854
855 if (ParentUUID != UUID.Zero)
856 {
857 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
858 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
859 if (part == null)
860 {
861 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
862 }
863 else
864 {
865 part.ParentGroup.AddAvatar(UUID);
866 if (part.SitTargetPosition != Vector3.Zero)
867 part.SitTargetAvatar = UUID;
868 ParentPosition = part.GetWorldPosition();
869 ParentID = part.LocalId;
870 ParentPart = part;
871 m_pos = m_prevSitOffset;
872 pos = ParentPosition;
873 }
874 ParentUUID = UUID.Zero;
875
876 IsChildAgent = false;
877
878// Animator.TrySetMovementAnimation("SIT");
879 }
880 else
881 {
882 IsChildAgent = false;
883 }
884
813 885
814 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 886 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
815 if (gm != null) 887 if (gm != null)
@@ -819,62 +891,72 @@ namespace OpenSim.Region.Framework.Scenes
819 891
820 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 892 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
821 893
822 // Moved this from SendInitialData to ensure that Appearance is initialized 894 if (ParentID == 0)
823 // before the inventory is processed in MakeRootAgent. This fixes a race condition
824 // related to the handling of attachments
825 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
826 if (m_scene.TestBorderCross(pos, Cardinals.E))
827 { 895 {
828 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 896 // Moved this from SendInitialData to ensure that Appearance is initialized
829 pos.X = crossedBorder.BorderLine.Z - 1; 897 // before the inventory is processed in MakeRootAgent. This fixes a race condition
830 } 898 // related to the handling of attachments
899 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
900 if (m_scene.TestBorderCross(pos, Cardinals.E))
901 {
902 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
903 pos.X = crossedBorder.BorderLine.Z - 1;
904 }
831 905
832 if (m_scene.TestBorderCross(pos, Cardinals.N)) 906 if (m_scene.TestBorderCross(pos, Cardinals.N))
833 { 907 {
834 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 908 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
835 pos.Y = crossedBorder.BorderLine.Z - 1; 909 pos.Y = crossedBorder.BorderLine.Z - 1;
836 } 910 }
837 911
838 CheckAndAdjustLandingPoint(ref pos); 912 CheckAndAdjustLandingPoint(ref pos);
839 913
840 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 914 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
841 { 915 {
842 m_log.WarnFormat( 916 m_log.WarnFormat(
843 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", 917 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
844 pos, Name, UUID); 918 pos, Name, UUID);
845 919
846 if (pos.X < 0f) pos.X = 0f; 920 if (pos.X < 0f) pos.X = 0f;
847 if (pos.Y < 0f) pos.Y = 0f; 921 if (pos.Y < 0f) pos.Y = 0f;
848 if (pos.Z < 0f) pos.Z = 0f; 922 if (pos.Z < 0f) pos.Z = 0f;
849 } 923 }
850 924
851 float localAVHeight = 1.56f; 925 float localAVHeight = 1.56f;
852 if (Appearance.AvatarHeight > 0) 926 if (Appearance.AvatarHeight > 0)
853 localAVHeight = Appearance.AvatarHeight; 927 localAVHeight = Appearance.AvatarHeight;
854 928
855 float posZLimit = 0; 929 float posZLimit = 0;
856 930
857 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 931 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
858 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 932 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
859 933
860 float newPosZ = posZLimit + localAVHeight / 2; 934 float newPosZ = posZLimit + localAVHeight / 2;
861 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 935 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
862 { 936 {
863 pos.Z = newPosZ; 937 pos.Z = newPosZ;
864 } 938 }
865 AbsolutePosition = pos; 939 AbsolutePosition = pos;
866 940
867 AddToPhysicalScene(isFlying); 941 if (m_teleportFlags == TeleportFlags.Default)
942 {
943 Vector3 vel = Velocity;
944 AddToPhysicalScene(isFlying);
945 if (PhysicsActor != null)
946 PhysicsActor.SetMomentum(vel);
947 }
948 else
949 AddToPhysicalScene(isFlying);
868 950
869 if (ForceFly) 951 if (ForceFly)
870 { 952 {
871 Flying = true; 953 Flying = true;
872 } 954 }
873 else if (FlyDisabled) 955 else if (FlyDisabled)
874 { 956 {
875 Flying = false; 957 Flying = false;
958 }
876 } 959 }
877
878 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying 960 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
879 // avatar to return to the standing position in mid-air. On login it looks like this is being sent 961 // avatar to return to the standing position in mid-air. On login it looks like this is being sent
880 // elsewhere anyway 962 // elsewhere anyway
@@ -892,14 +974,19 @@ namespace OpenSim.Region.Framework.Scenes
892 { 974 {
893 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); 975 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments...");
894 // Resume scripts 976 // Resume scripts
895 foreach (SceneObjectGroup sog in m_attachments) 977 Util.FireAndForget(delegate(object x) {
896 { 978 foreach (SceneObjectGroup sog in m_attachments)
897 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 979 {
898 sog.ResumeScripts(); 980 sog.ScheduleGroupForFullUpdate();
899 } 981 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
982 sog.ResumeScripts();
983 }
984 });
900 } 985 }
901 } 986 }
902 987
988 SendAvatarDataToAllAgents();
989
903 // send the animations of the other presences to me 990 // send the animations of the other presences to me
904 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence) 991 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
905 { 992 {
@@ -910,9 +997,12 @@ namespace OpenSim.Region.Framework.Scenes
910 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will 997 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will
911 // stall on the border crossing since the existing child agent will still have the last movement 998 // stall on the border crossing since the existing child agent will still have the last movement
912 // recorded, which stops the input from being processed. 999 // recorded, which stops the input from being processed.
1000
913 MovementFlag = 0; 1001 MovementFlag = 0;
914 1002
915 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1003 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1004
1005 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd;
916 } 1006 }
917 1007
918 public int GetStateSource() 1008 public int GetStateSource()
@@ -940,12 +1030,16 @@ namespace OpenSim.Region.Framework.Scenes
940 /// </remarks> 1030 /// </remarks>
941 public void MakeChildAgent() 1031 public void MakeChildAgent()
942 { 1032 {
1033 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1034
943 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); 1035 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName);
944 1036
945 // Reset these so that teleporting in and walking out isn't seen 1037 // Reset these so that teleporting in and walking out isn't seen
946 // as teleporting back 1038 // as teleporting back
947 TeleportFlags = TeleportFlags.Default; 1039 TeleportFlags = TeleportFlags.Default;
948 1040
1041 MovementFlag = 0;
1042
949 // It looks like Animator is set to null somewhere, and MakeChild 1043 // It looks like Animator is set to null somewhere, and MakeChild
950 // is called after that. Probably in aborted teleports. 1044 // is called after that. Probably in aborted teleports.
951 if (Animator == null) 1045 if (Animator == null)
@@ -953,6 +1047,7 @@ namespace OpenSim.Region.Framework.Scenes
953 else 1047 else
954 Animator.ResetAnimations(); 1048 Animator.ResetAnimations();
955 1049
1050
956// m_log.DebugFormat( 1051// m_log.DebugFormat(
957// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", 1052// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
958// Name, UUID, m_scene.RegionInfo.RegionName); 1053// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -964,6 +1059,7 @@ namespace OpenSim.Region.Framework.Scenes
964 IsChildAgent = true; 1059 IsChildAgent = true;
965 m_scene.SwapRootAgentCount(true); 1060 m_scene.SwapRootAgentCount(true);
966 RemoveFromPhysicalScene(); 1061 RemoveFromPhysicalScene();
1062 ParentID = 0; // Child agents can't be sitting
967 1063
968 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into 1064 // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into
969 1065
@@ -979,9 +1075,9 @@ namespace OpenSim.Region.Framework.Scenes
979 { 1075 {
980// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1076// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
981 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall; 1077 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall;
982 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
983 PhysicsActor.UnSubscribeEvents();
984 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1078 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1079 PhysicsActor.UnSubscribeEvents();
1080 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
985 PhysicsActor = null; 1081 PhysicsActor = null;
986 } 1082 }
987// else 1083// else
@@ -998,7 +1094,7 @@ namespace OpenSim.Region.Framework.Scenes
998 /// <param name="pos"></param> 1094 /// <param name="pos"></param>
999 public void Teleport(Vector3 pos) 1095 public void Teleport(Vector3 pos)
1000 { 1096 {
1001 TeleportWithMomentum(pos, null); 1097 TeleportWithMomentum(pos, Vector3.Zero);
1002 } 1098 }
1003 1099
1004 public void TeleportWithMomentum(Vector3 pos, Vector3? v) 1100 public void TeleportWithMomentum(Vector3 pos, Vector3? v)
@@ -1022,6 +1118,41 @@ namespace OpenSim.Region.Framework.Scenes
1022 SendTerseUpdateToAllClients(); 1118 SendTerseUpdateToAllClients();
1023 } 1119 }
1024 1120
1121 public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY)
1122 {
1123 CheckLandingPoint(ref newpos);
1124 AbsolutePosition = newpos;
1125
1126 if (newvel.HasValue)
1127 {
1128 if ((Vector3)newvel == Vector3.Zero)
1129 {
1130 if (PhysicsActor != null)
1131 PhysicsActor.SetMomentum(Vector3.Zero);
1132 m_velocity = Vector3.Zero;
1133 }
1134 else
1135 {
1136 if (PhysicsActor != null)
1137 PhysicsActor.SetMomentum((Vector3)newvel);
1138 m_velocity = (Vector3)newvel;
1139
1140 if (rotateToVelXY)
1141 {
1142 Vector3 lookAt = (Vector3)newvel;
1143 lookAt.Z = 0;
1144 lookAt.Normalize();
1145 ControllingClient.SendLocalTeleport(newpos, lookAt, (uint)TeleportFlags.ViaLocation);
1146 return;
1147 }
1148 }
1149 }
1150
1151 SendTerseUpdateToAllClients();
1152 }
1153
1154
1155
1025 public void StopFlying() 1156 public void StopFlying()
1026 { 1157 {
1027 ControllingClient.StopFlying(this); 1158 ControllingClient.StopFlying(this);
@@ -1337,8 +1468,18 @@ namespace OpenSim.Region.Framework.Scenes
1337 { 1468 {
1338 if (m_followCamAuto) 1469 if (m_followCamAuto)
1339 { 1470 {
1340 Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; 1471 // Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
1341 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback); 1472 // m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
1473
1474 Vector3 posAdjusted = AbsolutePosition + HEAD_ADJUSTMENT;
1475 Vector3 distTocam = CameraPosition - posAdjusted;
1476 float distTocamlen = distTocam.Length();
1477 if (distTocamlen > 0)
1478 {
1479 distTocam *= 1.0f / distTocamlen;
1480 m_scene.PhysicsScene.RaycastWorld(posAdjusted, distTocam, distTocamlen + 0.3f, RayCastCameraCallback);
1481 }
1482
1342 } 1483 }
1343 } 1484 }
1344 1485
@@ -1772,12 +1913,17 @@ namespace OpenSim.Region.Framework.Scenes
1772// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 1913// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
1773 1914
1774 SitGround = false; 1915 SitGround = false;
1916
1917/* move this down so avatar gets physical in the new position and not where it is siting
1775 if (PhysicsActor == null) 1918 if (PhysicsActor == null)
1776 AddToPhysicalScene(false); 1919 AddToPhysicalScene(false);
1920 */
1777 1921
1778 if (ParentID != 0) 1922 if (ParentID != 0)
1779 { 1923 {
1780 SceneObjectPart part = ParentPart; 1924 SceneObjectPart part = ParentPart;
1925 UnRegisterSeatControls(part.ParentGroup.UUID);
1926
1781 TaskInventoryDictionary taskIDict = part.TaskInventory; 1927 TaskInventoryDictionary taskIDict = part.TaskInventory;
1782 if (taskIDict != null) 1928 if (taskIDict != null)
1783 { 1929 {
@@ -1797,6 +1943,7 @@ namespace OpenSim.Region.Framework.Scenes
1797 if (part.SitTargetAvatar == UUID) 1943 if (part.SitTargetAvatar == UUID)
1798 part.SitTargetAvatar = UUID.Zero; 1944 part.SitTargetAvatar = UUID.Zero;
1799 1945
1946 part.ParentGroup.DeleteAvatar(UUID);
1800 ParentPosition = part.GetWorldPosition(); 1947 ParentPosition = part.GetWorldPosition();
1801 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1948 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1802 1949
@@ -1805,6 +1952,10 @@ namespace OpenSim.Region.Framework.Scenes
1805 1952
1806 ParentID = 0; 1953 ParentID = 0;
1807 ParentPart = null; 1954 ParentPart = null;
1955
1956 if (PhysicsActor == null)
1957 AddToPhysicalScene(false);
1958
1808 SendAvatarDataToAllAgents(); 1959 SendAvatarDataToAllAgents();
1809 m_requestedSitTargetID = 0; 1960 m_requestedSitTargetID = 0;
1810 1961
@@ -1812,6 +1963,9 @@ namespace OpenSim.Region.Framework.Scenes
1812 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 1963 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
1813 } 1964 }
1814 1965
1966 else if (PhysicsActor == null)
1967 AddToPhysicalScene(false);
1968
1815 Animator.TrySetMovementAnimation("STAND"); 1969 Animator.TrySetMovementAnimation("STAND");
1816 } 1970 }
1817 1971
@@ -1890,7 +2044,7 @@ namespace OpenSim.Region.Framework.Scenes
1890// m_log.DebugFormat("[SCENE PRESENCE]: {0} {1}", SitTargetisSet, SitTargetUnOccupied); 2044// m_log.DebugFormat("[SCENE PRESENCE]: {0} {1}", SitTargetisSet, SitTargetUnOccupied);
1891 2045
1892 if (PhysicsActor != null) 2046 if (PhysicsActor != null)
1893 m_sitAvatarHeight = PhysicsActor.Size.Z; 2047 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
1894 2048
1895 bool canSit = false; 2049 bool canSit = false;
1896 pos = part.AbsolutePosition + offset; 2050 pos = part.AbsolutePosition + offset;
@@ -1935,7 +2089,7 @@ namespace OpenSim.Region.Framework.Scenes
1935 forceMouselook = part.GetForceMouselook(); 2089 forceMouselook = part.GetForceMouselook();
1936 2090
1937 ControllingClient.SendSitResponse( 2091 ControllingClient.SendSitResponse(
1938 targetID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 2092 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
1939 2093
1940 m_requestedSitTargetUUID = targetID; 2094 m_requestedSitTargetUUID = targetID;
1941 2095
@@ -1949,6 +2103,9 @@ namespace OpenSim.Region.Framework.Scenes
1949 2103
1950 public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset) 2104 public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset)
1951 { 2105 {
2106 if (IsChildAgent)
2107 return;
2108
1952 if (ParentID != 0) 2109 if (ParentID != 0)
1953 { 2110 {
1954 StandUp(); 2111 StandUp();
@@ -2217,14 +2374,39 @@ namespace OpenSim.Region.Framework.Scenes
2217 2374
2218 //Quaternion result = (sitTargetOrient * vq) * nq; 2375 //Quaternion result = (sitTargetOrient * vq) * nq;
2219 2376
2220 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2377 double x, y, z, m;
2378
2379 Quaternion r = sitTargetOrient;
2380 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2381
2382 if (Math.Abs(1.0 - m) > 0.000001)
2383 {
2384 m = 1.0 / Math.Sqrt(m);
2385 r.X *= (float)m;
2386 r.Y *= (float)m;
2387 r.Z *= (float)m;
2388 r.W *= (float)m;
2389 }
2390
2391 x = 2 * (r.X * r.Z + r.Y * r.W);
2392 y = 2 * (-r.X * r.W + r.Y * r.Z);
2393 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2394
2395 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2396 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2397
2398 m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
2399
2400// m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset;
2221 Rotation = sitTargetOrient; 2401 Rotation = sitTargetOrient;
2222 ParentPosition = part.AbsolutePosition; 2402 ParentPosition = part.AbsolutePosition;
2403 part.ParentGroup.AddAvatar(UUID);
2223 } 2404 }
2224 else 2405 else
2225 { 2406 {
2226 m_pos -= part.AbsolutePosition; 2407 m_pos -= part.AbsolutePosition;
2227 ParentPosition = part.AbsolutePosition; 2408 ParentPosition = part.AbsolutePosition;
2409 part.ParentGroup.AddAvatar(UUID);
2228 2410
2229// m_log.DebugFormat( 2411// m_log.DebugFormat(
2230// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2412// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
@@ -2269,6 +2451,13 @@ namespace OpenSim.Region.Framework.Scenes
2269 Animator.RemoveAnimation(animID); 2451 Animator.RemoveAnimation(animID);
2270 } 2452 }
2271 2453
2454 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
2455 {
2456 Animator.avnChangeAnim(animID, addRemove, sendPack);
2457 }
2458
2459
2460
2272 /// <summary> 2461 /// <summary>
2273 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 2462 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
2274 /// </summary> 2463 /// </summary>
@@ -2322,14 +2511,15 @@ namespace OpenSim.Region.Framework.Scenes
2322 direc.Z *= 2.6f; 2511 direc.Z *= 2.6f;
2323 2512
2324 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2513 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
2325 Animator.TrySetMovementAnimation("PREJUMP"); 2514// Animator.TrySetMovementAnimation("PREJUMP");
2326 Animator.TrySetMovementAnimation("JUMP"); 2515// Animator.TrySetMovementAnimation("JUMP");
2327 } 2516 }
2328 } 2517 }
2329 } 2518 }
2330 2519
2331 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2520 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2332 m_forceToApply = direc; 2521 m_forceToApply = direc;
2522 Animator.UpdateMovementAnimations();
2333 } 2523 }
2334 2524
2335 #endregion 2525 #endregion
@@ -2722,8 +2912,9 @@ namespace OpenSim.Region.Framework.Scenes
2722 2912
2723 // If we don't have a PhysActor, we can't cross anyway 2913 // If we don't have a PhysActor, we can't cross anyway
2724 // Also don't do this while sat, sitting avatars cross with the 2914 // Also don't do this while sat, sitting avatars cross with the
2725 // object they sit on. 2915 // object they sit on. ParentUUID denoted a pending sit, don't
2726 if (ParentID != 0 || PhysicsActor == null) 2916 // interfere with it.
2917 if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero)
2727 return; 2918 return;
2728 2919
2729 if (!IsInTransit) 2920 if (!IsInTransit)
@@ -3064,6 +3255,9 @@ namespace OpenSim.Region.Framework.Scenes
3064 cAgent.AlwaysRun = SetAlwaysRun; 3255 cAgent.AlwaysRun = SetAlwaysRun;
3065 3256
3066 cAgent.Appearance = new AvatarAppearance(Appearance); 3257 cAgent.Appearance = new AvatarAppearance(Appearance);
3258
3259 cAgent.ParentPart = ParentUUID;
3260 cAgent.SitOffset = m_pos;
3067 3261
3068 lock (scriptedcontrols) 3262 lock (scriptedcontrols)
3069 { 3263 {
@@ -3072,7 +3266,7 @@ namespace OpenSim.Region.Framework.Scenes
3072 3266
3073 foreach (ScriptControllers c in scriptedcontrols.Values) 3267 foreach (ScriptControllers c in scriptedcontrols.Values)
3074 { 3268 {
3075 controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls); 3269 controls[i++] = new ControllerData(c.objectID, c.itemID, (uint)c.ignoreControls, (uint)c.eventControls);
3076 } 3270 }
3077 cAgent.Controllers = controls; 3271 cAgent.Controllers = controls;
3078 } 3272 }
@@ -3083,6 +3277,7 @@ namespace OpenSim.Region.Framework.Scenes
3083 cAgent.Anims = Animator.Animations.ToArray(); 3277 cAgent.Anims = Animator.Animations.ToArray();
3084 } 3278 }
3085 catch { } 3279 catch { }
3280 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation;
3086 3281
3087 if (Scene.AttachmentsModule != null) 3282 if (Scene.AttachmentsModule != null)
3088 Scene.AttachmentsModule.CopyAttachments(this, cAgent); 3283 Scene.AttachmentsModule.CopyAttachments(this, cAgent);
@@ -3103,6 +3298,8 @@ namespace OpenSim.Region.Framework.Scenes
3103 CameraAtAxis = cAgent.AtAxis; 3298 CameraAtAxis = cAgent.AtAxis;
3104 CameraLeftAxis = cAgent.LeftAxis; 3299 CameraLeftAxis = cAgent.LeftAxis;
3105 CameraUpAxis = cAgent.UpAxis; 3300 CameraUpAxis = cAgent.UpAxis;
3301 ParentUUID = cAgent.ParentPart;
3302 m_prevSitOffset = cAgent.SitOffset;
3106 3303
3107 // When we get to the point of re-computing neighbors everytime this 3304 // When we get to the point of re-computing neighbors everytime this
3108 // changes, then start using the agent's drawdistance rather than the 3305 // changes, then start using the agent's drawdistance rather than the
@@ -3140,6 +3337,7 @@ namespace OpenSim.Region.Framework.Scenes
3140 foreach (ControllerData c in cAgent.Controllers) 3337 foreach (ControllerData c in cAgent.Controllers)
3141 { 3338 {
3142 ScriptControllers sc = new ScriptControllers(); 3339 ScriptControllers sc = new ScriptControllers();
3340 sc.objectID = c.ObjectID;
3143 sc.itemID = c.ItemID; 3341 sc.itemID = c.ItemID;
3144 sc.ignoreControls = (ScriptControlled)c.IgnoreControls; 3342 sc.ignoreControls = (ScriptControlled)c.IgnoreControls;
3145 sc.eventControls = (ScriptControlled)c.EventControls; 3343 sc.eventControls = (ScriptControlled)c.EventControls;
@@ -3154,6 +3352,8 @@ namespace OpenSim.Region.Framework.Scenes
3154 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? 3352 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object?
3155 if (cAgent.Anims != null) 3353 if (cAgent.Anims != null)
3156 Animator.Animations.FromArray(cAgent.Anims); 3354 Animator.Animations.FromArray(cAgent.Anims);
3355 if (cAgent.DefaultAnim != null)
3356 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
3157 3357
3158 if (Scene.AttachmentsModule != null) 3358 if (Scene.AttachmentsModule != null)
3159 Scene.AttachmentsModule.CopyAttachments(cAgent, this); 3359 Scene.AttachmentsModule.CopyAttachments(cAgent, this);
@@ -3216,7 +3416,7 @@ namespace OpenSim.Region.Framework.Scenes
3216 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3416 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3217 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3417 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
3218 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong 3418 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
3219 PhysicsActor.SubscribeEvents(500); 3419 PhysicsActor.SubscribeEvents(100);
3220 PhysicsActor.LocalID = LocalId; 3420 PhysicsActor.LocalID = LocalId;
3221 } 3421 }
3222 3422
@@ -3246,18 +3446,6 @@ namespace OpenSim.Region.Framework.Scenes
3246 if (IsChildAgent) 3446 if (IsChildAgent)
3247 return; 3447 return;
3248 3448
3249 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
3250 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
3251 // as of this comment the interval is set in AddToPhysicalScene
3252 if (Animator != null)
3253 {
3254// if (m_updateCount > 0)
3255// {
3256 Animator.UpdateMovementAnimations();
3257// m_updateCount--;
3258// }
3259 }
3260
3261 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3449 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3262 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3450 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3263 3451
@@ -3300,6 +3488,8 @@ namespace OpenSim.Region.Framework.Scenes
3300 } 3488 }
3301 } 3489 }
3302 3490
3491 RaiseCollisionScriptEvents(coldata);
3492
3303 // Gods do not take damage and Invulnerable is set depending on parcel/region flags 3493 // Gods do not take damage and Invulnerable is set depending on parcel/region flags
3304 if (Invulnerable || GodLevel > 0) 3494 if (Invulnerable || GodLevel > 0)
3305 return; 3495 return;
@@ -3629,10 +3819,15 @@ namespace OpenSim.Region.Framework.Scenes
3629 3819
3630 public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID) 3820 public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID)
3631 { 3821 {
3822 SceneObjectPart p = m_scene.GetSceneObjectPart(Obj_localID);
3823 if (p == null)
3824 return;
3825
3632 ScriptControllers obj = new ScriptControllers(); 3826 ScriptControllers obj = new ScriptControllers();
3633 obj.ignoreControls = ScriptControlled.CONTROL_ZERO; 3827 obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
3634 obj.eventControls = ScriptControlled.CONTROL_ZERO; 3828 obj.eventControls = ScriptControlled.CONTROL_ZERO;
3635 3829
3830 obj.objectID = p.ParentGroup.UUID;
3636 obj.itemID = Script_item_UUID; 3831 obj.itemID = Script_item_UUID;
3637 if (pass_on == 0 && accept == 0) 3832 if (pass_on == 0 && accept == 0)
3638 { 3833 {
@@ -3681,6 +3876,21 @@ namespace OpenSim.Region.Framework.Scenes
3681 ControllingClient.SendTakeControls(int.MaxValue, false, false); 3876 ControllingClient.SendTakeControls(int.MaxValue, false, false);
3682 } 3877 }
3683 3878
3879 private void UnRegisterSeatControls(UUID obj)
3880 {
3881 List<UUID> takers = new List<UUID>();
3882
3883 foreach (ScriptControllers c in scriptedcontrols.Values)
3884 {
3885 if (c.objectID == obj)
3886 takers.Add(c.itemID);
3887 }
3888 foreach (UUID t in takers)
3889 {
3890 UnRegisterControlEventsToScript(0, t);
3891 }
3892 }
3893
3684 public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) 3894 public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID)
3685 { 3895 {
3686 ScriptControllers takecontrols; 3896 ScriptControllers takecontrols;
@@ -3999,6 +4209,12 @@ namespace OpenSim.Region.Framework.Scenes
3999 4209
4000 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 4210 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
4001 { 4211 {
4212 string reason;
4213
4214 // Honor bans
4215 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
4216 return;
4217
4002 SceneObjectGroup telehub = null; 4218 SceneObjectGroup telehub = null;
4003 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 4219 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
4004 { 4220 {
@@ -4038,11 +4254,206 @@ namespace OpenSim.Region.Framework.Scenes
4038 pos = land.LandData.UserLocation; 4254 pos = land.LandData.UserLocation;
4039 } 4255 }
4040 } 4256 }
4041 4257
4042 land.SendLandUpdateToClient(ControllingClient); 4258 land.SendLandUpdateToClient(ControllingClient);
4043 } 4259 }
4044 } 4260 }
4045 4261
4262 private DetectedObject CreateDetObject(SceneObjectPart obj)
4263 {
4264 DetectedObject detobj = new DetectedObject();
4265 detobj.keyUUID = obj.UUID;
4266 detobj.nameStr = obj.Name;
4267 detobj.ownerUUID = obj.OwnerID;
4268 detobj.posVector = obj.AbsolutePosition;
4269 detobj.rotQuat = obj.GetWorldRotation();
4270 detobj.velVector = obj.Velocity;
4271 detobj.colliderType = 0;
4272 detobj.groupUUID = obj.GroupID;
4273
4274 return detobj;
4275 }
4276
4277 private DetectedObject CreateDetObject(ScenePresence av)
4278 {
4279 DetectedObject detobj = new DetectedObject();
4280 detobj.keyUUID = av.UUID;
4281 detobj.nameStr = av.ControllingClient.Name;
4282 detobj.ownerUUID = av.UUID;
4283 detobj.posVector = av.AbsolutePosition;
4284 detobj.rotQuat = av.Rotation;
4285 detobj.velVector = av.Velocity;
4286 detobj.colliderType = 0;
4287 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
4288
4289 return detobj;
4290 }
4291
4292 private DetectedObject CreateDetObjectForGround()
4293 {
4294 DetectedObject detobj = new DetectedObject();
4295 detobj.keyUUID = UUID.Zero;
4296 detobj.nameStr = "";
4297 detobj.ownerUUID = UUID.Zero;
4298 detobj.posVector = AbsolutePosition;
4299 detobj.rotQuat = Quaternion.Identity;
4300 detobj.velVector = Vector3.Zero;
4301 detobj.colliderType = 0;
4302 detobj.groupUUID = UUID.Zero;
4303
4304 return detobj;
4305 }
4306
4307 private ColliderArgs CreateColliderArgs(SceneObjectPart dest, List<uint> colliders)
4308 {
4309 ColliderArgs colliderArgs = new ColliderArgs();
4310 List<DetectedObject> colliding = new List<DetectedObject>();
4311 foreach (uint localId in colliders)
4312 {
4313 if (localId == 0)
4314 continue;
4315
4316 SceneObjectPart obj = m_scene.GetSceneObjectPart(localId);
4317 if (obj != null)
4318 {
4319 if (!dest.CollisionFilteredOut(obj.UUID, obj.Name))
4320 colliding.Add(CreateDetObject(obj));
4321 }
4322 else
4323 {
4324 ScenePresence av = m_scene.GetScenePresence(localId);
4325 if (av != null && (!av.IsChildAgent))
4326 {
4327 if (!dest.CollisionFilteredOut(av.UUID, av.Name))
4328 colliding.Add(CreateDetObject(av));
4329 }
4330 }
4331 }
4332
4333 colliderArgs.Colliders = colliding;
4334
4335 return colliderArgs;
4336 }
4337
4338 private delegate void ScriptCollidingNotification(uint localID, ColliderArgs message);
4339
4340 private void SendCollisionEvent(SceneObjectGroup dest, scriptEvents ev, List<uint> colliders, ScriptCollidingNotification notify)
4341 {
4342 ColliderArgs CollidingMessage;
4343
4344 if (colliders.Count > 0)
4345 {
4346 if ((dest.RootPart.ScriptEvents & ev) != 0)
4347 {
4348 CollidingMessage = CreateColliderArgs(dest.RootPart, colliders);
4349
4350 if (CollidingMessage.Colliders.Count > 0)
4351 notify(dest.RootPart.LocalId, CollidingMessage);
4352 }
4353 }
4354 }
4355
4356 private void SendLandCollisionEvent(SceneObjectGroup dest, scriptEvents ev, ScriptCollidingNotification notify)
4357 {
4358 if ((dest.RootPart.ScriptEvents & ev) != 0)
4359 {
4360 ColliderArgs LandCollidingMessage = new ColliderArgs();
4361 List<DetectedObject> colliding = new List<DetectedObject>();
4362
4363 colliding.Add(CreateDetObjectForGround());
4364 LandCollidingMessage.Colliders = colliding;
4365
4366 notify(dest.RootPart.LocalId, LandCollidingMessage);
4367 }
4368 }
4369
4370 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
4371 {
4372 try
4373 {
4374 List<uint> thisHitColliders = new List<uint>();
4375 List<uint> endedColliders = new List<uint>();
4376 List<uint> startedColliders = new List<uint>();
4377 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
4378 CollisionForSoundInfo soundinfo;
4379 ContactPoint curcontact;
4380
4381 if (coldata.Count == 0)
4382 {
4383 if (m_lastColliders.Count == 0)
4384 return; // nothing to do
4385
4386 foreach (uint localID in m_lastColliders)
4387 {
4388 endedColliders.Add(localID);
4389 }
4390 m_lastColliders.Clear();
4391 }
4392
4393 else
4394 {
4395 foreach (uint id in coldata.Keys)
4396 {
4397 thisHitColliders.Add(id);
4398 if (!m_lastColliders.Contains(id))
4399 {
4400 startedColliders.Add(id);
4401 curcontact = coldata[id];
4402 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
4403 {
4404 soundinfo = new CollisionForSoundInfo();
4405 soundinfo.colliderID = id;
4406 soundinfo.position = curcontact.Position;
4407 soundinfo.relativeVel = curcontact.RelativeSpeed;
4408 soundinfolist.Add(soundinfo);
4409 }
4410 }
4411 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
4412 }
4413
4414 // calculate things that ended colliding
4415 foreach (uint localID in m_lastColliders)
4416 {
4417 if (!thisHitColliders.Contains(localID))
4418 {
4419 endedColliders.Add(localID);
4420 }
4421 }
4422 //add the items that started colliding this time to the last colliders list.
4423 foreach (uint localID in startedColliders)
4424 {
4425 m_lastColliders.Add(localID);
4426 }
4427 // remove things that ended colliding from the last colliders list
4428 foreach (uint localID in endedColliders)
4429 {
4430 m_lastColliders.Remove(localID);
4431 }
4432
4433 if (soundinfolist.Count > 0)
4434 CollisionSounds.AvatarCollisionSound(this, soundinfolist);
4435 }
4436
4437 foreach (SceneObjectGroup att in GetAttachments())
4438 {
4439 SendCollisionEvent(att, scriptEvents.collision_start, startedColliders, m_scene.EventManager.TriggerScriptCollidingStart);
4440 SendCollisionEvent(att, scriptEvents.collision , m_lastColliders , m_scene.EventManager.TriggerScriptColliding);
4441 SendCollisionEvent(att, scriptEvents.collision_end , endedColliders , m_scene.EventManager.TriggerScriptCollidingEnd);
4442
4443 if (startedColliders.Contains(0))
4444 SendLandCollisionEvent(att, scriptEvents.land_collision_start, m_scene.EventManager.TriggerScriptLandCollidingStart);
4445 if (m_lastColliders.Contains(0))
4446 SendLandCollisionEvent(att, scriptEvents.land_collision, m_scene.EventManager.TriggerScriptLandColliding);
4447 if (endedColliders.Contains(0))
4448 SendLandCollisionEvent(att, scriptEvents.land_collision_end, m_scene.EventManager.TriggerScriptLandCollidingEnd);
4449 }
4450 }
4451 finally
4452 {
4453 m_collisionEventFlag = false;
4454 }
4455 }
4456
4046 private void TeleportFlagsDebug() { 4457 private void TeleportFlagsDebug() {
4047 4458
4048 // Some temporary debugging help to show all the TeleportFlags we have... 4459 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -4067,6 +4478,5 @@ namespace OpenSim.Region.Framework.Scenes
4067 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 4478 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
4068 4479
4069 } 4480 }
4070
4071 } 4481 }
4072} 4482}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 0b34156..e223f47 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -244,6 +244,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
244 sr.Close(); 244 sr.Close();
245 } 245 }
246 246
247 XmlNodeList keymotion = doc.GetElementsByTagName("KeyframeMotion");
248 if (keymotion.Count > 0)
249 sceneObject.RootPart.KeyframeMotion = KeyframeMotion.FromData(sceneObject, Convert.FromBase64String(keymotion[0].InnerText));
250 else
251 sceneObject.RootPart.KeyframeMotion = null;
252
247 // Script state may, or may not, exist. Not having any, is NOT 253 // Script state may, or may not, exist. Not having any, is NOT
248 // ever a problem. 254 // ever a problem.
249 sceneObject.LoadScriptState(doc); 255 sceneObject.LoadScriptState(doc);
@@ -348,6 +354,21 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
348 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); 354 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2);
349 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 355 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
350 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 356 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
357
358 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
359 m_SOPXmlProcessors.Add("Force", ProcessForce);
360 m_SOPXmlProcessors.Add("Torque", ProcessTorque);
361 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive);
362
363
364 m_SOPXmlProcessors.Add("Vehicle", ProcessVehicle);
365
366 m_SOPXmlProcessors.Add("PhysicsShapeType", ProcessPhysicsShapeType);
367 m_SOPXmlProcessors.Add("Density", ProcessDensity);
368 m_SOPXmlProcessors.Add("Friction", ProcessFriction);
369 m_SOPXmlProcessors.Add("Bounce", ProcessBounce);
370 m_SOPXmlProcessors.Add("GravityModifier", ProcessGravityModifier);
371
351 #endregion 372 #endregion
352 373
353 #region TaskInventoryXmlProcessors initialization 374 #region TaskInventoryXmlProcessors initialization
@@ -375,7 +396,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
375 m_TaskInventoryXmlProcessors.Add("PermsMask", ProcessTIPermsMask); 396 m_TaskInventoryXmlProcessors.Add("PermsMask", ProcessTIPermsMask);
376 m_TaskInventoryXmlProcessors.Add("Type", ProcessTIType); 397 m_TaskInventoryXmlProcessors.Add("Type", ProcessTIType);
377 m_TaskInventoryXmlProcessors.Add("OwnerChanged", ProcessTIOwnerChanged); 398 m_TaskInventoryXmlProcessors.Add("OwnerChanged", ProcessTIOwnerChanged);
378 399
379 #endregion 400 #endregion
380 401
381 #region ShapeXmlProcessors initialization 402 #region ShapeXmlProcessors initialization
@@ -575,6 +596,49 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
575 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty); 596 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty);
576 } 597 }
577 598
599 private static void ProcessPhysicsShapeType(SceneObjectPart obj, XmlTextReader reader)
600 {
601 obj.PhysicsShapeType = (byte)reader.ReadElementContentAsInt("PhysicsShapeType", String.Empty);
602 }
603
604 private static void ProcessDensity(SceneObjectPart obj, XmlTextReader reader)
605 {
606 obj.Density = reader.ReadElementContentAsFloat("Density", String.Empty);
607 }
608
609 private static void ProcessFriction(SceneObjectPart obj, XmlTextReader reader)
610 {
611 obj.Friction = reader.ReadElementContentAsFloat("Friction", String.Empty);
612 }
613
614 private static void ProcessBounce(SceneObjectPart obj, XmlTextReader reader)
615 {
616 obj.Bounciness = reader.ReadElementContentAsFloat("Bounce", String.Empty);
617 }
618
619 private static void ProcessGravityModifier(SceneObjectPart obj, XmlTextReader reader)
620 {
621 obj.GravityModifier = reader.ReadElementContentAsFloat("GravityModifier", String.Empty);
622 }
623
624 private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader)
625 {
626 bool errors = false;
627 SOPVehicle _vehicle = new SOPVehicle();
628
629 _vehicle.FromXml2(reader, out errors);
630
631 if (errors)
632 {
633 obj.sopVehicle = null;
634 m_log.DebugFormat(
635 "[SceneObjectSerializer]: Parsing Vehicle for object part {0} {1} encountered errors. Please see earlier log entries.",
636 obj.Name, obj.UUID);
637 }
638 else
639 obj.sopVehicle = _vehicle;
640 }
641
578 private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader) 642 private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader)
579 { 643 {
580 List<string> errorNodeNames; 644 List<string> errorNodeNames;
@@ -739,6 +803,25 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
739 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 803 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
740 } 804 }
741 805
806 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
807 {
808 obj.Buoyancy = (float)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
809 }
810
811 private static void ProcessForce(SceneObjectPart obj, XmlTextReader reader)
812 {
813 obj.Force = Util.ReadVector(reader, "Force");
814 }
815 private static void ProcessTorque(SceneObjectPart obj, XmlTextReader reader)
816 {
817 obj.Torque = Util.ReadVector(reader, "Torque");
818 }
819
820 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlTextReader reader)
821 {
822 obj.VolumeDetectActive = Util.ReadBoolean(reader);
823 }
824
742 #endregion 825 #endregion
743 826
744 #region TaskInventoryXmlProcessors 827 #region TaskInventoryXmlProcessors
@@ -1126,6 +1209,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1126 }); 1209 });
1127 1210
1128 writer.WriteEndElement(); 1211 writer.WriteEndElement();
1212
1213 if (sog.RootPart.KeyframeMotion != null)
1214 {
1215 Byte[] data = sog.RootPart.KeyframeMotion.Serialize();
1216
1217 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty);
1218 writer.WriteBase64(data, 0, data.Length);
1219 writer.WriteEndElement();
1220 }
1221
1129 writer.WriteEndElement(); 1222 writer.WriteEndElement();
1130 } 1223 }
1131 1224
@@ -1225,6 +1318,27 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1225 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1318 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1226 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1319 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1227 1320
1321 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1322
1323 WriteVector(writer, "Force", sop.Force);
1324 WriteVector(writer, "Torque", sop.Torque);
1325
1326 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1327
1328 if (sop.sopVehicle != null)
1329 sop.sopVehicle.ToXml2(writer);
1330
1331 if(sop.PhysicsShapeType != sop.DefaultPhysicsShapeType())
1332 writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower());
1333 if (sop.Density != 1000.0f)
1334 writer.WriteElementString("Density", sop.Density.ToString().ToLower());
1335 if (sop.Friction != 0.6f)
1336 writer.WriteElementString("Friction", sop.Friction.ToString().ToLower());
1337 if (sop.Bounciness != 0.5f)
1338 writer.WriteElementString("Bounce", sop.Bounciness.ToString().ToLower());
1339 if (sop.GravityModifier != 1.0f)
1340 writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower());
1341
1228 writer.WriteEndElement(); 1342 writer.WriteEndElement();
1229 } 1343 }
1230 1344
@@ -1449,12 +1563,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1449 { 1563 {
1450 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1564 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1451 1565
1452 if (reader.IsEmptyElement)
1453 {
1454 reader.Read();
1455 return tinv;
1456 }
1457
1458 reader.ReadStartElement(name, String.Empty); 1566 reader.ReadStartElement(name, String.Empty);
1459 1567
1460 while (reader.Name == "TaskInventoryItem") 1568 while (reader.Name == "TaskInventoryItem")
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 742d42a..18e6ece 100644
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -298,6 +298,20 @@ namespace OpenSim.Region.Framework.Scenes
298 physfps = 0; 298 physfps = 0;
299 299
300#endregion 300#endregion
301 if (reportedFPS <= 0)
302 reportedFPS = 1;
303
304 float perframe = 1.0f / (float)reportedFPS;
305
306 float TotalFrameTime = m_frameMS * perframe;
307
308 float targetframetime = 1100.0f / (float)m_nominalReportedFps;
309
310 float sparetime;
311 if (TotalFrameTime > targetframetime)
312 {
313 sparetime = 0;
314 }
301 315
302 m_rootAgents = m_scene.SceneGraph.GetRootAgentCount(); 316 m_rootAgents = m_scene.SceneGraph.GetRootAgentCount();
303 m_childAgents = m_scene.SceneGraph.GetChildAgentCount(); 317 m_childAgents = m_scene.SceneGraph.GetChildAgentCount();
@@ -309,15 +323,13 @@ namespace OpenSim.Region.Framework.Scenes
309 // so that stat numbers are always consistent. 323 // so that stat numbers are always consistent.
310 CheckStatSanity(); 324 CheckStatSanity();
311 325
312 //Our time dilation is 0.91 when we're running a full speed, 326 // other MS is actually simulation time
313 // therefore to make sure we get an appropriate range, 327 // m_otherMS = m_frameMS - m_physicsMS - m_imageMS - m_netMS - m_agentMS;
314 // we have to factor in our error. (0.10f * statsUpdateFactor) 328 // m_imageMS m_netMS are not included in m_frameMS
315 // multiplies the fix for the error times the amount of times it'll occur a second 329
316 // / 10 divides the value by the number of times the sim heartbeat runs (10fps) 330 m_otherMS = m_frameMS - m_physicsMS - m_agentMS;
317 // Then we divide the whole amount by the amount of seconds pass in between stats updates. 331 if (m_otherMS < 0)
318 332 m_otherMS = 0;
319 // 'statsUpdateFactor' is how often stats packets are sent in seconds. Used below to change
320 // values to X-per-second values.
321 333
322 uint thisFrame = m_scene.Frame; 334 uint thisFrame = m_scene.Frame;
323 float framesUpdated = (float)(thisFrame - m_lastUpdateFrame) * m_reportedFpsCorrectionFactor; 335 float framesUpdated = (float)(thisFrame - m_lastUpdateFrame) * m_reportedFpsCorrectionFactor;
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 efb68a2..411e421 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -87,10 +87,6 @@ namespace OpenSim.Region.Framework.Scenes
87 /// <param name="assetUuids">The assets gathered</param> 87 /// <param name="assetUuids">The assets gathered</param>
88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids)
89 { 89 {
90 // avoid infinite loops
91 if (assetUuids.ContainsKey(assetUuid))
92 return;
93
94 try 90 try
95 { 91 {
96 assetUuids[assetUuid] = assetType; 92 assetUuids[assetUuid] = assetType;