aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/Environment/Scenes/SceneObjectPart.cs3785
1 files changed, 1866 insertions, 1919 deletions
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
index af535cc..d7aa962 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
@@ -1,3 +1,5 @@
1#region Header
2
1/* 3/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 4 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 5 * See CONTRIBUTORS.TXT for a full list of copyright holders.
@@ -25,6 +27,8 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 28 */
27 29
30#endregion Header
31
28using System; 32using System;
29using System.Collections.Generic; 33using System.Collections.Generic;
30using System.Drawing; 34using System.Drawing;
@@ -32,15 +36,33 @@ using System.Runtime.Serialization;
32using System.Security.Permissions; 36using System.Security.Permissions;
33using System.Xml; 37using System.Xml;
34using System.Xml.Serialization; 38using System.Xml.Serialization;
39
35using Axiom.Math; 40using Axiom.Math;
41
36using libsecondlife; 42using libsecondlife;
37using libsecondlife.Packets; 43using libsecondlife.Packets;
44
38using OpenSim.Framework; 45using OpenSim.Framework;
39using OpenSim.Region.Environment.Scenes.Scripting; 46using OpenSim.Region.Environment.Scenes.Scripting;
40using OpenSim.Region.Physics.Manager; 47using OpenSim.Region.Physics.Manager;
41 48
42namespace OpenSim.Region.Environment.Scenes 49namespace OpenSim.Region.Environment.Scenes
43{ 50{
51 #region Enumerations
52
53 [Flags]
54 public enum Changed : uint
55 {
56 INVENTORY = 1,
57 COLOR = 2,
58 SHAPE = 4,
59 SCALE = 8,
60 TEXTURE = 16,
61 LINK = 32,
62 ALLOWED_DROP = 64,
63 OWNER = 128
64 }
65
44 // I don't really know where to put this except here. 66 // I don't really know where to put this except here.
45 // Can't access the OpenSim.Region.ScriptEngine.Common.LSL_BaseClass.Changed constants 67 // Can't access the OpenSim.Region.ScriptEngine.Common.LSL_BaseClass.Changed constants
46 [Flags] 68 [Flags]
@@ -56,18 +78,7 @@ namespace OpenSim.Region.Environment.Scenes
56 Something5 = 64, 78 Something5 = 64,
57 Something6 = 128 79 Something6 = 128
58 } 80 }
59 [Flags] 81
60 public enum Changed : uint
61 {
62 INVENTORY = 1,
63 COLOR = 2,
64 SHAPE = 4,
65 SCALE = 8,
66 TEXTURE = 16,
67 LINK = 32,
68 ALLOWED_DROP = 64,
69 OWNER = 128
70 }
71 [Flags] 82 [Flags]
72 public enum TextureAnimFlags : byte 83 public enum TextureAnimFlags : byte
73 { 84 {
@@ -81,74 +92,96 @@ namespace OpenSim.Region.Environment.Scenes
81 SCALE = 0x40 92 SCALE = 0x40
82 } 93 }
83 94
95 #endregion Enumerations
84 96
85 [Serializable] 97 [Serializable]
86 public partial class SceneObjectPart : IScriptHost, ISerializable 98 public partial class SceneObjectPart : IScriptHost, ISerializable
87 { 99 {
88 [XmlIgnore] public PhysicsActor PhysActor = null; 100 #region Fields
89 101
102 [XmlIgnore]
103 public bool AllowedDrop = false;
104 public uint BaseMask = (uint)PermissionMask.All;
105 public uint Category;
106 public Int32 CreationDate;
107 public LLUUID CreatorID;
108 [XmlIgnore]
109 public bool DIE_AT_EDGE = false;
110 public uint EveryoneMask = (uint)PermissionMask.None;
111 public LLObject.ObjectFlags Flags = LLObject.ObjectFlags.None;
112 public LLUUID GroupID;
113 public uint GroupMask = (uint)PermissionMask.None;
90 public LLUUID LastOwnerID; 114 public LLUUID LastOwnerID;
115 public uint NextOwnerMask = (uint)PermissionMask.All;
116 public byte ObjectSaleType;
91 public LLUUID OwnerID; 117 public LLUUID OwnerID;
92 public LLUUID GroupID; 118 public uint OwnerMask = (uint)PermissionMask.All;
93 public int OwnershipCost; 119 public int OwnershipCost;
94 public byte ObjectSaleType; 120 public uint ParentID = 0;
95 public int SalePrice;
96 public uint Category;
97 121
98 // TODO: This needs to be persisted in next XML version update! 122 // TODO: This needs to be persisted in next XML version update!
99 [XmlIgnore] public int[] PayPrice = {-2,-2,-2,-2,-2}; 123 [XmlIgnore]
100 [XmlIgnore] public bool AllowedDrop = false; 124 public int[] PayPrice = {-2,-2,-2,-2,-2};
101 [XmlIgnore] private Dictionary<LLUUID, scriptEvents> m_scriptEvents = new Dictionary<LLUUID, scriptEvents>(); 125 [XmlIgnore]
102 [XmlIgnore] public scriptEvents m_aggregateScriptEvents=0; 126 public PhysicsActor PhysActor = null;
103 [XmlIgnore] private LLObject.ObjectFlags LocalFlags = LLObject.ObjectFlags.None; 127 public int SalePrice;
104 [XmlIgnore] public bool DIE_AT_EDGE = false;
105 [XmlIgnore] private int m_scriptAccessPin = 0;
106
107 [XmlIgnore] public bool m_IsAttachment = false;
108 [XmlIgnore] public uint m_attachmentPoint = (byte)0;
109 [XmlIgnore] public LLUUID m_attachedAvatar = LLUUID.Zero;
110 [XmlIgnore] public LLVector3 m_attachedPos = LLVector3.Zero;
111 [XmlIgnore] public LLUUID fromAssetID = LLUUID.Zero;
112
113 [XmlIgnore] public bool m_undoing = false;
114 128
115 public Int32 CreationDate; 129 //Xantor 20080528 Sound stuff:
116 public uint ParentID = 0; 130 // Note: This isn't persisted in the database right now, as the fields for that aren't just there yet.
131 // Not a big problem as long as the script that sets it remains in the prim on startup.
132 // for SL compatibility it should be persisted though (set sound / displaytext / particlesystem, kill script)
133 [XmlIgnore]
134 public LLUUID Sound;
135 [XmlIgnore]
136 public byte SoundFlags;
137 [XmlIgnore]
138 public double SoundGain;
139 [XmlIgnore]
140 public double SoundRadius;
141 [XmlIgnore]
142 public uint TimeStampFull = 0;
143 [XmlIgnore]
144 public uint TimeStampLastActivity = 0; // Will be used for AutoReturn
145 [XmlIgnore]
146 public uint TimeStampTerse = 0;
147 [XmlIgnore]
148 public LLUUID fromAssetID = LLUUID.Zero;
149 [XmlIgnore]
150 public bool m_IsAttachment = false;
151 [XmlIgnore]
152 public scriptEvents m_aggregateScriptEvents = 0;
153 [XmlIgnore]
154 public LLUUID m_attachedAvatar = LLUUID.Zero;
155 [XmlIgnore]
156 public LLVector3 m_attachedPos = LLVector3.Zero;
157 [XmlIgnore]
158 public uint m_attachmentPoint = (byte)0;
159 [XmlIgnore]
160 public PhysicsVector m_rotationAxis = new PhysicsVector(1f,1f,1f);
161 public LLUUID m_sitTargetAvatar = LLUUID.Zero;
162 [XmlIgnore]
163 public bool m_undoing = false;
117 164
165 [XmlIgnore]
166 private LLObject.ObjectFlags LocalFlags = LLObject.ObjectFlags.None;
167 private byte[] m_TextureAnimation;
168 private byte m_clickAction = 0;
169 private Color m_color = Color.Black;
170 private string m_description = String.Empty;
118 private List<uint> m_lastColliders = new List<uint>(); 171 private List<uint> m_lastColliders = new List<uint>();
119
120 private PhysicsVector m_lastRotationalVelocity = PhysicsVector.Zero; 172 private PhysicsVector m_lastRotationalVelocity = PhysicsVector.Zero;
121 private Vector3 m_sitTargetPosition = new Vector3(0, 0, 0); 173 private int m_linkNum = 0;
174 [XmlIgnore]
175 private int m_scriptAccessPin = 0;
176 [XmlIgnore]
177 private Dictionary<LLUUID, scriptEvents> m_scriptEvents = new Dictionary<LLUUID, scriptEvents>();
178 private string m_sitName = String.Empty;
122 private Quaternion m_sitTargetOrientation = new Quaternion(0, 0, 0, 1); 179 private Quaternion m_sitTargetOrientation = new Quaternion(0, 0, 0, 1);
123 public LLUUID m_sitTargetAvatar = LLUUID.Zero; 180 private Vector3 m_sitTargetPosition = new Vector3(0, 0, 0);
124 [XmlIgnore] public PhysicsVector m_rotationAxis = new PhysicsVector(1f,1f,1f); 181 private string m_text = String.Empty;
125 182 private string m_touchName = String.Empty;
126 #region Permissions
127
128 public uint BaseMask = (uint)PermissionMask.All;
129 public uint OwnerMask = (uint)PermissionMask.All;
130 public uint GroupMask = (uint)PermissionMask.None;
131 public uint EveryoneMask = (uint)PermissionMask.None;
132 public uint NextOwnerMask = (uint)PermissionMask.All;
133
134 private UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 183 private UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
135 184
136 public LLObject.ObjectFlags Flags = LLObject.ObjectFlags.None;
137
138 public uint ObjectFlags
139 {
140 get { return (uint)Flags; }
141 set { Flags = (LLObject.ObjectFlags)value; }
142 }
143
144 #endregion
145
146 protected byte[] m_particleSystem = new byte[0];
147
148 [XmlIgnore] public uint TimeStampFull = 0;
149 [XmlIgnore] public uint TimeStampTerse = 0;
150 [XmlIgnore] public uint TimeStampLastActivity = 0; // Will be used for AutoReturn
151
152 /// <summary> 185 /// <summary>
153 /// Only used internally to schedule client updates. 186 /// Only used internally to schedule client updates.
154 /// 0 - no update is scheduled 187 /// 0 - no update is scheduled
@@ -159,174 +192,213 @@ namespace OpenSim.Region.Environment.Scenes
159 /// </summary> 192 /// </summary>
160 private byte m_updateFlag; 193 private byte m_updateFlag;
161 194
162 #region Properties 195 protected LLVector3 m_acceleration;
163 196 protected LLVector3 m_angularVelocity;
164 public LLUUID CreatorID;
165 197
166 public LLUUID ObjectCreator 198 //unkown if this will be kept, added as a way of removing the group position from the group class
167 { 199 protected LLVector3 m_groupPosition;
168 get { return CreatorID; } 200 protected uint m_localId;
169 } 201 protected LLObject.MaterialType m_material = 0;
202 protected string m_name;
203 protected LLVector3 m_offsetPosition;
170 204
205 // FIXME, TODO, ERROR: 'ParentGroup' can't be in here, move it out.
206 protected SceneObjectGroup m_parentGroup;
207 protected byte[] m_particleSystem = new byte[0];
208 protected ulong m_regionHandle;
209 protected LLQuaternion m_rotationOffset;
210 protected LLVector3 m_rotationalvelocity;
211 protected PrimitiveBaseShape m_shape;
171 protected LLUUID m_uuid; 212 protected LLUUID m_uuid;
213 protected LLVector3 m_velocity;
172 214
173 public LLUUID UUID 215 #endregion Fields
174 {
175 get { return m_uuid; }
176 set { m_uuid = value; }
177 }
178 216
179 protected uint m_localId; 217 #region Constructors
180 218
181 public uint LocalId 219 /// <summary>
220 /// No arg constructor called by region restore db code
221 /// </summary>
222 public SceneObjectPart()
182 { 223 {
183 get { return m_localId; } 224 // It's not necessary to persist this
184 set { m_localId = value; } 225 m_TextureAnimation = new byte[0];
185 } 226 }
186 227
187 protected string m_name; 228 public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, LLUUID ownerID, uint localID,
188 229 PrimitiveBaseShape shape, LLVector3 groupPosition, LLVector3 offsetPosition)
189 public virtual string Name 230 : this(regionHandle, parent, ownerID, localID, shape, groupPosition, LLQuaternion.Identity, offsetPosition)
190 { 231 {
191 get { return m_name; }
192 set { m_name = value; }
193 } 232 }
194 233
195 public scriptEvents ScriptEvents 234 /// <summary>
235 /// Create a completely new SceneObjectPart (prim)
236 /// </summary>
237 /// <param name="regionHandle"></param>
238 /// <param name="parent"></param>
239 /// <param name="ownerID"></param>
240 /// <param name="localID"></param>
241 /// <param name="shape"></param>
242 /// <param name="position"></param>
243 public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, LLUUID ownerID, uint localID,
244 PrimitiveBaseShape shape, LLVector3 groupPosition, LLQuaternion rotationOffset,
245 LLVector3 offsetPosition)
196 { 246 {
197 get { return m_aggregateScriptEvents; } 247 m_name = "Primitive";
198 } 248 m_regionHandle = regionHandle;
199 249 m_parentGroup = parent;
200 protected LLObject.MaterialType m_material = 0;
201 250
202 public byte Material 251 CreationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds;
203 { 252 OwnerID = ownerID;
204 get { return (byte) m_material; } 253 CreatorID = OwnerID;
205 set { m_material = (LLObject.MaterialType) value; } 254 LastOwnerID = LLUUID.Zero;
206 } 255 UUID = LLUUID.Random();
256 LocalId = (uint) (localID);
257 Shape = shape;
258 // Todo: Add More Object Parameter from above!
259 OwnershipCost = 0;
260 ObjectSaleType = (byte) 0;
261 SalePrice = 0;
262 Category = (uint) 0;
263 LastOwnerID = CreatorID;
264 // End Todo: ///
265 GroupPosition = groupPosition;
266 OffsetPosition = offsetPosition;
267 RotationOffset = rotationOffset;
268 Velocity = new LLVector3(0, 0, 0);
269 m_rotationalvelocity = new LLVector3(0, 0, 0);
270 AngularVelocity = new LLVector3(0, 0, 0);
271 Acceleration = new LLVector3(0, 0, 0);
272 m_TextureAnimation = new byte[0];
207 273
208 protected ulong m_regionHandle; 274 // Prims currently only contain a single folder (Contents). From looking at the Second Life protocol,
275 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
276 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
209 277
210 public ulong RegionHandle 278 Flags = 0;
211 { 279 Flags |= LLObject.ObjectFlags.CreateSelected;
212 get { return m_regionHandle; }
213 set { m_regionHandle = value; }
214 }
215
216 public int ScriptAccessPin
217 {
218 get { return m_scriptAccessPin; }
219 set { m_scriptAccessPin = (int)value; }
220 }
221 280
222 public uint GetEffectiveObjectFlags() 281 TrimPermissions();
223 { 282 //m_undo = new UndoStack<UndoState>(ParentGroup.GetSceneMaxUndo());
224 LLObject.ObjectFlags f = Flags;
225 if (m_parentGroup == null || m_parentGroup.RootPart == this)
226 f &= ~(LLObject.ObjectFlags.Touch | LLObject.ObjectFlags.Money);
227 283
228 return (uint)Flags | (uint)LocalFlags; 284 ScheduleFullUpdate();
229 } 285 }
230 286
231 //unkown if this will be kept, added as a way of removing the group position from the group class
232 protected LLVector3 m_groupPosition;
233
234 /// <summary> 287 /// <summary>
235 /// Method for a prim to get it's world position from the group. 288 /// Re/create a SceneObjectPart (prim)
236 /// Remember, the Group Position simply gives the position of the group itself 289 /// currently not used, and maybe won't be
237 /// </summary> 290 /// </summary>
238 /// <returns>A Linked Child Prim objects position in world</returns> 291 /// <param name="regionHandle"></param>
239 public LLVector3 GetWorldPosition() 292 /// <param name="parent"></param>
293 /// <param name="ownerID"></param>
294 /// <param name="localID"></param>
295 /// <param name="shape"></param>
296 /// <param name="position"></param>
297 public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, int creationDate, LLUUID ownerID,
298 LLUUID creatorID, LLUUID lastOwnerID, uint localID, PrimitiveBaseShape shape,
299 LLVector3 position, LLQuaternion rotation, uint flags)
240 { 300 {
301 m_regionHandle = regionHandle;
302 m_parentGroup = parent;
303 TimeStampTerse = (uint) Util.UnixTimeSinceEpoch();
304 CreationDate = creationDate;
305 OwnerID = ownerID;
306 CreatorID = creatorID;
307 LastOwnerID = lastOwnerID;
308 UUID = LLUUID.Random();
309 LocalId = (uint) (localID);
310 Shape = shape;
311 OwnershipCost = 0;
312 ObjectSaleType = (byte) 0;
313 SalePrice = 0;
314 Category = (uint) 0;
315 LastOwnerID = CreatorID;
316 OffsetPosition = position;
317 RotationOffset = rotation;
318 ObjectFlags = flags;
241 319
242 Quaternion parentRot = new Quaternion( 320 // Since we don't store script state, this is only a 'temporary' objectflag now
243 ParentGroup.RootPart.RotationOffset.W, 321 // If the object is scripted, the script will get loaded and this will be set again
244 ParentGroup.RootPart.RotationOffset.X, 322 ObjectFlags &= ~(uint)(LLObject.ObjectFlags.Scripted | LLObject.ObjectFlags.Touch);
245 ParentGroup.RootPart.RotationOffset.Y,
246 ParentGroup.RootPart.RotationOffset.Z);
247
248 Vector3 axPos
249 = new Vector3(
250 OffsetPosition.X,
251 OffsetPosition.Y,
252 OffsetPosition.Z);
253 323
254 axPos = parentRot * axPos; 324 TrimPermissions();
255 LLVector3 translationOffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z); 325 // ApplyPhysics();
256 return GroupPosition + translationOffsetPosition;
257 326
258 //return (new LLVector3(axiomPos.x, axiomPos.y, axiomPos.z) + AbsolutePosition); 327 ScheduleFullUpdate();
259 } 328 }
260 329
261 /// <summary> 330 protected SceneObjectPart(SerializationInfo info, StreamingContext context)
262 /// Gets the rotation of this prim offset by the group rotation
263 /// </summary>
264 /// <returns></returns>
265 public LLQuaternion GetWorldRotation()
266 { 331 {
332 //System.Console.WriteLine("SceneObjectPart Deserialize BGN");
267 333
268 Quaternion newRot; 334 if (info == null)
269
270 if (this.LinkNum == 0)
271 { 335 {
272 newRot = new Quaternion(RotationOffset.W,RotationOffset.X,RotationOffset.Y,RotationOffset.Z); 336 throw new ArgumentNullException("info");
273
274 } 337 }
275 else
276 {
277 Quaternion parentRot = new Quaternion(
278 ParentGroup.RootPart.RotationOffset.W,
279 ParentGroup.RootPart.RotationOffset.X,
280 ParentGroup.RootPart.RotationOffset.Y,
281 ParentGroup.RootPart.RotationOffset.Z);
282 338
283 Quaternion oldRot 339 /*
284 = new Quaternion( 340 m_queue = (Queue<SceneObjectPart>)info.GetValue("m_queue", typeof(Queue<SceneObjectPart>));
285 RotationOffset.W, 341 m_ids = (List<LLUUID>)info.GetValue("m_ids", typeof(List<LLUUID>));
286 RotationOffset.X, 342 */
287 RotationOffset.Y,
288 RotationOffset.Z);
289 343
290 newRot = parentRot * oldRot; 344 //System.Console.WriteLine("SceneObjectPart Deserialize END");
291 } 345 }
292 return new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w);
293 346
294 //return new LLQuaternion(axiomPartRotation.x, axiomPartRotation.y, axiomPartRotation.z, axiomPartRotation.w); 347 #endregion Constructors
348
349 #region Public Properties
350
351 public LLVector3 AbsolutePosition
352 {
353 get {
354 if (m_IsAttachment)
355 return GroupPosition;
295 356
357 return m_offsetPosition + m_groupPosition; }
296 } 358 }
297 359
298 public void StoreUndoState() 360 /// <summary></summary>
361 public LLVector3 Acceleration
299 { 362 {
300 if (!m_undoing) 363 get { return m_acceleration; }
301 { 364 set { m_acceleration = value; }
302 if (m_parentGroup != null) 365 }
303 {
304 if (m_undo.Count > 0)
305 {
306 UndoState last = m_undo.Peek();
307 if (last != null)
308 {
309 if (last.Compare(this))
310 return;
311 }
312 }
313 366
367 /// <summary></summary>
368 public LLVector3 AngularVelocity
369 {
370 get { return m_angularVelocity; }
371 set { m_angularVelocity = value; }
372 }
314 373
315 if (m_parentGroup.GetSceneMaxUndo() > 0) 374 public byte ClickAction
316 { 375 {
317 UndoState nUndo = new UndoState(this); 376 get { return m_clickAction; }
377 set
378 {
379 m_clickAction = value;
380 }
381 }
318 382
319 m_undo.Push(nUndo); 383 public Color Color
384 {
385 get { return m_color; }
386 set
387 {
388 m_color = value;
389 TriggerScriptChangedEvent(Changed.COLOR);
320 390
321 } 391 /* ScheduleFullUpdate() need not be called b/c after
322 } 392 * setting the color, the text will be set, so then
393 * ScheduleFullUpdate() will be called. */
394 //ScheduleFullUpdate();
323 } 395 }
324 } 396 }
325 397
326 public void ClearUndoState() 398 public string Description
327 { 399 {
328 m_undo.Clear(); 400 get { return m_description; }
329 StoreUndoState(); 401 set { m_description = value; }
330 } 402 }
331 403
332 public LLVector3 GroupPosition 404 public LLVector3 GroupPosition
@@ -391,9 +463,50 @@ namespace OpenSim.Region.Environment.Scenes
391 } 463 }
392 } 464 }
393 465
394 private byte[] m_TextureAnimation; 466 public int LinkNum
467 {
468 get { return m_linkNum; }
469 set
470 {
471 m_linkNum = value;
472 TriggerScriptChangedEvent(Changed.LINK);
395 473
396 protected LLVector3 m_offsetPosition; 474 }
475 }
476
477 public uint LocalId
478 {
479 get { return m_localId; }
480 set { m_localId = value; }
481 }
482
483 public byte Material
484 {
485 get { return (byte) m_material; }
486 set { m_material = (LLObject.MaterialType) value; }
487 }
488
489 public virtual string Name
490 {
491 get { return m_name; }
492 set { m_name = value; }
493 }
494
495 public LLUUID ObjectCreator
496 {
497 get { return CreatorID; }
498 }
499
500 public uint ObjectFlags
501 {
502 get { return (uint)Flags; }
503 set { Flags = (LLObject.ObjectFlags)value; }
504 }
505
506 public LLUUID ObjectOwner
507 {
508 get { return OwnerID; }
509 }
397 510
398 public LLVector3 OffsetPosition 511 public LLVector3 OffsetPosition
399 { 512 {
@@ -416,16 +529,16 @@ namespace OpenSim.Region.Environment.Scenes
416 } 529 }
417 } 530 }
418 531
419 public LLVector3 AbsolutePosition 532 public SceneObjectGroup ParentGroup
420 { 533 {
421 get { 534 get { return m_parentGroup; }
422 if (m_IsAttachment)
423 return GroupPosition;
424
425 return m_offsetPosition + m_groupPosition; }
426 } 535 }
427 536
428 protected LLQuaternion m_rotationOffset; 537 public ulong RegionHandle
538 {
539 get { return m_regionHandle; }
540 set { m_regionHandle = value; }
541 }
429 542
430 public LLQuaternion RotationOffset 543 public LLQuaternion RotationOffset
431 { 544 {
@@ -479,11 +592,7 @@ namespace OpenSim.Region.Environment.Scenes
479 } 592 }
480 } 593 }
481 594
482 protected LLVector3 m_velocity; 595 public LLVector3 RotationalVelocity
483 protected LLVector3 m_rotationalvelocity;
484
485 /// <summary></summary>
486 public LLVector3 Velocity
487 { 596 {
488 get 597 get
489 { 598 {
@@ -494,103 +603,86 @@ namespace OpenSim.Region.Environment.Scenes
494 { 603 {
495 if (PhysActor.IsPhysical) 604 if (PhysActor.IsPhysical)
496 { 605 {
497 m_velocity.X = PhysActor.Velocity.X; 606 m_rotationalvelocity.FromBytes(PhysActor.RotationalVelocity.GetBytes(),0);
498 m_velocity.Y = PhysActor.Velocity.Y;
499 m_velocity.Z = PhysActor.Velocity.Z;
500 } 607 }
501 } 608 }
502 609
503 return m_velocity; 610 return m_rotationalvelocity;
504 }
505
506 set
507 {
508 m_velocity = value;
509 if (PhysActor != null)
510 {
511 if (PhysActor.IsPhysical)
512 {
513 PhysActor.Velocity = new PhysicsVector(value.X, value.Y, value.Z);
514 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
515 }
516 }
517 } 611 }
612 set { m_rotationalvelocity = value; }
518 } 613 }
519 614
520 public LLVector3 RotationalVelocity 615 public LLVector3 Scale
521 { 616 {
522 get 617 get { return m_shape.Scale; }
618 set
523 { 619 {
524 //if (PhysActor.Velocity.x != 0 || PhysActor.Velocity.y != 0 620 StoreUndoState();
525 //|| PhysActor.Velocity.z != 0) 621 m_shape.Scale = value;
526 //{ 622
527 if (PhysActor != null) 623 if (PhysActor != null && m_parentGroup != null)
528 { 624 {
529 if (PhysActor.IsPhysical) 625 if (m_parentGroup.Scene != null)
530 { 626 {
531 m_rotationalvelocity.FromBytes(PhysActor.RotationalVelocity.GetBytes(),0); 627 if (m_parentGroup.Scene.PhysicsScene != null)
628 {
629 PhysActor.Size = new PhysicsVector(m_shape.Scale.X, m_shape.Scale.Y, m_shape.Scale.Z);
630 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
631 }
532 } 632 }
533 } 633 }
534 634 TriggerScriptChangedEvent(Changed.SCALE);
535 return m_rotationalvelocity;
536 } 635 }
537 set { m_rotationalvelocity = value; }
538 }
539
540
541 protected LLVector3 m_angularVelocity;
542
543 /// <summary></summary>
544 public LLVector3 AngularVelocity
545 {
546 get { return m_angularVelocity; }
547 set { m_angularVelocity = value; }
548 } 636 }
549 637
550 protected LLVector3 m_acceleration; 638 public int ScriptAccessPin
551
552 /// <summary></summary>
553 public LLVector3 Acceleration
554 { 639 {
555 get { return m_acceleration; } 640 get { return m_scriptAccessPin; }
556 set { m_acceleration = value; } 641 set { m_scriptAccessPin = (int)value; }
557 } 642 }
558 643
559 private string m_description = String.Empty; 644 public scriptEvents ScriptEvents
560
561 public string Description
562 { 645 {
563 get { return m_description; } 646 get { return m_aggregateScriptEvents; }
564 set { m_description = value; }
565 } 647 }
566 648
567 private Color m_color = Color.Black; 649 public PrimitiveBaseShape Shape
568
569 public Color Color
570 { 650 {
571 get { return m_color; } 651 get { return m_shape; }
572 set 652 set
573 { 653 {
574 m_color = value; 654 m_shape = value;
575 TriggerScriptChangedEvent(Changed.COLOR); 655 TriggerScriptChangedEvent(Changed.SHAPE);
576
577 /* ScheduleFullUpdate() need not be called b/c after
578 * setting the color, the text will be set, so then
579 * ScheduleFullUpdate() will be called. */
580 //ScheduleFullUpdate();
581 } 656 }
582 } 657 }
583 658
584 private string m_text = String.Empty; 659 public string SitName
660 {
661 get { return m_sitName; }
662 set { m_sitName = value; }
663 }
664
665 public Quaternion SitTargetOrientation
666 {
667 get { return m_sitTargetOrientation; }
668 }
585 669
586 public Vector3 SitTargetPosition 670 public Vector3 SitTargetPosition
587 { 671 {
588 get { return m_sitTargetPosition; } 672 get { return m_sitTargetPosition; }
589 } 673 }
590 674
591 public Quaternion SitTargetOrientation 675 public bool Stopped
592 { 676 {
593 get { return m_sitTargetOrientation; } 677 get {
678 double threshold = 0.02;
679 return (Math.Abs(Velocity.X) < threshold &&
680 Math.Abs(Velocity.Y) < threshold &&
681 Math.Abs(Velocity.Z) < threshold &&
682 Math.Abs(AngularVelocity.X) < threshold &&
683 Math.Abs(AngularVelocity.Y) < threshold &&
684 Math.Abs(AngularVelocity.Z) < threshold);
685 }
594 } 686 }
595 687
596 public string Text 688 public string Text
@@ -610,61 +702,209 @@ namespace OpenSim.Region.Environment.Scenes
610 } 702 }
611 } 703 }
612 704
613 //Xantor 20080528 Sound stuff: 705 public string TouchName
614 // Note: This isn't persisted in the database right now, as the fields for that aren't just there yet. 706 {
615 // Not a big problem as long as the script that sets it remains in the prim on startup. 707 get { return m_touchName; }
616 // for SL compatibility it should be persisted though (set sound / displaytext / particlesystem, kill script) 708 set { m_touchName = value; }
617 [XmlIgnore] 709 }
618 public LLUUID Sound;
619 [XmlIgnore]
620 public byte SoundFlags;
621 [XmlIgnore]
622 public double SoundGain;
623 [XmlIgnore]
624 public double SoundRadius;
625 710
711 public LLUUID UUID
712 {
713 get { return m_uuid; }
714 set { m_uuid = value; }
715 }
626 716
627 private string m_sitName = String.Empty; 717 public byte UpdateFlag
718 {
719 get { return m_updateFlag; }
720 set { m_updateFlag = value; }
721 }
628 722
629 public string SitName 723 /// <summary></summary>
724 public LLVector3 Velocity
630 { 725 {
631 get { return m_sitName; } 726 get
632 set { m_sitName = value; } 727 {
728 //if (PhysActor.Velocity.x != 0 || PhysActor.Velocity.y != 0
729 //|| PhysActor.Velocity.z != 0)
730 //{
731 if (PhysActor != null)
732 {
733 if (PhysActor.IsPhysical)
734 {
735 m_velocity.X = PhysActor.Velocity.X;
736 m_velocity.Y = PhysActor.Velocity.Y;
737 m_velocity.Z = PhysActor.Velocity.Z;
738 }
739 }
740
741 return m_velocity;
742 }
743
744 set
745 {
746 m_velocity = value;
747 if (PhysActor != null)
748 {
749 if (PhysActor.IsPhysical)
750 {
751 PhysActor.Velocity = new PhysicsVector(value.X, value.Y, value.Z);
752 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
753 }
754 }
755 }
633 } 756 }
634 757
635 private string m_touchName = String.Empty; 758 #endregion Public Properties
636 759
637 public string TouchName 760 #region Private Methods
761
762 private uint ApplyMask(uint val, bool set, uint mask)
638 { 763 {
639 get { return m_touchName; } 764 if (set)
640 set { m_touchName = value; } 765 {
766 return val |= mask;
767 }
768 else
769 {
770 return val &= ~mask;
771 }
641 } 772 }
642 773
643 private int m_linkNum = 0; 774 /// <summary>
775 /// Clear all pending updates
776 /// </summary>
777 private void ClearUpdateSchedule()
778 {
779 m_updateFlag = 0;
780 }
644 781
645 public int LinkNum 782 private void SendObjectPropertiesToClient(LLUUID AgentID)
646 { 783 {
647 get { return m_linkNum; } 784 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
648 set 785 for (int i = 0; i < avatars.Count; i++)
649 { 786 {
650 m_linkNum = value; 787 // Ugly reference :(
651 TriggerScriptChangedEvent(Changed.LINK); 788 if (avatars[i].UUID == AgentID)
789 {
790 m_parentGroup.GetProperties(avatars[i].ControllingClient);
791 }
792 }
793 }
794
795 private void handleTimerAccounting(uint localID, double interval)
796 {
797 if (localID == LocalId)
798 {
799
800 float sec = (float)interval;
801 if (m_parentGroup != null)
802 {
803 if (sec == 0)
804 {
805 if (m_parentGroup.scriptScore + 0.001f >= float.MaxValue - 0.001)
806 m_parentGroup.scriptScore = 0;
807
808 m_parentGroup.scriptScore += 0.001f;
809 return;
810 }
811
812 if (m_parentGroup.scriptScore + (0.001f / sec) >= float.MaxValue - (0.001f / sec))
813 m_parentGroup.scriptScore = 0;
814 m_parentGroup.scriptScore += (0.001f / sec);
815 }
652 816
653 } 817 }
654 } 818 }
655 819
656 private byte m_clickAction = 0; 820 #endregion Private Methods
657 821
658 public byte ClickAction 822 #region Public Methods
823
824 public void AddFlag(LLObject.ObjectFlags flag)
659 { 825 {
660 get { return m_clickAction; } 826 LLObject.ObjectFlags prevflag = Flags;
661 set 827 //uint objflags = Flags;
828 if ((ObjectFlags & (uint) flag) == 0)
662 { 829 {
663 m_clickAction = value; 830 //Console.WriteLine("Adding flag: " + ((LLObject.ObjectFlags) flag).ToString());
831 Flags |= flag;
664 } 832 }
833 //uint currflag = (uint)Flags;
834 //System.Console.WriteLine("Aprev: " + prevflag.ToString() + " curr: " + Flags.ToString());
835 //ScheduleFullUpdate();
665 } 836 }
666 837
667 protected PrimitiveBaseShape m_shape; 838 /// <summary>
839 /// Tell all scene presences that they should send updates for this part to their clients
840 /// </summary>
841 public void AddFullUpdateToAllAvatars()
842 {
843 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
844 for (int i = 0; i < avatars.Count; i++)
845 {
846 avatars[i].QueuePartForUpdate(this);
847 }
848 }
849
850 public void AddFullUpdateToAvatar(ScenePresence presence)
851 {
852 presence.QueuePartForUpdate(this);
853 }
854
855 public void AddNewParticleSystem(Primitive.ParticleSystem pSystem)
856 {
857 m_particleSystem = pSystem.GetBytes();
858 }
859
860 /// Terse updates
861 public void AddTerseUpdateToAllAvatars()
862 {
863 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
864 for (int i = 0; i < avatars.Count; i++)
865 {
866 avatars[i].QueuePartForUpdate(this);
867 }
868 }
869
870 public void AddTerseUpdateToAvatar(ScenePresence presence)
871 {
872 presence.QueuePartForUpdate(this);
873 }
874
875 public void AddTextureAnimation(Primitive.TextureAnimation pTexAnim)
876 {
877 byte[] data = new byte[16];
878 int pos = 0;
879
880 // The flags don't like conversion from uint to byte, so we have to do
881 // it the crappy way. See the above function :(
882
883 data[pos] = ConvertScriptUintToByte(pTexAnim.Flags); pos++;
884 data[pos] = (byte)pTexAnim.Face; pos++;
885 data[pos] = (byte)pTexAnim.SizeX; pos++;
886 data[pos] = (byte)pTexAnim.SizeY; pos++;
887
888 Helpers.FloatToBytes(pTexAnim.Start).CopyTo(data, pos);
889 Helpers.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4);
890 Helpers.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8);
891
892 m_TextureAnimation = data;
893 }
894
895 public void AdjustSoundGain(double volume)
896 {
897 if (volume > 1)
898 volume = 1;
899 if (volume < 0)
900 volume = 0;
901
902 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars();
903 foreach (ScenePresence p in avatarts)
904 {
905 p.ControllingClient.SendAttachedSoundGainChange(UUID, (float)volume);
906 }
907 }
668 908
669 /// <summary> 909 /// <summary>
670 /// hook to the physics scene to apply impulse 910 /// hook to the physics scene to apply impulse
@@ -697,283 +937,1316 @@ namespace OpenSim.Region.Environment.Scenes
697 } 937 }
698 } 938 }
699 939
700 public void MoveToTarget(LLVector3 target, float tau) 940 /// <summary>
941 /// Apply physics to this part.
942 /// </summary>
943 /// <param name="rootObjectFlags"></param>
944 /// <param name="m_physicalPrim"></param>
945 public void ApplyPhysics(uint rootObjectFlags, bool m_physicalPrim)
701 { 946 {
702 if (tau > 0) 947 bool isPhysical = (((rootObjectFlags & (uint) LLObject.ObjectFlags.Physics) != 0) && m_physicalPrim);
948 bool isPhantom = ((rootObjectFlags & (uint) LLObject.ObjectFlags.Phantom) != 0);
949
950 // Added clarification.. since A rigid body is an object that you can kick around, etc.
951 bool RigidBody = isPhysical && !isPhantom;
952
953 // The only time the physics scene shouldn't know about the prim is if it's phantom
954 if (!isPhantom)
703 { 955 {
704 m_parentGroup.moveToTarget(target, tau); 956 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
957 Name,
958 Shape,
959 new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y,
960 AbsolutePosition.Z),
961 new PhysicsVector(Scale.X, Scale.Y, Scale.Z),
962 new Quaternion(RotationOffset.W, RotationOffset.X,
963 RotationOffset.Y, RotationOffset.Z), RigidBody);
964
965 // Basic Physics returns null.. joy joy joy.
966 if (PhysActor != null)
967 {
968 PhysActor.LocalID = LocalId;
969 DoPhysicsPropertyUpdate(RigidBody, true);
970 }
971 }
972 }
973
974 public void ClearUndoState()
975 {
976 m_undo.Clear();
977 StoreUndoState();
978 }
979
980 public byte ConvertScriptUintToByte(uint indata)
981 {
982 byte outdata = (byte)TextureAnimFlags.NONE;
983 if ((indata & 1) != 0) outdata |= (byte)TextureAnimFlags.ANIM_ON;
984 if ((indata & 2) != 0) outdata |= (byte)TextureAnimFlags.LOOP;
985 if ((indata & 4) != 0) outdata |= (byte)TextureAnimFlags.REVERSE;
986 if ((indata & 8) != 0) outdata |= (byte)TextureAnimFlags.PING_PONG;
987 if ((indata & 16) != 0) outdata |= (byte)TextureAnimFlags.SMOOTH;
988 if ((indata & 32) != 0) outdata |= (byte)TextureAnimFlags.ROTATE;
989 if ((indata & 64) != 0) outdata |= (byte)TextureAnimFlags.SCALE;
990 return outdata;
991 }
992
993 /// <summary>
994 /// Duplicates this part.
995 /// </summary>
996 /// <returns></returns>
997 public SceneObjectPart Copy(uint localID, LLUUID AgentID, LLUUID GroupID, int linkNum, bool userExposed)
998 {
999 SceneObjectPart dupe = (SceneObjectPart) MemberwiseClone();
1000 dupe.m_shape = m_shape.Copy();
1001 dupe.m_regionHandle = m_regionHandle;
1002 if (userExposed)
1003 dupe.UUID = LLUUID.Random();
1004
1005 dupe.LocalId = localID;
1006 dupe.OwnerID = AgentID;
1007 dupe.GroupID = GroupID;
1008 dupe.GroupPosition = new LLVector3(GroupPosition.X, GroupPosition.Y, GroupPosition.Z);
1009 dupe.OffsetPosition = new LLVector3(OffsetPosition.X, OffsetPosition.Y, OffsetPosition.Z);
1010 dupe.RotationOffset =
1011 new LLQuaternion(RotationOffset.X, RotationOffset.Y, RotationOffset.Z, RotationOffset.W);
1012 dupe.Velocity = new LLVector3(0, 0, 0);
1013 dupe.Acceleration = new LLVector3(0, 0, 0);
1014 dupe.AngularVelocity = new LLVector3(0, 0, 0);
1015 dupe.ObjectFlags = ObjectFlags;
1016
1017 dupe.OwnershipCost = OwnershipCost;
1018 dupe.ObjectSaleType = ObjectSaleType;
1019 dupe.SalePrice = SalePrice;
1020 dupe.Category = Category;
1021
1022 dupe.TaskInventory = (TaskInventoryDictionary)dupe.TaskInventory.Clone();
1023
1024 if (userExposed)
1025 dupe.ResetIDs(linkNum);
1026
1027 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1028 dupe.LastOwnerID = ObjectOwner;
1029
1030 byte[] extraP = new byte[Shape.ExtraParams.Length];
1031 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
1032 dupe.Shape.ExtraParams = extraP;
1033
1034 if (userExposed)
1035 {
1036 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != LLUUID.Zero)
1037 {
1038 m_parentGroup.Scene.AssetCache.GetAsset(dupe.m_shape.SculptTexture, dupe.SculptTextureCallback, true);
1039 }
1040 bool UsePhysics = ((dupe.ObjectFlags & (uint)LLObject.ObjectFlags.Physics) != 0);
1041 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
1042 }
1043 return dupe;
1044 }
1045
1046 public static SceneObjectPart Create()
1047 {
1048 SceneObjectPart part = new SceneObjectPart();
1049 part.UUID = LLUUID.Random();
1050
1051 PrimitiveBaseShape shape = PrimitiveBaseShape.Create();
1052 part.Shape = shape;
1053
1054 part.Name = "Primitive";
1055 part.OwnerID = LLUUID.Random();
1056
1057 return part;
1058 }
1059
1060 public void DoPhysicsPropertyUpdate(bool UsePhysics, bool isNew)
1061 {
1062 if (PhysActor != null)
1063 {
1064 if (UsePhysics != PhysActor.IsPhysical || isNew)
1065 {
1066 if (PhysActor.IsPhysical)
1067 {
1068 if (!isNew)
1069 ParentGroup.Scene.RemovePhysicalPrim(1);
1070
1071 PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1072 PhysActor.OnOutOfBounds -= PhysicsOutOfBounds;
1073 PhysActor.delink();
1074 }
1075
1076 PhysActor.IsPhysical = UsePhysics;
1077
1078
1079 // If we're not what we're supposed to be in the physics scene, recreate ourselves.
1080 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor);
1081 /// that's not wholesome. Had to make Scene public
1082 //PhysActor = null;
1083
1084 if ((ObjectFlags & (uint) LLObject.ObjectFlags.Phantom) == 0)
1085 {
1086 //PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
1087 //Name,
1088 //Shape,
1089 //new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y,
1090 //AbsolutePosition.Z),
1091 //new PhysicsVector(Scale.X, Scale.Y, Scale.Z),
1092 //new Quaternion(RotationOffset.W, RotationOffset.X,
1093 //RotationOffset.Y, RotationOffset.Z), UsePhysics);
1094 if (UsePhysics)
1095 {
1096 ParentGroup.Scene.AddPhysicalPrim(1);
1097
1098 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1099 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1100 if (ParentID != 0 && ParentID != LocalId)
1101 {
1102 if (ParentGroup.RootPart.PhysActor != null)
1103 {
1104 PhysActor.link(ParentGroup.RootPart.PhysActor);
1105 }
1106 }
1107 }
1108 }
1109 }
1110 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
1111 }
1112 }
1113
1114 /// <summary>
1115 /// Restore this part from the serialized xml representation.
1116 /// </summary>
1117 /// <param name="xmlreader"></param>
1118 /// <returns></returns>
1119 public static SceneObjectPart FromXml(XmlReader xmlReader)
1120 {
1121 // It's not necessary to persist this
1122
1123 XmlSerializer serializer = new XmlSerializer(typeof (SceneObjectPart));
1124 SceneObjectPart newobject = (SceneObjectPart) serializer.Deserialize(xmlReader);
1125 return newobject;
1126 }
1127
1128 public LLUUID GetAvatarOnSitTarget()
1129 {
1130 return m_sitTargetAvatar;
1131 }
1132
1133 public bool GetDieAtEdge()
1134 {
1135 if (m_parentGroup == null)
1136 return false;
1137 if (m_parentGroup.RootPart == null)
1138 return false;
1139
1140 return m_parentGroup.RootPart.DIE_AT_EDGE;
1141 }
1142
1143 public double GetDistanceTo(Vector3 a, Vector3 b)
1144 {
1145 float dx = a.x - b.x;
1146 float dy = a.y - b.y;
1147 float dz = a.z - b.z;
1148 return Math.Sqrt(dx * dx + dy * dy + dz * dz);
1149 }
1150
1151 public uint GetEffectiveObjectFlags()
1152 {
1153 LLObject.ObjectFlags f = Flags;
1154 if (m_parentGroup == null || m_parentGroup.RootPart == this)
1155 f &= ~(LLObject.ObjectFlags.Touch | LLObject.ObjectFlags.Money);
1156
1157 return (uint)Flags | (uint)LocalFlags;
1158 }
1159
1160 public LLVector3 GetGeometricCenter()
1161 {
1162 if (PhysActor != null)
1163 {
1164 return new LLVector3(PhysActor.CenterOfMass.X, PhysActor.CenterOfMass.Y, PhysActor.CenterOfMass.Z);
705 } 1165 }
706 else 1166 else
707 { 1167 {
708 StopMoveToTarget(); 1168 return new LLVector3(0, 0, 0);
709 } 1169 }
1170 }
710 1171
1172 public float GetMass()
1173 {
1174 if (PhysActor != null)
1175 {
1176 return PhysActor.Mass;
1177 }
1178 else
1179 {
1180 return 0;
1181 }
711 } 1182 }
712 1183
713 public void StopMoveToTarget() 1184 [SecurityPermission(SecurityAction.LinkDemand,
1185 Flags = SecurityPermissionFlag.SerializationFormatter)]
1186 public virtual void GetObjectData(
1187 SerializationInfo info, StreamingContext context)
714 { 1188 {
715 m_parentGroup.stopMoveToTarget(); 1189 if (info == null)
1190 {
1191 throw new ArgumentNullException("info");
1192 }
1193
1194 info.AddValue("m_inventoryFileName", GetInventoryFileName());
1195 info.AddValue("m_folderID", UUID);
1196 info.AddValue("PhysActor", PhysActor);
1197
1198 Dictionary<Guid, TaskInventoryItem> TaskInventory_work = new Dictionary<Guid, TaskInventoryItem>();
1199
1200 foreach (LLUUID id in TaskInventory.Keys)
1201 {
1202 TaskInventory_work.Add(id.UUID, TaskInventory[id]);
1203 }
1204
1205 info.AddValue("TaskInventory", TaskInventory_work);
1206
1207 info.AddValue("LastOwnerID", LastOwnerID.UUID);
1208 info.AddValue("OwnerID", OwnerID.UUID);
1209 info.AddValue("GroupID", GroupID.UUID);
1210
1211 info.AddValue("OwnershipCost", OwnershipCost);
1212 info.AddValue("ObjectSaleType", ObjectSaleType);
1213 info.AddValue("SalePrice", SalePrice);
1214 info.AddValue("Category", Category);
1215
1216 info.AddValue("CreationDate", CreationDate);
1217 info.AddValue("ParentID", ParentID);
1218
1219 info.AddValue("OwnerMask", OwnerMask);
1220 info.AddValue("NextOwnerMask", NextOwnerMask);
1221 info.AddValue("GroupMask", GroupMask);
1222 info.AddValue("EveryoneMask", EveryoneMask);
1223 info.AddValue("BaseMask", BaseMask);
1224
1225 info.AddValue("m_particleSystem", m_particleSystem);
1226
1227 info.AddValue("TimeStampFull", TimeStampFull);
1228 info.AddValue("TimeStampTerse", TimeStampTerse);
1229 info.AddValue("TimeStampLastActivity", TimeStampLastActivity);
1230
1231 info.AddValue("m_updateFlag", m_updateFlag);
1232 info.AddValue("CreatorID", CreatorID.UUID);
1233
1234 info.AddValue("m_inventorySerial", m_inventorySerial);
1235 info.AddValue("m_uuid", m_uuid.UUID);
1236 info.AddValue("m_localID", m_localId);
1237 info.AddValue("m_name", m_name);
1238 info.AddValue("m_flags", Flags);
1239 info.AddValue("m_material", m_material);
1240 info.AddValue("m_regionHandle", m_regionHandle);
1241
1242 info.AddValue("m_groupPosition.X", m_groupPosition.X);
1243 info.AddValue("m_groupPosition.Y", m_groupPosition.Y);
1244 info.AddValue("m_groupPosition.Z", m_groupPosition.Z);
1245
1246 info.AddValue("m_offsetPosition.X", m_offsetPosition.X);
1247 info.AddValue("m_offsetPosition.Y", m_offsetPosition.Y);
1248 info.AddValue("m_offsetPosition.Z", m_offsetPosition.Z);
1249
1250 info.AddValue("m_rotationOffset.W", m_rotationOffset.W);
1251 info.AddValue("m_rotationOffset.X", m_rotationOffset.X);
1252 info.AddValue("m_rotationOffset.Y", m_rotationOffset.Y);
1253 info.AddValue("m_rotationOffset.Z", m_rotationOffset.Z);
1254
1255 info.AddValue("m_velocity.X", m_velocity.X);
1256 info.AddValue("m_velocity.Y", m_velocity.Y);
1257 info.AddValue("m_velocity.Z", m_velocity.Z);
1258
1259 info.AddValue("m_rotationalvelocity.X", m_rotationalvelocity.X);
1260 info.AddValue("m_rotationalvelocity.Y", m_rotationalvelocity.Y);
1261 info.AddValue("m_rotationalvelocity.Z", m_rotationalvelocity.Z);
1262
1263 info.AddValue("m_angularVelocity.X", m_angularVelocity.X);
1264 info.AddValue("m_angularVelocity.Y", m_angularVelocity.Y);
1265 info.AddValue("m_angularVelocity.Z", m_angularVelocity.Z);
1266
1267 info.AddValue("m_acceleration.X", m_acceleration.X);
1268 info.AddValue("m_acceleration.Y", m_acceleration.Y);
1269 info.AddValue("m_acceleration.Z", m_acceleration.Z);
1270
1271 info.AddValue("m_description", m_description);
1272 info.AddValue("m_color", m_color);
1273 info.AddValue("m_text", m_text);
1274 info.AddValue("m_sitName", m_sitName);
1275 info.AddValue("m_touchName", m_touchName);
1276 info.AddValue("m_clickAction", m_clickAction);
1277 info.AddValue("m_shape", m_shape);
1278 info.AddValue("m_parentGroup", m_parentGroup);
1279 info.AddValue("PayPrice", PayPrice);
716 } 1280 }
717 1281
718 public void TriggerScriptChangedEvent(Changed val) 1282 public void GetProperties(IClientAPI client)
1283 {
1284 client.SendObjectPropertiesReply(LLUUID.Zero, (ulong)CreationDate, CreatorID, LLUUID.Zero, LLUUID.Zero,
1285 GroupID, (short)InventorySerial, LastOwnerID, UUID, OwnerID,
1286 ParentGroup.RootPart.TouchName, new byte[0], ParentGroup.RootPart.SitName, Name, Description,
1287 ParentGroup.RootPart.OwnerMask, ParentGroup.RootPart.NextOwnerMask, ParentGroup.RootPart.GroupMask, ParentGroup.RootPart.EveryoneMask,
1288 ParentGroup.RootPart.BaseMask);
1289 }
1290
1291 public LLUUID GetRootPartUUID()
719 { 1292 {
720 if (m_parentGroup != null) 1293 if (m_parentGroup != null)
721 { 1294 {
722 if (m_parentGroup.Scene != null) 1295 return m_parentGroup.UUID;
723 m_parentGroup.Scene.TriggerObjectChanged(LocalId, (uint)val);
724 } 1296 }
1297 return LLUUID.Zero;
1298 }
725 1299
1300 public Quaternion GetSitTargetOrientation()
1301 {
1302 return m_sitTargetOrientation;
726 } 1303 }
727 1304
728 public PrimitiveBaseShape Shape 1305 public LLQuaternion GetSitTargetOrientationLL()
729 { 1306 {
730 get { return m_shape; } 1307 return
731 set 1308 new LLQuaternion(m_sitTargetOrientation.x, m_sitTargetOrientation.y, m_sitTargetOrientation.z,
1309 m_sitTargetOrientation.w);
1310 }
1311
1312 public Vector3 GetSitTargetPosition()
1313 {
1314 return m_sitTargetPosition;
1315 }
1316
1317 public LLVector3 GetSitTargetPositionLL()
1318 {
1319 return new LLVector3(m_sitTargetPosition.x, m_sitTargetPosition.y, m_sitTargetPosition.z);
1320 }
1321
1322 /// <summary>
1323 /// Method for a prim to get it's world position from the group.
1324 /// Remember, the Group Position simply gives the position of the group itself
1325 /// </summary>
1326 /// <returns>A Linked Child Prim objects position in world</returns>
1327 public LLVector3 GetWorldPosition()
1328 {
1329 Quaternion parentRot = new Quaternion(
1330 ParentGroup.RootPart.RotationOffset.W,
1331 ParentGroup.RootPart.RotationOffset.X,
1332 ParentGroup.RootPart.RotationOffset.Y,
1333 ParentGroup.RootPart.RotationOffset.Z);
1334
1335 Vector3 axPos
1336 = new Vector3(
1337 OffsetPosition.X,
1338 OffsetPosition.Y,
1339 OffsetPosition.Z);
1340
1341 axPos = parentRot * axPos;
1342 LLVector3 translationOffsetPosition = new LLVector3(axPos.x, axPos.y, axPos.z);
1343 return GroupPosition + translationOffsetPosition;
1344
1345 //return (new LLVector3(axiomPos.x, axiomPos.y, axiomPos.z) + AbsolutePosition);
1346 }
1347
1348 /// <summary>
1349 /// Gets the rotation of this prim offset by the group rotation
1350 /// </summary>
1351 /// <returns></returns>
1352 public LLQuaternion GetWorldRotation()
1353 {
1354 Quaternion newRot;
1355
1356 if (this.LinkNum == 0)
732 { 1357 {
733 m_shape = value; 1358 newRot = new Quaternion(RotationOffset.W,RotationOffset.X,RotationOffset.Y,RotationOffset.Z);
734 TriggerScriptChangedEvent(Changed.SHAPE); 1359
1360 }
1361 else
1362 {
1363 Quaternion parentRot = new Quaternion(
1364 ParentGroup.RootPart.RotationOffset.W,
1365 ParentGroup.RootPart.RotationOffset.X,
1366 ParentGroup.RootPart.RotationOffset.Y,
1367 ParentGroup.RootPart.RotationOffset.Z);
1368
1369 Quaternion oldRot
1370 = new Quaternion(
1371 RotationOffset.W,
1372 RotationOffset.X,
1373 RotationOffset.Y,
1374 RotationOffset.Z);
1375
1376 newRot = parentRot * oldRot;
735 } 1377 }
1378 return new LLQuaternion(newRot.x, newRot.y, newRot.z, newRot.w);
1379
1380 //return new LLQuaternion(axiomPartRotation.x, axiomPartRotation.y, axiomPartRotation.z, axiomPartRotation.w);
736 } 1381 }
737 1382
738 public LLVector3 Scale 1383 public void MoveToTarget(LLVector3 target, float tau)
739 { 1384 {
740 get { return m_shape.Scale; } 1385 if (tau > 0)
741 set
742 { 1386 {
743 StoreUndoState(); 1387 m_parentGroup.moveToTarget(target, tau);
744 m_shape.Scale = value; 1388 }
1389 else
1390 {
1391 StopMoveToTarget();
1392 }
1393 }
745 1394
746 if (PhysActor != null && m_parentGroup != null) 1395 public virtual void OnGrab(LLVector3 offsetPos, IClientAPI remoteClient)
1396 {
1397 }
1398
1399 public void PhysicsCollision(EventArgs e)
1400 {
1401 // single threaded here
1402 if (e == null)
1403 {
1404 return;
1405 }
1406
1407 CollisionEventUpdate a = (CollisionEventUpdate)e;
1408 Dictionary<uint, float> collissionswith = a.m_objCollisionList;
1409 List<uint> thisHitColliders = new List<uint>();
1410 List<uint> endedColliders = new List<uint>();
1411 List<uint> startedColliders = new List<uint>();
1412
1413 // calculate things that started colliding this time
1414 // and build up list of colliders this time
1415 foreach (uint localid in collissionswith.Keys)
1416 {
1417 if (localid != 0)
747 { 1418 {
748 if (m_parentGroup.Scene != null) 1419 thisHitColliders.Add(localid);
1420 if (!m_lastColliders.Contains(localid))
749 { 1421 {
750 if (m_parentGroup.Scene.PhysicsScene != null) 1422 startedColliders.Add(localid);
1423 }
1424
1425 //m_log.Debug("[OBJECT]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
1426 }
1427 }
1428
1429 // calculate things that ended colliding
1430 foreach (uint localID in m_lastColliders)
1431 {
1432 if (!thisHitColliders.Contains(localID))
1433 {
1434 endedColliders.Add(localID);
1435 }
1436 }
1437
1438 //add the items that started colliding this time to the last colliders list.
1439 foreach (uint localID in startedColliders)
1440 {
1441 m_lastColliders.Add(localID);
1442 }
1443 // remove things that ended colliding from the last colliders list
1444 foreach (uint localID in endedColliders)
1445 {
1446 m_lastColliders.Remove(localID);
1447 }
1448 if (m_parentGroup == null)
1449 return;
1450 if (m_parentGroup.RootPart == null)
1451 return;
1452
1453 if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_start) != 0)
1454 {
1455 // do event notification
1456 if (startedColliders.Count > 0)
1457 {
1458 ColliderArgs StartCollidingMessage = new ColliderArgs();
1459 List<DetectedObject> colliding = new List<DetectedObject>();
1460 foreach (uint localId in startedColliders)
1461 {
1462 // always running this check because if the user deletes the object it would return a null reference.
1463 if (m_parentGroup == null)
1464 return;
1465 if (m_parentGroup.Scene == null)
1466 return;
1467 SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
1468 if (obj != null)
751 { 1469 {
752 PhysActor.Size = new PhysicsVector(m_shape.Scale.X, m_shape.Scale.Y, m_shape.Scale.Z); 1470 DetectedObject detobj = new DetectedObject();
753 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); 1471 detobj.keyUUID = obj.UUID;
1472 detobj.nameStr = obj.Name;
1473 detobj.ownerUUID = obj.OwnerID;
1474 detobj.posVector = obj.AbsolutePosition;
1475 detobj.rotQuat = obj.GetWorldRotation();
1476 detobj.velVector = obj.Velocity;
1477 detobj.colliderType = 0;
1478 detobj.groupUUID = obj.GroupID;
1479 colliding.Add(detobj);
754 } 1480 }
1481 else
1482 {
1483 List<ScenePresence> avlist = m_parentGroup.Scene.GetScenePresences();
1484 if (avlist != null)
1485 {
1486 foreach (ScenePresence av in avlist)
1487 {
1488 if (av.LocalId == localId)
1489 {
1490 DetectedObject detobj = new DetectedObject();
1491 detobj.keyUUID = av.UUID;
1492 detobj.nameStr = av.ControllingClient.Name;
1493 detobj.ownerUUID = av.UUID;
1494 detobj.posVector = av.AbsolutePosition;
1495 detobj.rotQuat = new LLQuaternion(av.Rotation.x, av.Rotation.y, av.Rotation.z, av.Rotation.w);
1496 detobj.velVector = av.Velocity;
1497 detobj.colliderType = 0;
1498 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
1499 colliding.Add(detobj);
1500 }
1501 }
1502 }
1503 }
1504 }
1505 if (colliding.Count > 0)
1506 {
1507 StartCollidingMessage.Colliders = colliding;
1508 // always running this check because if the user deletes the object it would return a null reference.
1509 if (m_parentGroup == null)
1510 return;
1511 if (m_parentGroup.Scene == null)
1512 return;
1513 m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(LocalId, StartCollidingMessage);
755 } 1514 }
756 } 1515 }
757 TriggerScriptChangedEvent(Changed.SCALE); 1516 }
1517 if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision) != 0)
1518 {
1519 if (m_lastColliders.Count > 0)
1520 {
1521 ColliderArgs CollidingMessage = new ColliderArgs();
1522 List<DetectedObject> colliding = new List<DetectedObject>();
1523 foreach (uint localId in m_lastColliders)
1524 {
1525 // always running this check because if the user deletes the object it would return a null reference.
1526 if (localId == 0)
1527 continue;
1528
1529 if (m_parentGroup == null)
1530 return;
1531 if (m_parentGroup.Scene == null)
1532 return;
1533 SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
1534 if (obj != null)
1535 {
1536 DetectedObject detobj = new DetectedObject();
1537 detobj.keyUUID = obj.UUID;
1538 detobj.nameStr = obj.Name;
1539 detobj.ownerUUID = obj.OwnerID;
1540 detobj.posVector = obj.AbsolutePosition;
1541 detobj.rotQuat = obj.GetWorldRotation();
1542 detobj.velVector = obj.Velocity;
1543 detobj.colliderType = 0;
1544 detobj.groupUUID = obj.GroupID;
1545 colliding.Add(detobj);
1546 }
1547 else
1548 {
1549 List<ScenePresence> avlist = m_parentGroup.Scene.GetScenePresences();
1550 if (avlist != null)
1551 {
1552 foreach (ScenePresence av in avlist)
1553 {
1554 if (av.LocalId == localId)
1555 {
1556 DetectedObject detobj = new DetectedObject();
1557 detobj.keyUUID = av.UUID;
1558 detobj.nameStr = av.Name;
1559 detobj.ownerUUID = av.UUID;
1560 detobj.posVector = av.AbsolutePosition;
1561 detobj.rotQuat = new LLQuaternion(av.Rotation.x, av.Rotation.y, av.Rotation.z, av.Rotation.w);
1562 detobj.velVector = av.Velocity;
1563 detobj.colliderType = 0;
1564 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
1565 colliding.Add(detobj);
1566 }
1567 }
1568
1569 }
1570 }
1571 }
1572 if (colliding.Count > 0)
1573 {
1574 CollidingMessage.Colliders = colliding;
1575 // always running this check because if the user deletes the object it would return a null reference.
1576 if (m_parentGroup == null)
1577 return;
1578 if (m_parentGroup.Scene == null)
1579 return;
1580 m_parentGroup.Scene.EventManager.TriggerScriptColliding(LocalId, CollidingMessage);
1581 }
1582
1583 }
1584 }
1585 if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_end) != 0)
1586 {
1587 if (endedColliders.Count > 0)
1588 {
1589 ColliderArgs EndCollidingMessage = new ColliderArgs();
1590 List<DetectedObject> colliding = new List<DetectedObject>();
1591 foreach (uint localId in endedColliders)
1592 {
1593 if (localId == 0)
1594 continue;
1595
1596 // always running this check because if the user deletes the object it would return a null reference.
1597 if (m_parentGroup == null)
1598 return;
1599 if (m_parentGroup.Scene == null)
1600 return;
1601 SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
1602 if (obj != null)
1603 {
1604 DetectedObject detobj = new DetectedObject();
1605 detobj.keyUUID = obj.UUID;
1606 detobj.nameStr = obj.Name;
1607 detobj.ownerUUID = obj.OwnerID;
1608 detobj.posVector = obj.AbsolutePosition;
1609 detobj.rotQuat = obj.GetWorldRotation();
1610 detobj.velVector = obj.Velocity;
1611 detobj.colliderType = 0;
1612 detobj.groupUUID = obj.GroupID;
1613 colliding.Add(detobj);
1614 }
1615 else
1616 {
1617 List<ScenePresence> avlist = m_parentGroup.Scene.GetScenePresences();
1618 if (avlist != null)
1619 {
1620 foreach (ScenePresence av in avlist)
1621 {
1622 if (av.LocalId == localId)
1623 {
1624 DetectedObject detobj = new DetectedObject();
1625 detobj.keyUUID = av.UUID;
1626 detobj.nameStr = av.Name;
1627 detobj.ownerUUID = av.UUID;
1628 detobj.posVector = av.AbsolutePosition;
1629 detobj.rotQuat = new LLQuaternion(av.Rotation.x, av.Rotation.y, av.Rotation.z, av.Rotation.w);
1630 detobj.velVector = av.Velocity;
1631 detobj.colliderType = 0;
1632 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
1633 colliding.Add(detobj);
1634 }
1635 }
1636
1637 }
1638 }
1639 }
1640 if (colliding.Count > 0)
1641 {
1642 EndCollidingMessage.Colliders = colliding;
1643 // always running this check because if the user deletes the object it would return a null reference.
1644 if (m_parentGroup == null)
1645 return;
1646 if (m_parentGroup.Scene == null)
1647 return;
1648 m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(LocalId, EndCollidingMessage);
1649 }
1650
1651 }
758 } 1652 }
759 } 1653 }
760 1654
761 public bool Stopped 1655 public void PhysicsOutOfBounds(PhysicsVector pos)
762 { 1656 {
763 get { 1657 m_log.Info("[PHYSICS]: Physical Object went out of bounds.");
764 double threshold = 0.02; 1658 RemFlag(LLObject.ObjectFlags.Physics);
765 return (Math.Abs(Velocity.X) < threshold && 1659 DoPhysicsPropertyUpdate(false, true);
766 Math.Abs(Velocity.Y) < threshold && 1660 //m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
767 Math.Abs(Velocity.Z) < threshold && 1661 }
768 Math.Abs(AngularVelocity.X) < threshold && 1662
769 Math.Abs(AngularVelocity.Y) < threshold && 1663 public void PhysicsRequestingTerseUpdate()
770 Math.Abs(AngularVelocity.Z) < threshold); 1664 {
1665 if (PhysActor != null)
1666 {
1667 LLVector3 newpos = new LLVector3(PhysActor.Position.GetBytes(), 0);
1668 if (newpos.X > 257f || newpos.X < -1f || newpos.Y > 257f || newpos.Y < -1f)
1669 {
1670 m_parentGroup.AbsolutePosition = newpos;
1671 return;
1672 }
771 } 1673 }
1674 ScheduleTerseUpdate();
1675
1676 //SendTerseUpdateToAllClients();
772 } 1677 }
773 1678
774 #endregion 1679 public void PreloadSound(string sound)
1680 {
1681 LLUUID ownerID = OwnerID;
1682 LLUUID objectID = UUID;
1683 LLUUID soundID = LLUUID.Zero;
775 1684
776 public LLUUID ObjectOwner 1685 if (!LLUUID.TryParse(sound, out soundID))
1686 {
1687 //Trys to fetch sound id from prim's inventory.
1688 //Prim's inventory doesn't support non script items yet
1689 SceneObjectPart op = this;
1690 foreach (KeyValuePair<LLUUID, TaskInventoryItem> item in op.TaskInventory)
1691 {
1692 if (item.Value.Name == sound)
1693 {
1694 soundID = item.Value.ItemID;
1695 break;
1696 }
1697 }
1698 }
1699
1700 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars();
1701 foreach (ScenePresence p in avatarts)
1702 {
1703 // TODO: some filtering by distance of avatar
1704
1705 p.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
1706 }
1707 }
1708
1709 public void RemFlag(LLObject.ObjectFlags flag)
777 { 1710 {
778 get { return OwnerID; } 1711 LLObject.ObjectFlags prevflag = Flags;
1712 if ((ObjectFlags & (uint) flag) != 0)
1713 {
1714 //Console.WriteLine("Removing flag: " + ((LLObject.ObjectFlags)flag).ToString());
1715 Flags &= ~flag;
1716 }
1717 //System.Console.WriteLine("prev: " + prevflag.ToString() + " curr: " + Flags.ToString());
1718 //ScheduleFullUpdate();
779 } 1719 }
780 1720
781 // FIXME, TODO, ERROR: 'ParentGroup' can't be in here, move it out. 1721 public void RemoveScriptEvents(LLUUID scriptid)
782 protected SceneObjectGroup m_parentGroup; 1722 {
1723 lock (m_scriptEvents)
1724 {
1725 if (m_scriptEvents.ContainsKey(scriptid))
1726 {
1727 scriptEvents oldparts = scriptEvents.None;
1728 oldparts = (scriptEvents) m_scriptEvents[scriptid];
783 1729
784 public SceneObjectGroup ParentGroup 1730 // remove values from aggregated script events
1731 m_aggregateScriptEvents &= ~oldparts;
1732 m_scriptEvents.Remove(scriptid);
1733 }
1734 }
1735 aggregateScriptEvents();
1736 }
1737
1738 /// <summary>
1739 /// Reset LLUUIDs for this part. This involves generate this part's own LLUUID and
1740 /// generating new LLUUIDs for all the items in the inventory.
1741 /// </summary>
1742 /// <param name="linkNum">Link number for the part</param>
1743 public void ResetIDs(int linkNum)
785 { 1744 {
786 get { return m_parentGroup; } 1745 UUID = LLUUID.Random();
1746 LinkNum = linkNum;
1747
1748 ResetInventoryIDs();
787 } 1749 }
788 1750
789 public byte UpdateFlag 1751 /// <summary>
1752 /// Resize this part.
1753 /// </summary>
1754 /// <param name="scale"></param>
1755 public void Resize(LLVector3 scale)
790 { 1756 {
791 get { return m_updateFlag; } 1757 StoreUndoState();
792 set { m_updateFlag = value; } 1758 m_shape.Scale = scale;
1759
1760 ParentGroup.HasGroupChanged = true;
1761 ScheduleFullUpdate();
793 } 1762 }
794 1763
795 #region Constructors 1764 /// <summary>
1765 /// Schedules this prim for a full update
1766 /// </summary>
1767 public void ScheduleFullUpdate()
1768 {
1769 if (m_parentGroup != null)
1770 {
1771 m_parentGroup.QueueForUpdateCheck();
1772 }
1773
1774 int timeNow = Util.UnixTimeSinceEpoch();
1775
1776 // If multiple updates are scheduled on the same second, we still need to perform all of them
1777 // So we'll force the issue by bumping up the timestamp so that later processing sees these need
1778 // to be performed.
1779 if (timeNow <= TimeStampFull)
1780 {
1781 TimeStampFull += 1;
1782 }
1783 else
1784 {
1785 TimeStampFull = (uint)timeNow;
1786 }
1787
1788 m_updateFlag = 2;
1789
1790 // m_log.DebugFormat(
1791 // "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}",
1792 // UUID, Name, TimeStampFull);
1793 }
796 1794
797 /// <summary> 1795 /// <summary>
798 /// No arg constructor called by region restore db code 1796 /// Schedule a terse update for this prim. Terse updates only send position,
1797 /// rotation, velocity, rotational velocity and shape information.
799 /// </summary> 1798 /// </summary>
800 public SceneObjectPart() 1799 public void ScheduleTerseUpdate()
801 { 1800 {
802 // It's not necessary to persist this 1801 if (m_updateFlag < 1)
803 m_TextureAnimation = new byte[0]; 1802 {
1803 if (m_parentGroup != null)
1804 {
1805 m_parentGroup.HasGroupChanged = true;
1806 m_parentGroup.QueueForUpdateCheck();
1807 }
1808 TimeStampTerse = (uint) Util.UnixTimeSinceEpoch();
1809 m_updateFlag = 1;
1810
1811 // m_log.DebugFormat(
1812 // "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}",
1813 // UUID, Name, TimeStampTerse);
1814 }
804 } 1815 }
805 1816
806 public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, LLUUID ownerID, uint localID, 1817 public void ScriptSetPhantomStatus(bool Phantom)
807 PrimitiveBaseShape shape, LLVector3 groupPosition, LLVector3 offsetPosition) 1818 {
808 : this(regionHandle, parent, ownerID, localID, shape, groupPosition, LLQuaternion.Identity, offsetPosition) 1819 if (m_parentGroup != null)
1820 {
1821 m_parentGroup.ScriptSetPhantomStatus(Phantom);
1822 }
1823 }
1824
1825 public void ScriptSetPhysicsStatus(bool UsePhysics)
809 { 1826 {
1827 if (m_parentGroup != null)
1828 {
1829 m_parentGroup.ScriptSetPhysicsStatus(UsePhysics);
1830 }
1831 }
1832
1833 public void SculptTextureCallback(LLUUID textureID, AssetBase texture)
1834 {
1835 if (m_shape.SculptEntry)
1836 {
1837 if (texture != null)
1838 {
1839 m_shape.SculptData = texture.Data;
1840 if (PhysActor != null)
1841 {
1842 // Tricks physics engine into thinking we've changed the part shape.
1843 PrimitiveBaseShape m_newshape = m_shape.Copy();
1844 PhysActor.Shape = m_newshape;
1845 m_shape = m_newshape;
1846 }
1847 }
1848 }
810 } 1849 }
811 1850
812 /// <summary> 1851 /// <summary>
813 /// Create a completely new SceneObjectPart (prim) 1852 ///
814 /// </summary> 1853 /// </summary>
815 /// <param name="regionHandle"></param> 1854 /// <param name="remoteClient"></param>
816 /// <param name="parent"></param> 1855 public void SendFullUpdate(IClientAPI remoteClient, uint clientFlags)
817 /// <param name="ownerID"></param>
818 /// <param name="localID"></param>
819 /// <param name="shape"></param>
820 /// <param name="position"></param>
821 public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, LLUUID ownerID, uint localID,
822 PrimitiveBaseShape shape, LLVector3 groupPosition, LLQuaternion rotationOffset,
823 LLVector3 offsetPosition)
824 { 1856 {
825 m_name = "Primitive"; 1857 m_parentGroup.SendPartFullUpdate(remoteClient, this, clientFlags);
826 m_regionHandle = regionHandle; 1858 }
827 m_parentGroup = parent;
828 1859
829 CreationDate = (Int32) (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; 1860 /// <summary>
830 OwnerID = ownerID; 1861 ///
831 CreatorID = OwnerID; 1862 /// </summary>
832 LastOwnerID = LLUUID.Zero; 1863 public void SendFullUpdateToAllClients()
833 UUID = LLUUID.Random(); 1864 {
834 LocalId = (uint) (localID); 1865 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
835 Shape = shape; 1866 for (int i = 0; i < avatars.Count; i++)
836 // Todo: Add More Object Parameter from above! 1867 {
837 OwnershipCost = 0; 1868 // Ugly reference :(
838 ObjectSaleType = (byte) 0; 1869 m_parentGroup.SendPartFullUpdate(avatars[i].ControllingClient, this,
839 SalePrice = 0; 1870 avatars[i].GenerateClientFlags(UUID));
840 Category = (uint) 0; 1871 }
841 LastOwnerID = CreatorID; 1872 }
842 // End Todo: ///
843 GroupPosition = groupPosition;
844 OffsetPosition = offsetPosition;
845 RotationOffset = rotationOffset;
846 Velocity = new LLVector3(0, 0, 0);
847 m_rotationalvelocity = new LLVector3(0, 0, 0);
848 AngularVelocity = new LLVector3(0, 0, 0);
849 Acceleration = new LLVector3(0, 0, 0);
850 m_TextureAnimation = new byte[0];
851 1873
852 // Prims currently only contain a single folder (Contents). From looking at the Second Life protocol, 1874 public void SendFullUpdateToAllClientsExcept(LLUUID agentID)
853 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from 1875 {
854 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log 1876 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
1877 for (int i = 0; i < avatars.Count; i++)
1878 {
1879 // Ugly reference :(
1880 if (avatars[i].UUID != agentID)
1881 {
1882 m_parentGroup.SendPartFullUpdate(avatars[i].ControllingClient, this,
1883 avatars[i].GenerateClientFlags(UUID));
1884 }
1885 }
1886 }
855 1887
856 Flags = 0; 1888 /// <summary>
857 Flags |= LLObject.ObjectFlags.CreateSelected; 1889 /// Sends a full update to the client
1890 /// </summary>
1891 /// <param name="remoteClient"></param>
1892 /// <param name="clientFlags"></param>
1893 public void SendFullUpdateToClient(IClientAPI remoteClient, uint clientflags)
1894 {
1895 LLVector3 lPos;
1896 lPos = OffsetPosition;
1897 SendFullUpdateToClient(remoteClient, lPos, clientflags);
1898 }
858 1899
859 TrimPermissions(); 1900 /// <summary>
860 //m_undo = new UndoStack<UndoState>(ParentGroup.GetSceneMaxUndo()); 1901 /// Sends a full update to the client
1902 /// </summary>
1903 /// <param name="remoteClient"></param>
1904 /// <param name="lPos"></param>
1905 /// <param name="clientFlags"></param>
1906 public void SendFullUpdateToClient(IClientAPI remoteClient, LLVector3 lPos, uint clientFlags)
1907 {
1908 clientFlags &= ~(uint) LLObject.ObjectFlags.CreateSelected;
861 1909
862 ScheduleFullUpdate(); 1910 if (remoteClient.AgentId == OwnerID)
1911 {
1912 if ((uint) (Flags & LLObject.ObjectFlags.CreateSelected) != 0)
1913 {
1914 clientFlags |= (uint) LLObject.ObjectFlags.CreateSelected;
1915 Flags &= ~LLObject.ObjectFlags.CreateSelected;
1916 }
1917 }
1918
1919 byte[] color = new byte[] {m_color.R, m_color.G, m_color.B, m_color.A};
1920 remoteClient.SendPrimitiveToClient(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, m_shape,
1921 lPos, Velocity, Acceleration, RotationOffset, RotationalVelocity, clientFlags, m_uuid, OwnerID,
1922 m_text, color, ParentID, m_particleSystem, m_clickAction, m_TextureAnimation, m_IsAttachment,
1923 m_attachmentPoint,fromAssetID, Sound, SoundGain, SoundFlags, SoundRadius);
863 } 1924 }
864 1925
865 /// <summary> 1926 /// <summary>
866 /// Re/create a SceneObjectPart (prim) 1927 /// Tell all the prims which have had updates scheduled
867 /// currently not used, and maybe won't be
868 /// </summary> 1928 /// </summary>
869 /// <param name="regionHandle"></param> 1929 public void SendScheduledUpdates()
870 /// <param name="parent"></param>
871 /// <param name="ownerID"></param>
872 /// <param name="localID"></param>
873 /// <param name="shape"></param>
874 /// <param name="position"></param>
875 public SceneObjectPart(ulong regionHandle, SceneObjectGroup parent, int creationDate, LLUUID ownerID,
876 LLUUID creatorID, LLUUID lastOwnerID, uint localID, PrimitiveBaseShape shape,
877 LLVector3 position, LLQuaternion rotation, uint flags)
878 { 1930 {
879 m_regionHandle = regionHandle; 1931 if (m_updateFlag == 1) //some change has been made so update the clients
880 m_parentGroup = parent; 1932 {
881 TimeStampTerse = (uint) Util.UnixTimeSinceEpoch(); 1933 AddTerseUpdateToAllAvatars();
882 CreationDate = creationDate; 1934 ClearUpdateSchedule();
883 OwnerID = ownerID;
884 CreatorID = creatorID;
885 LastOwnerID = lastOwnerID;
886 UUID = LLUUID.Random();
887 LocalId = (uint) (localID);
888 Shape = shape;
889 OwnershipCost = 0;
890 ObjectSaleType = (byte) 0;
891 SalePrice = 0;
892 Category = (uint) 0;
893 LastOwnerID = CreatorID;
894 OffsetPosition = position;
895 RotationOffset = rotation;
896 ObjectFlags = flags;
897 1935
898 // Since we don't store script state, this is only a 'temporary' objectflag now 1936 // This causes the Scene to 'poll' physical objects every couple of frames
899 // If the object is scripted, the script will get loaded and this will be set again 1937 // bad, so it's been replaced by an event driven method.
900 ObjectFlags &= ~(uint)(LLObject.ObjectFlags.Scripted | LLObject.ObjectFlags.Touch); 1938 //if ((ObjectFlags & (uint)LLObject.ObjectFlags.Physics) != 0)
1939 //{
1940 // Only send the constant terse updates on physical objects!
1941 //ScheduleTerseUpdate();
1942 //}
1943 }
1944 else
1945 {
1946 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
1947 {
1948 AddFullUpdateToAllAvatars();
1949 ClearUpdateSchedule();
1950 }
1951 }
1952 }
901 1953
902 TrimPermissions(); 1954 public void SendSound(string sound, double volume, bool triggered, byte flags)
903 // ApplyPhysics(); 1955 {
1956 if (volume > 1)
1957 volume = 1;
1958 if (volume < 0)
1959 volume = 0;
904 1960
905 ScheduleFullUpdate(); 1961 LLUUID ownerID = OwnerID;
1962 LLUUID objectID = UUID;
1963 LLUUID parentID = GetRootPartUUID();
1964 LLUUID soundID = LLUUID.Zero;
1965 LLVector3 position = AbsolutePosition; // region local
1966 ulong regionHandle = m_parentGroup.Scene.RegionInfo.RegionHandle;
1967
1968 //byte flags = 0;
1969
1970 if (!LLUUID.TryParse(sound, out soundID))
1971 {
1972 // search sound file from inventory
1973 SceneObjectPart op = this;
1974 foreach (KeyValuePair<LLUUID, TaskInventoryItem> item in op.TaskInventory)
1975 {
1976 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
1977 {
1978 soundID = item.Value.ItemID;
1979 break;
1980 }
1981 }
1982 }
1983
1984 if (soundID == LLUUID.Zero)
1985 return;
1986
1987 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars();
1988 foreach (ScenePresence p in avatarts)
1989 {
1990 double dis=Util.GetDistanceTo(p.AbsolutePosition, position);
1991 if (dis > 100.0) // Max audio distance
1992 continue;
1993
1994 // Scale by distance
1995 volume*=((100.0-dis)/100.0);
1996
1997 if (triggered)
1998 {
1999 p.ControllingClient.SendTriggeredSound(soundID, ownerID, objectID, parentID, regionHandle, position, (float)volume);
2000 }
2001 else
2002 {
2003 p.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)volume, flags);
2004 }
2005 }
906 } 2006 }
907 2007
908 #endregion 2008 /// <summary>
2009 /// Send a terse update to the client.
2010 /// </summary>
2011 /// <param name="remoteClient"></param>
2012 public void SendTerseUpdate(IClientAPI remoteClient)
2013 {
2014 m_parentGroup.SendPartTerseUpdate(remoteClient, this);
2015 }
909 2016
910 /// <summary> 2017 /// <summary>
911 /// Restore this part from the serialized xml representation. 2018 ///
912 /// </summary> 2019 /// </summary>
913 /// <param name="xmlreader"></param> 2020 public void SendTerseUpdateToAllClients()
914 /// <returns></returns>
915 public static SceneObjectPart FromXml(XmlReader xmlReader)
916 { 2021 {
917 // It's not necessary to persist this 2022 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
2023 for (int i = 0; i < avatars.Count; i++)
2024 {
2025 m_parentGroup.SendPartTerseUpdate(avatars[i].ControllingClient, this);
2026 }
2027 }
918 2028
919 XmlSerializer serializer = new XmlSerializer(typeof (SceneObjectPart)); 2029 public void SendTerseUpdateToClient(IClientAPI remoteClient)
920 SceneObjectPart newobject = (SceneObjectPart) serializer.Deserialize(xmlReader); 2030 {
921 return newobject; 2031 LLVector3 lPos;
2032 lPos = OffsetPosition;
2033 LLQuaternion mRot = RotationOffset;
2034 // TODO: I have no idea why we are making this check. This should be sorted out
2035 if ((ObjectFlags & (uint) LLObject.ObjectFlags.Physics) == 0)
2036 {
2037 remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, Shape.State, fromAssetID);
2038 }
2039 else
2040 {
2041 remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity,
2042 RotationalVelocity);
2043 //System.Console.WriteLine("LID: " + LocalID + " RVel:" + RotationalVelocity.ToString() + " TD: " + ((ushort)(m_parentGroup.Scene.TimeDilation * 500000f)).ToString() + ":" + m_parentGroup.Scene.TimeDilation.ToString());
2044 }
2045 }
2046
2047 public void SendTerseUpdateToClient(IClientAPI remoteClient, LLVector3 lPos)
2048 {
2049 LLQuaternion mRot = RotationOffset;
2050 if (m_IsAttachment)
2051 {
2052 remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, (byte)((m_attachmentPoint % 16) * 16 + (m_attachmentPoint / 16)),fromAssetID);
2053 }
2054 else
2055 {
2056 if ((ObjectFlags & (uint)LLObject.ObjectFlags.Physics) == 0)
2057 {
2058 remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, Shape.State, fromAssetID);
2059 }
2060 else
2061 {
2062 remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity,
2063 RotationalVelocity);
2064 //System.Console.WriteLine("LID: " + LocalID + "RVel:" + RotationalVelocity.ToString() + " TD: " + ((ushort)(m_parentGroup.Scene.TimeDilation * 500000f)).ToString() + ":" + m_parentGroup.Scene.TimeDilation.ToString());
2065 }
2066 }
2067 }
2068
2069 public void SetAttachmentPoint(uint AttachmentPoint)
2070 {
2071 m_attachmentPoint = AttachmentPoint;
2072
2073 // save the attachment point.
2074 //if (AttachmentPoint != 0)
2075 //{
2076 m_shape.State = (byte)AttachmentPoint;
2077 //}
2078 }
2079
2080 public void SetAvatarOnSitTarget(LLUUID avatarID)
2081 {
2082 m_sitTargetAvatar = avatarID;
2083 TriggerScriptChangedEvent(Changed.LINK);
2084 }
2085
2086 public void SetAxisRotation(int axis, int rotate)
2087 {
2088 if (m_parentGroup != null)
2089 {
2090 m_parentGroup.SetAxisRotation(axis, rotate);
2091 }
2092 }
2093
2094 public void SetBuoyancy(float fvalue)
2095 {
2096 if (PhysActor != null)
2097 {
2098 PhysActor.Buoyancy = fvalue;
2099 }
2100 }
2101
2102 public void SetDieAtEdge(bool p)
2103 {
2104 if (m_parentGroup == null)
2105 return;
2106 if (m_parentGroup.RootPart == null)
2107 return;
2108
2109 m_parentGroup.RootPart.DIE_AT_EDGE = p;
2110 }
2111
2112 public void SetFloatOnWater(int floatYN)
2113 {
2114 if (PhysActor != null)
2115 {
2116 if (floatYN == 1)
2117 {
2118 PhysActor.FloatOnWater = true;
2119 }
2120 else
2121 {
2122 PhysActor.FloatOnWater = false;
2123 }
2124 }
2125 }
2126
2127 public void SetGroup(LLUUID groupID, IClientAPI client)
2128 {
2129 GroupID = groupID;
2130 GetProperties(client);
2131 m_updateFlag = 2;
922 } 2132 }
923 2133
924 /// <summary> 2134 /// <summary>
925 /// Apply physics to this part. 2135 ///
926 /// </summary> 2136 /// </summary>
927 /// <param name="rootObjectFlags"></param> 2137 public void SetParent(SceneObjectGroup parent)
928 /// <param name="m_physicalPrim"></param>
929 public void ApplyPhysics(uint rootObjectFlags, bool m_physicalPrim)
930 { 2138 {
931 bool isPhysical = (((rootObjectFlags & (uint) LLObject.ObjectFlags.Physics) != 0) && m_physicalPrim); 2139 m_parentGroup = parent;
932 bool isPhantom = ((rootObjectFlags & (uint) LLObject.ObjectFlags.Phantom) != 0); 2140 }
933 2141
934 // Added clarification.. since A rigid body is an object that you can kick around, etc. 2142 // Use this for attachments! LocalID should be avatar's localid
935 bool RigidBody = isPhysical && !isPhantom; 2143 public void SetParentLocalId(uint localID)
2144 {
2145 ParentID = localID;
2146 }
936 2147
937 // The only time the physics scene shouldn't know about the prim is if it's phantom 2148 public void SetPhysicsAxisRotation()
938 if (!isPhantom) 2149 {
2150 PhysActor.LockAngularMotion(m_rotationAxis);
2151 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
2152 }
2153
2154 public void SetScriptEvents(LLUUID scriptid, int events)
2155 {
2156 scriptEvents oldparts;
2157 lock (m_scriptEvents)
939 { 2158 {
940 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( 2159 if (m_scriptEvents.ContainsKey(scriptid))
941 Name, 2160 {
942 Shape, 2161 oldparts = m_scriptEvents[scriptid];
943 new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y,
944 AbsolutePosition.Z),
945 new PhysicsVector(Scale.X, Scale.Y, Scale.Z),
946 new Quaternion(RotationOffset.W, RotationOffset.X,
947 RotationOffset.Y, RotationOffset.Z), RigidBody);
948 2162
949 // Basic Physics returns null.. joy joy joy. 2163 // remove values from aggregated script events
950 if (PhysActor != null) 2164 m_scriptEvents[scriptid] = (scriptEvents) events;
2165 }
2166 else
951 { 2167 {
952 PhysActor.LocalID = LocalId; 2168 m_scriptEvents.Add(scriptid, (scriptEvents) events);
953 DoPhysicsPropertyUpdate(RigidBody, true);
954 } 2169 }
955 } 2170 }
2171 aggregateScriptEvents();
956 } 2172 }
957 2173
958 public void TrimPermissions() 2174 public void SetSitTarget(Vector3 offset, Quaternion orientation)
959 { 2175 {
2176 m_sitTargetPosition = offset;
2177 m_sitTargetOrientation = orientation;
2178 }
960 2179
961 BaseMask &= (uint)PermissionMask.All; 2180 // Utility function so the databases don't have to reference axiom.math
962 OwnerMask &= (uint)PermissionMask.All; 2181 public void SetSitTargetLL(LLVector3 offset, LLQuaternion orientation)
963 GroupMask &= (uint)PermissionMask.All; 2182 {
964 EveryoneMask &= (uint)PermissionMask.All; 2183 if (
965 NextOwnerMask &= (uint)PermissionMask.All; 2184 !(offset.X == 0 && offset.Y == 0 && offset.Z == 0 && (orientation.W == 0 || orientation.W == 1) &&
2185 orientation.X == 0 && orientation.Y == 0 && orientation.Z == 0))
2186 {
2187 m_sitTargetPosition = new Vector3(offset.X, offset.Y, offset.Z);
2188 m_sitTargetOrientation = new Quaternion(orientation.W, orientation.X, orientation.Y, orientation.Z);
2189 }
2190 }
966 2191
2192 /// <summary>
2193 /// Set the text displayed for this part.
2194 /// </summary>
2195 /// <param name="text"></param>
2196 public void SetText(string text)
2197 {
2198 Text = text;
2199
2200 ParentGroup.HasGroupChanged = true;
2201 ScheduleFullUpdate();
967 } 2202 }
968 2203
969 /// <summary> 2204 /// <summary>
970 /// Serialize this part to xml. 2205 /// Set the text displayed for this part.
971 /// </summary> 2206 /// </summary>
972 /// <param name="xmlWriter"></param> 2207 /// <param name="text"></param>
973 public void ToXml(XmlWriter xmlWriter) 2208 /// <param name="color"></param>
2209 /// <param name="alpha"></param>
2210 public void SetText(string text, Vector3 color, double alpha)
974 { 2211 {
975 XmlSerializer serializer = new XmlSerializer(typeof (SceneObjectPart)); 2212 Color = Color.FromArgb(0xff - (int) (alpha*0xff),
976 serializer.Serialize(xmlWriter, this); 2213 (int) (color.x*0xff),
2214 (int) (color.y*0xff),
2215 (int) (color.z*0xff));
2216 SetText(text);
2217 }
2218
2219 public void StopMoveToTarget()
2220 {
2221 m_parentGroup.stopMoveToTarget();
2222 }
2223
2224 public void StoreUndoState()
2225 {
2226 if (!m_undoing)
2227 {
2228 if (m_parentGroup != null)
2229 {
2230 if (m_undo.Count > 0)
2231 {
2232 UndoState last = m_undo.Peek();
2233 if (last != null)
2234 {
2235 if (last.Compare(this))
2236 return;
2237 }
2238 }
2239
2240
2241 if (m_parentGroup.GetSceneMaxUndo() > 0)
2242 {
2243 UndoState nUndo = new UndoState(this);
2244
2245 m_undo.Push(nUndo);
2246
2247 }
2248 }
2249 }
977 } 2250 }
978 2251
979 public EntityIntersection TestIntersection(Ray iray, Quaternion parentrot) 2252 public EntityIntersection TestIntersection(Ray iray, Quaternion parentrot)
@@ -1086,14 +2359,6 @@ namespace OpenSim.Region.Environment.Scenes
1086 return returnresult; 2359 return returnresult;
1087 } 2360 }
1088 2361
1089 public double GetDistanceTo(Vector3 a, Vector3 b)
1090 {
1091 float dx = a.x - b.x;
1092 float dy = a.y - b.y;
1093 float dz = a.z - b.z;
1094 return Math.Sqrt(dx * dx + dy * dy + dz * dz);
1095 }
1096
1097 public EntityIntersection TestIntersectionOBB(Ray iray, Quaternion parentrot, bool frontFacesOnly, bool faceCenters) 2362 public EntityIntersection TestIntersectionOBB(Ray iray, Quaternion parentrot, bool frontFacesOnly, bool faceCenters)
1098 { 2363 {
1099 // In this case we're using a rectangular prism, which has 6 faces and therefore 6 planes 2364 // In this case we're using a rectangular prism, which has 6 faces and therefore 6 planes
@@ -1183,7 +2448,7 @@ namespace OpenSim.Region.Environment.Scenes
1183 tScale = new Vector3(AXscale.x, -AXscale.y, AXscale.z); 2448 tScale = new Vector3(AXscale.x, -AXscale.y, AXscale.z);
1184 rScale = ((AXrot * tScale)); 2449 rScale = ((AXrot * tScale));
1185 vertexes[0] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); 2450 vertexes[0] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z)));
1186 // vertexes[0].x = pos.X + vertexes[0].x; 2451 // vertexes[0].x = pos.X + vertexes[0].x;
1187 //vertexes[0].y = pos.Y + vertexes[0].y; 2452 //vertexes[0].y = pos.Y + vertexes[0].y;
1188 //vertexes[0].z = pos.Z + vertexes[0].z; 2453 //vertexes[0].z = pos.Z + vertexes[0].z;
1189 2454
@@ -1195,8 +2460,8 @@ namespace OpenSim.Region.Environment.Scenes
1195 rScale = ((AXrot * tScale)); 2460 rScale = ((AXrot * tScale));
1196 vertexes[1] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); 2461 vertexes[1] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z)));
1197 2462
1198 // vertexes[1].x = pos.X + vertexes[1].x; 2463 // vertexes[1].x = pos.X + vertexes[1].x;
1199 // vertexes[1].y = pos.Y + vertexes[1].y; 2464 // vertexes[1].y = pos.Y + vertexes[1].y;
1200 //vertexes[1].z = pos.Z + vertexes[1].z; 2465 //vertexes[1].z = pos.Z + vertexes[1].z;
1201 2466
1202 FaceB[0] = vertexes[1]; 2467 FaceB[0] = vertexes[1];
@@ -1221,8 +2486,8 @@ namespace OpenSim.Region.Environment.Scenes
1221 vertexes[3] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); 2486 vertexes[3] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z)));
1222 2487
1223 //vertexes[3].x = pos.X + vertexes[3].x; 2488 //vertexes[3].x = pos.X + vertexes[3].x;
1224 // vertexes[3].y = pos.Y + vertexes[3].y; 2489 // vertexes[3].y = pos.Y + vertexes[3].y;
1225 // vertexes[3].z = pos.Z + vertexes[3].z; 2490 // vertexes[3].z = pos.Z + vertexes[3].z;
1226 2491
1227 FaceD[0] = vertexes[3]; 2492 FaceD[0] = vertexes[3];
1228 FaceC[1] = vertexes[3]; 2493 FaceC[1] = vertexes[3];
@@ -1232,9 +2497,9 @@ namespace OpenSim.Region.Environment.Scenes
1232 rScale = ((AXrot * tScale)); 2497 rScale = ((AXrot * tScale));
1233 vertexes[4] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); 2498 vertexes[4] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z)));
1234 2499
1235 // vertexes[4].x = pos.X + vertexes[4].x; 2500 // vertexes[4].x = pos.X + vertexes[4].x;
1236 // vertexes[4].y = pos.Y + vertexes[4].y; 2501 // vertexes[4].y = pos.Y + vertexes[4].y;
1237 // vertexes[4].z = pos.Z + vertexes[4].z; 2502 // vertexes[4].z = pos.Z + vertexes[4].z;
1238 2503
1239 FaceB[1] = vertexes[4]; 2504 FaceB[1] = vertexes[4];
1240 FaceA[2] = vertexes[4]; 2505 FaceA[2] = vertexes[4];
@@ -1244,9 +2509,9 @@ namespace OpenSim.Region.Environment.Scenes
1244 rScale = ((AXrot * tScale)); 2509 rScale = ((AXrot * tScale));
1245 vertexes[5] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); 2510 vertexes[5] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z)));
1246 2511
1247 // vertexes[5].x = pos.X + vertexes[5].x; 2512 // vertexes[5].x = pos.X + vertexes[5].x;
1248 // vertexes[5].y = pos.Y + vertexes[5].y; 2513 // vertexes[5].y = pos.Y + vertexes[5].y;
1249 // vertexes[5].z = pos.Z + vertexes[5].z; 2514 // vertexes[5].z = pos.Z + vertexes[5].z;
1250 2515
1251 FaceD[1] = vertexes[5]; 2516 FaceD[1] = vertexes[5];
1252 FaceC[2] = vertexes[5]; 2517 FaceC[2] = vertexes[5];
@@ -1256,9 +2521,9 @@ namespace OpenSim.Region.Environment.Scenes
1256 rScale = ((AXrot * tScale)); 2521 rScale = ((AXrot * tScale));
1257 vertexes[6] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); 2522 vertexes[6] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z)));
1258 2523
1259 // vertexes[6].x = pos.X + vertexes[6].x; 2524 // vertexes[6].x = pos.X + vertexes[6].x;
1260 // vertexes[6].y = pos.Y + vertexes[6].y; 2525 // vertexes[6].y = pos.Y + vertexes[6].y;
1261 // vertexes[6].z = pos.Z + vertexes[6].z; 2526 // vertexes[6].z = pos.Z + vertexes[6].z;
1262 2527
1263 FaceB[2] = vertexes[6]; 2528 FaceB[2] = vertexes[6];
1264 FaceA[3] = vertexes[6]; 2529 FaceA[3] = vertexes[6];
@@ -1268,9 +2533,9 @@ namespace OpenSim.Region.Environment.Scenes
1268 rScale = ((AXrot * tScale)); 2533 rScale = ((AXrot * tScale));
1269 vertexes[7] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z))); 2534 vertexes[7] = (new Vector3((pos.X + rScale.x), (pos.Y + rScale.y), (pos.Z + rScale.z)));
1270 2535
1271 // vertexes[7].x = pos.X + vertexes[7].x; 2536 // vertexes[7].x = pos.X + vertexes[7].x;
1272 // vertexes[7].y = pos.Y + vertexes[7].y; 2537 // vertexes[7].y = pos.Y + vertexes[7].y;
1273 // vertexes[7].z = pos.Z + vertexes[7].z; 2538 // vertexes[7].z = pos.Z + vertexes[7].z;
1274 2539
1275 FaceD[2] = vertexes[7]; 2540 FaceD[2] = vertexes[7];
1276 FaceC[3] = vertexes[7]; 2541 FaceC[3] = vertexes[7];
@@ -1352,7 +2617,7 @@ namespace OpenSim.Region.Environment.Scenes
1352 //if (fmax > 0) 2617 //if (fmax > 0)
1353 // a= fmax; 2618 // a= fmax;
1354 //else 2619 //else
1355 // a=fmin; 2620 // a=fmin;
1356 2621
1357 //q = iray.Origin + a * iray.Direction; 2622 //q = iray.Origin + a * iray.Direction;
1358 #endregion 2623 #endregion
@@ -1437,370 +2702,122 @@ namespace OpenSim.Region.Environment.Scenes
1437 return returnresult; 2702 return returnresult;
1438 } 2703 }
1439 2704
1440 // Use this for attachments! LocalID should be avatar's localid
1441 public void SetParentLocalId(uint localID)
1442 {
1443 ParentID = localID;
1444 }
1445
1446 public void SetAttachmentPoint(uint AttachmentPoint)
1447 {
1448 m_attachmentPoint = AttachmentPoint;
1449
1450 // save the attachment point.
1451 //if (AttachmentPoint != 0)
1452 //{
1453 m_shape.State = (byte)AttachmentPoint;
1454 //}
1455 }
1456
1457 /// <summary> 2705 /// <summary>
1458 /// 2706 /// Serialize this part to xml.
1459 /// </summary> 2707 /// </summary>
1460 public void SetParent(SceneObjectGroup parent) 2708 /// <param name="xmlWriter"></param>
1461 { 2709 public void ToXml(XmlWriter xmlWriter)
1462 m_parentGroup = parent;
1463 }
1464
1465 public void SetSitTarget(Vector3 offset, Quaternion orientation)
1466 {
1467 m_sitTargetPosition = offset;
1468 m_sitTargetOrientation = orientation;
1469 }
1470
1471 public void SetBuoyancy(float fvalue)
1472 { 2710 {
1473 if (PhysActor != null) 2711 XmlSerializer serializer = new XmlSerializer(typeof (SceneObjectPart));
1474 { 2712 serializer.Serialize(xmlWriter, this);
1475 PhysActor.Buoyancy = fvalue;
1476 }
1477 } 2713 }
1478 2714
1479 public void SetAxisRotation(int axis, int rotate) 2715 public void TriggerScriptChangedEvent(Changed val)
1480 { 2716 {
1481 if (m_parentGroup != null) 2717 if (m_parentGroup != null)
1482 { 2718 {
1483 m_parentGroup.SetAxisRotation(axis, rotate); 2719 if (m_parentGroup.Scene != null)
1484 } 2720 m_parentGroup.Scene.TriggerObjectChanged(LocalId, (uint)val);
1485 }
1486
1487 public void SetPhysicsAxisRotation()
1488 {
1489 PhysActor.LockAngularMotion(m_rotationAxis);
1490 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
1491 }
1492
1493 public void SetFloatOnWater(int floatYN)
1494 {
1495 if (PhysActor != null)
1496 {
1497 if (floatYN == 1)
1498 {
1499 PhysActor.FloatOnWater = true;
1500 }
1501 else
1502 {
1503 PhysActor.FloatOnWater = false;
1504 }
1505 }
1506 }
1507
1508 public LLVector3 GetSitTargetPositionLL()
1509 {
1510 return new LLVector3(m_sitTargetPosition.x, m_sitTargetPosition.y, m_sitTargetPosition.z);
1511 }
1512
1513 public LLQuaternion GetSitTargetOrientationLL()
1514 {
1515 return
1516 new LLQuaternion(m_sitTargetOrientation.x, m_sitTargetOrientation.y, m_sitTargetOrientation.z,
1517 m_sitTargetOrientation.w);
1518 }
1519
1520 // Utility function so the databases don't have to reference axiom.math
1521 public void SetSitTargetLL(LLVector3 offset, LLQuaternion orientation)
1522 {
1523 if (
1524 !(offset.X == 0 && offset.Y == 0 && offset.Z == 0 && (orientation.W == 0 || orientation.W == 1) &&
1525 orientation.X == 0 && orientation.Y == 0 && orientation.Z == 0))
1526 {
1527 m_sitTargetPosition = new Vector3(offset.X, offset.Y, offset.Z);
1528 m_sitTargetOrientation = new Quaternion(orientation.W, orientation.X, orientation.Y, orientation.Z);
1529 } 2721 }
1530 } 2722 }
1531 2723
1532 public Vector3 GetSitTargetPosition() 2724 public void TrimPermissions()
1533 {
1534 return m_sitTargetPosition;
1535 }
1536
1537 public Quaternion GetSitTargetOrientation()
1538 {
1539 return m_sitTargetOrientation;
1540 }
1541
1542 public void SetAvatarOnSitTarget(LLUUID avatarID)
1543 {
1544 m_sitTargetAvatar = avatarID;
1545 TriggerScriptChangedEvent(Changed.LINK);
1546 }
1547
1548 public LLUUID GetAvatarOnSitTarget()
1549 { 2725 {
1550 return m_sitTargetAvatar; 2726 BaseMask &= (uint)PermissionMask.All;
2727 OwnerMask &= (uint)PermissionMask.All;
2728 GroupMask &= (uint)PermissionMask.All;
2729 EveryoneMask &= (uint)PermissionMask.All;
2730 NextOwnerMask &= (uint)PermissionMask.All;
1551 } 2731 }
1552 2732
1553 public LLUUID GetRootPartUUID() 2733 public void Undo()
1554 { 2734 {
1555 if (m_parentGroup != null) 2735 if (m_undo.Count > 0)
1556 { 2736 {
1557 return m_parentGroup.UUID; 2737 UndoState goback = m_undo.Pop();
2738 if (goback != null)
2739 goback.PlaybackState(this);
1558 } 2740 }
1559 return LLUUID.Zero;
1560 }
1561
1562 public static SceneObjectPart Create()
1563 {
1564 SceneObjectPart part = new SceneObjectPart();
1565 part.UUID = LLUUID.Random();
1566
1567 PrimitiveBaseShape shape = PrimitiveBaseShape.Create();
1568 part.Shape = shape;
1569
1570 part.Name = "Primitive";
1571 part.OwnerID = LLUUID.Random();
1572
1573 return part;
1574 } 2741 }
1575 2742
1576 #region Copying 2743 public void UpdateExtraParam(ushort type, bool inUse, byte[] data)
1577
1578 /// <summary>
1579 /// Duplicates this part.
1580 /// </summary>
1581 /// <returns></returns>
1582 public SceneObjectPart Copy(uint localID, LLUUID AgentID, LLUUID GroupID, int linkNum, bool userExposed)
1583 { 2744 {
1584 SceneObjectPart dupe = (SceneObjectPart) MemberwiseClone(); 2745 m_shape.ReadInUpdateExtraParam(type, inUse, data);
1585 dupe.m_shape = m_shape.Copy();
1586 dupe.m_regionHandle = m_regionHandle;
1587 if (userExposed)
1588 dupe.UUID = LLUUID.Random();
1589
1590 dupe.LocalId = localID;
1591 dupe.OwnerID = AgentID;
1592 dupe.GroupID = GroupID;
1593 dupe.GroupPosition = new LLVector3(GroupPosition.X, GroupPosition.Y, GroupPosition.Z);
1594 dupe.OffsetPosition = new LLVector3(OffsetPosition.X, OffsetPosition.Y, OffsetPosition.Z);
1595 dupe.RotationOffset =
1596 new LLQuaternion(RotationOffset.X, RotationOffset.Y, RotationOffset.Z, RotationOffset.W);
1597 dupe.Velocity = new LLVector3(0, 0, 0);
1598 dupe.Acceleration = new LLVector3(0, 0, 0);
1599 dupe.AngularVelocity = new LLVector3(0, 0, 0);
1600 dupe.ObjectFlags = ObjectFlags;
1601
1602 dupe.OwnershipCost = OwnershipCost;
1603 dupe.ObjectSaleType = ObjectSaleType;
1604 dupe.SalePrice = SalePrice;
1605 dupe.Category = Category;
1606
1607 dupe.TaskInventory = (TaskInventoryDictionary)dupe.TaskInventory.Clone();
1608
1609 if (userExposed)
1610 dupe.ResetIDs(linkNum);
1611
1612 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1613 dupe.LastOwnerID = ObjectOwner;
1614
1615 byte[] extraP = new byte[Shape.ExtraParams.Length];
1616 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
1617 dupe.Shape.ExtraParams = extraP;
1618 2746
1619 if (userExposed) 2747 if (type == 0x30)
1620 { 2748 {
1621 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != LLUUID.Zero) 2749 if (m_shape.SculptEntry && m_shape.SculptTexture != LLUUID.Zero)
1622 { 2750 {
1623 m_parentGroup.Scene.AssetCache.GetAsset(dupe.m_shape.SculptTexture, dupe.SculptTextureCallback, true); 2751 //AssetBase tx = m_parentGroup.Scene.getase
2752 m_parentGroup.Scene.AssetCache.GetAsset(m_shape.SculptTexture, SculptTextureCallback, true);
1624 } 2753 }
1625 bool UsePhysics = ((dupe.ObjectFlags & (uint)LLObject.ObjectFlags.Physics) != 0);
1626 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
1627 } 2754 }
1628 return dupe;
1629 }
1630 2755
1631 #endregion 2756 ParentGroup.HasGroupChanged = true;
1632 2757 ScheduleFullUpdate();
1633 /// <summary>
1634 /// Reset LLUUIDs for this part. This involves generate this part's own LLUUID and
1635 /// generating new LLUUIDs for all the items in the inventory.
1636 /// </summary>
1637 /// <param name="linkNum">Link number for the part</param>
1638 public void ResetIDs(int linkNum)
1639 {
1640 UUID = LLUUID.Random();
1641 LinkNum = linkNum;
1642
1643 ResetInventoryIDs();
1644 }
1645
1646 #region Update Scheduling
1647
1648 /// <summary>
1649 /// Clear all pending updates
1650 /// </summary>
1651 private void ClearUpdateSchedule()
1652 {
1653 m_updateFlag = 0;
1654 }
1655
1656 /// <summary>
1657 /// Schedules this prim for a full update
1658 /// </summary>
1659 public void ScheduleFullUpdate()
1660 {
1661 if (m_parentGroup != null)
1662 {
1663 m_parentGroup.QueueForUpdateCheck();
1664 }
1665
1666 int timeNow = Util.UnixTimeSinceEpoch();
1667
1668 // If multiple updates are scheduled on the same second, we still need to perform all of them
1669 // So we'll force the issue by bumping up the timestamp so that later processing sees these need
1670 // to be performed.
1671 if (timeNow <= TimeStampFull)
1672 {
1673 TimeStampFull += 1;
1674 }
1675 else
1676 {
1677 TimeStampFull = (uint)timeNow;
1678 }
1679
1680 m_updateFlag = 2;
1681
1682// m_log.DebugFormat(
1683// "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}",
1684// UUID, Name, TimeStampFull);
1685 } 2758 }
1686 2759
1687 public void AddFlag(LLObject.ObjectFlags flag) 2760 public void UpdateGroupPosition(LLVector3 pos)
1688 { 2761 {
1689 LLObject.ObjectFlags prevflag = Flags; 2762 if ((pos.X != GroupPosition.X) ||
1690 //uint objflags = Flags; 2763 (pos.Y != GroupPosition.Y) ||
1691 if ((ObjectFlags & (uint) flag) == 0) 2764 (pos.Z != GroupPosition.Z))
1692 { 2765 {
1693 //Console.WriteLine("Adding flag: " + ((LLObject.ObjectFlags) flag).ToString()); 2766 LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z);
1694 Flags |= flag; 2767 GroupPosition = newPos;
2768 ScheduleTerseUpdate();
1695 } 2769 }
1696 //uint currflag = (uint)Flags;
1697 //System.Console.WriteLine("Aprev: " + prevflag.ToString() + " curr: " + Flags.ToString());
1698 //ScheduleFullUpdate();
1699 } 2770 }
1700 2771
1701 public void RemFlag(LLObject.ObjectFlags flag) 2772 public virtual void UpdateMovement()
1702 { 2773 {
1703 LLObject.ObjectFlags prevflag = Flags;
1704 if ((ObjectFlags & (uint) flag) != 0)
1705 {
1706 //Console.WriteLine("Removing flag: " + ((LLObject.ObjectFlags)flag).ToString());
1707 Flags &= ~flag;
1708 }
1709 //System.Console.WriteLine("prev: " + prevflag.ToString() + " curr: " + Flags.ToString());
1710 //ScheduleFullUpdate();
1711 } 2774 }
1712 2775
1713 /// <summary> 2776 /// <summary>
1714 /// Schedule a terse update for this prim. Terse updates only send position, 2777 ///
1715 /// rotation, velocity, rotational velocity and shape information.
1716 /// </summary> 2778 /// </summary>
1717 public void ScheduleTerseUpdate() 2779 /// <param name="pos"></param>
2780 public void UpdateOffSet(LLVector3 pos)
1718 { 2781 {
1719 if (m_updateFlag < 1) 2782 if ((pos.X != OffsetPosition.X) ||
2783 (pos.Y != OffsetPosition.Y) ||
2784 (pos.Z != OffsetPosition.Z))
1720 { 2785 {
1721 if (m_parentGroup != null) 2786 LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z);
1722 { 2787 OffsetPosition = newPos;
1723 m_parentGroup.HasGroupChanged = true; 2788 ScheduleTerseUpdate();
1724 m_parentGroup.QueueForUpdateCheck();
1725 }
1726 TimeStampTerse = (uint) Util.UnixTimeSinceEpoch();
1727 m_updateFlag = 1;
1728
1729// m_log.DebugFormat(
1730// "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}",
1731// UUID, Name, TimeStampTerse);
1732 } 2789 }
1733 } 2790 }
1734 2791
1735 /// <summary> 2792 public void UpdatePermissions(LLUUID AgentID, byte field, uint localID, uint mask, byte addRemTF)
1736 /// Tell all the prims which have had updates scheduled
1737 /// </summary>
1738 public void SendScheduledUpdates()
1739 { 2793 {
1740 if (m_updateFlag == 1) //some change has been made so update the clients 2794 bool set = addRemTF == 1;
1741 {
1742 AddTerseUpdateToAllAvatars();
1743 ClearUpdateSchedule();
1744 2795
1745 // This causes the Scene to 'poll' physical objects every couple of frames 2796 // Are we the owner?
1746 // bad, so it's been replaced by an event driven method. 2797 if (AgentID == OwnerID)
1747 //if ((ObjectFlags & (uint)LLObject.ObjectFlags.Physics) != 0)
1748 //{
1749 // Only send the constant terse updates on physical objects!
1750 //ScheduleTerseUpdate();
1751 //}
1752 }
1753 else
1754 { 2798 {
1755 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 2799 switch (field)
1756 { 2800 {
1757 AddFullUpdateToAllAvatars(); 2801 case 2:
1758 ClearUpdateSchedule(); 2802 OwnerMask = ApplyMask(OwnerMask, set, mask);
2803 break;
2804 case 4:
2805 GroupMask = ApplyMask(GroupMask, set, mask);
2806 break;
2807 case 8:
2808 EveryoneMask = ApplyMask(EveryoneMask, set, mask);
2809 break;
2810 case 16:
2811 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask);
2812 break;
1759 } 2813 }
1760 } 2814 SendFullUpdateToAllClients();
1761 }
1762
1763 #endregion
1764 2815
1765 #region Shape 2816 SendObjectPropertiesToClient(AgentID);
1766 2817
1767 /// <summary>
1768 /// Update the shape of this part.
1769 /// </summary>
1770 /// <param name="shapeBlock"></param>
1771 public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock)
1772 {
1773 m_shape.PathBegin = shapeBlock.PathBegin;
1774 m_shape.PathEnd = shapeBlock.PathEnd;
1775 m_shape.PathScaleX = shapeBlock.PathScaleX;
1776 m_shape.PathScaleY = shapeBlock.PathScaleY;
1777 m_shape.PathShearX = shapeBlock.PathShearX;
1778 m_shape.PathShearY = shapeBlock.PathShearY;
1779 m_shape.PathSkew = shapeBlock.PathSkew;
1780 m_shape.ProfileBegin = shapeBlock.ProfileBegin;
1781 m_shape.ProfileEnd = shapeBlock.ProfileEnd;
1782 m_shape.PathCurve = shapeBlock.PathCurve;
1783 m_shape.ProfileCurve = shapeBlock.ProfileCurve;
1784 m_shape.ProfileHollow = shapeBlock.ProfileHollow;
1785 m_shape.PathRadiusOffset = shapeBlock.PathRadiusOffset;
1786 m_shape.PathRevolutions = shapeBlock.PathRevolutions;
1787 m_shape.PathTaperX = shapeBlock.PathTaperX;
1788 m_shape.PathTaperY = shapeBlock.PathTaperY;
1789 m_shape.PathTwist = shapeBlock.PathTwist;
1790 m_shape.PathTwistBegin = shapeBlock.PathTwistBegin;
1791 if (PhysActor != null)
1792 {
1793 PhysActor.Shape = m_shape;
1794 } 2818 }
1795
1796 ParentGroup.HasGroupChanged = true;
1797 ScheduleFullUpdate();
1798 } 2819 }
1799 2820
1800 #endregion
1801
1802 #region ExtraParams
1803
1804 public void UpdatePrimFlags(ushort type, bool inUse, byte[] data) 2821 public void UpdatePrimFlags(ushort type, bool inUse, byte[] data)
1805 { 2822 {
1806 //m_log.Info("TSomething1:" + ((type & (ushort)ExtraParamType.Something1) == (ushort)ExtraParamType.Something1)); 2823 //m_log.Info("TSomething1:" + ((type & (ushort)ExtraParamType.Something1) == (ushort)ExtraParamType.Something1));
@@ -1930,152 +2947,49 @@ namespace OpenSim.Region.Environment.Scenes
1930 ScheduleFullUpdate(); 2947 ScheduleFullUpdate();
1931 } 2948 }
1932 2949
1933 public void ScriptSetPhysicsStatus(bool UsePhysics) 2950 public void UpdateRotation(LLQuaternion rot)
1934 {
1935 if (m_parentGroup != null)
1936 {
1937 m_parentGroup.ScriptSetPhysicsStatus(UsePhysics);
1938 }
1939 }
1940
1941 public void ScriptSetPhantomStatus(bool Phantom)
1942 {
1943 if (m_parentGroup != null)
1944 {
1945 m_parentGroup.ScriptSetPhantomStatus(Phantom);
1946 }
1947 }
1948
1949 public void DoPhysicsPropertyUpdate(bool UsePhysics, bool isNew)
1950 {
1951 if (PhysActor != null)
1952 {
1953 if (UsePhysics != PhysActor.IsPhysical || isNew)
1954 {
1955 if (PhysActor.IsPhysical)
1956 {
1957 if (!isNew)
1958 ParentGroup.Scene.RemovePhysicalPrim(1);
1959
1960 PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1961 PhysActor.OnOutOfBounds -= PhysicsOutOfBounds;
1962 PhysActor.delink();
1963 }
1964
1965 PhysActor.IsPhysical = UsePhysics;
1966
1967
1968 // If we're not what we're supposed to be in the physics scene, recreate ourselves.
1969 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor);
1970 /// that's not wholesome. Had to make Scene public
1971 //PhysActor = null;
1972
1973 if ((ObjectFlags & (uint) LLObject.ObjectFlags.Phantom) == 0)
1974 {
1975 //PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
1976 //Name,
1977 //Shape,
1978 //new PhysicsVector(AbsolutePosition.X, AbsolutePosition.Y,
1979 //AbsolutePosition.Z),
1980 //new PhysicsVector(Scale.X, Scale.Y, Scale.Z),
1981 //new Quaternion(RotationOffset.W, RotationOffset.X,
1982 //RotationOffset.Y, RotationOffset.Z), UsePhysics);
1983 if (UsePhysics)
1984 {
1985 ParentGroup.Scene.AddPhysicalPrim(1);
1986
1987 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1988 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1989 if (ParentID != 0 && ParentID != LocalId)
1990 {
1991 if (ParentGroup.RootPart.PhysActor != null)
1992 {
1993 PhysActor.link(ParentGroup.RootPart.PhysActor);
1994 }
1995 }
1996 }
1997 }
1998 }
1999 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
2000 }
2001 }
2002
2003 public void UpdateExtraParam(ushort type, bool inUse, byte[] data)
2004 {
2005 m_shape.ReadInUpdateExtraParam(type, inUse, data);
2006
2007 if (type == 0x30)
2008 {
2009 if (m_shape.SculptEntry && m_shape.SculptTexture != LLUUID.Zero)
2010 {
2011 //AssetBase tx = m_parentGroup.Scene.getase
2012 m_parentGroup.Scene.AssetCache.GetAsset(m_shape.SculptTexture, SculptTextureCallback, true);
2013 }
2014 }
2015
2016 ParentGroup.HasGroupChanged = true;
2017 ScheduleFullUpdate();
2018 }
2019
2020 public void SculptTextureCallback(LLUUID textureID, AssetBase texture)
2021 {
2022 if (m_shape.SculptEntry)
2023 {
2024 if (texture != null)
2025 {
2026 m_shape.SculptData = texture.Data;
2027 if (PhysActor != null)
2028 {
2029 // Tricks physics engine into thinking we've changed the part shape.
2030 PrimitiveBaseShape m_newshape = m_shape.Copy();
2031 PhysActor.Shape = m_newshape;
2032 m_shape = m_newshape;
2033 }
2034 }
2035 }
2036 }
2037
2038 #endregion
2039
2040 #region Physics
2041
2042 public float GetMass()
2043 { 2951 {
2044 if (PhysActor != null) 2952 if ((rot.X != RotationOffset.X) ||
2045 { 2953 (rot.Y != RotationOffset.Y) ||
2046 return PhysActor.Mass; 2954 (rot.Z != RotationOffset.Z) ||
2047 } 2955 (rot.W != RotationOffset.W))
2048 else
2049 { 2956 {
2050 return 0; 2957 //StoreUndoState();
2958 RotationOffset = new LLQuaternion(rot.X, rot.Y, rot.Z, rot.W);
2959 ParentGroup.HasGroupChanged = true;
2960 ScheduleTerseUpdate();
2051 } 2961 }
2052 } 2962 }
2053 2963
2054 public LLVector3 GetGeometricCenter() 2964 /// <summary>
2965 /// Update the shape of this part.
2966 /// </summary>
2967 /// <param name="shapeBlock"></param>
2968 public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock)
2055 { 2969 {
2970 m_shape.PathBegin = shapeBlock.PathBegin;
2971 m_shape.PathEnd = shapeBlock.PathEnd;
2972 m_shape.PathScaleX = shapeBlock.PathScaleX;
2973 m_shape.PathScaleY = shapeBlock.PathScaleY;
2974 m_shape.PathShearX = shapeBlock.PathShearX;
2975 m_shape.PathShearY = shapeBlock.PathShearY;
2976 m_shape.PathSkew = shapeBlock.PathSkew;
2977 m_shape.ProfileBegin = shapeBlock.ProfileBegin;
2978 m_shape.ProfileEnd = shapeBlock.ProfileEnd;
2979 m_shape.PathCurve = shapeBlock.PathCurve;
2980 m_shape.ProfileCurve = shapeBlock.ProfileCurve;
2981 m_shape.ProfileHollow = shapeBlock.ProfileHollow;
2982 m_shape.PathRadiusOffset = shapeBlock.PathRadiusOffset;
2983 m_shape.PathRevolutions = shapeBlock.PathRevolutions;
2984 m_shape.PathTaperX = shapeBlock.PathTaperX;
2985 m_shape.PathTaperY = shapeBlock.PathTaperY;
2986 m_shape.PathTwist = shapeBlock.PathTwist;
2987 m_shape.PathTwistBegin = shapeBlock.PathTwistBegin;
2056 if (PhysActor != null) 2988 if (PhysActor != null)
2057 { 2989 {
2058 return new LLVector3(PhysActor.CenterOfMass.X, PhysActor.CenterOfMass.Y, PhysActor.CenterOfMass.Z); 2990 PhysActor.Shape = m_shape;
2059 }
2060 else
2061 {
2062 return new LLVector3(0, 0, 0);
2063 } 2991 }
2064 }
2065
2066 #endregion
2067 2992
2068 #region Texture
2069
2070 /// <summary>
2071 /// Update the texture entry for this part.
2072 /// </summary>
2073 /// <param name="textureEntry"></param>
2074 public void UpdateTextureEntry(byte[] textureEntry)
2075 {
2076 m_shape.TextureEntry = textureEntry;
2077 TriggerScriptChangedEvent(Changed.TEXTURE);
2078
2079 ParentGroup.HasGroupChanged = true; 2993 ParentGroup.HasGroupChanged = true;
2080 ScheduleFullUpdate(); 2994 ScheduleFullUpdate();
2081 } 2995 }
@@ -2107,684 +3021,19 @@ namespace OpenSim.Region.Environment.Scenes
2107 UpdateTextureEntry(tex.ToBytes()); 3021 UpdateTextureEntry(tex.ToBytes());
2108 } 3022 }
2109 3023
2110 public byte ConvertScriptUintToByte(uint indata)
2111 {
2112 byte outdata = (byte)TextureAnimFlags.NONE;
2113 if ((indata & 1) != 0) outdata |= (byte)TextureAnimFlags.ANIM_ON;
2114 if ((indata & 2) != 0) outdata |= (byte)TextureAnimFlags.LOOP;
2115 if ((indata & 4) != 0) outdata |= (byte)TextureAnimFlags.REVERSE;
2116 if ((indata & 8) != 0) outdata |= (byte)TextureAnimFlags.PING_PONG;
2117 if ((indata & 16) != 0) outdata |= (byte)TextureAnimFlags.SMOOTH;
2118 if ((indata & 32) != 0) outdata |= (byte)TextureAnimFlags.ROTATE;
2119 if ((indata & 64) != 0) outdata |= (byte)TextureAnimFlags.SCALE;
2120 return outdata;
2121 }
2122
2123 public void AddTextureAnimation(Primitive.TextureAnimation pTexAnim)
2124 {
2125 byte[] data = new byte[16];
2126 int pos = 0;
2127
2128 // The flags don't like conversion from uint to byte, so we have to do
2129 // it the crappy way. See the above function :(
2130
2131 data[pos] = ConvertScriptUintToByte(pTexAnim.Flags); pos++;
2132 data[pos] = (byte)pTexAnim.Face; pos++;
2133 data[pos] = (byte)pTexAnim.SizeX; pos++;
2134 data[pos] = (byte)pTexAnim.SizeY; pos++;
2135
2136 Helpers.FloatToBytes(pTexAnim.Start).CopyTo(data, pos);
2137 Helpers.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4);
2138 Helpers.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8);
2139
2140 m_TextureAnimation = data;
2141 }
2142
2143 #endregion
2144
2145 #region ParticleSystem
2146
2147 public void AddNewParticleSystem(Primitive.ParticleSystem pSystem)
2148 {
2149 m_particleSystem = pSystem.GetBytes();
2150 }
2151
2152 #endregion
2153
2154 #region Position
2155
2156 /// <summary> 3024 /// <summary>
2157 /// 3025 /// Update the texture entry for this part.
2158 /// </summary>
2159 /// <param name="pos"></param>
2160 public void UpdateOffSet(LLVector3 pos)
2161 {
2162 if ((pos.X != OffsetPosition.X) ||
2163 (pos.Y != OffsetPosition.Y) ||
2164 (pos.Z != OffsetPosition.Z))
2165 {
2166 LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z);
2167 OffsetPosition = newPos;
2168 ScheduleTerseUpdate();
2169 }
2170 }
2171
2172 public void UpdateGroupPosition(LLVector3 pos)
2173 {
2174 if ((pos.X != GroupPosition.X) ||
2175 (pos.Y != GroupPosition.Y) ||
2176 (pos.Z != GroupPosition.Z))
2177 {
2178 LLVector3 newPos = new LLVector3(pos.X, pos.Y, pos.Z);
2179 GroupPosition = newPos;
2180 ScheduleTerseUpdate();
2181 }
2182 }
2183
2184 #endregion
2185
2186 #region rotation
2187
2188 public void UpdateRotation(LLQuaternion rot)
2189 {
2190 if ((rot.X != RotationOffset.X) ||
2191 (rot.Y != RotationOffset.Y) ||
2192 (rot.Z != RotationOffset.Z) ||
2193 (rot.W != RotationOffset.W))
2194 {
2195 //StoreUndoState();
2196 RotationOffset = new LLQuaternion(rot.X, rot.Y, rot.Z, rot.W);
2197 ParentGroup.HasGroupChanged = true;
2198 ScheduleTerseUpdate();
2199 }
2200 }
2201
2202 #endregion
2203
2204 #region Sound
2205 public void PreloadSound(string sound)
2206 {
2207 LLUUID ownerID = OwnerID;
2208 LLUUID objectID = UUID;
2209 LLUUID soundID = LLUUID.Zero;
2210
2211 if (!LLUUID.TryParse(sound, out soundID))
2212 {
2213 //Trys to fetch sound id from prim's inventory.
2214 //Prim's inventory doesn't support non script items yet
2215 SceneObjectPart op = this;
2216 foreach (KeyValuePair<LLUUID, TaskInventoryItem> item in op.TaskInventory)
2217 {
2218 if (item.Value.Name == sound)
2219 {
2220 soundID = item.Value.ItemID;
2221 break;
2222 }
2223 }
2224 }
2225
2226 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars();
2227 foreach (ScenePresence p in avatarts)
2228 {
2229 // TODO: some filtering by distance of avatar
2230
2231 p.ControllingClient.SendPreLoadSound(objectID, objectID, soundID);
2232 }
2233 }
2234
2235 public void AdjustSoundGain(double volume)
2236 {
2237 if (volume > 1)
2238 volume = 1;
2239 if (volume < 0)
2240 volume = 0;
2241
2242 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars();
2243 foreach (ScenePresence p in avatarts)
2244 {
2245 p.ControllingClient.SendAttachedSoundGainChange(UUID, (float)volume);
2246 }
2247 }
2248
2249 public void SendSound(string sound, double volume, bool triggered, byte flags)
2250 {
2251 if (volume > 1)
2252 volume = 1;
2253 if (volume < 0)
2254 volume = 0;
2255
2256 LLUUID ownerID = OwnerID;
2257 LLUUID objectID = UUID;
2258 LLUUID parentID = GetRootPartUUID();
2259 LLUUID soundID = LLUUID.Zero;
2260 LLVector3 position = AbsolutePosition; // region local
2261 ulong regionHandle = m_parentGroup.Scene.RegionInfo.RegionHandle;
2262
2263 //byte flags = 0;
2264
2265 if (!LLUUID.TryParse(sound, out soundID))
2266 {
2267 // search sound file from inventory
2268 SceneObjectPart op = this;
2269 foreach (KeyValuePair<LLUUID, TaskInventoryItem> item in op.TaskInventory)
2270 {
2271 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2272 {
2273 soundID = item.Value.ItemID;
2274 break;
2275 }
2276 }
2277 }
2278
2279 if (soundID == LLUUID.Zero)
2280 return;
2281
2282 List<ScenePresence> avatarts = m_parentGroup.Scene.GetAvatars();
2283 foreach (ScenePresence p in avatarts)
2284 {
2285 double dis=Util.GetDistanceTo(p.AbsolutePosition, position);
2286 if (dis > 100.0) // Max audio distance
2287 continue;
2288
2289 // Scale by distance
2290 volume*=((100.0-dis)/100.0);
2291
2292 if (triggered)
2293 {
2294 p.ControllingClient.SendTriggeredSound(soundID, ownerID, objectID, parentID, regionHandle, position, (float)volume);
2295 }
2296 else
2297 {
2298 p.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)volume, flags);
2299 }
2300 }
2301 }
2302
2303 #endregion
2304
2305 #region Resizing/Scale
2306
2307 /// <summary>
2308 /// Resize this part.
2309 /// </summary>
2310 /// <param name="scale"></param>
2311 public void Resize(LLVector3 scale)
2312 {
2313 StoreUndoState();
2314 m_shape.Scale = scale;
2315
2316 ParentGroup.HasGroupChanged = true;
2317 ScheduleFullUpdate();
2318 }
2319
2320 #endregion
2321
2322 public void UpdatePermissions(LLUUID AgentID, byte field, uint localID, uint mask, byte addRemTF)
2323 {
2324 bool set = addRemTF == 1;
2325
2326 // Are we the owner?
2327 if (AgentID == OwnerID)
2328 {
2329 switch (field)
2330 {
2331 case 2:
2332 OwnerMask = ApplyMask(OwnerMask, set, mask);
2333 break;
2334 case 4:
2335 GroupMask = ApplyMask(GroupMask, set, mask);
2336 break;
2337 case 8:
2338 EveryoneMask = ApplyMask(EveryoneMask, set, mask);
2339 break;
2340 case 16:
2341 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask);
2342 break;
2343 }
2344 SendFullUpdateToAllClients();
2345
2346 SendObjectPropertiesToClient(AgentID);
2347
2348 }
2349 }
2350
2351 private void SendObjectPropertiesToClient(LLUUID AgentID)
2352 {
2353 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
2354 for (int i = 0; i < avatars.Count; i++)
2355 {
2356 // Ugly reference :(
2357 if (avatars[i].UUID == AgentID)
2358 {
2359 m_parentGroup.GetProperties(avatars[i].ControllingClient);
2360 }
2361 }
2362 }
2363
2364 private uint ApplyMask(uint val, bool set, uint mask)
2365 {
2366 if (set)
2367 {
2368 return val |= mask;
2369 }
2370 else
2371 {
2372 return val &= ~mask;
2373 }
2374 }
2375
2376 #region Client Update Methods
2377
2378 /// <summary>
2379 /// Tell all scene presences that they should send updates for this part to their clients
2380 /// </summary>
2381 public void AddFullUpdateToAllAvatars()
2382 {
2383 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
2384 for (int i = 0; i < avatars.Count; i++)
2385 {
2386 avatars[i].QueuePartForUpdate(this);
2387 }
2388 }
2389
2390 public void SendFullUpdateToAllClientsExcept(LLUUID agentID)
2391 {
2392 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
2393 for (int i = 0; i < avatars.Count; i++)
2394 {
2395 // Ugly reference :(
2396 if (avatars[i].UUID != agentID)
2397 {
2398 m_parentGroup.SendPartFullUpdate(avatars[i].ControllingClient, this,
2399 avatars[i].GenerateClientFlags(UUID));
2400 }
2401 }
2402 }
2403
2404 public void AddFullUpdateToAvatar(ScenePresence presence)
2405 {
2406 presence.QueuePartForUpdate(this);
2407 }
2408
2409 /// <summary>
2410 ///
2411 /// </summary>
2412 public void SendFullUpdateToAllClients()
2413 {
2414 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
2415 for (int i = 0; i < avatars.Count; i++)
2416 {
2417 // Ugly reference :(
2418 m_parentGroup.SendPartFullUpdate(avatars[i].ControllingClient, this,
2419 avatars[i].GenerateClientFlags(UUID));
2420 }
2421 }
2422
2423 /// <summary>
2424 ///
2425 /// </summary>
2426 /// <param name="remoteClient"></param>
2427 public void SendFullUpdate(IClientAPI remoteClient, uint clientFlags)
2428 {
2429 m_parentGroup.SendPartFullUpdate(remoteClient, this, clientFlags);
2430 }
2431
2432 /// <summary>
2433 /// Sends a full update to the client
2434 /// </summary>
2435 /// <param name="remoteClient"></param>
2436 /// <param name="clientFlags"></param>
2437 public void SendFullUpdateToClient(IClientAPI remoteClient, uint clientflags)
2438 {
2439 LLVector3 lPos;
2440 lPos = OffsetPosition;
2441 SendFullUpdateToClient(remoteClient, lPos, clientflags);
2442 }
2443
2444 /// <summary>
2445 /// Sends a full update to the client
2446 /// </summary>
2447 /// <param name="remoteClient"></param>
2448 /// <param name="lPos"></param>
2449 /// <param name="clientFlags"></param>
2450 public void SendFullUpdateToClient(IClientAPI remoteClient, LLVector3 lPos, uint clientFlags)
2451 {
2452 clientFlags &= ~(uint) LLObject.ObjectFlags.CreateSelected;
2453
2454 if (remoteClient.AgentId == OwnerID)
2455 {
2456 if ((uint) (Flags & LLObject.ObjectFlags.CreateSelected) != 0)
2457 {
2458 clientFlags |= (uint) LLObject.ObjectFlags.CreateSelected;
2459 Flags &= ~LLObject.ObjectFlags.CreateSelected;
2460 }
2461 }
2462
2463 byte[] color = new byte[] {m_color.R, m_color.G, m_color.B, m_color.A};
2464 remoteClient.SendPrimitiveToClient(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, m_shape,
2465 lPos, Velocity, Acceleration, RotationOffset, RotationalVelocity, clientFlags, m_uuid, OwnerID,
2466 m_text, color, ParentID, m_particleSystem, m_clickAction, m_TextureAnimation, m_IsAttachment,
2467 m_attachmentPoint,fromAssetID, Sound, SoundGain, SoundFlags, SoundRadius);
2468 }
2469
2470 /// Terse updates
2471 public void AddTerseUpdateToAllAvatars()
2472 {
2473 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
2474 for (int i = 0; i < avatars.Count; i++)
2475 {
2476 avatars[i].QueuePartForUpdate(this);
2477 }
2478 }
2479
2480 public void AddTerseUpdateToAvatar(ScenePresence presence)
2481 {
2482 presence.QueuePartForUpdate(this);
2483 }
2484
2485 /// <summary>
2486 ///
2487 /// </summary>
2488 public void SendTerseUpdateToAllClients()
2489 {
2490 List<ScenePresence> avatars = m_parentGroup.Scene.GetScenePresences();
2491 for (int i = 0; i < avatars.Count; i++)
2492 {
2493 m_parentGroup.SendPartTerseUpdate(avatars[i].ControllingClient, this);
2494 }
2495 }
2496
2497 /// <summary>
2498 /// Send a terse update to the client.
2499 /// </summary> 3026 /// </summary>
2500 /// <param name="remoteClient"></param> 3027 /// <param name="textureEntry"></param>
2501 public void SendTerseUpdate(IClientAPI remoteClient) 3028 public void UpdateTextureEntry(byte[] textureEntry)
2502 {
2503 m_parentGroup.SendPartTerseUpdate(remoteClient, this);
2504 }
2505
2506 public void SendTerseUpdateToClient(IClientAPI remoteClient)
2507 {
2508 LLVector3 lPos;
2509 lPos = OffsetPosition;
2510 LLQuaternion mRot = RotationOffset;
2511 // TODO: I have no idea why we are making this check. This should be sorted out
2512 if ((ObjectFlags & (uint) LLObject.ObjectFlags.Physics) == 0)
2513 {
2514 remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, Shape.State, fromAssetID);
2515 }
2516 else
2517 {
2518 remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity,
2519 RotationalVelocity);
2520 //System.Console.WriteLine("LID: " + LocalID + " RVel:" + RotationalVelocity.ToString() + " TD: " + ((ushort)(m_parentGroup.Scene.TimeDilation * 500000f)).ToString() + ":" + m_parentGroup.Scene.TimeDilation.ToString());
2521 }
2522 }
2523
2524 public void SendTerseUpdateToClient(IClientAPI remoteClient, LLVector3 lPos)
2525 {
2526 LLQuaternion mRot = RotationOffset;
2527 if (m_IsAttachment)
2528 {
2529 remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, (byte)((m_attachmentPoint % 16) * 16 + (m_attachmentPoint / 16)),fromAssetID);
2530 }
2531 else
2532 {
2533 if ((ObjectFlags & (uint)LLObject.ObjectFlags.Physics) == 0)
2534 {
2535 remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity, RotationalVelocity, Shape.State, fromAssetID);
2536 }
2537 else
2538 {
2539 remoteClient.SendPrimTerseUpdate(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, lPos, mRot, Velocity,
2540 RotationalVelocity);
2541 //System.Console.WriteLine("LID: " + LocalID + "RVel:" + RotationalVelocity.ToString() + " TD: " + ((ushort)(m_parentGroup.Scene.TimeDilation * 500000f)).ToString() + ":" + m_parentGroup.Scene.TimeDilation.ToString());
2542 }
2543 }
2544 }
2545
2546 #endregion
2547
2548 public virtual void UpdateMovement()
2549 {
2550 }
2551
2552 #region Events
2553
2554 public void PhysicsRequestingTerseUpdate()
2555 {
2556 if (PhysActor != null)
2557 {
2558 LLVector3 newpos = new LLVector3(PhysActor.Position.GetBytes(), 0);
2559 if (newpos.X > 257f || newpos.X < -1f || newpos.Y > 257f || newpos.Y < -1f)
2560 {
2561 m_parentGroup.AbsolutePosition = newpos;
2562 return;
2563 }
2564 }
2565 ScheduleTerseUpdate();
2566
2567 //SendTerseUpdateToAllClients();
2568 }
2569
2570 #endregion
2571
2572 public void PhysicsOutOfBounds(PhysicsVector pos)
2573 {
2574 m_log.Info("[PHYSICS]: Physical Object went out of bounds.");
2575 RemFlag(LLObject.ObjectFlags.Physics);
2576 DoPhysicsPropertyUpdate(false, true);
2577 //m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
2578 }
2579
2580 public virtual void OnGrab(LLVector3 offsetPos, IClientAPI remoteClient)
2581 { 3029 {
2582 } 3030 m_shape.TextureEntry = textureEntry;
3031 TriggerScriptChangedEvent(Changed.TEXTURE);
2583 3032
2584 /// <summary>
2585 /// Set the text displayed for this part.
2586 /// </summary>
2587 /// <param name="text"></param>
2588 public void SetText(string text)
2589 {
2590 Text = text;
2591
2592 ParentGroup.HasGroupChanged = true; 3033 ParentGroup.HasGroupChanged = true;
2593 ScheduleFullUpdate(); 3034 ScheduleFullUpdate();
2594 } 3035 }
2595 3036
2596 /// <summary>
2597 /// Set the text displayed for this part.
2598 /// </summary>
2599 /// <param name="text"></param>
2600 /// <param name="color"></param>
2601 /// <param name="alpha"></param>
2602 public void SetText(string text, Vector3 color, double alpha)
2603 {
2604 Color = Color.FromArgb(0xff - (int) (alpha*0xff),
2605 (int) (color.x*0xff),
2606 (int) (color.y*0xff),
2607 (int) (color.z*0xff));
2608 SetText(text);
2609 }
2610
2611 public int registerTargetWaypoint(LLVector3 target, float tolerance)
2612 {
2613 if (m_parentGroup != null)
2614 {
2615 return m_parentGroup.registerTargetWaypoint(target, tolerance);
2616 }
2617 return 0;
2618 }
2619 public void unregisterTargetWaypoint(int handle)
2620 {
2621 if (m_parentGroup != null)
2622 {
2623 m_parentGroup.unregisterTargetWaypoint(handle);
2624 }
2625 }
2626 protected SceneObjectPart(SerializationInfo info, StreamingContext context)
2627 {
2628 //System.Console.WriteLine("SceneObjectPart Deserialize BGN");
2629
2630 if (info == null)
2631 {
2632 throw new ArgumentNullException("info");
2633 }
2634
2635 /*
2636 m_queue = (Queue<SceneObjectPart>)info.GetValue("m_queue", typeof(Queue<SceneObjectPart>));
2637 m_ids = (List<LLUUID>)info.GetValue("m_ids", typeof(List<LLUUID>));
2638 */
2639
2640 //System.Console.WriteLine("SceneObjectPart Deserialize END");
2641 }
2642
2643 [SecurityPermission(SecurityAction.LinkDemand,
2644 Flags = SecurityPermissionFlag.SerializationFormatter)]
2645 public virtual void GetObjectData(
2646 SerializationInfo info, StreamingContext context)
2647 {
2648 if (info == null)
2649 {
2650 throw new ArgumentNullException("info");
2651 }
2652
2653 info.AddValue("m_inventoryFileName", GetInventoryFileName());
2654 info.AddValue("m_folderID", UUID);
2655 info.AddValue("PhysActor", PhysActor);
2656
2657 Dictionary<Guid, TaskInventoryItem> TaskInventory_work = new Dictionary<Guid, TaskInventoryItem>();
2658
2659 foreach (LLUUID id in TaskInventory.Keys)
2660 {
2661 TaskInventory_work.Add(id.UUID, TaskInventory[id]);
2662 }
2663
2664 info.AddValue("TaskInventory", TaskInventory_work);
2665
2666 info.AddValue("LastOwnerID", LastOwnerID.UUID);
2667 info.AddValue("OwnerID", OwnerID.UUID);
2668 info.AddValue("GroupID", GroupID.UUID);
2669
2670 info.AddValue("OwnershipCost", OwnershipCost);
2671 info.AddValue("ObjectSaleType", ObjectSaleType);
2672 info.AddValue("SalePrice", SalePrice);
2673 info.AddValue("Category", Category);
2674
2675 info.AddValue("CreationDate", CreationDate);
2676 info.AddValue("ParentID", ParentID);
2677
2678 info.AddValue("OwnerMask", OwnerMask);
2679 info.AddValue("NextOwnerMask", NextOwnerMask);
2680 info.AddValue("GroupMask", GroupMask);
2681 info.AddValue("EveryoneMask", EveryoneMask);
2682 info.AddValue("BaseMask", BaseMask);
2683
2684 info.AddValue("m_particleSystem", m_particleSystem);
2685
2686 info.AddValue("TimeStampFull", TimeStampFull);
2687 info.AddValue("TimeStampTerse", TimeStampTerse);
2688 info.AddValue("TimeStampLastActivity", TimeStampLastActivity);
2689
2690 info.AddValue("m_updateFlag", m_updateFlag);
2691 info.AddValue("CreatorID", CreatorID.UUID);
2692
2693 info.AddValue("m_inventorySerial", m_inventorySerial);
2694 info.AddValue("m_uuid", m_uuid.UUID);
2695 info.AddValue("m_localID", m_localId);
2696 info.AddValue("m_name", m_name);
2697 info.AddValue("m_flags", Flags);
2698 info.AddValue("m_material", m_material);
2699 info.AddValue("m_regionHandle", m_regionHandle);
2700
2701 info.AddValue("m_groupPosition.X", m_groupPosition.X);
2702 info.AddValue("m_groupPosition.Y", m_groupPosition.Y);
2703 info.AddValue("m_groupPosition.Z", m_groupPosition.Z);
2704
2705 info.AddValue("m_offsetPosition.X", m_offsetPosition.X);
2706 info.AddValue("m_offsetPosition.Y", m_offsetPosition.Y);
2707 info.AddValue("m_offsetPosition.Z", m_offsetPosition.Z);
2708
2709 info.AddValue("m_rotationOffset.W", m_rotationOffset.W);
2710 info.AddValue("m_rotationOffset.X", m_rotationOffset.X);
2711 info.AddValue("m_rotationOffset.Y", m_rotationOffset.Y);
2712 info.AddValue("m_rotationOffset.Z", m_rotationOffset.Z);
2713
2714 info.AddValue("m_velocity.X", m_velocity.X);
2715 info.AddValue("m_velocity.Y", m_velocity.Y);
2716 info.AddValue("m_velocity.Z", m_velocity.Z);
2717
2718 info.AddValue("m_rotationalvelocity.X", m_rotationalvelocity.X);
2719 info.AddValue("m_rotationalvelocity.Y", m_rotationalvelocity.Y);
2720 info.AddValue("m_rotationalvelocity.Z", m_rotationalvelocity.Z);
2721
2722 info.AddValue("m_angularVelocity.X", m_angularVelocity.X);
2723 info.AddValue("m_angularVelocity.Y", m_angularVelocity.Y);
2724 info.AddValue("m_angularVelocity.Z", m_angularVelocity.Z);
2725
2726 info.AddValue("m_acceleration.X", m_acceleration.X);
2727 info.AddValue("m_acceleration.Y", m_acceleration.Y);
2728 info.AddValue("m_acceleration.Z", m_acceleration.Z);
2729
2730 info.AddValue("m_description", m_description);
2731 info.AddValue("m_color", m_color);
2732 info.AddValue("m_text", m_text);
2733 info.AddValue("m_sitName", m_sitName);
2734 info.AddValue("m_touchName", m_touchName);
2735 info.AddValue("m_clickAction", m_clickAction);
2736 info.AddValue("m_shape", m_shape);
2737 info.AddValue("m_parentGroup", m_parentGroup);
2738 info.AddValue("PayPrice", PayPrice);
2739 }
2740
2741 public void Undo()
2742 {
2743 if (m_undo.Count > 0)
2744 {
2745 UndoState goback = m_undo.Pop();
2746 if (goback != null)
2747 goback.PlaybackState(this);
2748 }
2749 }
2750
2751 public void SetScriptEvents(LLUUID scriptid, int events)
2752 {
2753 scriptEvents oldparts;
2754 lock (m_scriptEvents)
2755 {
2756 if (m_scriptEvents.ContainsKey(scriptid))
2757 {
2758 oldparts = m_scriptEvents[scriptid];
2759
2760 // remove values from aggregated script events
2761 m_scriptEvents[scriptid] = (scriptEvents) events;
2762 }
2763 else
2764 {
2765 m_scriptEvents.Add(scriptid, (scriptEvents) events);
2766 }
2767 }
2768 aggregateScriptEvents();
2769 }
2770
2771 public void RemoveScriptEvents(LLUUID scriptid)
2772 {
2773 lock (m_scriptEvents)
2774 {
2775 if (m_scriptEvents.ContainsKey(scriptid))
2776 {
2777 scriptEvents oldparts = scriptEvents.None;
2778 oldparts = (scriptEvents) m_scriptEvents[scriptid];
2779
2780 // remove values from aggregated script events
2781 m_aggregateScriptEvents &= ~oldparts;
2782 m_scriptEvents.Remove(scriptid);
2783 }
2784 }
2785 aggregateScriptEvents();
2786 }
2787
2788 public void aggregateScriptEvents() 3037 public void aggregateScriptEvents()
2789 { 3038 {
2790 // Aggregate script events 3039 // Aggregate script events
@@ -2856,325 +3105,23 @@ namespace OpenSim.Region.Environment.Scenes
2856 ScheduleFullUpdate(); 3105 ScheduleFullUpdate();
2857 } 3106 }
2858 3107
2859 public void PhysicsCollision(EventArgs e) 3108 public int registerTargetWaypoint(LLVector3 target, float tolerance)
2860 { 3109 {
2861 // single threaded here 3110 if (m_parentGroup != null)
2862 if (e == null)
2863 {
2864 return;
2865 }
2866
2867 CollisionEventUpdate a = (CollisionEventUpdate)e;
2868 Dictionary<uint, float> collissionswith = a.m_objCollisionList;
2869 List<uint> thisHitColliders = new List<uint>();
2870 List<uint> endedColliders = new List<uint>();
2871 List<uint> startedColliders = new List<uint>();
2872
2873 // calculate things that started colliding this time
2874 // and build up list of colliders this time
2875 foreach (uint localid in collissionswith.Keys)
2876 {
2877 if (localid != 0)
2878 {
2879 thisHitColliders.Add(localid);
2880 if (!m_lastColliders.Contains(localid))
2881 {
2882 startedColliders.Add(localid);
2883 }
2884
2885 //m_log.Debug("[OBJECT]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
2886 }
2887 }
2888
2889 // calculate things that ended colliding
2890 foreach (uint localID in m_lastColliders)
2891 {
2892 if (!thisHitColliders.Contains(localID))
2893 {
2894 endedColliders.Add(localID);
2895 }
2896 }
2897
2898 //add the items that started colliding this time to the last colliders list.
2899 foreach (uint localID in startedColliders)
2900 {
2901 m_lastColliders.Add(localID);
2902 }
2903 // remove things that ended colliding from the last colliders list
2904 foreach (uint localID in endedColliders)
2905 {
2906 m_lastColliders.Remove(localID);
2907 }
2908 if (m_parentGroup == null)
2909 return;
2910 if (m_parentGroup.RootPart == null)
2911 return;
2912
2913 if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_start) != 0)
2914 {
2915 // do event notification
2916 if (startedColliders.Count > 0)
2917 {
2918 ColliderArgs StartCollidingMessage = new ColliderArgs();
2919 List<DetectedObject> colliding = new List<DetectedObject>();
2920 foreach (uint localId in startedColliders)
2921 {
2922 // always running this check because if the user deletes the object it would return a null reference.
2923 if (m_parentGroup == null)
2924 return;
2925 if (m_parentGroup.Scene == null)
2926 return;
2927 SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
2928 if (obj != null)
2929 {
2930 DetectedObject detobj = new DetectedObject();
2931 detobj.keyUUID = obj.UUID;
2932 detobj.nameStr = obj.Name;
2933 detobj.ownerUUID = obj.OwnerID;
2934 detobj.posVector = obj.AbsolutePosition;
2935 detobj.rotQuat = obj.GetWorldRotation();
2936 detobj.velVector = obj.Velocity;
2937 detobj.colliderType = 0;
2938 detobj.groupUUID = obj.GroupID;
2939 colliding.Add(detobj);
2940 }
2941 else
2942 {
2943 List<ScenePresence> avlist = m_parentGroup.Scene.GetScenePresences();
2944 if (avlist != null)
2945 {
2946 foreach (ScenePresence av in avlist)
2947 {
2948 if (av.LocalId == localId)
2949 {
2950 DetectedObject detobj = new DetectedObject();
2951 detobj.keyUUID = av.UUID;
2952 detobj.nameStr = av.ControllingClient.Name;
2953 detobj.ownerUUID = av.UUID;
2954 detobj.posVector = av.AbsolutePosition;
2955 detobj.rotQuat = new LLQuaternion(av.Rotation.x, av.Rotation.y, av.Rotation.z, av.Rotation.w);
2956 detobj.velVector = av.Velocity;
2957 detobj.colliderType = 0;
2958 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
2959 colliding.Add(detobj);
2960 }
2961 }
2962 }
2963 }
2964 }
2965 if (colliding.Count > 0)
2966 {
2967 StartCollidingMessage.Colliders = colliding;
2968 // always running this check because if the user deletes the object it would return a null reference.
2969 if (m_parentGroup == null)
2970 return;
2971 if (m_parentGroup.Scene == null)
2972 return;
2973 m_parentGroup.Scene.EventManager.TriggerScriptCollidingStart(LocalId, StartCollidingMessage);
2974 }
2975 }
2976 }
2977 if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision) != 0)
2978 {
2979 if (m_lastColliders.Count > 0)
2980 {
2981 ColliderArgs CollidingMessage = new ColliderArgs();
2982 List<DetectedObject> colliding = new List<DetectedObject>();
2983 foreach (uint localId in m_lastColliders)
2984 {
2985 // always running this check because if the user deletes the object it would return a null reference.
2986 if (localId == 0)
2987 continue;
2988
2989 if (m_parentGroup == null)
2990 return;
2991 if (m_parentGroup.Scene == null)
2992 return;
2993 SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
2994 if (obj != null)
2995 {
2996 DetectedObject detobj = new DetectedObject();
2997 detobj.keyUUID = obj.UUID;
2998 detobj.nameStr = obj.Name;
2999 detobj.ownerUUID = obj.OwnerID;
3000 detobj.posVector = obj.AbsolutePosition;
3001 detobj.rotQuat = obj.GetWorldRotation();
3002 detobj.velVector = obj.Velocity;
3003 detobj.colliderType = 0;
3004 detobj.groupUUID = obj.GroupID;
3005 colliding.Add(detobj);
3006 }
3007 else
3008 {
3009 List<ScenePresence> avlist = m_parentGroup.Scene.GetScenePresences();
3010 if (avlist != null)
3011 {
3012 foreach (ScenePresence av in avlist)
3013 {
3014 if (av.LocalId == localId)
3015 {
3016 DetectedObject detobj = new DetectedObject();
3017 detobj.keyUUID = av.UUID;
3018 detobj.nameStr = av.Name;
3019 detobj.ownerUUID = av.UUID;
3020 detobj.posVector = av.AbsolutePosition;
3021 detobj.rotQuat = new LLQuaternion(av.Rotation.x, av.Rotation.y, av.Rotation.z, av.Rotation.w);
3022 detobj.velVector = av.Velocity;
3023 detobj.colliderType = 0;
3024 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
3025 colliding.Add(detobj);
3026 }
3027 }
3028
3029 }
3030 }
3031 }
3032 if (colliding.Count > 0)
3033 {
3034 CollidingMessage.Colliders = colliding;
3035 // always running this check because if the user deletes the object it would return a null reference.
3036 if (m_parentGroup == null)
3037 return;
3038 if (m_parentGroup.Scene == null)
3039 return;
3040 m_parentGroup.Scene.EventManager.TriggerScriptColliding(LocalId, CollidingMessage);
3041 }
3042
3043 }
3044 }
3045 if ((m_parentGroup.RootPart.ScriptEvents & scriptEvents.collision_end) != 0)
3046 { 3111 {
3047 if (endedColliders.Count > 0) 3112 return m_parentGroup.registerTargetWaypoint(target, tolerance);
3048 {
3049 ColliderArgs EndCollidingMessage = new ColliderArgs();
3050 List<DetectedObject> colliding = new List<DetectedObject>();
3051 foreach (uint localId in endedColliders)
3052 {
3053 if (localId == 0)
3054 continue;
3055
3056 // always running this check because if the user deletes the object it would return a null reference.
3057 if (m_parentGroup == null)
3058 return;
3059 if (m_parentGroup.Scene == null)
3060 return;
3061 SceneObjectPart obj = m_parentGroup.Scene.GetSceneObjectPart(localId);
3062 if (obj != null)
3063 {
3064 DetectedObject detobj = new DetectedObject();
3065 detobj.keyUUID = obj.UUID;
3066 detobj.nameStr = obj.Name;
3067 detobj.ownerUUID = obj.OwnerID;
3068 detobj.posVector = obj.AbsolutePosition;
3069 detobj.rotQuat = obj.GetWorldRotation();
3070 detobj.velVector = obj.Velocity;
3071 detobj.colliderType = 0;
3072 detobj.groupUUID = obj.GroupID;
3073 colliding.Add(detobj);
3074 }
3075 else
3076 {
3077 List<ScenePresence> avlist = m_parentGroup.Scene.GetScenePresences();
3078 if (avlist != null)
3079 {
3080 foreach (ScenePresence av in avlist)
3081 {
3082 if (av.LocalId == localId)
3083 {
3084 DetectedObject detobj = new DetectedObject();
3085 detobj.keyUUID = av.UUID;
3086 detobj.nameStr = av.Name;
3087 detobj.ownerUUID = av.UUID;
3088 detobj.posVector = av.AbsolutePosition;
3089 detobj.rotQuat = new LLQuaternion(av.Rotation.x, av.Rotation.y, av.Rotation.z, av.Rotation.w);
3090 detobj.velVector = av.Velocity;
3091 detobj.colliderType = 0;
3092 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
3093 colliding.Add(detobj);
3094 }
3095 }
3096
3097 }
3098 }
3099 }
3100 if (colliding.Count > 0)
3101 {
3102 EndCollidingMessage.Colliders = colliding;
3103 // always running this check because if the user deletes the object it would return a null reference.
3104 if (m_parentGroup == null)
3105 return;
3106 if (m_parentGroup.Scene == null)
3107 return;
3108 m_parentGroup.Scene.EventManager.TriggerScriptCollidingEnd(LocalId, EndCollidingMessage);
3109 }
3110
3111 }
3112 } 3113 }
3114 return 0;
3113 } 3115 }
3114 3116
3115 3117 public void unregisterTargetWaypoint(int handle)
3116
3117 public void SetDieAtEdge(bool p)
3118 {
3119 if (m_parentGroup == null)
3120 return;
3121 if (m_parentGroup.RootPart == null)
3122 return;
3123
3124 m_parentGroup.RootPart.DIE_AT_EDGE = p;
3125 }
3126 public bool GetDieAtEdge()
3127 {
3128 if (m_parentGroup == null)
3129 return false;
3130 if (m_parentGroup.RootPart == null)
3131 return false;
3132
3133 return m_parentGroup.RootPart.DIE_AT_EDGE;
3134 }
3135
3136 public void GetProperties(IClientAPI client)
3137 {
3138
3139 client.SendObjectPropertiesReply(LLUUID.Zero, (ulong)CreationDate, CreatorID, LLUUID.Zero, LLUUID.Zero,
3140 GroupID, (short)InventorySerial, LastOwnerID, UUID, OwnerID,
3141 ParentGroup.RootPart.TouchName, new byte[0], ParentGroup.RootPart.SitName, Name, Description,
3142 ParentGroup.RootPart.OwnerMask, ParentGroup.RootPart.NextOwnerMask, ParentGroup.RootPart.GroupMask, ParentGroup.RootPart.EveryoneMask,
3143 ParentGroup.RootPart.BaseMask);
3144
3145 }
3146
3147 public void SetGroup(LLUUID groupID, IClientAPI client)
3148 {
3149 GroupID = groupID;
3150 GetProperties(client);
3151 m_updateFlag = 2;
3152 }
3153
3154 private void handleTimerAccounting(uint localID, double interval)
3155 { 3118 {
3156 if (localID == LocalId) 3119 if (m_parentGroup != null)
3157 { 3120 {
3158 3121 m_parentGroup.unregisterTargetWaypoint(handle);
3159 float sec = (float)interval;
3160 if (m_parentGroup != null)
3161 {
3162 if (sec == 0)
3163 {
3164 if (m_parentGroup.scriptScore + 0.001f >= float.MaxValue - 0.001)
3165 m_parentGroup.scriptScore = 0;
3166
3167 m_parentGroup.scriptScore += 0.001f;
3168 return;
3169 }
3170
3171 if (m_parentGroup.scriptScore + (0.001f / sec) >= float.MaxValue - (0.001f / sec))
3172 m_parentGroup.scriptScore = 0;
3173 m_parentGroup.scriptScore += (0.001f / sec);
3174 }
3175
3176 } 3122 }
3177 } 3123 }
3178 3124
3125 #endregion Public Methods
3179 } 3126 }
3180} 3127} \ No newline at end of file