aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-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.cs70
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs695
-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.cs801
-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
23 files changed, 6524 insertions, 1867 deletions
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..cf68ff4 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -149,27 +149,47 @@ namespace OpenSim.Region.Framework.Scenes
149 /// <param name="remoteClient"></param> 149 /// <param name="remoteClient"></param>
150 public void SelectPrim(uint primLocalID, IClientAPI remoteClient) 150 public void SelectPrim(uint primLocalID, IClientAPI remoteClient)
151 { 151 {
152 /*
153 SceneObjectPart part = GetSceneObjectPart(primLocalID);
154
155 if (null == part)
156 return;
157
158 if (part.IsRoot)
159 {
160 SceneObjectGroup sog = part.ParentGroup;
161 sog.SendPropertiesToClient(remoteClient);
162
163 // A prim is only tainted if it's allowed to be edited by the person clicking it.
164 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
165 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
166 {
167 sog.IsSelected = true;
168 EventManager.TriggerParcelPrimCountTainted();
169 }
170 }
171 else
172 {
173 part.SendPropertiesToClient(remoteClient);
174 }
175 */
152 SceneObjectPart part = GetSceneObjectPart(primLocalID); 176 SceneObjectPart part = GetSceneObjectPart(primLocalID);
153 177
154 if (null == part) 178 if (null == part)
155 return; 179 return;
156 180
157 if (part.IsRoot) 181 SceneObjectGroup sog = part.ParentGroup;
158 { 182 if (sog == null)
159 SceneObjectGroup sog = part.ParentGroup; 183 return;
160 sog.SendPropertiesToClient(remoteClient);
161 sog.IsSelected = true;
162 184
163 // A prim is only tainted if it's allowed to be edited by the person clicking it. 185 part.SendPropertiesToClient(remoteClient);
164 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId) 186
165 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId)) 187 // A prim is only tainted if it's allowed to be edited by the person clicking it.
166 { 188 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
167 EventManager.TriggerParcelPrimCountTainted(); 189 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
168 }
169 }
170 else
171 { 190 {
172 part.SendPropertiesToClient(remoteClient); 191 part.IsSelected = true;
192 EventManager.TriggerParcelPrimCountTainted();
173 } 193 }
174 } 194 }
175 195
@@ -222,7 +242,7 @@ namespace OpenSim.Region.Framework.Scenes
222 SceneObjectPart part = GetSceneObjectPart(primLocalID); 242 SceneObjectPart part = GetSceneObjectPart(primLocalID);
223 if (part == null) 243 if (part == null)
224 return; 244 return;
225 245 /*
226 // A deselect packet contains all the local prims being deselected. However, since selection is still 246 // 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 247 // 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 248 // we end up sending many duplicate ObjectUpdates
@@ -235,7 +255,9 @@ namespace OpenSim.Region.Framework.Scenes
235 // handled by group, but by prim. Legacy cruft. 255 // handled by group, but by prim. Legacy cruft.
236 // TODO: Make selection flagging per prim! 256 // TODO: Make selection flagging per prim!
237 // 257 //
238 part.ParentGroup.IsSelected = false; 258 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
259 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
260 part.ParentGroup.IsSelected = false;
239 261
240 if (part.ParentGroup.IsAttachment) 262 if (part.ParentGroup.IsAttachment)
241 isAttachment = true; 263 isAttachment = true;
@@ -255,6 +277,22 @@ namespace OpenSim.Region.Framework.Scenes
255 part.UUID, remoteClient.AgentId)) 277 part.UUID, remoteClient.AgentId))
256 EventManager.TriggerParcelPrimCountTainted(); 278 EventManager.TriggerParcelPrimCountTainted();
257 } 279 }
280 */
281
282 bool oldgprSelect = part.ParentGroup.IsSelected;
283
284 // This is wrong, wrong, wrong. Selection should not be
285 // handled by group, but by prim. Legacy cruft.
286 // TODO: Make selection flagging per prim!
287 //
288 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
289 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
290 {
291 part.IsSelected = false;
292 if (!part.ParentGroup.IsAttachment && oldgprSelect != part.ParentGroup.IsSelected)
293 EventManager.TriggerParcelPrimCountTainted();
294 }
295
258 } 296 }
259 297
260 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount, 298 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 d449116..8591b09 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -124,6 +124,7 @@ namespace OpenSim.Region.Framework.Scenes
124 // TODO: need to figure out how allow client agents but deny 124 // TODO: need to figure out how allow client agents but deny
125 // root agents when ACL denies access to root agent 125 // root agents when ACL denies access to root agent
126 public bool m_strictAccessControl = true; 126 public bool m_strictAccessControl = true;
127 public bool m_seeIntoBannedRegion = false;
127 public int MaxUndoCount = 5; 128 public int MaxUndoCount = 5;
128 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 129 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
129 public bool LoginLock = false; 130 public bool LoginLock = false;
@@ -139,12 +140,14 @@ namespace OpenSim.Region.Framework.Scenes
139 140
140 protected int m_splitRegionID; 141 protected int m_splitRegionID;
141 protected Timer m_restartWaitTimer = new Timer(); 142 protected Timer m_restartWaitTimer = new Timer();
143 protected Timer m_timerWatchdog = new Timer();
142 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 144 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
143 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 145 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
144 protected string m_simulatorVersion = "OpenSimulator Server"; 146 protected string m_simulatorVersion = "OpenSimulator Server";
145 protected ModuleLoader m_moduleLoader; 147 protected ModuleLoader m_moduleLoader;
146 protected AgentCircuitManager m_authenticateHandler; 148 protected AgentCircuitManager m_authenticateHandler;
147 protected SceneCommunicationService m_sceneGridService; 149 protected SceneCommunicationService m_sceneGridService;
150 protected ISnmpModule m_snmpService = null;
148 151
149 protected ISimulationDataService m_SimulationDataService; 152 protected ISimulationDataService m_SimulationDataService;
150 protected IEstateDataService m_EstateDataService; 153 protected IEstateDataService m_EstateDataService;
@@ -206,7 +209,7 @@ namespace OpenSim.Region.Framework.Scenes
206 private int m_update_events = 1; 209 private int m_update_events = 1;
207 private int m_update_backup = 200; 210 private int m_update_backup = 200;
208 private int m_update_terrain = 50; 211 private int m_update_terrain = 50;
209// private int m_update_land = 1; 212 private int m_update_land = 10;
210 private int m_update_coarse_locations = 50; 213 private int m_update_coarse_locations = 50;
211 214
212 private int agentMS; 215 private int agentMS;
@@ -226,6 +229,7 @@ namespace OpenSim.Region.Framework.Scenes
226 /// </summary> 229 /// </summary>
227 private int m_lastFrameTick; 230 private int m_lastFrameTick;
228 231
232 public bool CombineRegions = false;
229 /// <summary> 233 /// <summary>
230 /// Tick at which the last maintenance run occurred. 234 /// Tick at which the last maintenance run occurred.
231 /// </summary> 235 /// </summary>
@@ -256,6 +260,11 @@ namespace OpenSim.Region.Framework.Scenes
256 /// </summary> 260 /// </summary>
257 private int m_LastLogin; 261 private int m_LastLogin;
258 262
263 private int m_lastIncoming;
264 private int m_lastOutgoing;
265 private int m_hbRestarts = 0;
266
267
259 /// <summary> 268 /// <summary>
260 /// Thread that runs the scene loop. 269 /// Thread that runs the scene loop.
261 /// </summary> 270 /// </summary>
@@ -271,7 +280,7 @@ namespace OpenSim.Region.Framework.Scenes
271 private volatile bool m_shuttingDown; 280 private volatile bool m_shuttingDown;
272 281
273// private int m_lastUpdate; 282// private int m_lastUpdate;
274// private bool m_firstHeartbeat = true; 283 private bool m_firstHeartbeat = true;
275 284
276 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time; 285 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time;
277 private bool m_reprioritizationEnabled = true; 286 private bool m_reprioritizationEnabled = true;
@@ -316,6 +325,19 @@ namespace OpenSim.Region.Framework.Scenes
316 get { return m_sceneGridService; } 325 get { return m_sceneGridService; }
317 } 326 }
318 327
328 public ISnmpModule SnmpService
329 {
330 get
331 {
332 if (m_snmpService == null)
333 {
334 m_snmpService = RequestModuleInterface<ISnmpModule>();
335 }
336
337 return m_snmpService;
338 }
339 }
340
319 public ISimulationDataService SimulationDataService 341 public ISimulationDataService SimulationDataService
320 { 342 {
321 get 343 get
@@ -616,6 +638,8 @@ namespace OpenSim.Region.Framework.Scenes
616 m_EstateDataService = estateDataService; 638 m_EstateDataService = estateDataService;
617 m_regionHandle = m_regInfo.RegionHandle; 639 m_regionHandle = m_regInfo.RegionHandle;
618 m_regionName = m_regInfo.RegionName; 640 m_regionName = m_regInfo.RegionName;
641 m_lastIncoming = 0;
642 m_lastOutgoing = 0;
619 643
620 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 644 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
621 m_asyncSceneObjectDeleter.Enabled = true; 645 m_asyncSceneObjectDeleter.Enabled = true;
@@ -696,102 +720,111 @@ namespace OpenSim.Region.Framework.Scenes
696 720
697 // Region config overrides global config 721 // Region config overrides global config
698 // 722 //
699 if (m_config.Configs["Startup"] != null) 723 try
700 { 724 {
701 IConfig startupConfig = m_config.Configs["Startup"]; 725 if (m_config.Configs["Startup"] != null)
702
703 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance);
704 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
705 if (!m_useBackup)
706 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
707
708 //Animation states
709 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
710
711 PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims);
712 CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims);
713
714 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
715 if (RegionInfo.NonphysPrimMax > 0)
716 { 726 {
717 m_maxNonphys = RegionInfo.NonphysPrimMax; 727 IConfig startupConfig = m_config.Configs["Startup"];
718 }
719
720 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
721 728
722 if (RegionInfo.PhysPrimMax > 0) 729 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance);
723 { 730 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
724 m_maxPhys = RegionInfo.PhysPrimMax; 731 if (!m_useBackup)
725 } 732 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
733
734 //Animation states
735 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
726 736
727 // Here, if clamping is requested in either global or 737 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
728 // local config, it will be used 738 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
729 //
730 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize);
731 if (RegionInfo.ClampPrimSize)
732 {
733 m_clampPrimSize = true;
734 }
735 739
736 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete); 740 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
737 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 741 if (RegionInfo.NonphysPrimMax > 0)
738 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); 742 {
739 m_dontPersistBefore = 743 m_maxNonphys = RegionInfo.NonphysPrimMax;
740 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE); 744 }
741 m_dontPersistBefore *= 10000000;
742 m_persistAfter =
743 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
744 m_persistAfter *= 10000000;
745 745
746 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 746 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
747 747
748 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); 748 if (RegionInfo.PhysPrimMax > 0)
749 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); 749 {
750 m_maxPhys = RegionInfo.PhysPrimMax;
751 }
750 752
751 IConfig packetConfig = m_config.Configs["PacketPool"]; 753 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
752 if (packetConfig != null) 754 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
753 {
754 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
755 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
756 }
757 755
758 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 756 // Here, if clamping is requested in either global or
757 // local config, it will be used
758 //
759 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize);
760 if (RegionInfo.ClampPrimSize)
761 {
762 m_clampPrimSize = true;
763 }
759 764
760 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 765 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete);
761 if (m_generateMaptiles) 766 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
762 { 767 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
763 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0); 768 m_dontPersistBefore =
764 if (maptileRefresh != 0) 769 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
770 m_dontPersistBefore *= 10000000;
771 m_persistAfter =
772 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
773 m_persistAfter *= 10000000;
774
775 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
776 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
777
778 IConfig packetConfig = m_config.Configs["PacketPool"];
779 if (packetConfig != null)
765 { 780 {
766 m_mapGenerationTimer.Interval = maptileRefresh * 1000; 781 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
767 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister; 782 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
768 m_mapGenerationTimer.AutoReset = true;
769 m_mapGenerationTimer.Start();
770 } 783 }
771 }
772 else
773 {
774 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
775 UUID tileID;
776 784
777 if (UUID.TryParse(tile, out tileID)) 785 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
786 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
787 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
788
789 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
790 if (m_generateMaptiles)
778 { 791 {
779 RegionInfo.RegionSettings.TerrainImageID = tileID; 792 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0);
793 if (maptileRefresh != 0)
794 {
795 m_mapGenerationTimer.Interval = maptileRefresh * 1000;
796 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister;
797 m_mapGenerationTimer.AutoReset = true;
798 m_mapGenerationTimer.Start();
799 }
780 } 800 }
781 } 801 else
802 {
803 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
804 UUID tileID;
782 805
783 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime); 806 if (UUID.TryParse(tile, out tileID))
784 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup); 807 {
785 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 808 RegionInfo.RegionSettings.TerrainImageID = tileID;
786 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement); 809 }
787 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events); 810 }
788 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects);
789 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics);
790 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
791 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
792 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
793 811
794 SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates); 812 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime);
813 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup);
814 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
815 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement);
816 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events);
817 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects);
818 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics);
819 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
820 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
821 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
822 SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates);
823 }
824 }
825 catch (Exception e)
826 {
827 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
795 } 828 }
796 829
797 #endregion Region Config 830 #endregion Region Config
@@ -1218,7 +1251,22 @@ namespace OpenSim.Region.Framework.Scenes
1218 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1251 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1219 if (m_heartbeatThread != null) 1252 if (m_heartbeatThread != null)
1220 { 1253 {
1254 m_hbRestarts++;
1255 if(m_hbRestarts > 10)
1256 Environment.Exit(1);
1257 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1258
1259//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1260//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1261//proc.EnableRaisingEvents=false;
1262//proc.StartInfo.FileName = "/bin/kill";
1263//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1264//proc.Start();
1265//proc.WaitForExit();
1266//Thread.Sleep(1000);
1267//Environment.Exit(1);
1221 m_heartbeatThread.Abort(); 1268 m_heartbeatThread.Abort();
1269 Watchdog.AbortThread(m_heartbeatThread.ManagedThreadId);
1222 m_heartbeatThread = null; 1270 m_heartbeatThread = null;
1223 } 1271 }
1224// m_lastUpdate = Util.EnvironmentTickCount(); 1272// m_lastUpdate = Util.EnvironmentTickCount();
@@ -1509,6 +1557,8 @@ namespace OpenSim.Region.Framework.Scenes
1509 tmpMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc); 1557 tmpMS = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc);
1510 tmpMS = (int)(MinFrameTime * 1000) - tmpMS; 1558 tmpMS = (int)(MinFrameTime * 1000) - tmpMS;
1511 1559
1560 m_firstHeartbeat = false;
1561
1512 if (tmpMS > 0) 1562 if (tmpMS > 0)
1513 { 1563 {
1514 Thread.Sleep(tmpMS); 1564 Thread.Sleep(tmpMS);
@@ -1559,9 +1609,9 @@ namespace OpenSim.Region.Framework.Scenes
1559 1609
1560 private void CheckAtTargets() 1610 private void CheckAtTargets()
1561 { 1611 {
1562 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1612 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1563 lock (m_groupsWithTargets) 1613 lock (m_groupsWithTargets)
1564 objs = m_groupsWithTargets.Values; 1614 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1565 1615
1566 foreach (SceneObjectGroup entry in objs) 1616 foreach (SceneObjectGroup entry in objs)
1567 entry.checkAtTargets(); 1617 entry.checkAtTargets();
@@ -1642,7 +1692,7 @@ namespace OpenSim.Region.Framework.Scenes
1642 msg.fromAgentName = "Server"; 1692 msg.fromAgentName = "Server";
1643 msg.dialog = (byte)19; // Object msg 1693 msg.dialog = (byte)19; // Object msg
1644 msg.fromGroup = false; 1694 msg.fromGroup = false;
1645 msg.offline = (byte)0; 1695 msg.offline = (byte)1;
1646 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1696 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1647 msg.Position = Vector3.Zero; 1697 msg.Position = Vector3.Zero;
1648 msg.RegionID = RegionInfo.RegionID.Guid; 1698 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1864,6 +1914,19 @@ namespace OpenSim.Region.Framework.Scenes
1864 EventManager.TriggerPrimsLoaded(this); 1914 EventManager.TriggerPrimsLoaded(this);
1865 } 1915 }
1866 1916
1917 public bool SuportsRayCastFiltered()
1918 {
1919 if (PhysicsScene == null)
1920 return false;
1921 return PhysicsScene.SuportsRaycastWorldFiltered();
1922 }
1923
1924 public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter)
1925 {
1926 if (PhysicsScene == null)
1927 return null;
1928 return PhysicsScene.RaycastWorld(position, direction, length, Count,filter);
1929 }
1867 1930
1868 /// <summary> 1931 /// <summary>
1869 /// Gets a new rez location based on the raycast and the size of the object that is being rezzed. 1932 /// Gets a new rez location based on the raycast and the size of the object that is being rezzed.
@@ -1880,14 +1943,24 @@ namespace OpenSim.Region.Framework.Scenes
1880 /// <returns></returns> 1943 /// <returns></returns>
1881 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1944 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1882 { 1945 {
1946
1947 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1948 Vector3 wpos = Vector3.Zero;
1949 // Check for water surface intersection from above
1950 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1951 {
1952 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1953 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1954 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1955 wpos.Z = wheight;
1956 }
1957
1883 Vector3 pos = Vector3.Zero; 1958 Vector3 pos = Vector3.Zero;
1884 if (RayEndIsIntersection == (byte)1) 1959 if (RayEndIsIntersection == (byte)1)
1885 { 1960 {
1886 pos = RayEnd; 1961 pos = RayEnd;
1887 return pos;
1888 } 1962 }
1889 1963 else if (RayTargetID != UUID.Zero)
1890 if (RayTargetID != UUID.Zero)
1891 { 1964 {
1892 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1965 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1893 1966
@@ -1909,7 +1982,7 @@ namespace OpenSim.Region.Framework.Scenes
1909 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1982 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1910 1983
1911 // Un-comment out the following line to Get Raytrace results printed to the console. 1984 // Un-comment out the following line to Get Raytrace results printed to the console.
1912 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1985 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1913 float ScaleOffset = 0.5f; 1986 float ScaleOffset = 0.5f;
1914 1987
1915 // If we hit something 1988 // If we hit something
@@ -1932,13 +2005,10 @@ namespace OpenSim.Region.Framework.Scenes
1932 //pos.Z -= 0.25F; 2005 //pos.Z -= 0.25F;
1933 2006
1934 } 2007 }
1935
1936 return pos;
1937 } 2008 }
1938 else 2009 else
1939 { 2010 {
1940 // We don't have a target here, so we're going to raytrace all the objects in the scene. 2011 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1941
1942 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 2012 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1943 2013
1944 // Un-comment the following line to print the raytrace results to the console. 2014 // Un-comment the following line to print the raytrace results to the console.
@@ -1947,13 +2017,12 @@ namespace OpenSim.Region.Framework.Scenes
1947 if (ei.HitTF) 2017 if (ei.HitTF)
1948 { 2018 {
1949 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 2019 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1950 } else 2020 }
2021 else
1951 { 2022 {
1952 // fall back to our stupid functionality 2023 // fall back to our stupid functionality
1953 pos = RayEnd; 2024 pos = RayEnd;
1954 } 2025 }
1955
1956 return pos;
1957 } 2026 }
1958 } 2027 }
1959 else 2028 else
@@ -1964,8 +2033,12 @@ namespace OpenSim.Region.Framework.Scenes
1964 //increase height so its above the ground. 2033 //increase height so its above the ground.
1965 //should be getting the normal of the ground at the rez point and using that? 2034 //should be getting the normal of the ground at the rez point and using that?
1966 pos.Z += scale.Z / 2f; 2035 pos.Z += scale.Z / 2f;
1967 return pos; 2036// return pos;
1968 } 2037 }
2038
2039 // check against posible water intercept
2040 if (wpos.Z > pos.Z) pos = wpos;
2041 return pos;
1969 } 2042 }
1970 2043
1971 2044
@@ -2054,7 +2127,10 @@ namespace OpenSim.Region.Framework.Scenes
2054 public bool AddRestoredSceneObject( 2127 public bool AddRestoredSceneObject(
2055 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 2128 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
2056 { 2129 {
2057 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 2130 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
2131 if (result)
2132 sceneObject.IsDeleted = false;
2133 return result;
2058 } 2134 }
2059 2135
2060 /// <summary> 2136 /// <summary>
@@ -2146,6 +2222,15 @@ namespace OpenSim.Region.Framework.Scenes
2146 /// </summary> 2222 /// </summary>
2147 public void DeleteAllSceneObjects() 2223 public void DeleteAllSceneObjects()
2148 { 2224 {
2225 DeleteAllSceneObjects(false);
2226 }
2227
2228 /// <summary>
2229 /// Delete every object from the scene. This does not include attachments worn by avatars.
2230 /// </summary>
2231 public void DeleteAllSceneObjects(bool exceptNoCopy)
2232 {
2233 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2149 lock (Entities) 2234 lock (Entities)
2150 { 2235 {
2151 EntityBase[] entities = Entities.GetEntities(); 2236 EntityBase[] entities = Entities.GetEntities();
@@ -2154,11 +2239,24 @@ namespace OpenSim.Region.Framework.Scenes
2154 if (e is SceneObjectGroup) 2239 if (e is SceneObjectGroup)
2155 { 2240 {
2156 SceneObjectGroup sog = (SceneObjectGroup)e; 2241 SceneObjectGroup sog = (SceneObjectGroup)e;
2157 if (!sog.IsAttachment) 2242 if (sog != null && !sog.IsAttachment)
2158 DeleteSceneObject((SceneObjectGroup)e, false); 2243 {
2244 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2245 {
2246 DeleteSceneObject((SceneObjectGroup)e, false);
2247 }
2248 else
2249 {
2250 toReturn.Add((SceneObjectGroup)e);
2251 }
2252 }
2159 } 2253 }
2160 } 2254 }
2161 } 2255 }
2256 if (toReturn.Count > 0)
2257 {
2258 returnObjects(toReturn.ToArray(), UUID.Zero);
2259 }
2162 } 2260 }
2163 2261
2164 /// <summary> 2262 /// <summary>
@@ -2193,6 +2291,8 @@ namespace OpenSim.Region.Framework.Scenes
2193 } 2291 }
2194 2292
2195 group.DeleteGroupFromScene(silent); 2293 group.DeleteGroupFromScene(silent);
2294 if (!silent)
2295 SendKillObject(new List<uint>() { group.LocalId });
2196 2296
2197// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2297// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2198 } 2298 }
@@ -2482,6 +2582,8 @@ namespace OpenSim.Region.Framework.Scenes
2482 2582
2483 if (newPosition != Vector3.Zero) 2583 if (newPosition != Vector3.Zero)
2484 newObject.RootPart.GroupPosition = newPosition; 2584 newObject.RootPart.GroupPosition = newPosition;
2585 if (newObject.RootPart.KeyframeMotion != null)
2586 newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
2485 2587
2486 if (!AddSceneObject(newObject)) 2588 if (!AddSceneObject(newObject))
2487 { 2589 {
@@ -2550,10 +2652,17 @@ namespace OpenSim.Region.Framework.Scenes
2550 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2652 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2551 public bool AddSceneObject(SceneObjectGroup sceneObject) 2653 public bool AddSceneObject(SceneObjectGroup sceneObject)
2552 { 2654 {
2655 if (sceneObject.OwnerID == UUID.Zero)
2656 {
2657 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2658 return false;
2659 }
2660
2553 // If the user is banned, we won't let any of their objects 2661 // If the user is banned, we won't let any of their objects
2554 // enter. Period. 2662 // enter. Period.
2555 // 2663 //
2556 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2664 int flags = GetUserFlags(sceneObject.OwnerID);
2665 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2557 { 2666 {
2558 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2667 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2559 2668
@@ -2595,16 +2704,27 @@ namespace OpenSim.Region.Framework.Scenes
2595 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2704 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2596 2705
2597 if (AttachmentsModule != null) 2706 if (AttachmentsModule != null)
2598 AttachmentsModule.AttachObject(sp, grp, 0, false); 2707 AttachmentsModule.AttachObject(sp, grp, 0, false, false);
2599 } 2708 }
2600 else 2709 else
2601 { 2710 {
2711 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2602 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2712 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2603 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2713 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2604 } 2714 }
2715 if (sceneObject.OwnerID == UUID.Zero)
2716 {
2717 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2718 return false;
2719 }
2605 } 2720 }
2606 else 2721 else
2607 { 2722 {
2723 if (sceneObject.OwnerID == UUID.Zero)
2724 {
2725 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2726 return false;
2727 }
2608 AddRestoredSceneObject(sceneObject, true, false); 2728 AddRestoredSceneObject(sceneObject, true, false);
2609 2729
2610 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2730 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2633,6 +2753,24 @@ namespace OpenSim.Region.Framework.Scenes
2633 return 2; // StateSource.PrimCrossing 2753 return 2; // StateSource.PrimCrossing
2634 } 2754 }
2635 2755
2756 public int GetUserFlags(UUID user)
2757 {
2758 //Unfortunately the SP approach means that the value is cached until region is restarted
2759 /*
2760 ScenePresence sp;
2761 if (TryGetScenePresence(user, out sp))
2762 {
2763 return sp.UserFlags;
2764 }
2765 else
2766 {
2767 */
2768 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2769 if (uac == null)
2770 return 0;
2771 return uac.UserFlags;
2772 //}
2773 }
2636 #endregion 2774 #endregion
2637 2775
2638 #region Add/Remove Avatar Methods 2776 #region Add/Remove Avatar Methods
@@ -2646,7 +2784,7 @@ namespace OpenSim.Region.Framework.Scenes
2646 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 2784 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2647 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2785 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2648 2786
2649// CheckHeartbeat(); 2787 CheckHeartbeat();
2650 2788
2651 ScenePresence sp = GetScenePresence(client.AgentId); 2789 ScenePresence sp = GetScenePresence(client.AgentId);
2652 2790
@@ -2700,7 +2838,13 @@ namespace OpenSim.Region.Framework.Scenes
2700 2838
2701 EventManager.TriggerOnNewClient(client); 2839 EventManager.TriggerOnNewClient(client);
2702 if (vialogin) 2840 if (vialogin)
2841 {
2703 EventManager.TriggerOnClientLogin(client); 2842 EventManager.TriggerOnClientLogin(client);
2843 // Send initial parcel data
2844 Vector3 pos = sp.AbsolutePosition;
2845 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2846 land.SendLandUpdateToClient(client);
2847 }
2704 2848
2705 return sp; 2849 return sp;
2706 } 2850 }
@@ -2789,19 +2933,12 @@ namespace OpenSim.Region.Framework.Scenes
2789 // and the scene presence and the client, if they exist 2933 // and the scene presence and the client, if they exist
2790 try 2934 try
2791 { 2935 {
2792 // We need to wait for the client to make UDP contact first. 2936 ScenePresence sp = GetScenePresence(agentID);
2793 // It's the UDP contact that creates the scene presence 2937 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2794 ScenePresence sp = WaitGetScenePresence(agentID); 2938
2795 if (sp != null) 2939 if (sp != null)
2796 {
2797 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2798
2799 sp.ControllingClient.Close(); 2940 sp.ControllingClient.Close();
2800 } 2941
2801 else
2802 {
2803 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2804 }
2805 // BANG! SLASH! 2942 // BANG! SLASH!
2806 m_authenticateHandler.RemoveCircuit(agentID); 2943 m_authenticateHandler.RemoveCircuit(agentID);
2807 2944
@@ -2846,6 +2983,8 @@ namespace OpenSim.Region.Framework.Scenes
2846 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; 2983 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition;
2847 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; 2984 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
2848 2985
2986 client.onClientChangeObject += m_sceneGraph.ClientChangeObject;
2987
2849 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; 2988 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation;
2850 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; 2989 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation;
2851 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; 2990 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
@@ -2902,6 +3041,7 @@ namespace OpenSim.Region.Framework.Scenes
2902 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 3041 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2903 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 3042 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2904 client.OnCopyInventoryItem += CopyInventoryItem; 3043 client.OnCopyInventoryItem += CopyInventoryItem;
3044 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2905 client.OnMoveInventoryItem += MoveInventoryItem; 3045 client.OnMoveInventoryItem += MoveInventoryItem;
2906 client.OnRemoveInventoryItem += RemoveInventoryItem; 3046 client.OnRemoveInventoryItem += RemoveInventoryItem;
2907 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 3047 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2973,6 +3113,8 @@ namespace OpenSim.Region.Framework.Scenes
2973 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; 3113 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition;
2974 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; 3114 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition;
2975 3115
3116 client.onClientChangeObject -= m_sceneGraph.ClientChangeObject;
3117
2976 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3118 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation;
2977 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3119 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation;
2978 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; 3120 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation;
@@ -3075,7 +3217,7 @@ namespace OpenSim.Region.Framework.Scenes
3075 /// </summary> 3217 /// </summary>
3076 /// <param name="agentId">The avatar's Unique ID</param> 3218 /// <param name="agentId">The avatar's Unique ID</param>
3077 /// <param name="client">The IClientAPI for the client</param> 3219 /// <param name="client">The IClientAPI for the client</param>
3078 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3220 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
3079 { 3221 {
3080 if (EntityTransferModule != null) 3222 if (EntityTransferModule != null)
3081 { 3223 {
@@ -3086,6 +3228,7 @@ namespace OpenSim.Region.Framework.Scenes
3086 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3228 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
3087 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3229 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
3088 } 3230 }
3231 return false;
3089 } 3232 }
3090 3233
3091 /// <summary> 3234 /// <summary>
@@ -3195,6 +3338,16 @@ namespace OpenSim.Region.Framework.Scenes
3195 /// <param name="flags"></param> 3338 /// <param name="flags"></param>
3196 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3339 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3197 { 3340 {
3341 //Add half the avatar's height so that the user doesn't fall through prims
3342 ScenePresence presence;
3343 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3344 {
3345 if (presence.Appearance != null)
3346 {
3347 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3348 }
3349 }
3350
3198 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3351 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3199 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3352 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3200 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3353 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3323,6 +3476,7 @@ namespace OpenSim.Region.Framework.Scenes
3323 avatar.Close(); 3476 avatar.Close();
3324 3477
3325 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3478 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3479 m_log.Debug("[Scene] The avatar has left the building");
3326 } 3480 }
3327 catch (Exception e) 3481 catch (Exception e)
3328 { 3482 {
@@ -3472,13 +3626,16 @@ namespace OpenSim.Region.Framework.Scenes
3472 sp = null; 3626 sp = null;
3473 } 3627 }
3474 3628
3475 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3476 3629
3477 //On login test land permisions 3630 //On login test land permisions
3478 if (vialogin) 3631 if (vialogin)
3479 { 3632 {
3480 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3633 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3634 if (cache != null)
3635 cache.Remove(agent.firstname + " " + agent.lastname);
3636 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3481 { 3637 {
3638 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3482 return false; 3639 return false;
3483 } 3640 }
3484 } 3641 }
@@ -3501,9 +3658,15 @@ namespace OpenSim.Region.Framework.Scenes
3501 3658
3502 try 3659 try
3503 { 3660 {
3504 if (!AuthorizeUser(agent, out reason)) 3661 // Always check estate if this is a login. Always
3505 return false; 3662 // check if banned regions are to be blacked out.
3506 } catch (Exception e) 3663 if (vialogin || (!m_seeIntoBannedRegion))
3664 {
3665 if (!AuthorizeUser(agent, out reason))
3666 return false;
3667 }
3668 }
3669 catch (Exception e)
3507 { 3670 {
3508 m_log.ErrorFormat( 3671 m_log.ErrorFormat(
3509 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 3672 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
@@ -3634,6 +3797,8 @@ namespace OpenSim.Region.Framework.Scenes
3634 } 3797 }
3635 3798
3636 // Honor parcel landing type and position. 3799 // Honor parcel landing type and position.
3800 /*
3801 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3637 if (land != null) 3802 if (land != null)
3638 { 3803 {
3639 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3804 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3641,25 +3806,34 @@ namespace OpenSim.Region.Framework.Scenes
3641 agent.startpos = land.LandData.UserLocation; 3806 agent.startpos = land.LandData.UserLocation;
3642 } 3807 }
3643 } 3808 }
3809 */// This is now handled properly in ScenePresence.MakeRootAgent
3644 } 3810 }
3645 3811
3646 return true; 3812 return true;
3647 } 3813 }
3648 3814
3649 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3815 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3650 { 3816 {
3651 bool banned = land.IsBannedFromLand(agent.AgentID); 3817 reason = String.Empty;
3652 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3818 if (Permissions.IsGod(agentID))
3819 return true;
3820
3821 ILandObject land = LandChannel.GetLandObject(posX, posY);
3822 if (land == null)
3823 return false;
3824
3825 bool banned = land.IsBannedFromLand(agentID);
3826 bool restricted = land.IsRestrictedFromLand(agentID);
3653 3827
3654 if (banned || restricted) 3828 if (banned || restricted)
3655 { 3829 {
3656 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3830 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3657 if (nearestParcel != null) 3831 if (nearestParcel != null)
3658 { 3832 {
3659 //Move agent to nearest allowed 3833 //Move agent to nearest allowed
3660 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3834 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3661 agent.startpos.X = newPosition.X; 3835 posX = newPosition.X;
3662 agent.startpos.Y = newPosition.Y; 3836 posY = newPosition.Y;
3663 } 3837 }
3664 else 3838 else
3665 { 3839 {
@@ -3721,7 +3895,7 @@ namespace OpenSim.Region.Framework.Scenes
3721 3895
3722 if (!m_strictAccessControl) return true; 3896 if (!m_strictAccessControl) return true;
3723 if (Permissions.IsGod(agent.AgentID)) return true; 3897 if (Permissions.IsGod(agent.AgentID)) return true;
3724 3898
3725 if (AuthorizationService != null) 3899 if (AuthorizationService != null)
3726 { 3900 {
3727 if (!AuthorizationService.IsAuthorizedForRegion( 3901 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3736,7 +3910,7 @@ namespace OpenSim.Region.Framework.Scenes
3736 3910
3737 if (m_regInfo.EstateSettings != null) 3911 if (m_regInfo.EstateSettings != null)
3738 { 3912 {
3739 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3913 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3740 { 3914 {
3741 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3915 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3742 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3916 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3926,6 +4100,15 @@ namespace OpenSim.Region.Framework.Scenes
3926 4100
3927 // XPTO: if this agent is not allowed here as root, always return false 4101 // XPTO: if this agent is not allowed here as root, always return false
3928 4102
4103 // We have to wait until the viewer contacts this region after receiving EAC.
4104 // That calls AddNewClient, which finally creates the ScenePresence
4105 int flags = GetUserFlags(cAgentData.AgentID);
4106 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
4107 {
4108 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
4109 return false;
4110 }
4111
3929 // TODO: This check should probably be in QueryAccess(). 4112 // TODO: This check should probably be in QueryAccess().
3930 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4113 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3931 if (nearestParcel == null) 4114 if (nearestParcel == null)
@@ -4019,12 +4202,22 @@ namespace OpenSim.Region.Framework.Scenes
4019 return false; 4202 return false;
4020 } 4203 }
4021 4204
4205 public bool IncomingCloseAgent(UUID agentID)
4206 {
4207 return IncomingCloseAgent(agentID, false);
4208 }
4209
4210 public bool IncomingCloseChildAgent(UUID agentID)
4211 {
4212 return IncomingCloseAgent(agentID, true);
4213 }
4214
4022 /// <summary> 4215 /// <summary>
4023 /// Tell a single agent to disconnect from the region. 4216 /// Tell a single agent to disconnect from the region.
4024 /// </summary> 4217 /// </summary>
4025 /// <param name="regionHandle"></param>
4026 /// <param name="agentID"></param> 4218 /// <param name="agentID"></param>
4027 public bool IncomingCloseAgent(UUID agentID) 4219 /// <param name="childOnly"></param>
4220 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
4028 { 4221 {
4029 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4222 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
4030 4223
@@ -4617,35 +4810,81 @@ namespace OpenSim.Region.Framework.Scenes
4617 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4810 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4618 } 4811 }
4619 4812
4620 public int GetHealth() 4813 public int GetHealth(out int flags, out string message)
4621 { 4814 {
4622 // Returns: 4815 // Returns:
4623 // 1 = sim is up and accepting http requests. The heartbeat has 4816 // 1 = sim is up and accepting http requests. The heartbeat has
4624 // stopped and the sim is probably locked up, but a remote 4817 // stopped and the sim is probably locked up, but a remote
4625 // admin restart may succeed 4818 // admin restart may succeed
4626 // 4819 //
4627 // 2 = Sim is up and the heartbeat is running. The sim is likely 4820 // 2 = Sim is up and the heartbeat is running. The sim is likely
4628 // usable for people within and logins _may_ work 4821 // usable for people within
4822 //
4823 // 3 = Sim is up and one packet thread is running. Sim is
4824 // unstable and will not accept new logins
4629 // 4825 //
4630 // 3 = We have seen a new user enter within the past 4 minutes 4826 // 4 = Sim is up and both packet threads are running. Sim is
4827 // likely usable
4828 //
4829 // 5 = We have seen a new user enter within the past 4 minutes
4631 // which can be seen as positive confirmation of sim health 4830 // which can be seen as positive confirmation of sim health
4632 // 4831 //
4832
4833 flags = 0;
4834 message = String.Empty;
4835
4836 CheckHeartbeat();
4837
4838 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4839 {
4840 // We're still starting
4841 // 0 means "in startup", it can't happen another way, since
4842 // to get here, we must be able to accept http connections
4843 return 0;
4844 }
4845
4633 int health=1; // Start at 1, means we're up 4846 int health=1; // Start at 1, means we're up
4634 4847
4635 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) 4848 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000)
4636 health += 1; 4849 {
4850 health+=1;
4851 flags |= 1;
4852 }
4853
4854 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4855 {
4856 health+=1;
4857 flags |= 2;
4858 }
4859
4860 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4861 {
4862 health+=1;
4863 flags |= 4;
4864 }
4637 else 4865 else
4866 {
4867int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4868System.Diagnostics.Process proc = new System.Diagnostics.Process();
4869proc.EnableRaisingEvents=false;
4870proc.StartInfo.FileName = "/bin/kill";
4871proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4872proc.Start();
4873proc.WaitForExit();
4874Thread.Sleep(1000);
4875Environment.Exit(1);
4876 }
4877
4878 if (flags != 7)
4638 return health; 4879 return health;
4639 4880
4640 // A login in the last 4 mins? We can't be doing too badly 4881 // A login in the last 4 mins? We can't be doing too badly
4641 // 4882 //
4642 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4883 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4643 health++; 4884 health++;
4644 else 4885 else
4645 return health; 4886 return health;
4646 4887
4647// CheckHeartbeat();
4648
4649 return health; 4888 return health;
4650 } 4889 }
4651 4890
@@ -4733,7 +4972,7 @@ namespace OpenSim.Region.Framework.Scenes
4733 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); 4972 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
4734 if (wasUsingPhysics) 4973 if (wasUsingPhysics)
4735 { 4974 {
4736 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 4975 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
4737 } 4976 }
4738 } 4977 }
4739 4978
@@ -4832,14 +5071,14 @@ namespace OpenSim.Region.Framework.Scenes
4832 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; 5071 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z;
4833 } 5072 }
4834 5073
4835// private void CheckHeartbeat() 5074 private void CheckHeartbeat()
4836// { 5075 {
4837// if (m_firstHeartbeat) 5076 if (m_firstHeartbeat)
4838// return; 5077 return;
4839// 5078
4840// if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) 5079 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) > 5000)
4841// StartTimer(); 5080 Start();
4842// } 5081 }
4843 5082
4844 public override ISceneObject DeserializeObject(string representation) 5083 public override ISceneObject DeserializeObject(string representation)
4845 { 5084 {
@@ -4851,9 +5090,14 @@ namespace OpenSim.Region.Framework.Scenes
4851 get { return m_allowScriptCrossings; } 5090 get { return m_allowScriptCrossings; }
4852 } 5091 }
4853 5092
4854 public Vector3? GetNearestAllowedPosition(ScenePresence avatar) 5093 public Vector3 GetNearestAllowedPosition(ScenePresence avatar)
5094 {
5095 return GetNearestAllowedPosition(avatar, null);
5096 }
5097
5098 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
4855 { 5099 {
4856 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 5100 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel);
4857 5101
4858 if (nearestParcel != null) 5102 if (nearestParcel != null)
4859 { 5103 {
@@ -4862,10 +5106,7 @@ namespace OpenSim.Region.Framework.Scenes
4862 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5106 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4863 if (nearestPoint != null) 5107 if (nearestPoint != null)
4864 { 5108 {
4865// m_log.DebugFormat( 5109 Debug.WriteLine("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString());
4866// "[SCENE]: Found a sane previous position based on velocity for {0}, sending them to {1} in {2}",
4867// avatar.Name, nearestPoint, nearestParcel.LandData.Name);
4868
4869 return nearestPoint.Value; 5110 return nearestPoint.Value;
4870 } 5111 }
4871 5112
@@ -4875,17 +5116,20 @@ namespace OpenSim.Region.Framework.Scenes
4875 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5116 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4876 if (nearestPoint != null) 5117 if (nearestPoint != null)
4877 { 5118 {
4878// m_log.DebugFormat( 5119 Debug.WriteLine("They had a zero velocity, sending them to: " + nearestPoint.ToString());
4879// "[SCENE]: {0} had a zero velocity, sending them to {1}", avatar.Name, nearestPoint);
4880
4881 return nearestPoint.Value; 5120 return nearestPoint.Value;
4882 } 5121 }
4883 5122
4884 //Ultimate backup if we have no idea where they are 5123 ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y);
4885// m_log.DebugFormat( 5124 if (dest != excludeParcel)
4886// "[SCENE]: No idea where {0} is, sending them to {1}", avatar.Name, avatar.lastKnownAllowedPosition); 5125 {
5126 // Ultimate backup if we have no idea where they are and
5127 // the last allowed position was in another parcel
5128 Debug.WriteLine("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString());
5129 return avatar.lastKnownAllowedPosition;
5130 }
4887 5131
4888 return avatar.lastKnownAllowedPosition; 5132 // else fall through to region edge
4889 } 5133 }
4890 5134
4891 //Go to the edge, this happens in teleporting to a region with no available parcels 5135 //Go to the edge, this happens in teleporting to a region with no available parcels
@@ -4919,13 +5163,18 @@ namespace OpenSim.Region.Framework.Scenes
4919 5163
4920 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) 5164 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
4921 { 5165 {
5166 return GetNearestAllowedParcel(avatarId, x, y, null);
5167 }
5168
5169 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
5170 {
4922 List<ILandObject> all = AllParcels(); 5171 List<ILandObject> all = AllParcels();
4923 float minParcelDistance = float.MaxValue; 5172 float minParcelDistance = float.MaxValue;
4924 ILandObject nearestParcel = null; 5173 ILandObject nearestParcel = null;
4925 5174
4926 foreach (var parcel in all) 5175 foreach (var parcel in all)
4927 { 5176 {
4928 if (!parcel.IsEitherBannedOrRestricted(avatarId)) 5177 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel)
4929 { 5178 {
4930 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 5179 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
4931 if (parcelDistance < minParcelDistance) 5180 if (parcelDistance < minParcelDistance)
@@ -5167,7 +5416,55 @@ namespace OpenSim.Region.Framework.Scenes
5167 mapModule.GenerateMaptile(); 5416 mapModule.GenerateMaptile();
5168 } 5417 }
5169 5418
5170 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5419// public void CleanDroppedAttachments()
5420// {
5421// List<SceneObjectGroup> objectsToDelete =
5422// new List<SceneObjectGroup>();
5423//
5424// lock (m_cleaningAttachments)
5425// {
5426// ForEachSOG(delegate (SceneObjectGroup grp)
5427// {
5428// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5429// {
5430// UUID agentID = grp.OwnerID;
5431// if (agentID == UUID.Zero)
5432// {
5433// objectsToDelete.Add(grp);
5434// return;
5435// }
5436//
5437// ScenePresence sp = GetScenePresence(agentID);
5438// if (sp == null)
5439// {
5440// objectsToDelete.Add(grp);
5441// return;
5442// }
5443// }
5444// });
5445// }
5446//
5447// foreach (SceneObjectGroup grp in objectsToDelete)
5448// {
5449// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5450// DeleteSceneObject(grp, true);
5451// }
5452// }
5453
5454 public void ThreadAlive(int threadCode)
5455 {
5456 switch(threadCode)
5457 {
5458 case 1: // Incoming
5459 m_lastIncoming = Util.EnvironmentTickCount();
5460 break;
5461 case 2: // Incoming
5462 m_lastOutgoing = Util.EnvironmentTickCount();
5463 break;
5464 }
5465 }
5466
5467 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5171 { 5468 {
5172 RegenerateMaptile(); 5469 RegenerateMaptile();
5173 5470
@@ -5195,6 +5492,8 @@ namespace OpenSim.Region.Framework.Scenes
5195 /// <returns></returns> 5492 /// <returns></returns>
5196 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5493 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5197 { 5494 {
5495 reason = "You are banned from the region";
5496
5198 if (EntityTransferModule.IsInTransit(agentID)) 5497 if (EntityTransferModule.IsInTransit(agentID))
5199 { 5498 {
5200 reason = "Agent is still in transit from this region"; 5499 reason = "Agent is still in transit from this region";
@@ -5206,6 +5505,12 @@ namespace OpenSim.Region.Framework.Scenes
5206 return false; 5505 return false;
5207 } 5506 }
5208 5507
5508 if (Permissions.IsGod(agentID))
5509 {
5510 reason = String.Empty;
5511 return true;
5512 }
5513
5209 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. 5514 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check.
5210 // However, the long term fix is to make sure root agent count is always accurate. 5515 // However, the long term fix is to make sure root agent count is always accurate.
5211 m_sceneGraph.RecalculateStats(); 5516 m_sceneGraph.RecalculateStats();
@@ -5226,6 +5531,41 @@ namespace OpenSim.Region.Framework.Scenes
5226 } 5531 }
5227 } 5532 }
5228 5533
5534 ScenePresence presence = GetScenePresence(agentID);
5535 IClientAPI client = null;
5536 AgentCircuitData aCircuit = null;
5537
5538 if (presence != null)
5539 {
5540 client = presence.ControllingClient;
5541 if (client != null)
5542 aCircuit = client.RequestClientInfo();
5543 }
5544
5545 // We may be called before there is a presence or a client.
5546 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5547 if (client == null)
5548 {
5549 aCircuit = new AgentCircuitData();
5550 aCircuit.AgentID = agentID;
5551 aCircuit.firstname = String.Empty;
5552 aCircuit.lastname = String.Empty;
5553 }
5554
5555 try
5556 {
5557 if (!AuthorizeUser(aCircuit, out reason))
5558 {
5559 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5560 return false;
5561 }
5562 }
5563 catch (Exception e)
5564 {
5565 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5566 return false;
5567 }
5568
5229 if (position == Vector3.Zero) // Teleport 5569 if (position == Vector3.Zero) // Teleport
5230 { 5570 {
5231 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5571 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
@@ -5254,13 +5594,46 @@ namespace OpenSim.Region.Framework.Scenes
5254 } 5594 }
5255 } 5595 }
5256 } 5596 }
5597
5598 float posX = 128.0f;
5599 float posY = 128.0f;
5600
5601 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5602 {
5603 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5604 return false;
5605 }
5606 }
5607 else // Walking
5608 {
5609 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5610 if (land == null)
5611 return false;
5612
5613 bool banned = land.IsBannedFromLand(agentID);
5614 bool restricted = land.IsRestrictedFromLand(agentID);
5615
5616 if (banned || restricted)
5617 return false;
5257 } 5618 }
5258 5619
5259 reason = String.Empty; 5620 reason = String.Empty;
5260 return true; 5621 return true;
5261 } 5622 }
5262 5623
5263 /// <summary> 5624 public void StartTimerWatchdog()
5625 {
5626 m_timerWatchdog.Interval = 1000;
5627 m_timerWatchdog.Elapsed += TimerWatchdog;
5628 m_timerWatchdog.AutoReset = true;
5629 m_timerWatchdog.Start();
5630 }
5631
5632 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5633 {
5634 CheckHeartbeat();
5635 }
5636
5264 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5637 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5265 /// autopilot that moves an avatar to a sit target!. 5638 /// autopilot that moves an avatar to a sit target!.
5266 /// </summary> 5639 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 9c6b884..9b8a3ae 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -136,6 +136,8 @@ namespace OpenSim.Region.Framework.Scenes
136 get { return m_permissions; } 136 get { return m_permissions; }
137 } 137 }
138 138
139 protected string m_datastore;
140
139 /* Used by the loadbalancer plugin on GForge */ 141 /* Used by the loadbalancer plugin on GForge */
140 protected RegionStatus m_regStatus; 142 protected RegionStatus m_regStatus;
141 public RegionStatus RegionStatus 143 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 1e900a0..11d703a 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 public bool HasGroupChanged 134 public bool HasGroupChanged
112 { 135 {
@@ -114,9 +137,39 @@ namespace OpenSim.Region.Framework.Scenes
114 { 137 {
115 if (value) 138 if (value)
116 { 139 {
140 if (m_isBackedUp)
141 {
142 m_scene.SceneGraph.FireChangeBackup(this);
143 }
117 timeLastChanged = DateTime.Now.Ticks; 144 timeLastChanged = DateTime.Now.Ticks;
118 if (!m_hasGroupChanged) 145 if (!m_hasGroupChanged)
119 timeFirstChanged = DateTime.Now.Ticks; 146 timeFirstChanged = DateTime.Now.Ticks;
147 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
148 {
149 if (m_rand == null)
150 {
151 byte[] val = new byte[16];
152 m_rootPart.UUID.ToBytes(val, 0);
153 m_rand = new Random(BitConverter.ToInt32(val, 0));
154 }
155
156 if (m_scene.GetRootAgentCount() == 0)
157 {
158 //If the region is empty, this change has been made by an automated process
159 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
160
161 float factor = 1.5f + (float)(m_rand.NextDouble());
162 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
163 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
164 }
165 else
166 {
167 //If the region is not empty, we want to obey the minimum and maximum persist times
168 //but add a random factor so we stagger the object persistance a little
169 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
170 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
171 }
172 }
120 } 173 }
121 m_hasGroupChanged = value; 174 m_hasGroupChanged = value;
122 175
@@ -131,7 +184,7 @@ namespace OpenSim.Region.Framework.Scenes
131 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since 184 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since
132 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation. 185 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation.
133 /// </summary> 186 /// </summary>
134 public bool HasGroupChangedDueToDelink { get; private set; } 187 public bool HasGroupChangedDueToDelink { get; set; }
135 188
136 private bool isTimeToPersist() 189 private bool isTimeToPersist()
137 { 190 {
@@ -141,8 +194,19 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 194 return false;
142 if (m_scene.ShuttingDown) 195 if (m_scene.ShuttingDown)
143 return true; 196 return true;
197
198 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
199 {
200 m_maxPersistTime = m_scene.m_persistAfter;
201 m_minPersistTime = m_scene.m_dontPersistBefore;
202 }
203
144 long currentTime = DateTime.Now.Ticks; 204 long currentTime = DateTime.Now.Ticks;
145 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 205
206 if (timeLastChanged == 0) timeLastChanged = currentTime;
207 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
208
209 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
146 return true; 210 return true;
147 return false; 211 return false;
148 } 212 }
@@ -261,10 +325,10 @@ namespace OpenSim.Region.Framework.Scenes
261 325
262 private bool m_scriptListens_atTarget; 326 private bool m_scriptListens_atTarget;
263 private bool m_scriptListens_notAtTarget; 327 private bool m_scriptListens_notAtTarget;
264
265 private bool m_scriptListens_atRotTarget; 328 private bool m_scriptListens_atRotTarget;
266 private bool m_scriptListens_notAtRotTarget; 329 private bool m_scriptListens_notAtRotTarget;
267 330
331 public bool m_dupeInProgress = false;
268 internal Dictionary<UUID, string> m_savedScriptState; 332 internal Dictionary<UUID, string> m_savedScriptState;
269 333
270 #region Properties 334 #region Properties
@@ -301,6 +365,16 @@ namespace OpenSim.Region.Framework.Scenes
301 get { return m_parts.Count; } 365 get { return m_parts.Count; }
302 } 366 }
303 367
368// protected Quaternion m_rotation = Quaternion.Identity;
369//
370// public virtual Quaternion Rotation
371// {
372// get { return m_rotation; }
373// set {
374// m_rotation = value;
375// }
376// }
377
304 public Quaternion GroupRotation 378 public Quaternion GroupRotation
305 { 379 {
306 get { return m_rootPart.RotationOffset; } 380 get { return m_rootPart.RotationOffset; }
@@ -407,7 +481,15 @@ namespace OpenSim.Region.Framework.Scenes
407 { 481 {
408 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); 482 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
409 } 483 }
410 484
485
486
487 private struct avtocrossInfo
488 {
489 public ScenePresence av;
490 public uint ParentID;
491 }
492
411 /// <summary> 493 /// <summary>
412 /// The absolute position of this scene object in the scene 494 /// The absolute position of this scene object in the scene
413 /// </summary> 495 /// </summary>
@@ -420,14 +502,128 @@ namespace OpenSim.Region.Framework.Scenes
420 502
421 if (Scene != null) 503 if (Scene != null)
422 { 504 {
423 if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) 505 // if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
424 || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) 506 // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
507 // && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
508 if ((Scene.TestBorderCross(val, Cardinals.E) || Scene.TestBorderCross(val, Cardinals.W)
509 || Scene.TestBorderCross(val, Cardinals.N) || Scene.TestBorderCross(val, Cardinals.S))
425 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 510 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
426 { 511 {
427 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 512 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
513 uint x = 0;
514 uint y = 0;
515 string version = String.Empty;
516 Vector3 newpos = Vector3.Zero;
517 OpenSim.Services.Interfaces.GridRegion destination = null;
518
519 bool canCross = true;
520 foreach (ScenePresence av in m_linkedAvatars)
521 {
522 // We need to cross these agents. First, let's find
523 // out if any of them can't cross for some reason.
524 // We have to deny the crossing entirely if any
525 // of them are banned. Alternatively, we could
526 // unsit banned agents....
527
528
529 // We set the avatar position as being the object
530 // position to get the region to send to
531 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null)
532 {
533 canCross = false;
534 break;
535 }
536
537 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
538 }
539
540 if (canCross)
541 {
542 // We unparent the SP quietly so that it won't
543 // be made to stand up
544
545 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
546
547 foreach (ScenePresence av in m_linkedAvatars)
548 {
549 avtocrossInfo avinfo = new avtocrossInfo();
550 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
551 if (parentPart != null)
552 av.ParentUUID = parentPart.UUID;
553
554 avinfo.av = av;
555 avinfo.ParentID = av.ParentID;
556 avsToCross.Add(avinfo);
557
558 av.ParentID = 0;
559 }
560
561// m_linkedAvatars.Clear();
562 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
563
564 // Normalize
565 if (val.X >= Constants.RegionSize)
566 val.X -= Constants.RegionSize;
567 if (val.Y >= Constants.RegionSize)
568 val.Y -= Constants.RegionSize;
569 if (val.X < 0)
570 val.X += Constants.RegionSize;
571 if (val.Y < 0)
572 val.Y += Constants.RegionSize;
573
574 // If it's deleted, crossing was successful
575 if (IsDeleted)
576 {
577 // foreach (ScenePresence av in m_linkedAvatars)
578 foreach (avtocrossInfo avinfo in avsToCross)
579 {
580 ScenePresence av = avinfo.av;
581 if (!av.IsInTransit) // just in case...
582 {
583 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
584
585 av.IsInTransit = true;
586
587 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
588 d.BeginInvoke(av, val, x, y, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
589 }
590 else
591 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val);
592 }
593 avsToCross.Clear();
594 return;
595 }
596 else // cross failed, put avas back ??
597 {
598 foreach (avtocrossInfo avinfo in avsToCross)
599 {
600 ScenePresence av = avinfo.av;
601 av.ParentUUID = UUID.Zero;
602 av.ParentID = avinfo.ParentID;
603// m_linkedAvatars.Add(av);
604 }
605 }
606 avsToCross.Clear();
607
608 }
609 else if (RootPart.PhysActor != null)
610 {
611 RootPart.PhysActor.CrossingFailure();
612 }
613
614 Vector3 oldp = AbsolutePosition;
615 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
616 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
617 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
428 } 618 }
429 } 619 }
430 620
621/* don't see the need but worse don't see where is restored to false if things stay in
622 foreach (SceneObjectPart part in m_parts.GetArray())
623 {
624 part.IgnoreUndoUpdate = true;
625 }
626 */
431 if (RootPart.GetStatusSandbox()) 627 if (RootPart.GetStatusSandbox())
432 { 628 {
433 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 629 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -441,10 +637,30 @@ namespace OpenSim.Region.Framework.Scenes
441 return; 637 return;
442 } 638 }
443 } 639 }
444
445 SceneObjectPart[] parts = m_parts.GetArray(); 640 SceneObjectPart[] parts = m_parts.GetArray();
446 for (int i = 0; i < parts.Length; i++) 641 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
447 parts[i].GroupPosition = val; 642 if (m_dupeInProgress)
643 triggerScriptEvent = false;
644 foreach (SceneObjectPart part in parts)
645 {
646 part.GroupPosition = val;
647 if (triggerScriptEvent)
648 part.TriggerScriptChangedEvent(Changed.POSITION);
649 }
650 if (!m_dupeInProgress)
651 {
652 foreach (ScenePresence av in m_linkedAvatars)
653 {
654 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
655 if (p != null && m_parts.TryGetValue(p.UUID, out p))
656 {
657 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
658 av.AbsolutePosition += offset;
659 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
660 av.SendAvatarDataToAllAgents();
661 }
662 }
663 }
448 664
449 //if (m_rootPart.PhysActor != null) 665 //if (m_rootPart.PhysActor != null)
450 //{ 666 //{
@@ -459,6 +675,40 @@ namespace OpenSim.Region.Framework.Scenes
459 } 675 }
460 } 676 }
461 677
678 public override Vector3 Velocity
679 {
680 get { return RootPart.Velocity; }
681 set { RootPart.Velocity = value; }
682 }
683
684 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
685 {
686 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
687 ScenePresence agent = icon.EndInvoke(iar);
688
689 //// If the cross was successful, this agent is a child agent
690 if (agent.IsChildAgent)
691 {
692 if (agent.ParentUUID != UUID.Zero)
693 {
694 agent.ParentPart = null;
695 agent.ParentPosition = Vector3.Zero;
696 // agent.ParentUUID = UUID.Zero;
697 }
698 }
699
700 agent.ParentUUID = UUID.Zero;
701
702// agent.Reset();
703// else // Not successful
704// agent.RestoreInCurrentScene();
705
706 // In any case
707 agent.IsInTransit = false;
708
709 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
710 }
711
462 public override uint LocalId 712 public override uint LocalId
463 { 713 {
464 get { return m_rootPart.LocalId; } 714 get { return m_rootPart.LocalId; }
@@ -529,6 +779,11 @@ namespace OpenSim.Region.Framework.Scenes
529 m_isSelected = value; 779 m_isSelected = value;
530 // Tell physics engine that group is selected 780 // Tell physics engine that group is selected
531 781
782 // this is not right
783 // but ode engines should only really need to know about root part
784 // so they can put entire object simulation on hold and not colliding
785 // keep as was for now
786
532 PhysicsActor pa = m_rootPart.PhysActor; 787 PhysicsActor pa = m_rootPart.PhysActor;
533 if (pa != null) 788 if (pa != null)
534 { 789 {
@@ -545,6 +800,42 @@ namespace OpenSim.Region.Framework.Scenes
545 childPa.Selected = value; 800 childPa.Selected = value;
546 } 801 }
547 } 802 }
803 if (RootPart.KeyframeMotion != null)
804 RootPart.KeyframeMotion.Selected = value;
805 }
806 }
807
808 public void PartSelectChanged(bool partSelect)
809 {
810 // any part selected makes group selected
811 if (m_isSelected == partSelect)
812 return;
813
814 if (partSelect)
815 {
816 IsSelected = partSelect;
817// if (!IsAttachment)
818// ScheduleGroupForFullUpdate();
819 }
820 else
821 {
822 // bad bad bad 2 heavy for large linksets
823 // since viewer does send lot of (un)selects
824 // this needs to be replaced by a specific list or count ?
825 // but that will require extra code in several places
826
827 SceneObjectPart[] parts = m_parts.GetArray();
828 for (int i = 0; i < parts.Length; i++)
829 {
830 SceneObjectPart part = parts[i];
831 if (part.IsSelected)
832 return;
833 }
834 IsSelected = partSelect;
835 if (!IsAttachment)
836 {
837 ScheduleGroupForFullUpdate();
838 }
548 } 839 }
549 } 840 }
550 841
@@ -622,6 +913,7 @@ namespace OpenSim.Region.Framework.Scenes
622 /// </summary> 913 /// </summary>
623 public SceneObjectGroup() 914 public SceneObjectGroup()
624 { 915 {
916
625 } 917 }
626 918
627 /// <summary> 919 /// <summary>
@@ -638,7 +930,7 @@ namespace OpenSim.Region.Framework.Scenes
638 /// Constructor. This object is added to the scene later via AttachToScene() 930 /// Constructor. This object is added to the scene later via AttachToScene()
639 /// </summary> 931 /// </summary>
640 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 932 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
641 { 933 {
642 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 934 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
643 } 935 }
644 936
@@ -674,6 +966,9 @@ namespace OpenSim.Region.Framework.Scenes
674 /// </summary> 966 /// </summary>
675 public virtual void AttachToBackup() 967 public virtual void AttachToBackup()
676 { 968 {
969 if (IsAttachment) return;
970 m_scene.SceneGraph.FireAttachToBackup(this);
971
677 if (InSceneBackup) 972 if (InSceneBackup)
678 { 973 {
679 //m_log.DebugFormat( 974 //m_log.DebugFormat(
@@ -716,6 +1011,13 @@ namespace OpenSim.Region.Framework.Scenes
716 1011
717 ApplyPhysics(); 1012 ApplyPhysics();
718 1013
1014 if (RootPart.PhysActor != null)
1015 RootPart.Force = RootPart.Force;
1016 if (RootPart.PhysActor != null)
1017 RootPart.Torque = RootPart.Torque;
1018 if (RootPart.PhysActor != null)
1019 RootPart.Buoyancy = RootPart.Buoyancy;
1020
719 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 1021 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
720 // for the same object with very different properties. The caller must schedule the update. 1022 // for the same object with very different properties. The caller must schedule the update.
721 //ScheduleGroupForFullUpdate(); 1023 //ScheduleGroupForFullUpdate();
@@ -731,6 +1033,10 @@ namespace OpenSim.Region.Framework.Scenes
731 EntityIntersection result = new EntityIntersection(); 1033 EntityIntersection result = new EntityIntersection();
732 1034
733 SceneObjectPart[] parts = m_parts.GetArray(); 1035 SceneObjectPart[] parts = m_parts.GetArray();
1036
1037 // Find closest hit here
1038 float idist = float.MaxValue;
1039
734 for (int i = 0; i < parts.Length; i++) 1040 for (int i = 0; i < parts.Length; i++)
735 { 1041 {
736 SceneObjectPart part = parts[i]; 1042 SceneObjectPart part = parts[i];
@@ -745,11 +1051,6 @@ namespace OpenSim.Region.Framework.Scenes
745 1051
746 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 1052 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
747 1053
748 // This may need to be updated to the maximum draw distance possible..
749 // We might (and probably will) be checking for prim creation from other sims
750 // when the camera crosses the border.
751 float idist = Constants.RegionSize;
752
753 if (inter.HitTF) 1054 if (inter.HitTF)
754 { 1055 {
755 // We need to find the closest prim to return to the testcaller along the ray 1056 // We need to find the closest prim to return to the testcaller along the ray
@@ -760,10 +1061,11 @@ namespace OpenSim.Region.Framework.Scenes
760 result.obj = part; 1061 result.obj = part;
761 result.normal = inter.normal; 1062 result.normal = inter.normal;
762 result.distance = inter.distance; 1063 result.distance = inter.distance;
1064
1065 idist = inter.distance;
763 } 1066 }
764 } 1067 }
765 } 1068 }
766
767 return result; 1069 return result;
768 } 1070 }
769 1071
@@ -775,25 +1077,27 @@ namespace OpenSim.Region.Framework.Scenes
775 /// <returns></returns> 1077 /// <returns></returns>
776 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 1078 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
777 { 1079 {
778 maxX = -256f; 1080 maxX = float.MinValue;
779 maxY = -256f; 1081 maxY = float.MinValue;
780 maxZ = -256f; 1082 maxZ = float.MinValue;
781 minX = 256f; 1083 minX = float.MaxValue;
782 minY = 256f; 1084 minY = float.MaxValue;
783 minZ = 8192f; 1085 minZ = float.MaxValue;
784 1086
785 SceneObjectPart[] parts = m_parts.GetArray(); 1087 SceneObjectPart[] parts = m_parts.GetArray();
786 for (int i = 0; i < parts.Length; i++) 1088 foreach (SceneObjectPart part in parts)
787 { 1089 {
788 SceneObjectPart part = parts[i];
789
790 Vector3 worldPos = part.GetWorldPosition(); 1090 Vector3 worldPos = part.GetWorldPosition();
791 Vector3 offset = worldPos - AbsolutePosition; 1091 Vector3 offset = worldPos - AbsolutePosition;
792 Quaternion worldRot; 1092 Quaternion worldRot;
793 if (part.ParentID == 0) 1093 if (part.ParentID == 0)
1094 {
794 worldRot = part.RotationOffset; 1095 worldRot = part.RotationOffset;
1096 }
795 else 1097 else
1098 {
796 worldRot = part.GetWorldRotation(); 1099 worldRot = part.GetWorldRotation();
1100 }
797 1101
798 Vector3 frontTopLeft; 1102 Vector3 frontTopLeft;
799 Vector3 frontTopRight; 1103 Vector3 frontTopRight;
@@ -805,6 +1109,8 @@ namespace OpenSim.Region.Framework.Scenes
805 Vector3 backBottomLeft; 1109 Vector3 backBottomLeft;
806 Vector3 backBottomRight; 1110 Vector3 backBottomRight;
807 1111
1112 // Vector3[] corners = new Vector3[8];
1113
808 Vector3 orig = Vector3.Zero; 1114 Vector3 orig = Vector3.Zero;
809 1115
810 frontTopLeft.X = orig.X - (part.Scale.X / 2); 1116 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -839,6 +1145,38 @@ namespace OpenSim.Region.Framework.Scenes
839 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1145 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
840 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1146 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
841 1147
1148
1149
1150 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1151 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1152 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1153 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1154 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1155 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1156 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1157 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1158
1159 //for (int i = 0; i < 8; i++)
1160 //{
1161 // corners[i] = corners[i] * worldRot;
1162 // corners[i] += offset;
1163
1164 // if (corners[i].X > maxX)
1165 // maxX = corners[i].X;
1166 // if (corners[i].X < minX)
1167 // minX = corners[i].X;
1168
1169 // if (corners[i].Y > maxY)
1170 // maxY = corners[i].Y;
1171 // if (corners[i].Y < minY)
1172 // minY = corners[i].Y;
1173
1174 // if (corners[i].Z > maxZ)
1175 // maxZ = corners[i].Y;
1176 // if (corners[i].Z < minZ)
1177 // minZ = corners[i].Z;
1178 //}
1179
842 frontTopLeft = frontTopLeft * worldRot; 1180 frontTopLeft = frontTopLeft * worldRot;
843 frontTopRight = frontTopRight * worldRot; 1181 frontTopRight = frontTopRight * worldRot;
844 frontBottomLeft = frontBottomLeft * worldRot; 1182 frontBottomLeft = frontBottomLeft * worldRot;
@@ -860,6 +1198,15 @@ namespace OpenSim.Region.Framework.Scenes
860 backTopLeft += offset; 1198 backTopLeft += offset;
861 backTopRight += offset; 1199 backTopRight += offset;
862 1200
1201 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1202 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1203 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1204 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1205 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1206 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1207 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1208 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1209
863 if (frontTopRight.X > maxX) 1210 if (frontTopRight.X > maxX)
864 maxX = frontTopRight.X; 1211 maxX = frontTopRight.X;
865 if (frontTopLeft.X > maxX) 1212 if (frontTopLeft.X > maxX)
@@ -1003,17 +1350,118 @@ namespace OpenSim.Region.Framework.Scenes
1003 1350
1004 #endregion 1351 #endregion
1005 1352
1353 public void GetResourcesCosts(SceneObjectPart apart,
1354 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost)
1355 {
1356 // this information may need to be cached
1357
1358 float cost;
1359 float tmpcost;
1360
1361 bool ComplexCost = false;
1362
1363 SceneObjectPart p;
1364 SceneObjectPart[] parts;
1365
1366 lock (m_parts)
1367 {
1368 parts = m_parts.GetArray();
1369 }
1370
1371 int nparts = parts.Length;
1372
1373
1374 for (int i = 0; i < nparts; i++)
1375 {
1376 p = parts[i];
1377
1378 if (p.UsesComplexCost)
1379 {
1380 ComplexCost = true;
1381 break;
1382 }
1383 }
1384
1385 if (ComplexCost)
1386 {
1387 linksetResCost = 0;
1388 linksetPhysCost = 0;
1389 partCost = 0;
1390 partPhysCost = 0;
1391
1392 for (int i = 0; i < nparts; i++)
1393 {
1394 p = parts[i];
1395
1396 cost = p.StreamingCost;
1397 tmpcost = p.SimulationCost;
1398 if (tmpcost > cost)
1399 cost = tmpcost;
1400 tmpcost = p.PhysicsCost;
1401 if (tmpcost > cost)
1402 cost = tmpcost;
1403
1404 linksetPhysCost += tmpcost;
1405 linksetResCost += cost;
1406
1407 if (p == apart)
1408 {
1409 partCost = cost;
1410 partPhysCost = tmpcost;
1411 }
1412 }
1413 }
1414 else
1415 {
1416 partPhysCost = 1.0f;
1417 partCost = 1.0f;
1418 linksetResCost = (float)nparts;
1419 linksetPhysCost = linksetResCost;
1420 }
1421 }
1422
1423 public void GetSelectedCosts(out float PhysCost, out float StreamCost, out float SimulCost)
1424 {
1425 SceneObjectPart p;
1426 SceneObjectPart[] parts;
1427
1428 lock (m_parts)
1429 {
1430 parts = m_parts.GetArray();
1431 }
1432
1433 int nparts = parts.Length;
1434
1435 PhysCost = 0;
1436 StreamCost = 0;
1437 SimulCost = 0;
1438
1439 for (int i = 0; i < nparts; i++)
1440 {
1441 p = parts[i];
1442
1443 StreamCost += p.StreamingCost;
1444 SimulCost += p.SimulationCost;
1445 PhysCost += p.PhysicsCost;
1446 }
1447 }
1448
1006 public void SaveScriptedState(XmlTextWriter writer) 1449 public void SaveScriptedState(XmlTextWriter writer)
1007 { 1450 {
1451 SaveScriptedState(writer, false);
1452 }
1453
1454 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1455 {
1008 XmlDocument doc = new XmlDocument(); 1456 XmlDocument doc = new XmlDocument();
1009 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1457 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
1010 1458
1011 SceneObjectPart[] parts = m_parts.GetArray(); 1459 SceneObjectPart[] parts = m_parts.GetArray();
1012 for (int i = 0; i < parts.Length; i++) 1460 for (int i = 0; i < parts.Length; i++)
1013 { 1461 {
1014 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1462 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
1015 foreach (KeyValuePair<UUID, string> kvp in pstates) 1463 foreach (KeyValuePair<UUID, string> kvp in pstates)
1016 states.Add(kvp.Key, kvp.Value); 1464 states[kvp.Key] = kvp.Value;
1017 } 1465 }
1018 1466
1019 if (states.Count > 0) 1467 if (states.Count > 0)
@@ -1033,6 +1481,169 @@ namespace OpenSim.Region.Framework.Scenes
1033 } 1481 }
1034 1482
1035 /// <summary> 1483 /// <summary>
1484 /// Add the avatar to this linkset (avatar is sat).
1485 /// </summary>
1486 /// <param name="agentID"></param>
1487 public void AddAvatar(UUID agentID)
1488 {
1489 ScenePresence presence;
1490 if (m_scene.TryGetScenePresence(agentID, out presence))
1491 {
1492 if (!m_linkedAvatars.Contains(presence))
1493 {
1494 m_linkedAvatars.Add(presence);
1495 }
1496 }
1497 }
1498
1499 /// <summary>
1500 /// Delete the avatar from this linkset (avatar is unsat).
1501 /// </summary>
1502 /// <param name="agentID"></param>
1503 public void DeleteAvatar(UUID agentID)
1504 {
1505 ScenePresence presence;
1506 if (m_scene.TryGetScenePresence(agentID, out presence))
1507 {
1508 if (m_linkedAvatars.Contains(presence))
1509 {
1510 m_linkedAvatars.Remove(presence);
1511 }
1512 }
1513 }
1514
1515 /// <summary>
1516 /// Returns the list of linked presences (avatars sat on this group)
1517 /// </summary>
1518 /// <param name="agentID"></param>
1519 public List<ScenePresence> GetLinkedAvatars()
1520 {
1521 return m_linkedAvatars;
1522 }
1523
1524 /// <summary>
1525 /// Attach this scene object to the given avatar.
1526 /// </summary>
1527 /// <param name="agentID"></param>
1528 /// <param name="attachmentpoint"></param>
1529 /// <param name="AttachOffset"></param>
1530 private void AttachToAgent(
1531 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1532 {
1533 if (avatar != null)
1534 {
1535 // don't attach attachments to child agents
1536 if (avatar.IsChildAgent) return;
1537
1538 // Remove from database and parcel prim count
1539 m_scene.DeleteFromStorage(so.UUID);
1540 m_scene.EventManager.TriggerParcelPrimCountTainted();
1541
1542 so.AttachedAvatar = avatar.UUID;
1543
1544 if (so.RootPart.PhysActor != null)
1545 {
1546 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1547 so.RootPart.PhysActor = null;
1548 }
1549
1550 so.AbsolutePosition = attachOffset;
1551 so.RootPart.AttachedPos = attachOffset;
1552 so.IsAttachment = true;
1553 so.RootPart.SetParentLocalId(avatar.LocalId);
1554 so.AttachmentPoint = attachmentpoint;
1555
1556 avatar.AddAttachment(this);
1557
1558 if (!silent)
1559 {
1560 // Killing it here will cause the client to deselect it
1561 // It then reappears on the avatar, deselected
1562 // through the full update below
1563 //
1564 if (IsSelected)
1565 {
1566 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1567 }
1568
1569 IsSelected = false; // fudge....
1570 ScheduleGroupForFullUpdate();
1571 }
1572 }
1573 else
1574 {
1575 m_log.WarnFormat(
1576 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1577 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1578 }
1579 }
1580
1581 public byte GetAttachmentPoint()
1582 {
1583 return m_rootPart.Shape.State;
1584 }
1585
1586 public void DetachToGround()
1587 {
1588 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1589 if (avatar == null)
1590 return;
1591
1592 avatar.RemoveAttachment(this);
1593
1594 Vector3 detachedpos = new Vector3(127f,127f,127f);
1595 if (avatar == null)
1596 return;
1597
1598 detachedpos = avatar.AbsolutePosition;
1599 FromItemID = UUID.Zero;
1600
1601 AbsolutePosition = detachedpos;
1602 AttachedAvatar = UUID.Zero;
1603
1604 //SceneObjectPart[] parts = m_parts.GetArray();
1605 //for (int i = 0; i < parts.Length; i++)
1606 // parts[i].AttachedAvatar = UUID.Zero;
1607
1608 m_rootPart.SetParentLocalId(0);
1609 AttachmentPoint = (byte)0;
1610 // must check if buildind should be true or false here
1611 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1612 HasGroupChanged = true;
1613 RootPart.Rezzed = DateTime.Now;
1614 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1615 AttachToBackup();
1616 m_scene.EventManager.TriggerParcelPrimCountTainted();
1617 m_rootPart.ScheduleFullUpdate();
1618 m_rootPart.ClearUndoState();
1619 }
1620
1621 public void DetachToInventoryPrep()
1622 {
1623 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1624 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1625 if (avatar != null)
1626 {
1627 //detachedpos = avatar.AbsolutePosition;
1628 avatar.RemoveAttachment(this);
1629 }
1630
1631 AttachedAvatar = UUID.Zero;
1632
1633 /*SceneObjectPart[] parts = m_parts.GetArray();
1634 for (int i = 0; i < parts.Length; i++)
1635 parts[i].AttachedAvatar = UUID.Zero;*/
1636
1637 m_rootPart.SetParentLocalId(0);
1638 //m_rootPart.SetAttachmentPoint((byte)0);
1639 IsAttachment = false;
1640 AbsolutePosition = m_rootPart.AttachedPos;
1641 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1642 //AttachToBackup();
1643 //m_rootPart.ScheduleFullUpdate();
1644 }
1645
1646 /// <summary>
1036 /// 1647 ///
1037 /// </summary> 1648 /// </summary>
1038 /// <param name="part"></param> 1649 /// <param name="part"></param>
@@ -1082,7 +1693,10 @@ namespace OpenSim.Region.Framework.Scenes
1082 public void AddPart(SceneObjectPart part) 1693 public void AddPart(SceneObjectPart part)
1083 { 1694 {
1084 part.SetParent(this); 1695 part.SetParent(this);
1085 part.LinkNum = m_parts.Add(part.UUID, part); 1696 m_parts.Add(part.UUID, part);
1697
1698 part.LinkNum = m_parts.Count;
1699
1086 if (part.LinkNum == 2) 1700 if (part.LinkNum == 2)
1087 RootPart.LinkNum = 1; 1701 RootPart.LinkNum = 1;
1088 } 1702 }
@@ -1170,7 +1784,7 @@ namespace OpenSim.Region.Framework.Scenes
1170// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 1784// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1171// remoteClient.Name, part.Name, part.LocalId, offsetPos); 1785// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1172 1786
1173 part.StoreUndoState(); 1787// part.StoreUndoState();
1174 part.OnGrab(offsetPos, remoteClient); 1788 part.OnGrab(offsetPos, remoteClient);
1175 } 1789 }
1176 1790
@@ -1190,6 +1804,11 @@ namespace OpenSim.Region.Framework.Scenes
1190 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1804 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1191 public void DeleteGroupFromScene(bool silent) 1805 public void DeleteGroupFromScene(bool silent)
1192 { 1806 {
1807 // We need to keep track of this state in case this group is still queued for backup.
1808 IsDeleted = true;
1809
1810 DetachFromBackup();
1811
1193 SceneObjectPart[] parts = m_parts.GetArray(); 1812 SceneObjectPart[] parts = m_parts.GetArray();
1194 for (int i = 0; i < parts.Length; i++) 1813 for (int i = 0; i < parts.Length; i++)
1195 { 1814 {
@@ -1213,6 +1832,7 @@ namespace OpenSim.Region.Framework.Scenes
1213 } 1832 }
1214 }); 1833 });
1215 } 1834 }
1835
1216 } 1836 }
1217 1837
1218 public void AddScriptLPS(int count) 1838 public void AddScriptLPS(int count)
@@ -1282,28 +1902,43 @@ namespace OpenSim.Region.Framework.Scenes
1282 /// </summary> 1902 /// </summary>
1283 public void ApplyPhysics() 1903 public void ApplyPhysics()
1284 { 1904 {
1285 // Apply physics to the root prim
1286 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1287
1288 // Apply physics to child prims
1289 SceneObjectPart[] parts = m_parts.GetArray(); 1905 SceneObjectPart[] parts = m_parts.GetArray();
1290 if (parts.Length > 1) 1906 if (parts.Length > 1)
1291 { 1907 {
1908 ResetChildPrimPhysicsPositions();
1909
1910 // Apply physics to the root prim
1911 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
1912
1913
1292 for (int i = 0; i < parts.Length; i++) 1914 for (int i = 0; i < parts.Length; i++)
1293 { 1915 {
1294 SceneObjectPart part = parts[i]; 1916 SceneObjectPart part = parts[i];
1295 if (part.LocalId != m_rootPart.LocalId) 1917 if (part.LocalId != m_rootPart.LocalId)
1296 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 1918 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1297 } 1919 }
1298
1299 // Hack to get the physics scene geometries in the right spot 1920 // Hack to get the physics scene geometries in the right spot
1300 ResetChildPrimPhysicsPositions(); 1921// ResetChildPrimPhysicsPositions();
1922 if (m_rootPart.PhysActor != null)
1923 {
1924 m_rootPart.PhysActor.Building = false;
1925 }
1926 }
1927 else
1928 {
1929 // Apply physics to the root prim
1930 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1301 } 1931 }
1302 } 1932 }
1303 1933
1304 public void SetOwnerId(UUID userId) 1934 public void SetOwnerId(UUID userId)
1305 { 1935 {
1306 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1936 ForEachPart(delegate(SceneObjectPart part)
1937 {
1938
1939 part.OwnerID = userId;
1940
1941 });
1307 } 1942 }
1308 1943
1309 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1944 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1335,11 +1970,17 @@ namespace OpenSim.Region.Framework.Scenes
1335 return; 1970 return;
1336 } 1971 }
1337 1972
1973 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1974 return;
1975
1338 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1976 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1339 // any exception propogate upwards. 1977 // any exception propogate upwards.
1340 try 1978 try
1341 { 1979 {
1342 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1980 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1981 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1982 m_scene.LoadingPrims) // Land may not be valid yet
1983
1343 { 1984 {
1344 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1985 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1345 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1986 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1366,6 +2007,7 @@ namespace OpenSim.Region.Framework.Scenes
1366 } 2007 }
1367 } 2008 }
1368 } 2009 }
2010
1369 } 2011 }
1370 2012
1371 if (m_scene.UseBackup && HasGroupChanged) 2013 if (m_scene.UseBackup && HasGroupChanged)
@@ -1373,10 +2015,30 @@ namespace OpenSim.Region.Framework.Scenes
1373 // don't backup while it's selected or you're asking for changes mid stream. 2015 // don't backup while it's selected or you're asking for changes mid stream.
1374 if (isTimeToPersist() || forcedBackup) 2016 if (isTimeToPersist() || forcedBackup)
1375 { 2017 {
2018 if (m_rootPart.PhysActor != null &&
2019 (!m_rootPart.PhysActor.IsPhysical))
2020 {
2021 // Possible ghost prim
2022 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
2023 {
2024 foreach (SceneObjectPart part in m_parts.GetArray())
2025 {
2026 // Re-set physics actor positions and
2027 // orientations
2028 part.GroupPosition = m_rootPart.GroupPosition;
2029 }
2030 }
2031 }
1376// m_log.DebugFormat( 2032// m_log.DebugFormat(
1377// "[SCENE]: Storing {0}, {1} in {2}", 2033// "[SCENE]: Storing {0}, {1} in {2}",
1378// Name, UUID, m_scene.RegionInfo.RegionName); 2034// Name, UUID, m_scene.RegionInfo.RegionName);
1379 2035
2036 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
2037 {
2038 RootPart.Shape.State = 0;
2039 ScheduleGroupForFullUpdate();
2040 }
2041
1380 SceneObjectGroup backup_group = Copy(false); 2042 SceneObjectGroup backup_group = Copy(false);
1381 backup_group.RootPart.Velocity = RootPart.Velocity; 2043 backup_group.RootPart.Velocity = RootPart.Velocity;
1382 backup_group.RootPart.Acceleration = RootPart.Acceleration; 2044 backup_group.RootPart.Acceleration = RootPart.Acceleration;
@@ -1390,6 +2052,11 @@ namespace OpenSim.Region.Framework.Scenes
1390 2052
1391 backup_group.ForEachPart(delegate(SceneObjectPart part) 2053 backup_group.ForEachPart(delegate(SceneObjectPart part)
1392 { 2054 {
2055 if (part.KeyframeMotion != null)
2056 {
2057 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize());
2058 part.KeyframeMotion.UpdateSceneObject(this);
2059 }
1393 part.Inventory.ProcessInventoryBackup(datastore); 2060 part.Inventory.ProcessInventoryBackup(datastore);
1394 }); 2061 });
1395 2062
@@ -1442,10 +2109,14 @@ namespace OpenSim.Region.Framework.Scenes
1442 /// <returns></returns> 2109 /// <returns></returns>
1443 public SceneObjectGroup Copy(bool userExposed) 2110 public SceneObjectGroup Copy(bool userExposed)
1444 { 2111 {
2112 m_dupeInProgress = true;
1445 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 2113 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1446 dupe.m_isBackedUp = false; 2114 dupe.m_isBackedUp = false;
1447 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 2115 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1448 2116
2117 // new group as no sitting avatars
2118 dupe.m_linkedAvatars = new List<ScenePresence>();
2119
1449 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 2120 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1450 // attachments do not bordercross while they're being duplicated. This is hacktastic! 2121 // attachments do not bordercross while they're being duplicated. This is hacktastic!
1451 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! 2122 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
@@ -1456,7 +2127,7 @@ namespace OpenSim.Region.Framework.Scenes
1456 // This is only necessary when userExposed is false! 2127 // This is only necessary when userExposed is false!
1457 2128
1458 bool previousAttachmentStatus = dupe.IsAttachment; 2129 bool previousAttachmentStatus = dupe.IsAttachment;
1459 2130
1460 if (!userExposed) 2131 if (!userExposed)
1461 dupe.IsAttachment = true; 2132 dupe.IsAttachment = true;
1462 2133
@@ -1474,11 +2145,11 @@ namespace OpenSim.Region.Framework.Scenes
1474 dupe.m_rootPart.TrimPermissions(); 2145 dupe.m_rootPart.TrimPermissions();
1475 2146
1476 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 2147 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1477 2148
1478 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 2149 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1479 { 2150 {
1480 return p1.LinkNum.CompareTo(p2.LinkNum); 2151 return p1.LinkNum.CompareTo(p2.LinkNum);
1481 } 2152 }
1482 ); 2153 );
1483 2154
1484 foreach (SceneObjectPart part in partList) 2155 foreach (SceneObjectPart part in partList)
@@ -1488,41 +2159,53 @@ namespace OpenSim.Region.Framework.Scenes
1488 { 2159 {
1489 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2160 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1490 newPart.LinkNum = part.LinkNum; 2161 newPart.LinkNum = part.LinkNum;
1491 } 2162 if (userExposed)
2163 newPart.ParentID = dupe.m_rootPart.LocalId;
2164 }
1492 else 2165 else
1493 { 2166 {
1494 newPart = dupe.m_rootPart; 2167 newPart = dupe.m_rootPart;
1495 } 2168 }
2169/*
2170 bool isphys = ((newPart.Flags & PrimFlags.Physics) != 0);
2171 bool isphan = ((newPart.Flags & PrimFlags.Phantom) != 0);
1496 2172
1497 // Need to duplicate the physics actor as well 2173 // Need to duplicate the physics actor as well
1498 PhysicsActor originalPartPa = part.PhysActor; 2174 if (userExposed && (isphys || !isphan || newPart.VolumeDetectActive))
1499 if (originalPartPa != null && userExposed)
1500 { 2175 {
1501 PrimitiveBaseShape pbs = newPart.Shape; 2176 PrimitiveBaseShape pbs = newPart.Shape;
1502
1503 newPart.PhysActor 2177 newPart.PhysActor
1504 = m_scene.PhysicsScene.AddPrimShape( 2178 = m_scene.PhysicsScene.AddPrimShape(
1505 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 2179 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1506 pbs, 2180 pbs,
1507 newPart.AbsolutePosition, 2181 newPart.AbsolutePosition,
1508 newPart.Scale, 2182 newPart.Scale,
1509 newPart.RotationOffset, 2183 newPart.GetWorldRotation(),
1510 originalPartPa.IsPhysical, 2184 isphys,
2185 isphan,
1511 newPart.LocalId); 2186 newPart.LocalId);
1512 2187
1513 newPart.DoPhysicsPropertyUpdate(originalPartPa.IsPhysical, true); 2188 newPart.DoPhysicsPropertyUpdate(isphys, true);
1514 } 2189 */
2190 if (userExposed)
2191 newPart.ApplyPhysics((uint)newPart.Flags,newPart.VolumeDetectActive,true);
2192// }
1515 } 2193 }
1516 2194
1517 if (userExposed) 2195 if (userExposed)
1518 { 2196 {
1519 dupe.UpdateParentIDs(); 2197// done above dupe.UpdateParentIDs();
2198
2199 if (dupe.m_rootPart.PhysActor != null)
2200 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
2201
1520 dupe.HasGroupChanged = true; 2202 dupe.HasGroupChanged = true;
1521 dupe.AttachToBackup(); 2203 dupe.AttachToBackup();
1522 2204
1523 ScheduleGroupForFullUpdate(); 2205 ScheduleGroupForFullUpdate();
1524 } 2206 }
1525 2207
2208 m_dupeInProgress = false;
1526 return dupe; 2209 return dupe;
1527 } 2210 }
1528 2211
@@ -1534,11 +2217,24 @@ namespace OpenSim.Region.Framework.Scenes
1534 /// <param name="cGroupID"></param> 2217 /// <param name="cGroupID"></param>
1535 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2218 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1536 { 2219 {
1537 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2220 // SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed));
2221 // give newpart a new local ID lettng old part keep same
2222 SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2223 newpart.LocalId = m_scene.AllocateLocalId();
2224
2225 SetRootPart(newpart);
2226 if (userExposed)
2227 RootPart.Velocity = Vector3.Zero; // In case source is moving
1538 } 2228 }
1539 2229
1540 public void ScriptSetPhysicsStatus(bool usePhysics) 2230 public void ScriptSetPhysicsStatus(bool usePhysics)
1541 { 2231 {
2232 if (usePhysics)
2233 {
2234 if (RootPart.KeyframeMotion != null)
2235 RootPart.KeyframeMotion.Stop();
2236 RootPart.KeyframeMotion = null;
2237 }
1542 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2238 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1543 } 2239 }
1544 2240
@@ -1586,13 +2282,14 @@ namespace OpenSim.Region.Framework.Scenes
1586 2282
1587 if (pa != null) 2283 if (pa != null)
1588 { 2284 {
1589 pa.AddForce(impulse, true); 2285 // false to be applied as a impulse
2286 pa.AddForce(impulse, false);
1590 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2287 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1591 } 2288 }
1592 } 2289 }
1593 } 2290 }
1594 2291
1595 public void applyAngularImpulse(Vector3 impulse) 2292 public void ApplyAngularImpulse(Vector3 impulse)
1596 { 2293 {
1597 PhysicsActor pa = RootPart.PhysActor; 2294 PhysicsActor pa = RootPart.PhysActor;
1598 2295
@@ -1600,21 +2297,8 @@ namespace OpenSim.Region.Framework.Scenes
1600 { 2297 {
1601 if (!IsAttachment) 2298 if (!IsAttachment)
1602 { 2299 {
1603 pa.AddAngularForce(impulse, true); 2300 // false to be applied as a impulse
1604 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2301 pa.AddAngularForce(impulse, false);
1605 }
1606 }
1607 }
1608
1609 public void setAngularImpulse(Vector3 impulse)
1610 {
1611 PhysicsActor pa = RootPart.PhysActor;
1612
1613 if (pa != null)
1614 {
1615 if (!IsAttachment)
1616 {
1617 pa.Torque = impulse;
1618 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2302 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1619 } 2303 }
1620 } 2304 }
@@ -1622,20 +2306,10 @@ namespace OpenSim.Region.Framework.Scenes
1622 2306
1623 public Vector3 GetTorque() 2307 public Vector3 GetTorque()
1624 { 2308 {
1625 PhysicsActor pa = RootPart.PhysActor; 2309 return RootPart.Torque;
1626
1627 if (pa != null)
1628 {
1629 if (!IsAttachment)
1630 {
1631 Vector3 torque = pa.Torque;
1632 return torque;
1633 }
1634 }
1635
1636 return Vector3.Zero;
1637 } 2310 }
1638 2311
2312 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1639 public void moveToTarget(Vector3 target, float tau) 2313 public void moveToTarget(Vector3 target, float tau)
1640 { 2314 {
1641 if (IsAttachment) 2315 if (IsAttachment)
@@ -1667,6 +2341,46 @@ namespace OpenSim.Region.Framework.Scenes
1667 pa.PIDActive = false; 2341 pa.PIDActive = false;
1668 } 2342 }
1669 2343
2344 public void rotLookAt(Quaternion target, float strength, float damping)
2345 {
2346 SceneObjectPart rootpart = m_rootPart;
2347 if (rootpart != null)
2348 {
2349 if (IsAttachment)
2350 {
2351 /*
2352 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2353 if (avatar != null)
2354 {
2355 Rotate the Av?
2356 } */
2357 }
2358 else
2359 {
2360 if (rootpart.PhysActor != null)
2361 { // APID must be implemented in your physics system for this to function.
2362 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2363 rootpart.PhysActor.APIDStrength = strength;
2364 rootpart.PhysActor.APIDDamping = damping;
2365 rootpart.PhysActor.APIDActive = true;
2366 }
2367 }
2368 }
2369 }
2370
2371 public void stopLookAt()
2372 {
2373 SceneObjectPart rootpart = m_rootPart;
2374 if (rootpart != null)
2375 {
2376 if (rootpart.PhysActor != null)
2377 { // APID must be implemented in your physics system for this to function.
2378 rootpart.PhysActor.APIDActive = false;
2379 }
2380 }
2381
2382 }
2383
1670 /// <summary> 2384 /// <summary>
1671 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2385 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1672 /// </summary> 2386 /// </summary>
@@ -1683,7 +2397,7 @@ namespace OpenSim.Region.Framework.Scenes
1683 { 2397 {
1684 pa.PIDHoverHeight = height; 2398 pa.PIDHoverHeight = height;
1685 pa.PIDHoverType = hoverType; 2399 pa.PIDHoverType = hoverType;
1686 pa.PIDTau = tau; 2400 pa.PIDHoverTau = tau;
1687 pa.PIDHoverActive = true; 2401 pa.PIDHoverActive = true;
1688 } 2402 }
1689 else 2403 else
@@ -1723,7 +2437,12 @@ namespace OpenSim.Region.Framework.Scenes
1723 /// <param name="cGroupID"></param> 2437 /// <param name="cGroupID"></param>
1724 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2438 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1725 { 2439 {
1726 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2440 // give new ID to the new part, letting old keep original
2441 // SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2442 SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2443 newPart.LocalId = m_scene.AllocateLocalId();
2444 newPart.SetParent(this);
2445
1727 AddPart(newPart); 2446 AddPart(newPart);
1728 2447
1729 SetPartAsNonRoot(newPart); 2448 SetPartAsNonRoot(newPart);
@@ -1852,11 +2571,11 @@ namespace OpenSim.Region.Framework.Scenes
1852 /// Immediately send a full update for this scene object. 2571 /// Immediately send a full update for this scene object.
1853 /// </summary> 2572 /// </summary>
1854 public void SendGroupFullUpdate() 2573 public void SendGroupFullUpdate()
1855 { 2574 {
1856 if (IsDeleted) 2575 if (IsDeleted)
1857 return; 2576 return;
1858 2577
1859// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2578// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1860 2579
1861 RootPart.SendFullUpdateToAllClients(); 2580 RootPart.SendFullUpdateToAllClients();
1862 2581
@@ -1990,6 +2709,11 @@ namespace OpenSim.Region.Framework.Scenes
1990 2709
1991 SceneObjectPart linkPart = objectGroup.m_rootPart; 2710 SceneObjectPart linkPart = objectGroup.m_rootPart;
1992 2711
2712 if (m_rootPart.PhysActor != null)
2713 m_rootPart.PhysActor.Building = true;
2714 if (linkPart.PhysActor != null)
2715 linkPart.PhysActor.Building = true;
2716
1993 // physics flags from group to be applied to linked parts 2717 // physics flags from group to be applied to linked parts
1994 bool grpusephys = UsesPhysics; 2718 bool grpusephys = UsesPhysics;
1995 bool grptemporary = IsTemporary; 2719 bool grptemporary = IsTemporary;
@@ -1998,19 +2722,21 @@ namespace OpenSim.Region.Framework.Scenes
1998 Quaternion oldRootRotation = linkPart.RotationOffset; 2722 Quaternion oldRootRotation = linkPart.RotationOffset;
1999 2723
2000 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; 2724 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition;
2725
2001 linkPart.ParentID = m_rootPart.LocalId; 2726 linkPart.ParentID = m_rootPart.LocalId;
2002 linkPart.GroupPosition = AbsolutePosition; 2727
2003 Vector3 axPos = linkPart.OffsetPosition; 2728 linkPart.GroupPosition = AbsolutePosition;
2004 2729
2730 Vector3 axPos = linkPart.OffsetPosition;
2005 Quaternion parentRot = m_rootPart.RotationOffset; 2731 Quaternion parentRot = m_rootPart.RotationOffset;
2006 axPos *= Quaternion.Inverse(parentRot); 2732 axPos *= Quaternion.Conjugate(parentRot);
2007
2008 linkPart.OffsetPosition = axPos; 2733 linkPart.OffsetPosition = axPos;
2734
2009 Quaternion oldRot = linkPart.RotationOffset; 2735 Quaternion oldRot = linkPart.RotationOffset;
2010 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2736 Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot;
2011 linkPart.RotationOffset = newRot; 2737 linkPart.RotationOffset = newRot;
2012 2738
2013 linkPart.ParentID = m_rootPart.LocalId; 2739// linkPart.ParentID = m_rootPart.LocalId; done above
2014 2740
2015 if (m_rootPart.LinkNum == 0) 2741 if (m_rootPart.LinkNum == 0)
2016 m_rootPart.LinkNum = 1; 2742 m_rootPart.LinkNum = 1;
@@ -2038,7 +2764,7 @@ namespace OpenSim.Region.Framework.Scenes
2038 linkPart.CreateSelected = true; 2764 linkPart.CreateSelected = true;
2039 2765
2040 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now 2766 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
2041 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive); 2767 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true);
2042 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 2768 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2043 { 2769 {
2044 linkPart.PhysActor.link(m_rootPart.PhysActor); 2770 linkPart.PhysActor.link(m_rootPart.PhysActor);
@@ -2046,6 +2772,7 @@ namespace OpenSim.Region.Framework.Scenes
2046 } 2772 }
2047 2773
2048 linkPart.LinkNum = linkNum++; 2774 linkPart.LinkNum = linkNum++;
2775 linkPart.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2049 2776
2050 SceneObjectPart[] ogParts = objectGroup.Parts; 2777 SceneObjectPart[] ogParts = objectGroup.Parts;
2051 Array.Sort(ogParts, delegate(SceneObjectPart a, SceneObjectPart b) 2778 Array.Sort(ogParts, delegate(SceneObjectPart a, SceneObjectPart b)
@@ -2060,7 +2787,7 @@ namespace OpenSim.Region.Framework.Scenes
2060 { 2787 {
2061 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); 2788 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2062 // let physics know 2789 // let physics know
2063 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive); 2790 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true);
2064 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 2791 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2065 { 2792 {
2066 part.PhysActor.link(m_rootPart.PhysActor); 2793 part.PhysActor.link(m_rootPart.PhysActor);
@@ -2075,7 +2802,7 @@ namespace OpenSim.Region.Framework.Scenes
2075 objectGroup.IsDeleted = true; 2802 objectGroup.IsDeleted = true;
2076 2803
2077 objectGroup.m_parts.Clear(); 2804 objectGroup.m_parts.Clear();
2078 2805
2079 // Can't do this yet since backup still makes use of the root part without any synchronization 2806 // Can't do this yet since backup still makes use of the root part without any synchronization
2080// objectGroup.m_rootPart = null; 2807// objectGroup.m_rootPart = null;
2081 2808
@@ -2086,6 +2813,9 @@ namespace OpenSim.Region.Framework.Scenes
2086 // unmoved prims! 2813 // unmoved prims!
2087 ResetChildPrimPhysicsPositions(); 2814 ResetChildPrimPhysicsPositions();
2088 2815
2816 if (m_rootPart.PhysActor != null)
2817 m_rootPart.PhysActor.Building = false;
2818
2089 //HasGroupChanged = true; 2819 //HasGroupChanged = true;
2090 //ScheduleGroupForFullUpdate(); 2820 //ScheduleGroupForFullUpdate();
2091 } 2821 }
@@ -2153,7 +2883,10 @@ namespace OpenSim.Region.Framework.Scenes
2153// m_log.DebugFormat( 2883// m_log.DebugFormat(
2154// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", 2884// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2155// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); 2885// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2156 2886
2887 if (m_rootPart.PhysActor != null)
2888 m_rootPart.PhysActor.Building = true;
2889
2157 linkPart.ClearUndoState(); 2890 linkPart.ClearUndoState();
2158 2891
2159 Quaternion worldRot = linkPart.GetWorldRotation(); 2892 Quaternion worldRot = linkPart.GetWorldRotation();
@@ -2213,6 +2946,14 @@ namespace OpenSim.Region.Framework.Scenes
2213 2946
2214 // When we delete a group, we currently have to force persist to the database if the object id has changed 2947 // When we delete a group, we currently have to force persist to the database if the object id has changed
2215 // (since delete works by deleting all rows which have a given object id) 2948 // (since delete works by deleting all rows which have a given object id)
2949
2950 // this is as it seems to be in sl now
2951 if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none)
2952 linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now
2953
2954 if (m_rootPart.PhysActor != null)
2955 m_rootPart.PhysActor.Building = false;
2956
2216 objectGroup.HasGroupChangedDueToDelink = true; 2957 objectGroup.HasGroupChangedDueToDelink = true;
2217 2958
2218 return objectGroup; 2959 return objectGroup;
@@ -2224,6 +2965,7 @@ namespace OpenSim.Region.Framework.Scenes
2224 /// <param name="objectGroup"></param> 2965 /// <param name="objectGroup"></param>
2225 public virtual void DetachFromBackup() 2966 public virtual void DetachFromBackup()
2226 { 2967 {
2968 m_scene.SceneGraph.FireDetachFromBackup(this);
2227 if (m_isBackedUp && Scene != null) 2969 if (m_isBackedUp && Scene != null)
2228 m_scene.EventManager.OnBackup -= ProcessBackup; 2970 m_scene.EventManager.OnBackup -= ProcessBackup;
2229 2971
@@ -2242,7 +2984,8 @@ namespace OpenSim.Region.Framework.Scenes
2242 2984
2243 axPos *= parentRot; 2985 axPos *= parentRot;
2244 part.OffsetPosition = axPos; 2986 part.OffsetPosition = axPos;
2245 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2987 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2988 part.GroupPosition = newPos;
2246 part.OffsetPosition = Vector3.Zero; 2989 part.OffsetPosition = Vector3.Zero;
2247 part.RotationOffset = worldRot; 2990 part.RotationOffset = worldRot;
2248 2991
@@ -2253,20 +2996,20 @@ namespace OpenSim.Region.Framework.Scenes
2253 2996
2254 part.LinkNum = linkNum; 2997 part.LinkNum = linkNum;
2255 2998
2256 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2999 part.OffsetPosition = newPos - AbsolutePosition;
2257 3000
2258 Quaternion rootRotation = m_rootPart.RotationOffset; 3001 Quaternion rootRotation = m_rootPart.RotationOffset;
2259 3002
2260 Vector3 pos = part.OffsetPosition; 3003 Vector3 pos = part.OffsetPosition;
2261 pos *= Quaternion.Inverse(rootRotation); 3004 pos *= Quaternion.Conjugate(rootRotation);
2262 part.OffsetPosition = pos; 3005 part.OffsetPosition = pos;
2263 3006
2264 parentRot = m_rootPart.RotationOffset; 3007 parentRot = m_rootPart.RotationOffset;
2265 oldRot = part.RotationOffset; 3008 oldRot = part.RotationOffset;
2266 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 3009 Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot;
2267 part.RotationOffset = newRot; 3010 part.RotationOffset = newRot;
2268 3011
2269 part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect); 3012 part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2270 } 3013 }
2271 3014
2272 /// <summary> 3015 /// <summary>
@@ -2288,10 +3031,14 @@ namespace OpenSim.Region.Framework.Scenes
2288 { 3031 {
2289 if (!m_rootPart.BlockGrab) 3032 if (!m_rootPart.BlockGrab)
2290 { 3033 {
2291 Vector3 llmoveforce = pos - AbsolutePosition; 3034/* Vector3 llmoveforce = pos - AbsolutePosition;
2292 Vector3 grabforce = llmoveforce; 3035 Vector3 grabforce = llmoveforce;
2293 grabforce = (grabforce / 10) * pa.Mass; 3036 grabforce = (grabforce / 10) * pa.Mass;
2294 pa.AddForce(grabforce, true); 3037 */
3038 // empirically convert distance diference to a impulse
3039 Vector3 grabforce = pos - AbsolutePosition;
3040 grabforce = grabforce * (pa.Mass/ 10.0f);
3041 pa.AddForce(grabforce, false);
2295 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 3042 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
2296 } 3043 }
2297 } 3044 }
@@ -2517,8 +3264,22 @@ namespace OpenSim.Region.Framework.Scenes
2517 } 3264 }
2518 } 3265 }
2519 3266
2520 for (int i = 0; i < parts.Length; i++) 3267 if (parts.Length > 1)
2521 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 3268 {
3269 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3270
3271 for (int i = 0; i < parts.Length; i++)
3272 {
3273
3274 if (parts[i].UUID != m_rootPart.UUID)
3275 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3276 }
3277
3278 if (m_rootPart.PhysActor != null)
3279 m_rootPart.PhysActor.Building = false;
3280 }
3281 else
3282 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
2522 } 3283 }
2523 } 3284 }
2524 3285
@@ -2531,6 +3292,17 @@ namespace OpenSim.Region.Framework.Scenes
2531 } 3292 }
2532 } 3293 }
2533 3294
3295
3296
3297 /// <summary>
3298 /// Gets the number of parts
3299 /// </summary>
3300 /// <returns></returns>
3301 public int GetPartCount()
3302 {
3303 return Parts.Count();
3304 }
3305
2534 /// <summary> 3306 /// <summary>
2535 /// Update the texture entry for this part 3307 /// Update the texture entry for this part
2536 /// </summary> 3308 /// </summary>
@@ -2592,11 +3364,6 @@ namespace OpenSim.Region.Framework.Scenes
2592 /// <param name="scale"></param> 3364 /// <param name="scale"></param>
2593 public void GroupResize(Vector3 scale) 3365 public void GroupResize(Vector3 scale)
2594 { 3366 {
2595// m_log.DebugFormat(
2596// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2597
2598 RootPart.StoreUndoState(true);
2599
2600 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3367 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
2601 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); 3368 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
2602 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); 3369 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
@@ -2623,7 +3390,6 @@ namespace OpenSim.Region.Framework.Scenes
2623 SceneObjectPart obPart = parts[i]; 3390 SceneObjectPart obPart = parts[i];
2624 if (obPart.UUID != m_rootPart.UUID) 3391 if (obPart.UUID != m_rootPart.UUID)
2625 { 3392 {
2626// obPart.IgnoreUndoUpdate = true;
2627 Vector3 oldSize = new Vector3(obPart.Scale); 3393 Vector3 oldSize = new Vector3(obPart.Scale);
2628 3394
2629 float f = 1.0f; 3395 float f = 1.0f;
@@ -2687,8 +3453,6 @@ namespace OpenSim.Region.Framework.Scenes
2687 z *= a; 3453 z *= a;
2688 } 3454 }
2689 } 3455 }
2690
2691// obPart.IgnoreUndoUpdate = false;
2692 } 3456 }
2693 } 3457 }
2694 } 3458 }
@@ -2698,9 +3462,7 @@ namespace OpenSim.Region.Framework.Scenes
2698 prevScale.Y *= y; 3462 prevScale.Y *= y;
2699 prevScale.Z *= z; 3463 prevScale.Z *= z;
2700 3464
2701// RootPart.IgnoreUndoUpdate = true;
2702 RootPart.Resize(prevScale); 3465 RootPart.Resize(prevScale);
2703// RootPart.IgnoreUndoUpdate = false;
2704 3466
2705 parts = m_parts.GetArray(); 3467 parts = m_parts.GetArray();
2706 for (int i = 0; i < parts.Length; i++) 3468 for (int i = 0; i < parts.Length; i++)
@@ -2709,8 +3471,6 @@ namespace OpenSim.Region.Framework.Scenes
2709 3471
2710 if (obPart.UUID != m_rootPart.UUID) 3472 if (obPart.UUID != m_rootPart.UUID)
2711 { 3473 {
2712 obPart.IgnoreUndoUpdate = true;
2713
2714 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3474 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2715 currentpos.X *= x; 3475 currentpos.X *= x;
2716 currentpos.Y *= y; 3476 currentpos.Y *= y;
@@ -2723,16 +3483,12 @@ namespace OpenSim.Region.Framework.Scenes
2723 3483
2724 obPart.Resize(newSize); 3484 obPart.Resize(newSize);
2725 obPart.UpdateOffSet(currentpos); 3485 obPart.UpdateOffSet(currentpos);
2726
2727 obPart.IgnoreUndoUpdate = false;
2728 } 3486 }
2729 3487
2730// obPart.IgnoreUndoUpdate = false; 3488 HasGroupChanged = true;
2731// obPart.StoreUndoState(); 3489 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3490 ScheduleGroupForTerseUpdate();
2732 } 3491 }
2733
2734// m_log.DebugFormat(
2735// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale);
2736 } 3492 }
2737 3493
2738 #endregion 3494 #endregion
@@ -2745,14 +3501,6 @@ namespace OpenSim.Region.Framework.Scenes
2745 /// <param name="pos"></param> 3501 /// <param name="pos"></param>
2746 public void UpdateGroupPosition(Vector3 pos) 3502 public void UpdateGroupPosition(Vector3 pos)
2747 { 3503 {
2748// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
2749
2750 RootPart.StoreUndoState(true);
2751
2752// SceneObjectPart[] parts = m_parts.GetArray();
2753// for (int i = 0; i < parts.Length; i++)
2754// parts[i].StoreUndoState();
2755
2756 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3504 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2757 { 3505 {
2758 if (IsAttachment) 3506 if (IsAttachment)
@@ -2785,21 +3533,17 @@ namespace OpenSim.Region.Framework.Scenes
2785 /// </summary> 3533 /// </summary>
2786 /// <param name="pos"></param> 3534 /// <param name="pos"></param>
2787 /// <param name="localID"></param> 3535 /// <param name="localID"></param>
3536 ///
3537
2788 public void UpdateSinglePosition(Vector3 pos, uint localID) 3538 public void UpdateSinglePosition(Vector3 pos, uint localID)
2789 { 3539 {
2790 SceneObjectPart part = GetPart(localID); 3540 SceneObjectPart part = GetPart(localID);
2791 3541
2792// SceneObjectPart[] parts = m_parts.GetArray();
2793// for (int i = 0; i < parts.Length; i++)
2794// parts[i].StoreUndoState();
2795
2796 if (part != null) 3542 if (part != null)
2797 { 3543 {
2798// m_log.DebugFormat( 3544// unlock parts position change
2799// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); 3545 if (m_rootPart.PhysActor != null)
2800 3546 m_rootPart.PhysActor.Building = true;
2801 part.StoreUndoState(false);
2802 part.IgnoreUndoUpdate = true;
2803 3547
2804 if (part.UUID == m_rootPart.UUID) 3548 if (part.UUID == m_rootPart.UUID)
2805 { 3549 {
@@ -2810,8 +3554,10 @@ namespace OpenSim.Region.Framework.Scenes
2810 part.UpdateOffSet(pos); 3554 part.UpdateOffSet(pos);
2811 } 3555 }
2812 3556
3557 if (m_rootPart.PhysActor != null)
3558 m_rootPart.PhysActor.Building = false;
3559
2813 HasGroupChanged = true; 3560 HasGroupChanged = true;
2814 part.IgnoreUndoUpdate = false;
2815 } 3561 }
2816 } 3562 }
2817 3563
@@ -2821,13 +3567,7 @@ namespace OpenSim.Region.Framework.Scenes
2821 /// <param name="pos"></param> 3567 /// <param name="pos"></param>
2822 public void UpdateRootPosition(Vector3 pos) 3568 public void UpdateRootPosition(Vector3 pos)
2823 { 3569 {
2824// m_log.DebugFormat( 3570 // needs to be called with phys building true
2825// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
2826
2827// SceneObjectPart[] parts = m_parts.GetArray();
2828// for (int i = 0; i < parts.Length; i++)
2829// parts[i].StoreUndoState();
2830
2831 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3571 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2832 Vector3 oldPos = 3572 Vector3 oldPos =
2833 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3573 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
@@ -2850,7 +3590,14 @@ namespace OpenSim.Region.Framework.Scenes
2850 AbsolutePosition = newPos; 3590 AbsolutePosition = newPos;
2851 3591
2852 HasGroupChanged = true; 3592 HasGroupChanged = true;
2853 ScheduleGroupForTerseUpdate(); 3593 if (m_rootPart.Undoing)
3594 {
3595 ScheduleGroupForFullUpdate();
3596 }
3597 else
3598 {
3599 ScheduleGroupForTerseUpdate();
3600 }
2854 } 3601 }
2855 3602
2856 #endregion 3603 #endregion
@@ -2863,24 +3610,16 @@ namespace OpenSim.Region.Framework.Scenes
2863 /// <param name="rot"></param> 3610 /// <param name="rot"></param>
2864 public void UpdateGroupRotationR(Quaternion rot) 3611 public void UpdateGroupRotationR(Quaternion rot)
2865 { 3612 {
2866// m_log.DebugFormat(
2867// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
2868
2869// SceneObjectPart[] parts = m_parts.GetArray();
2870// for (int i = 0; i < parts.Length; i++)
2871// parts[i].StoreUndoState();
2872
2873 m_rootPart.StoreUndoState(true);
2874
2875 m_rootPart.UpdateRotation(rot); 3613 m_rootPart.UpdateRotation(rot);
2876 3614
3615/* this is done by rootpart RotationOffset set called by UpdateRotation
2877 PhysicsActor actor = m_rootPart.PhysActor; 3616 PhysicsActor actor = m_rootPart.PhysActor;
2878 if (actor != null) 3617 if (actor != null)
2879 { 3618 {
2880 actor.Orientation = m_rootPart.RotationOffset; 3619 actor.Orientation = m_rootPart.RotationOffset;
2881 m_scene.PhysicsScene.AddPhysicsActorTaint(actor); 3620 m_scene.PhysicsScene.AddPhysicsActorTaint(actor);
2882 } 3621 }
2883 3622*/
2884 HasGroupChanged = true; 3623 HasGroupChanged = true;
2885 ScheduleGroupForTerseUpdate(); 3624 ScheduleGroupForTerseUpdate();
2886 } 3625 }
@@ -2892,16 +3631,6 @@ namespace OpenSim.Region.Framework.Scenes
2892 /// <param name="rot"></param> 3631 /// <param name="rot"></param>
2893 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 3632 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
2894 { 3633 {
2895// m_log.DebugFormat(
2896// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
2897
2898// SceneObjectPart[] parts = m_parts.GetArray();
2899// for (int i = 0; i < parts.Length; i++)
2900// parts[i].StoreUndoState();
2901
2902 RootPart.StoreUndoState(true);
2903 RootPart.IgnoreUndoUpdate = true;
2904
2905 m_rootPart.UpdateRotation(rot); 3634 m_rootPart.UpdateRotation(rot);
2906 3635
2907 PhysicsActor actor = m_rootPart.PhysActor; 3636 PhysicsActor actor = m_rootPart.PhysActor;
@@ -2920,8 +3649,6 @@ namespace OpenSim.Region.Framework.Scenes
2920 3649
2921 HasGroupChanged = true; 3650 HasGroupChanged = true;
2922 ScheduleGroupForTerseUpdate(); 3651 ScheduleGroupForTerseUpdate();
2923
2924 RootPart.IgnoreUndoUpdate = false;
2925 } 3652 }
2926 3653
2927 /// <summary> 3654 /// <summary>
@@ -2934,13 +3661,11 @@ namespace OpenSim.Region.Framework.Scenes
2934 SceneObjectPart part = GetPart(localID); 3661 SceneObjectPart part = GetPart(localID);
2935 3662
2936 SceneObjectPart[] parts = m_parts.GetArray(); 3663 SceneObjectPart[] parts = m_parts.GetArray();
2937 for (int i = 0; i < parts.Length; i++)
2938 parts[i].StoreUndoState();
2939 3664
2940 if (part != null) 3665 if (part != null)
2941 { 3666 {
2942// m_log.DebugFormat( 3667 if (m_rootPart.PhysActor != null)
2943// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); 3668 m_rootPart.PhysActor.Building = true;
2944 3669
2945 if (part.UUID == m_rootPart.UUID) 3670 if (part.UUID == m_rootPart.UUID)
2946 { 3671 {
@@ -2950,6 +3675,9 @@ namespace OpenSim.Region.Framework.Scenes
2950 { 3675 {
2951 part.UpdateRotation(rot); 3676 part.UpdateRotation(rot);
2952 } 3677 }
3678
3679 if (m_rootPart.PhysActor != null)
3680 m_rootPart.PhysActor.Building = false;
2953 } 3681 }
2954 } 3682 }
2955 3683
@@ -2963,12 +3691,8 @@ namespace OpenSim.Region.Framework.Scenes
2963 SceneObjectPart part = GetPart(localID); 3691 SceneObjectPart part = GetPart(localID);
2964 if (part != null) 3692 if (part != null)
2965 { 3693 {
2966// m_log.DebugFormat( 3694 if (m_rootPart.PhysActor != null)
2967// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", 3695 m_rootPart.PhysActor.Building = true;
2968// part.Name, part.LocalId, rot);
2969
2970 part.StoreUndoState();
2971 part.IgnoreUndoUpdate = true;
2972 3696
2973 if (part.UUID == m_rootPart.UUID) 3697 if (part.UUID == m_rootPart.UUID)
2974 { 3698 {
@@ -2981,7 +3705,8 @@ namespace OpenSim.Region.Framework.Scenes
2981 part.OffsetPosition = pos; 3705 part.OffsetPosition = pos;
2982 } 3706 }
2983 3707
2984 part.IgnoreUndoUpdate = false; 3708 if (m_rootPart.PhysActor != null)
3709 m_rootPart.PhysActor.Building = false;
2985 } 3710 }
2986 } 3711 }
2987 3712
@@ -2991,15 +3716,12 @@ namespace OpenSim.Region.Framework.Scenes
2991 /// <param name="rot"></param> 3716 /// <param name="rot"></param>
2992 public void UpdateRootRotation(Quaternion rot) 3717 public void UpdateRootRotation(Quaternion rot)
2993 { 3718 {
2994// m_log.DebugFormat( 3719 // needs to be called with phys building true
2995// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
2996// Name, LocalId, rot);
2997
2998 Quaternion axRot = rot; 3720 Quaternion axRot = rot;
2999 Quaternion oldParentRot = m_rootPart.RotationOffset; 3721 Quaternion oldParentRot = m_rootPart.RotationOffset;
3000 3722
3001 m_rootPart.StoreUndoState(); 3723 //Don't use UpdateRotation because it schedules an update prematurely
3002 m_rootPart.UpdateRotation(rot); 3724 m_rootPart.RotationOffset = rot;
3003 3725
3004 PhysicsActor pa = m_rootPart.PhysActor; 3726 PhysicsActor pa = m_rootPart.PhysActor;
3005 3727
@@ -3015,35 +3737,145 @@ namespace OpenSim.Region.Framework.Scenes
3015 SceneObjectPart prim = parts[i]; 3737 SceneObjectPart prim = parts[i];
3016 if (prim.UUID != m_rootPart.UUID) 3738 if (prim.UUID != m_rootPart.UUID)
3017 { 3739 {
3018 prim.IgnoreUndoUpdate = true; 3740 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3741 NewRot = Quaternion.Inverse(axRot) * NewRot;
3742 prim.RotationOffset = NewRot;
3743
3019 Vector3 axPos = prim.OffsetPosition; 3744 Vector3 axPos = prim.OffsetPosition;
3745
3020 axPos *= oldParentRot; 3746 axPos *= oldParentRot;
3021 axPos *= Quaternion.Inverse(axRot); 3747 axPos *= Quaternion.Inverse(axRot);
3022 prim.OffsetPosition = axPos; 3748 prim.OffsetPosition = axPos;
3023 Quaternion primsRot = prim.RotationOffset; 3749 }
3024 Quaternion newRot = oldParentRot * primsRot; 3750 }
3025 newRot = Quaternion.Inverse(axRot) * newRot; 3751
3026 prim.RotationOffset = newRot; 3752 HasGroupChanged = true;
3027 prim.ScheduleTerseUpdate(); 3753 ScheduleGroupForFullUpdate();
3028 prim.IgnoreUndoUpdate = false; 3754 }
3029 }
3030 }
3031
3032// for (int i = 0; i < parts.Length; i++)
3033// {
3034// SceneObjectPart childpart = parts[i];
3035// if (childpart != m_rootPart)
3036// {
3037//// childpart.IgnoreUndoUpdate = false;
3038//// childpart.StoreUndoState();
3039// }
3040// }
3041 3755
3042 m_rootPart.ScheduleTerseUpdate(); 3756 private enum updatetype :int
3757 {
3758 none = 0,
3759 partterse = 1,
3760 partfull = 2,
3761 groupterse = 3,
3762 groupfull = 4
3763 }
3043 3764
3044// m_log.DebugFormat( 3765 public void doChangeObject(SceneObjectPart part, ObjectChangeData data)
3045// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3766 {
3046// Name, LocalId, rot); 3767 // TODO this still as excessive *.Schedule*Update()s
3768
3769 if (part != null && part.ParentGroup != null)
3770 {
3771 ObjectChangeType change = data.change;
3772 bool togroup = ((change & ObjectChangeType.Group) != 0);
3773 // bool uniform = ((what & ObjectChangeType.UniformScale) != 0); not in use
3774
3775 SceneObjectGroup group = part.ParentGroup;
3776 PhysicsActor pha = group.RootPart.PhysActor;
3777
3778 updatetype updateType = updatetype.none;
3779
3780 if (togroup)
3781 {
3782 // related to group
3783 if ((change & (ObjectChangeType.Rotation | ObjectChangeType.Position)) != 0)
3784 {
3785 if ((change & ObjectChangeType.Rotation) != 0)
3786 {
3787 group.RootPart.UpdateRotation(data.rotation);
3788 updateType = updatetype.none;
3789 }
3790 if ((change & ObjectChangeType.Position) != 0)
3791 {
3792 if (IsAttachment || m_scene.Permissions.CanObjectEntry(group.UUID, false, data.position))
3793 UpdateGroupPosition(data.position);
3794 updateType = updatetype.groupterse;
3795 }
3796 else
3797 // ugly rotation update of all parts
3798 {
3799 group.AbsolutePosition = AbsolutePosition;
3800 }
3801
3802 }
3803 if ((change & ObjectChangeType.Scale) != 0)
3804 {
3805 if (pha != null)
3806 pha.Building = true;
3807
3808 group.GroupResize(data.scale);
3809 updateType = updatetype.none;
3810
3811 if (pha != null)
3812 pha.Building = false;
3813 }
3814 }
3815 else
3816 {
3817 // related to single prim in a link-set ( ie group)
3818 if (pha != null)
3819 pha.Building = true;
3820
3821 // root part is special
3822 // parts offset positions or rotations need to change also
3823
3824 if (part == group.RootPart)
3825 {
3826 if ((change & ObjectChangeType.Rotation) != 0)
3827 group.UpdateRootRotation(data.rotation);
3828 if ((change & ObjectChangeType.Position) != 0)
3829 group.UpdateRootPosition(data.position);
3830 if ((change & ObjectChangeType.Scale) != 0)
3831 part.Resize(data.scale);
3832 }
3833 else
3834 {
3835 if ((change & ObjectChangeType.Position) != 0)
3836 {
3837 part.OffsetPosition = data.position;
3838 updateType = updatetype.partterse;
3839 }
3840 if ((change & ObjectChangeType.Rotation) != 0)
3841 {
3842 part.UpdateRotation(data.rotation);
3843 updateType = updatetype.none;
3844 }
3845 if ((change & ObjectChangeType.Scale) != 0)
3846 {
3847 part.Resize(data.scale);
3848 updateType = updatetype.none;
3849 }
3850 }
3851
3852 if (pha != null)
3853 pha.Building = false;
3854 }
3855
3856 if (updateType != updatetype.none)
3857 {
3858 group.HasGroupChanged = true;
3859
3860 switch (updateType)
3861 {
3862 case updatetype.partterse:
3863 part.ScheduleTerseUpdate();
3864 break;
3865 case updatetype.partfull:
3866 part.ScheduleFullUpdate();
3867 break;
3868 case updatetype.groupterse:
3869 group.ScheduleGroupForTerseUpdate();
3870 break;
3871 case updatetype.groupfull:
3872 group.ScheduleGroupForFullUpdate();
3873 break;
3874 default:
3875 break;
3876 }
3877 }
3878 }
3047 } 3879 }
3048 3880
3049 #endregion 3881 #endregion
@@ -3142,10 +3974,11 @@ namespace OpenSim.Region.Framework.Scenes
3142 scriptPosTarget target = m_targets[idx]; 3974 scriptPosTarget target = m_targets[idx];
3143 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance) 3975 if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance)
3144 { 3976 {
3977 at_target = true;
3978
3145 // trigger at_target 3979 // trigger at_target
3146 if (m_scriptListens_atTarget) 3980 if (m_scriptListens_atTarget)
3147 { 3981 {
3148 at_target = true;
3149 scriptPosTarget att = new scriptPosTarget(); 3982 scriptPosTarget att = new scriptPosTarget();
3150 att.targetPos = target.targetPos; 3983 att.targetPos = target.targetPos;
3151 att.tolerance = target.tolerance; 3984 att.tolerance = target.tolerance;
@@ -3263,11 +4096,50 @@ namespace OpenSim.Region.Framework.Scenes
3263 } 4096 }
3264 } 4097 }
3265 } 4098 }
3266 4099
4100 public Vector3 GetGeometricCenter()
4101 {
4102 // this is not real geometric center but a average of positions relative to root prim acording to
4103 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
4104 // ignoring tortured prims details since sl also seems to ignore
4105 // so no real use in doing it on physics
4106
4107 Vector3 gc = Vector3.Zero;
4108
4109 int nparts = m_parts.Count;
4110 if (nparts <= 1)
4111 return gc;
4112
4113 SceneObjectPart[] parts = m_parts.GetArray();
4114 nparts = parts.Length; // just in case it changed
4115 if (nparts <= 1)
4116 return gc;
4117
4118 Quaternion parentRot = RootPart.RotationOffset;
4119 Vector3 pPos;
4120
4121 // average all parts positions
4122 for (int i = 0; i < nparts; i++)
4123 {
4124 // do it directly
4125 // gc += parts[i].GetWorldPosition();
4126 if (parts[i] != RootPart)
4127 {
4128 pPos = parts[i].OffsetPosition;
4129 gc += pPos;
4130 }
4131
4132 }
4133 gc /= nparts;
4134
4135 // relative to root:
4136// gc -= AbsolutePosition;
4137 return gc;
4138 }
4139
3267 public float GetMass() 4140 public float GetMass()
3268 { 4141 {
3269 float retmass = 0f; 4142 float retmass = 0f;
3270
3271 SceneObjectPart[] parts = m_parts.GetArray(); 4143 SceneObjectPart[] parts = m_parts.GetArray();
3272 for (int i = 0; i < parts.Length; i++) 4144 for (int i = 0; i < parts.Length; i++)
3273 retmass += parts[i].GetMass(); 4145 retmass += parts[i].GetMass();
@@ -3275,6 +4147,39 @@ namespace OpenSim.Region.Framework.Scenes
3275 return retmass; 4147 return retmass;
3276 } 4148 }
3277 4149
4150 // center of mass of full object
4151 public Vector3 GetCenterOfMass()
4152 {
4153 PhysicsActor pa = RootPart.PhysActor;
4154
4155 if(((RootPart.Flags & PrimFlags.Physics) !=0) && pa !=null)
4156 {
4157 // physics knows better about center of mass of physical prims
4158 Vector3 tmp = pa.CenterOfMass;
4159 return tmp;
4160 }
4161
4162 Vector3 Ptot = Vector3.Zero;
4163 float totmass = 0f;
4164 float m;
4165
4166 SceneObjectPart[] parts = m_parts.GetArray();
4167 for (int i = 0; i < parts.Length; i++)
4168 {
4169 m = parts[i].GetMass();
4170 Ptot += parts[i].GetPartCenterOfMass() * m;
4171 totmass += m;
4172 }
4173
4174 if (totmass == 0)
4175 totmass = 0;
4176 else
4177 totmass = 1 / totmass;
4178 Ptot *= totmass;
4179
4180 return Ptot;
4181 }
4182
3278 /// <summary> 4183 /// <summary>
3279 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that 4184 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that
3280 /// the physics engine can use it. 4185 /// the physics engine can use it.
@@ -3428,6 +4333,14 @@ namespace OpenSim.Region.Framework.Scenes
3428 FromItemID = uuid; 4333 FromItemID = uuid;
3429 } 4334 }
3430 4335
4336 public void ResetOwnerChangeFlag()
4337 {
4338 ForEachPart(delegate(SceneObjectPart part)
4339 {
4340 part.ResetOwnerChangeFlag();
4341 });
4342 }
4343
3431 #endregion 4344 #endregion
3432 } 4345 }
3433} 4346}
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 c223474..14ef0fb 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,11 +87,14 @@ 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;
91 m_inventorySerial++; 96 m_inventorySerial++;
97 QueryScriptStates();
92 } 98 }
93 } 99 }
94 100
@@ -123,38 +129,45 @@ namespace OpenSim.Region.Framework.Scenes
123 public void ResetInventoryIDs() 129 public void ResetInventoryIDs()
124 { 130 {
125 if (null == m_part) 131 if (null == m_part)
126 return; 132 m_items.LockItemsForWrite(true);
127 133
128 lock (m_items) 134 if (Items.Count == 0)
129 { 135 {
130 if (0 == m_items.Count) 136 m_items.LockItemsForWrite(false);
131 return; 137 return;
138 }
132 139
133 IList<TaskInventoryItem> items = GetInventoryItems(); 140 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
134 m_items.Clear(); 141 Items.Clear();
135 142
136 foreach (TaskInventoryItem item in items) 143 foreach (TaskInventoryItem item in items)
137 { 144 {
138 item.ResetIDs(m_part.UUID); 145 item.ResetIDs(m_part.UUID);
139 m_items.Add(item.ItemID, item); 146 Items.Add(item.ItemID, item);
140 }
141 } 147 }
148 m_items.LockItemsForWrite(false);
142 } 149 }
143 150
144 public void ResetObjectID() 151 public void ResetObjectID()
145 { 152 {
146 lock (Items) 153 m_items.LockItemsForWrite(true);
154
155 if (Items.Count == 0)
147 { 156 {
148 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 157 m_items.LockItemsForWrite(false);
149 Items.Clear(); 158 return;
150
151 foreach (TaskInventoryItem item in items)
152 {
153 item.ParentPartID = m_part.UUID;
154 item.ParentID = m_part.UUID;
155 Items.Add(item.ItemID, item);
156 }
157 } 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);
158 } 171 }
159 172
160 /// <summary> 173 /// <summary>
@@ -163,17 +176,14 @@ namespace OpenSim.Region.Framework.Scenes
163 /// <param name="ownerId"></param> 176 /// <param name="ownerId"></param>
164 public void ChangeInventoryOwner(UUID ownerId) 177 public void ChangeInventoryOwner(UUID ownerId)
165 { 178 {
166 lock (Items) 179 List<TaskInventoryItem> items = GetInventoryItems();
167 {
168 if (0 == Items.Count)
169 {
170 return;
171 }
172 }
173 180
181 if (items.Count == 0)
182 return;
183
184 m_items.LockItemsForWrite(true);
174 HasInventoryChanged = true; 185 HasInventoryChanged = true;
175 m_part.ParentGroup.HasGroupChanged = true; 186 m_part.ParentGroup.HasGroupChanged = true;
176 List<TaskInventoryItem> items = GetInventoryItems();
177 foreach (TaskInventoryItem item in items) 187 foreach (TaskInventoryItem item in items)
178 { 188 {
179 if (ownerId != item.OwnerID) 189 if (ownerId != item.OwnerID)
@@ -184,6 +194,7 @@ namespace OpenSim.Region.Framework.Scenes
184 item.PermsGranter = UUID.Zero; 194 item.PermsGranter = UUID.Zero;
185 item.OwnerChanged = true; 195 item.OwnerChanged = true;
186 } 196 }
197 m_items.LockItemsForWrite(false);
187 } 198 }
188 199
189 /// <summary> 200 /// <summary>
@@ -192,12 +203,11 @@ namespace OpenSim.Region.Framework.Scenes
192 /// <param name="groupID"></param> 203 /// <param name="groupID"></param>
193 public void ChangeInventoryGroup(UUID groupID) 204 public void ChangeInventoryGroup(UUID groupID)
194 { 205 {
195 lock (Items) 206 m_items.LockItemsForWrite(true);
207 if (0 == Items.Count)
196 { 208 {
197 if (0 == Items.Count) 209 m_items.LockItemsForWrite(false);
198 { 210 return;
199 return;
200 }
201 } 211 }
202 212
203 // Don't let this set the HasGroupChanged flag for attachments 213 // Don't let this set the HasGroupChanged flag for attachments
@@ -209,12 +219,45 @@ namespace OpenSim.Region.Framework.Scenes
209 m_part.ParentGroup.HasGroupChanged = true; 219 m_part.ParentGroup.HasGroupChanged = true;
210 } 220 }
211 221
212 List<TaskInventoryItem> items = GetInventoryItems(); 222 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
213 foreach (TaskInventoryItem item in items) 223 foreach (TaskInventoryItem item in items)
214 { 224 {
215 if (groupID != item.GroupID) 225 if (groupID != item.GroupID)
226 {
216 item.GroupID = groupID; 227 item.GroupID = groupID;
228 }
217 } 229 }
230 m_items.LockItemsForWrite(false);
231 }
232
233 private void QueryScriptStates()
234 {
235 if (m_part == null || m_part.ParentGroup == null)
236 return;
237
238 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
239 if (engines == null) // No engine at all
240 return;
241
242 Items.LockItemsForRead(true);
243 foreach (TaskInventoryItem item in Items.Values)
244 {
245 if (item.InvType == (int)InventoryType.LSL)
246 {
247 foreach (IScriptModule e in engines)
248 {
249 bool running;
250
251 if (e.HasScript(item.ItemID, out running))
252 {
253 item.ScriptRunning = running;
254 break;
255 }
256 }
257 }
258 }
259
260 Items.LockItemsForRead(false);
218 } 261 }
219 262
220 public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 263 public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
@@ -259,7 +302,10 @@ namespace OpenSim.Region.Framework.Scenes
259 { 302 {
260 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL); 303 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
261 foreach (TaskInventoryItem item in scripts) 304 foreach (TaskInventoryItem item in scripts)
305 {
262 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 306 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
307 m_part.RemoveScriptEvents(item.ItemID);
308 }
263 } 309 }
264 310
265 /// <summary> 311 /// <summary>
@@ -273,7 +319,10 @@ namespace OpenSim.Region.Framework.Scenes
273// 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);
274 320
275 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");
276 return false; 324 return false;
325 }
277 326
278 m_part.AddFlag(PrimFlags.Scripted); 327 m_part.AddFlag(PrimFlags.Scripted);
279 328
@@ -283,14 +332,13 @@ namespace OpenSim.Region.Framework.Scenes
283 if (stateSource == 2 && // Prim crossing 332 if (stateSource == 2 && // Prim crossing
284 m_part.ParentGroup.Scene.m_trustBinaries) 333 m_part.ParentGroup.Scene.m_trustBinaries)
285 { 334 {
286 lock (m_items) 335 m_items.LockItemsForWrite(true);
287 { 336 m_items[item.ItemID].PermsMask = 0;
288 m_items[item.ItemID].PermsMask = 0; 337 m_items[item.ItemID].PermsGranter = UUID.Zero;
289 m_items[item.ItemID].PermsGranter = UUID.Zero; 338 m_items.LockItemsForWrite(false);
290 }
291
292 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 339 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
293 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);
294 m_part.ParentGroup.AddActiveScriptCount(1); 342 m_part.ParentGroup.AddActiveScriptCount(1);
295 m_part.ScheduleFullUpdate(); 343 m_part.ScheduleFullUpdate();
296 return true; 344 return true;
@@ -311,16 +359,28 @@ namespace OpenSim.Region.Framework.Scenes
311 if (m_part.ParentGroup.m_savedScriptState != null) 359 if (m_part.ParentGroup.m_savedScriptState != null)
312 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); 360 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
313 361
314 lock (m_items) 362 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
315 { 363 StoreScriptError(item.ItemID, msg);
316 m_items[item.ItemID].OldItemID = item.OldItemID; 364 m_log.ErrorFormat(
317 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",
318 m_items[item.ItemID].PermsGranter = UUID.Zero; 366 item.Name, item.ItemID, m_part.AbsolutePosition,
319 } 367 m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID);
368
369 m_items.LockItemsForWrite(true);
320 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
321 string script = Utils.BytesToString(asset.Data); 377 string script = Utils.BytesToString(asset.Data);
322 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 378 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
323 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);
381 if (!item.ScriptRunning)
382 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
383 m_part.LocalId, item.ItemID);
324 m_part.ParentGroup.AddActiveScriptCount(1); 384 m_part.ParentGroup.AddActiveScriptCount(1);
325 m_part.ScheduleFullUpdate(); 385 m_part.ScheduleFullUpdate();
326 386
@@ -390,22 +450,149 @@ namespace OpenSim.Region.Framework.Scenes
390 return stateID; 450 return stateID;
391 } 451 }
392 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>
393 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)
394 { 461 {
395 TaskInventoryItem item = GetInventoryItem(itemId); 462 lock (m_scriptErrors)
396 if (item != null)
397 { 463 {
398 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 }
399 } 491 }
400 else 492 else
401 { 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);
402 m_log.ErrorFormat( 497 m_log.ErrorFormat(
403 "[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}",
404 itemId, m_part.Name, m_part.UUID, 499 itemId, m_part.Name, m_part.UUID,
405 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 500 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
501 }
502
503 }
406 504
407 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);
408 } 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 }
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);
409 } 596 }
410 597
411 /// <summary> 598 /// <summary>
@@ -418,15 +605,7 @@ namespace OpenSim.Region.Framework.Scenes
418 /// </param> 605 /// </param>
419 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 606 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
420 { 607 {
421 bool scriptPresent = false; 608 if (m_items.ContainsKey(itemId))
422
423 lock (m_items)
424 {
425 if (m_items.ContainsKey(itemId))
426 scriptPresent = true;
427 }
428
429 if (scriptPresent)
430 { 609 {
431 if (!sceneObjectBeingDeleted) 610 if (!sceneObjectBeingDeleted)
432 m_part.RemoveScriptEvents(itemId); 611 m_part.RemoveScriptEvents(itemId);
@@ -451,14 +630,16 @@ namespace OpenSim.Region.Framework.Scenes
451 /// <returns></returns> 630 /// <returns></returns>
452 private bool InventoryContainsName(string name) 631 private bool InventoryContainsName(string name)
453 { 632 {
454 lock (m_items) 633 m_items.LockItemsForRead(true);
634 foreach (TaskInventoryItem item in m_items.Values)
455 { 635 {
456 foreach (TaskInventoryItem item in m_items.Values) 636 if (item.Name == name)
457 { 637 {
458 if (item.Name == name) 638 m_items.LockItemsForRead(false);
459 return true; 639 return true;
460 } 640 }
461 } 641 }
642 m_items.LockItemsForRead(false);
462 return false; 643 return false;
463 } 644 }
464 645
@@ -500,8 +681,9 @@ namespace OpenSim.Region.Framework.Scenes
500 /// <param name="item"></param> 681 /// <param name="item"></param>
501 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 682 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
502 { 683 {
503 List<TaskInventoryItem> il = GetInventoryItems(); 684 m_items.LockItemsForRead(true);
504 685 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
686 m_items.LockItemsForRead(false);
505 foreach (TaskInventoryItem i in il) 687 foreach (TaskInventoryItem i in il)
506 { 688 {
507 if (i.Name == item.Name) 689 if (i.Name == item.Name)
@@ -539,14 +721,14 @@ namespace OpenSim.Region.Framework.Scenes
539 item.Name = name; 721 item.Name = name;
540 item.GroupID = m_part.GroupID; 722 item.GroupID = m_part.GroupID;
541 723
542 lock (m_items) 724 m_items.LockItemsForWrite(true);
543 m_items.Add(item.ItemID, item); 725 m_items.Add(item.ItemID, item);
544 726 m_items.LockItemsForWrite(false);
545 if (allowedDrop) 727 if (allowedDrop)
546 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 728 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
547 else 729 else
548 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 730 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
549 731
550 m_inventorySerial++; 732 m_inventorySerial++;
551 //m_inventorySerial += 2; 733 //m_inventorySerial += 2;
552 HasInventoryChanged = true; 734 HasInventoryChanged = true;
@@ -562,15 +744,15 @@ namespace OpenSim.Region.Framework.Scenes
562 /// <param name="items"></param> 744 /// <param name="items"></param>
563 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 745 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
564 { 746 {
565 lock (m_items) 747 m_items.LockItemsForWrite(true);
748 foreach (TaskInventoryItem item in items)
566 { 749 {
567 foreach (TaskInventoryItem item in items) 750 m_items.Add(item.ItemID, item);
568 { 751// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
569 m_items.Add(item.ItemID, item);
570// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
571 }
572 m_inventorySerial++;
573 } 752 }
753 m_items.LockItemsForWrite(false);
754
755 m_inventorySerial++;
574 } 756 }
575 757
576 /// <summary> 758 /// <summary>
@@ -581,23 +763,24 @@ namespace OpenSim.Region.Framework.Scenes
581 public TaskInventoryItem GetInventoryItem(UUID itemId) 763 public TaskInventoryItem GetInventoryItem(UUID itemId)
582 { 764 {
583 TaskInventoryItem item; 765 TaskInventoryItem item;
584 766 m_items.LockItemsForRead(true);
585 lock (m_items) 767 m_items.TryGetValue(itemId, out item);
586 m_items.TryGetValue(itemId, out item); 768 m_items.LockItemsForRead(false);
587
588 return item; 769 return item;
589 } 770 }
590 771
591 public TaskInventoryItem GetInventoryItem(string name) 772 public TaskInventoryItem GetInventoryItem(string name)
592 { 773 {
593 lock (m_items) 774 m_items.LockItemsForRead(true);
775 foreach (TaskInventoryItem item in m_items.Values)
594 { 776 {
595 foreach (TaskInventoryItem item in m_items.Values) 777 if (item.Name == name)
596 { 778 {
597 if (item.Name == name) 779 m_items.LockItemsForRead(false);
598 return item; 780 return item;
599 } 781 }
600 } 782 }
783 m_items.LockItemsForRead(false);
601 784
602 return null; 785 return null;
603 } 786 }
@@ -606,15 +789,16 @@ namespace OpenSim.Region.Framework.Scenes
606 { 789 {
607 List<TaskInventoryItem> items = new List<TaskInventoryItem>(); 790 List<TaskInventoryItem> items = new List<TaskInventoryItem>();
608 791
609 lock (m_items) 792 m_items.LockItemsForRead(true);
793
794 foreach (TaskInventoryItem item in m_items.Values)
610 { 795 {
611 foreach (TaskInventoryItem item in m_items.Values) 796 if (item.Name == name)
612 { 797 items.Add(item);
613 if (item.Name == name)
614 items.Add(item);
615 }
616 } 798 }
617 799
800 m_items.LockItemsForRead(false);
801
618 return items; 802 return items;
619 } 803 }
620 804
@@ -633,6 +817,10 @@ namespace OpenSim.Region.Framework.Scenes
633 string xmlData = Utils.BytesToString(rezAsset.Data); 817 string xmlData = Utils.BytesToString(rezAsset.Data);
634 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 818 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
635 819
820 group.RootPart.AttachPoint = group.RootPart.Shape.State;
821 group.RootPart.AttachOffset = group.AbsolutePosition;
822 group.RootPart.AttachRotation = group.GroupRotation;
823
636 group.ResetIDs(); 824 group.ResetIDs();
637 825
638 SceneObjectPart rootPart = group.GetPart(group.UUID); 826 SceneObjectPart rootPart = group.GetPart(group.UUID);
@@ -707,8 +895,9 @@ namespace OpenSim.Region.Framework.Scenes
707 895
708 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 896 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
709 { 897 {
710 TaskInventoryItem it = GetInventoryItem(item.ItemID); 898 m_items.LockItemsForWrite(true);
711 if (it != null) 899
900 if (m_items.ContainsKey(item.ItemID))
712 { 901 {
713// 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);
714 903
@@ -721,14 +910,10 @@ namespace OpenSim.Region.Framework.Scenes
721 item.GroupID = m_part.GroupID; 910 item.GroupID = m_part.GroupID;
722 911
723 if (item.AssetID == UUID.Zero) 912 if (item.AssetID == UUID.Zero)
724 item.AssetID = it.AssetID; 913 item.AssetID = m_items[item.ItemID].AssetID;
725 914
726 lock (m_items) 915 m_items[item.ItemID] = item;
727 { 916 m_inventorySerial++;
728 m_items[item.ItemID] = item;
729 m_inventorySerial++;
730 }
731
732 if (fireScriptEvents) 917 if (fireScriptEvents)
733 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 918 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
734 919
@@ -737,7 +922,7 @@ namespace OpenSim.Region.Framework.Scenes
737 HasInventoryChanged = true; 922 HasInventoryChanged = true;
738 m_part.ParentGroup.HasGroupChanged = true; 923 m_part.ParentGroup.HasGroupChanged = true;
739 } 924 }
740 925 m_items.LockItemsForWrite(false);
741 return true; 926 return true;
742 } 927 }
743 else 928 else
@@ -748,8 +933,9 @@ namespace OpenSim.Region.Framework.Scenes
748 item.ItemID, m_part.Name, m_part.UUID, 933 item.ItemID, m_part.Name, m_part.UUID,
749 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 934 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
750 } 935 }
751 return false; 936 m_items.LockItemsForWrite(false);
752 937
938 return false;
753 } 939 }
754 940
755 /// <summary> 941 /// <summary>
@@ -760,43 +946,59 @@ namespace OpenSim.Region.Framework.Scenes
760 /// in this prim's inventory.</returns> 946 /// in this prim's inventory.</returns>
761 public int RemoveInventoryItem(UUID itemID) 947 public int RemoveInventoryItem(UUID itemID)
762 { 948 {
763 TaskInventoryItem item = GetInventoryItem(itemID); 949 m_items.LockItemsForRead(true);
764 if (item != null) 950
951 if (m_items.ContainsKey(itemID))
765 { 952 {
766 int type = m_items[itemID].InvType; 953 int type = m_items[itemID].InvType;
954 m_items.LockItemsForRead(false);
767 if (type == 10) // Script 955 if (type == 10) // Script
768 { 956 {
769 m_part.RemoveScriptEvents(itemID);
770 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 957 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
771 } 958 }
959 m_items.LockItemsForWrite(true);
772 m_items.Remove(itemID); 960 m_items.Remove(itemID);
961 m_items.LockItemsForWrite(false);
773 m_inventorySerial++; 962 m_inventorySerial++;
774 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 963 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
775 964
776 HasInventoryChanged = true; 965 HasInventoryChanged = true;
777 m_part.ParentGroup.HasGroupChanged = true; 966 m_part.ParentGroup.HasGroupChanged = true;
778 967
779 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 {
780 m_part.RemFlag(PrimFlags.Scripted); 982 m_part.RemFlag(PrimFlags.Scripted);
983 }
781 984
782 m_part.ScheduleFullUpdate(); 985 m_part.ScheduleFullUpdate();
783 986
784 return type; 987 return type;
785
786 } 988 }
787 else 989 else
788 { 990 {
991 m_items.LockItemsForRead(false);
789 m_log.ErrorFormat( 992 m_log.ErrorFormat(
790 "[PRIM INVENTORY]: " + 993 "[PRIM INVENTORY]: " +
791 "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",
792 itemID, m_part.Name, m_part.UUID, 995 itemID, m_part.Name, m_part.UUID);
793 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
794 } 996 }
795 997
796 return -1; 998 return -1;
797 } 999 }
798 1000
799 private bool CreateInventoryFile() 1001 private bool CreateInventoryFileName()
800 { 1002 {
801// m_log.DebugFormat( 1003// m_log.DebugFormat(
802// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", 1004// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
@@ -805,70 +1007,12 @@ namespace OpenSim.Region.Framework.Scenes
805 if (m_inventoryFileName == String.Empty || 1007 if (m_inventoryFileName == String.Empty ||
806 m_inventoryFileNameSerial < m_inventorySerial) 1008 m_inventoryFileNameSerial < m_inventorySerial)
807 { 1009 {
808 // Something changed, we need to create a new file
809 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 1010 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
810 m_inventoryFileNameSerial = m_inventorySerial; 1011 m_inventoryFileNameSerial = m_inventorySerial;
811 1012
812 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
813
814 lock (m_items)
815 {
816 foreach (TaskInventoryItem item in m_items.Values)
817 {
818// m_log.DebugFormat(
819// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}",
820// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
821
822 UUID ownerID = item.OwnerID;
823 uint everyoneMask = 0;
824 uint baseMask = item.BasePermissions;
825 uint ownerMask = item.CurrentPermissions;
826 uint groupMask = item.GroupPermissions;
827
828 invString.AddItemStart();
829 invString.AddNameValueLine("item_id", item.ItemID.ToString());
830 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
831
832 invString.AddPermissionsStart();
833
834 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
835 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
836 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
837 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
838 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
839
840 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
841 invString.AddNameValueLine("owner_id", ownerID.ToString());
842
843 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
844
845 invString.AddNameValueLine("group_id", item.GroupID.ToString());
846 invString.AddSectionEnd();
847
848 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
849 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
850 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
851 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
852
853 invString.AddSaleStart();
854 invString.AddNameValueLine("sale_type", "not");
855 invString.AddNameValueLine("sale_price", "0");
856 invString.AddSectionEnd();
857
858 invString.AddNameValueLine("name", item.Name + "|");
859 invString.AddNameValueLine("desc", item.Description + "|");
860
861 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
862 invString.AddSectionEnd();
863 }
864 }
865
866 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
867
868 return true; 1013 return true;
869 } 1014 }
870 1015
871 // No need to recreate, the existing file is fine
872 return false; 1016 return false;
873 } 1017 }
874 1018
@@ -878,43 +1022,110 @@ namespace OpenSim.Region.Framework.Scenes
878 /// <param name="xferManager"></param> 1022 /// <param name="xferManager"></param>
879 public void RequestInventoryFile(IClientAPI client, IXfer xferManager) 1023 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
880 { 1024 {
881 lock (m_items) 1025 bool changed = CreateInventoryFileName();
882 {
883 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
884 // a new script if any previous deletion has left the prim inventory empty.
885 if (m_items.Count == 0) // No inventory
886 {
887// m_log.DebugFormat(
888// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items",
889// m_part.Name, m_part.LocalId, m_part.UUID, client.Name);
890 1026
891 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1027 bool includeAssets = false;
892 return; 1028 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
893 } 1029 includeAssets = true;
1030
1031 if (m_inventoryPrivileged != includeAssets)
1032 changed = true;
1033
1034 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
894 1035
895 CreateInventoryFile(); 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 }
1044
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 }
896 1051
897 // In principle, we should only do the rest if the inventory changed; 1052 if (!changed)
898 // by sending m_inventorySerial to the client, it ought to know 1053 {
899 // that nothing changed and that it doesn't need to request the file.
900 // Unfortunately, it doesn't look like the client optimizes this;
901 // the client seems to always come back and request the Xfer,
902 // no matter what value m_inventorySerial has.
903 // FIXME: Could probably be > 0 here rather than > 2
904 if (m_inventoryFileData.Length > 2) 1054 if (m_inventoryFileData.Length > 2)
905 { 1055 {
906 // Add the file for Xfer 1056 xferManager.AddNewFile(m_inventoryFileName,
907 // m_log.DebugFormat( 1057 m_inventoryFileData);
908 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}", 1058 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
909 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId); 1059 Util.StringToBytes256(m_inventoryFileName));
910 1060
911 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); 1061 Items.LockItemsForRead(false);
1062 return;
912 } 1063 }
913
914 // Tell the client we're ready to Xfer the file
915 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
916 Util.StringToBytes256(m_inventoryFileName));
917 } 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]);
918 } 1129 }
919 1130
920 /// <summary> 1131 /// <summary>
@@ -923,13 +1134,19 @@ namespace OpenSim.Region.Framework.Scenes
923 /// <param name="datastore"></param> 1134 /// <param name="datastore"></param>
924 public void ProcessInventoryBackup(ISimulationDataService datastore) 1135 public void ProcessInventoryBackup(ISimulationDataService datastore)
925 { 1136 {
926 if (HasInventoryChanged) 1137// Removed this because linking will cause an immediate delete of the new
927 { 1138// child prim from the database and the subsequent storing of the prim sees
928 HasInventoryChanged = false; 1139// the inventory of it as unchanged and doesn't store it at all. The overhead
929 List<TaskInventoryItem> items = GetInventoryItems(); 1140// of storing prim inventory needlessly is much less than the aggravation
930 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);
931 1147
932 } 1148 HasInventoryChanged = false;
1149// }
933 } 1150 }
934 1151
935 public class InventoryStringBuilder 1152 public class InventoryStringBuilder
@@ -995,87 +1212,63 @@ namespace OpenSim.Region.Framework.Scenes
995 { 1212 {
996 uint mask=0x7fffffff; 1213 uint mask=0x7fffffff;
997 1214
998 lock (m_items) 1215 foreach (TaskInventoryItem item in m_items.Values)
999 { 1216 {
1000 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)
1001 { 1225 {
1002 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1226 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1003 mask &= ~((uint)PermissionMask.Copy >> 13); 1227 mask &= ~((uint)PermissionMask.Copy >> 13);
1004 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1228 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1005 mask &= ~((uint)PermissionMask.Transfer >> 13); 1229 mask &= ~((uint)PermissionMask.Transfer >> 13);
1006 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1230 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1007 mask &= ~((uint)PermissionMask.Modify >> 13); 1231 mask &= ~((uint)PermissionMask.Modify >> 13);
1008
1009 if (item.InvType != (int)InventoryType.Object)
1010 {
1011 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1012 mask &= ~((uint)PermissionMask.Copy >> 13);
1013 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1014 mask &= ~((uint)PermissionMask.Transfer >> 13);
1015 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1016 mask &= ~((uint)PermissionMask.Modify >> 13);
1017 }
1018 else
1019 {
1020 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1021 mask &= ~((uint)PermissionMask.Copy >> 13);
1022 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1023 mask &= ~((uint)PermissionMask.Transfer >> 13);
1024 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1025 mask &= ~((uint)PermissionMask.Modify >> 13);
1026 }
1027
1028 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1029 mask &= ~(uint)PermissionMask.Copy;
1030 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1031 mask &= ~(uint)PermissionMask.Transfer;
1032 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1033 mask &= ~(uint)PermissionMask.Modify;
1034 } 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;
1035 } 1240 }
1036
1037 return mask; 1241 return mask;
1038 } 1242 }
1039 1243
1040 public void ApplyNextOwnerPermissions() 1244 public void ApplyNextOwnerPermissions()
1041 { 1245 {
1042 lock (m_items) 1246 foreach (TaskInventoryItem item in m_items.Values)
1043 { 1247 {
1044 foreach (TaskInventoryItem item in m_items.Values) 1248 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1045 { 1249 {
1046// m_log.DebugFormat ( 1250 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1047// "[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;
1048// item.NextPermissions, item.Name, m_part.Name, item.CurrentPermissions, item.BasePermissions, item.EveryonePermissions); 1252 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1049 1253 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1050 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1254 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1051 { 1255 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1052 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1053 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1054 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1055 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1056 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1057 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1058 }
1059
1060 item.CurrentPermissions &= item.NextPermissions;
1061 item.BasePermissions &= item.NextPermissions;
1062 item.EveryonePermissions &= item.NextPermissions;
1063 item.OwnerChanged = true;
1064 item.PermsMask = 0;
1065 item.PermsGranter = UUID.Zero;
1066 } 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;
1067 } 1263 }
1068 } 1264 }
1069 1265
1070 public void ApplyGodPermissions(uint perms) 1266 public void ApplyGodPermissions(uint perms)
1071 { 1267 {
1072 lock (m_items) 1268 foreach (TaskInventoryItem item in m_items.Values)
1073 { 1269 {
1074 foreach (TaskInventoryItem item in m_items.Values) 1270 item.CurrentPermissions = perms;
1075 { 1271 item.BasePermissions = perms;
1076 item.CurrentPermissions = perms;
1077 item.BasePermissions = perms;
1078 }
1079 } 1272 }
1080 1273
1081 m_inventorySerial++; 1274 m_inventorySerial++;
@@ -1088,14 +1281,11 @@ namespace OpenSim.Region.Framework.Scenes
1088 /// <returns></returns> 1281 /// <returns></returns>
1089 public bool ContainsScripts() 1282 public bool ContainsScripts()
1090 { 1283 {
1091 lock (m_items) 1284 foreach (TaskInventoryItem item in m_items.Values)
1092 { 1285 {
1093 foreach (TaskInventoryItem item in m_items.Values) 1286 if (item.InvType == (int)InventoryType.LSL)
1094 { 1287 {
1095 if (item.InvType == (int)InventoryType.LSL) 1288 return true;
1096 {
1097 return true;
1098 }
1099 } 1289 }
1100 } 1290 }
1101 1291
@@ -1109,17 +1299,15 @@ namespace OpenSim.Region.Framework.Scenes
1109 public int ScriptCount() 1299 public int ScriptCount()
1110 { 1300 {
1111 int count = 0; 1301 int count = 0;
1112 lock (m_items) 1302 Items.LockItemsForRead(true);
1303 foreach (TaskInventoryItem item in m_items.Values)
1113 { 1304 {
1114 foreach (TaskInventoryItem item in m_items.Values) 1305 if (item.InvType == (int)InventoryType.LSL)
1115 { 1306 {
1116 if (item.InvType == (int)InventoryType.LSL) 1307 count++;
1117 {
1118 count++;
1119 }
1120 } 1308 }
1121 } 1309 }
1122 1310 Items.LockItemsForRead(false);
1123 return count; 1311 return count;
1124 } 1312 }
1125 /// <summary> 1313 /// <summary>
@@ -1155,11 +1343,8 @@ namespace OpenSim.Region.Framework.Scenes
1155 { 1343 {
1156 List<UUID> ret = new List<UUID>(); 1344 List<UUID> ret = new List<UUID>();
1157 1345
1158 lock (m_items) 1346 foreach (TaskInventoryItem item in m_items.Values)
1159 { 1347 ret.Add(item.ItemID);
1160 foreach (TaskInventoryItem item in m_items.Values)
1161 ret.Add(item.ItemID);
1162 }
1163 1348
1164 return ret; 1349 return ret;
1165 } 1350 }
@@ -1168,8 +1353,9 @@ namespace OpenSim.Region.Framework.Scenes
1168 { 1353 {
1169 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1354 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1170 1355
1171 lock (m_items) 1356 Items.LockItemsForRead(true);
1172 ret = new List<TaskInventoryItem>(m_items.Values); 1357 ret = new List<TaskInventoryItem>(m_items.Values);
1358 Items.LockItemsForRead(false);
1173 1359
1174 return ret; 1360 return ret;
1175 } 1361 }
@@ -1178,18 +1364,24 @@ namespace OpenSim.Region.Framework.Scenes
1178 { 1364 {
1179 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1365 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1180 1366
1181 lock (m_items) 1367 Items.LockItemsForRead(true);
1182 { 1368
1183 foreach (TaskInventoryItem item in m_items.Values) 1369 foreach (TaskInventoryItem item in m_items.Values)
1184 if (item.InvType == (int)type) 1370 if (item.InvType == (int)type)
1185 ret.Add(item); 1371 ret.Add(item);
1186 } 1372
1373 Items.LockItemsForRead(false);
1187 1374
1188 return ret; 1375 return ret;
1189 } 1376 }
1190 1377
1191 public Dictionary<UUID, string> GetScriptStates() 1378 public Dictionary<UUID, string> GetScriptStates()
1192 { 1379 {
1380 return GetScriptStates(false);
1381 }
1382
1383 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1384 {
1193 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1385 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1194 1386
1195 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1387 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1211,14 +1403,21 @@ namespace OpenSim.Region.Framework.Scenes
1211 string n = e.GetXMLState(item.ItemID); 1403 string n = e.GetXMLState(item.ItemID);
1212 if (n != String.Empty) 1404 if (n != String.Empty)
1213 { 1405 {
1214 if (!ret.ContainsKey(item.ItemID)) 1406 if (oldIDs)
1215 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 }
1216 break; 1416 break;
1217 } 1417 }
1218 } 1418 }
1219 } 1419 }
1220 } 1420 }
1221
1222 return ret; 1421 return ret;
1223 } 1422 }
1224 1423
@@ -1251,4 +1450,4 @@ namespace OpenSim.Region.Framework.Scenes
1251 } 1450 }
1252 } 1451 }
1253 } 1452 }
1254} \ No newline at end of file 1453}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 909c7c8..f3e8377 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 // Attachment objects 3282 // Attachment objects
3088 List<SceneObjectGroup> attachments = GetAttachments(); 3283 List<SceneObjectGroup> attachments = GetAttachments();
@@ -3126,6 +3321,8 @@ namespace OpenSim.Region.Framework.Scenes
3126 CameraAtAxis = cAgent.AtAxis; 3321 CameraAtAxis = cAgent.AtAxis;
3127 CameraLeftAxis = cAgent.LeftAxis; 3322 CameraLeftAxis = cAgent.LeftAxis;
3128 CameraUpAxis = cAgent.UpAxis; 3323 CameraUpAxis = cAgent.UpAxis;
3324 ParentUUID = cAgent.ParentPart;
3325 m_prevSitOffset = cAgent.SitOffset;
3129 3326
3130 // When we get to the point of re-computing neighbors everytime this 3327 // When we get to the point of re-computing neighbors everytime this
3131 // changes, then start using the agent's drawdistance rather than the 3328 // changes, then start using the agent's drawdistance rather than the
@@ -3163,6 +3360,7 @@ namespace OpenSim.Region.Framework.Scenes
3163 foreach (ControllerData c in cAgent.Controllers) 3360 foreach (ControllerData c in cAgent.Controllers)
3164 { 3361 {
3165 ScriptControllers sc = new ScriptControllers(); 3362 ScriptControllers sc = new ScriptControllers();
3363 sc.objectID = c.ObjectID;
3166 sc.itemID = c.ItemID; 3364 sc.itemID = c.ItemID;
3167 sc.ignoreControls = (ScriptControlled)c.IgnoreControls; 3365 sc.ignoreControls = (ScriptControlled)c.IgnoreControls;
3168 sc.eventControls = (ScriptControlled)c.EventControls; 3366 sc.eventControls = (ScriptControlled)c.EventControls;
@@ -3177,6 +3375,8 @@ namespace OpenSim.Region.Framework.Scenes
3177 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? 3375 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object?
3178 if (cAgent.Anims != null) 3376 if (cAgent.Anims != null)
3179 Animator.Animations.FromArray(cAgent.Anims); 3377 Animator.Animations.FromArray(cAgent.Anims);
3378 if (cAgent.DefaultAnim != null)
3379 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
3180 3380
3181 if (cAgent.AttachmentObjects != null && cAgent.AttachmentObjects.Count > 0) 3381 if (cAgent.AttachmentObjects != null && cAgent.AttachmentObjects.Count > 0)
3182 { 3382 {
@@ -3249,7 +3449,7 @@ namespace OpenSim.Region.Framework.Scenes
3249 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3449 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3250 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3450 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
3251 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong 3451 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
3252 PhysicsActor.SubscribeEvents(500); 3452 PhysicsActor.SubscribeEvents(100);
3253 PhysicsActor.LocalID = LocalId; 3453 PhysicsActor.LocalID = LocalId;
3254 } 3454 }
3255 3455
@@ -3279,18 +3479,6 @@ namespace OpenSim.Region.Framework.Scenes
3279 if (IsChildAgent) 3479 if (IsChildAgent)
3280 return; 3480 return;
3281 3481
3282 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
3283 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
3284 // as of this comment the interval is set in AddToPhysicalScene
3285 if (Animator != null)
3286 {
3287// if (m_updateCount > 0)
3288// {
3289 Animator.UpdateMovementAnimations();
3290// m_updateCount--;
3291// }
3292 }
3293
3294 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3482 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3295 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3483 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3296 3484
@@ -3333,6 +3521,8 @@ namespace OpenSim.Region.Framework.Scenes
3333 } 3521 }
3334 } 3522 }
3335 3523
3524 RaiseCollisionScriptEvents(coldata);
3525
3336 // Gods do not take damage and Invulnerable is set depending on parcel/region flags 3526 // Gods do not take damage and Invulnerable is set depending on parcel/region flags
3337 if (Invulnerable || GodLevel > 0) 3527 if (Invulnerable || GodLevel > 0)
3338 return; 3528 return;
@@ -3662,10 +3852,15 @@ namespace OpenSim.Region.Framework.Scenes
3662 3852
3663 public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID) 3853 public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID)
3664 { 3854 {
3855 SceneObjectPart p = m_scene.GetSceneObjectPart(Obj_localID);
3856 if (p == null)
3857 return;
3858
3665 ScriptControllers obj = new ScriptControllers(); 3859 ScriptControllers obj = new ScriptControllers();
3666 obj.ignoreControls = ScriptControlled.CONTROL_ZERO; 3860 obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
3667 obj.eventControls = ScriptControlled.CONTROL_ZERO; 3861 obj.eventControls = ScriptControlled.CONTROL_ZERO;
3668 3862
3863 obj.objectID = p.ParentGroup.UUID;
3669 obj.itemID = Script_item_UUID; 3864 obj.itemID = Script_item_UUID;
3670 if (pass_on == 0 && accept == 0) 3865 if (pass_on == 0 && accept == 0)
3671 { 3866 {
@@ -3714,6 +3909,21 @@ namespace OpenSim.Region.Framework.Scenes
3714 ControllingClient.SendTakeControls(int.MaxValue, false, false); 3909 ControllingClient.SendTakeControls(int.MaxValue, false, false);
3715 } 3910 }
3716 3911
3912 private void UnRegisterSeatControls(UUID obj)
3913 {
3914 List<UUID> takers = new List<UUID>();
3915
3916 foreach (ScriptControllers c in scriptedcontrols.Values)
3917 {
3918 if (c.objectID == obj)
3919 takers.Add(c.itemID);
3920 }
3921 foreach (UUID t in takers)
3922 {
3923 UnRegisterControlEventsToScript(0, t);
3924 }
3925 }
3926
3717 public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) 3927 public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID)
3718 { 3928 {
3719 ScriptControllers takecontrols; 3929 ScriptControllers takecontrols;
@@ -4032,6 +4242,12 @@ namespace OpenSim.Region.Framework.Scenes
4032 4242
4033 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 4243 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
4034 { 4244 {
4245 string reason;
4246
4247 // Honor bans
4248 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
4249 return;
4250
4035 SceneObjectGroup telehub = null; 4251 SceneObjectGroup telehub = null;
4036 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 4252 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
4037 { 4253 {
@@ -4071,11 +4287,206 @@ namespace OpenSim.Region.Framework.Scenes
4071 pos = land.LandData.UserLocation; 4287 pos = land.LandData.UserLocation;
4072 } 4288 }
4073 } 4289 }
4074 4290
4075 land.SendLandUpdateToClient(ControllingClient); 4291 land.SendLandUpdateToClient(ControllingClient);
4076 } 4292 }
4077 } 4293 }
4078 4294
4295 private DetectedObject CreateDetObject(SceneObjectPart obj)
4296 {
4297 DetectedObject detobj = new DetectedObject();
4298 detobj.keyUUID = obj.UUID;
4299 detobj.nameStr = obj.Name;
4300 detobj.ownerUUID = obj.OwnerID;
4301 detobj.posVector = obj.AbsolutePosition;
4302 detobj.rotQuat = obj.GetWorldRotation();
4303 detobj.velVector = obj.Velocity;
4304 detobj.colliderType = 0;
4305 detobj.groupUUID = obj.GroupID;
4306
4307 return detobj;
4308 }
4309
4310 private DetectedObject CreateDetObject(ScenePresence av)
4311 {
4312 DetectedObject detobj = new DetectedObject();
4313 detobj.keyUUID = av.UUID;
4314 detobj.nameStr = av.ControllingClient.Name;
4315 detobj.ownerUUID = av.UUID;
4316 detobj.posVector = av.AbsolutePosition;
4317 detobj.rotQuat = av.Rotation;
4318 detobj.velVector = av.Velocity;
4319 detobj.colliderType = 0;
4320 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
4321
4322 return detobj;
4323 }
4324
4325 private DetectedObject CreateDetObjectForGround()
4326 {
4327 DetectedObject detobj = new DetectedObject();
4328 detobj.keyUUID = UUID.Zero;
4329 detobj.nameStr = "";
4330 detobj.ownerUUID = UUID.Zero;
4331 detobj.posVector = AbsolutePosition;
4332 detobj.rotQuat = Quaternion.Identity;
4333 detobj.velVector = Vector3.Zero;
4334 detobj.colliderType = 0;
4335 detobj.groupUUID = UUID.Zero;
4336
4337 return detobj;
4338 }
4339
4340 private ColliderArgs CreateColliderArgs(SceneObjectPart dest, List<uint> colliders)
4341 {
4342 ColliderArgs colliderArgs = new ColliderArgs();
4343 List<DetectedObject> colliding = new List<DetectedObject>();
4344 foreach (uint localId in colliders)
4345 {
4346 if (localId == 0)
4347 continue;
4348
4349 SceneObjectPart obj = m_scene.GetSceneObjectPart(localId);
4350 if (obj != null)
4351 {
4352 if (!dest.CollisionFilteredOut(obj.UUID, obj.Name))
4353 colliding.Add(CreateDetObject(obj));
4354 }
4355 else
4356 {
4357 ScenePresence av = m_scene.GetScenePresence(localId);
4358 if (av != null && (!av.IsChildAgent))
4359 {
4360 if (!dest.CollisionFilteredOut(av.UUID, av.Name))
4361 colliding.Add(CreateDetObject(av));
4362 }
4363 }
4364 }
4365
4366 colliderArgs.Colliders = colliding;
4367
4368 return colliderArgs;
4369 }
4370
4371 private delegate void ScriptCollidingNotification(uint localID, ColliderArgs message);
4372
4373 private void SendCollisionEvent(SceneObjectGroup dest, scriptEvents ev, List<uint> colliders, ScriptCollidingNotification notify)
4374 {
4375 ColliderArgs CollidingMessage;
4376
4377 if (colliders.Count > 0)
4378 {
4379 if ((dest.RootPart.ScriptEvents & ev) != 0)
4380 {
4381 CollidingMessage = CreateColliderArgs(dest.RootPart, colliders);
4382
4383 if (CollidingMessage.Colliders.Count > 0)
4384 notify(dest.RootPart.LocalId, CollidingMessage);
4385 }
4386 }
4387 }
4388
4389 private void SendLandCollisionEvent(SceneObjectGroup dest, scriptEvents ev, ScriptCollidingNotification notify)
4390 {
4391 if ((dest.RootPart.ScriptEvents & ev) != 0)
4392 {
4393 ColliderArgs LandCollidingMessage = new ColliderArgs();
4394 List<DetectedObject> colliding = new List<DetectedObject>();
4395
4396 colliding.Add(CreateDetObjectForGround());
4397 LandCollidingMessage.Colliders = colliding;
4398
4399 notify(dest.RootPart.LocalId, LandCollidingMessage);
4400 }
4401 }
4402
4403 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
4404 {
4405 try
4406 {
4407 List<uint> thisHitColliders = new List<uint>();
4408 List<uint> endedColliders = new List<uint>();
4409 List<uint> startedColliders = new List<uint>();
4410 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
4411 CollisionForSoundInfo soundinfo;
4412 ContactPoint curcontact;
4413
4414 if (coldata.Count == 0)
4415 {
4416 if (m_lastColliders.Count == 0)
4417 return; // nothing to do
4418
4419 foreach (uint localID in m_lastColliders)
4420 {
4421 endedColliders.Add(localID);
4422 }
4423 m_lastColliders.Clear();
4424 }
4425
4426 else
4427 {
4428 foreach (uint id in coldata.Keys)
4429 {
4430 thisHitColliders.Add(id);
4431 if (!m_lastColliders.Contains(id))
4432 {
4433 startedColliders.Add(id);
4434 curcontact = coldata[id];
4435 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
4436 {
4437 soundinfo = new CollisionForSoundInfo();
4438 soundinfo.colliderID = id;
4439 soundinfo.position = curcontact.Position;
4440 soundinfo.relativeVel = curcontact.RelativeSpeed;
4441 soundinfolist.Add(soundinfo);
4442 }
4443 }
4444 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
4445 }
4446
4447 // calculate things that ended colliding
4448 foreach (uint localID in m_lastColliders)
4449 {
4450 if (!thisHitColliders.Contains(localID))
4451 {
4452 endedColliders.Add(localID);
4453 }
4454 }
4455 //add the items that started colliding this time to the last colliders list.
4456 foreach (uint localID in startedColliders)
4457 {
4458 m_lastColliders.Add(localID);
4459 }
4460 // remove things that ended colliding from the last colliders list
4461 foreach (uint localID in endedColliders)
4462 {
4463 m_lastColliders.Remove(localID);
4464 }
4465
4466 if (soundinfolist.Count > 0)
4467 CollisionSounds.AvatarCollisionSound(this, soundinfolist);
4468 }
4469
4470 foreach (SceneObjectGroup att in GetAttachments())
4471 {
4472 SendCollisionEvent(att, scriptEvents.collision_start, startedColliders, m_scene.EventManager.TriggerScriptCollidingStart);
4473 SendCollisionEvent(att, scriptEvents.collision , m_lastColliders , m_scene.EventManager.TriggerScriptColliding);
4474 SendCollisionEvent(att, scriptEvents.collision_end , endedColliders , m_scene.EventManager.TriggerScriptCollidingEnd);
4475
4476 if (startedColliders.Contains(0))
4477 SendLandCollisionEvent(att, scriptEvents.land_collision_start, m_scene.EventManager.TriggerScriptLandCollidingStart);
4478 if (m_lastColliders.Contains(0))
4479 SendLandCollisionEvent(att, scriptEvents.land_collision, m_scene.EventManager.TriggerScriptLandColliding);
4480 if (endedColliders.Contains(0))
4481 SendLandCollisionEvent(att, scriptEvents.land_collision_end, m_scene.EventManager.TriggerScriptLandCollidingEnd);
4482 }
4483 }
4484 finally
4485 {
4486 m_collisionEventFlag = false;
4487 }
4488 }
4489
4079 private void TeleportFlagsDebug() { 4490 private void TeleportFlagsDebug() {
4080 4491
4081 // Some temporary debugging help to show all the TeleportFlags we have... 4492 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -4100,6 +4511,5 @@ namespace OpenSim.Region.Framework.Scenes
4100 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 4511 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
4101 4512
4102 } 4513 }
4103
4104 } 4514 }
4105} 4515}
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;