aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectPart.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs2966
1 files changed, 1780 insertions, 1186 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index d1c5f72..2c183ad 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -64,7 +64,8 @@ namespace OpenSim.Region.Framework.Scenes
64 TELEPORT = 512, 64 TELEPORT = 512,
65 REGION_RESTART = 1024, 65 REGION_RESTART = 1024,
66 MEDIA = 2048, 66 MEDIA = 2048,
67 ANIMATION = 16384 67 ANIMATION = 16384,
68 POSITION = 32768
68 } 69 }
69 70
70 // I don't really know where to put this except here. 71 // I don't really know where to put this except here.
@@ -123,7 +124,18 @@ namespace OpenSim.Region.Framework.Scenes
123 /// Denote all sides of the prim 124 /// Denote all sides of the prim
124 /// </value> 125 /// </value>
125 public const int ALL_SIDES = -1; 126 public const int ALL_SIDES = -1;
126 127
128 private const scriptEvents PhysicsNeededSubsEvents = (
129 scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end |
130 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
131 );
132 private const scriptEvents PhyscicsPhantonSubsEvents = (
133 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
134 );
135 private const scriptEvents PhyscicsVolumeDtcSubsEvents = (
136 scriptEvents.collision_start | scriptEvents.collision_end
137 );
138
127 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 139 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
128 140
129 /// <summary> 141 /// <summary>
@@ -136,8 +148,8 @@ namespace OpenSim.Region.Framework.Scenes
136 /// <summary> 148 /// <summary>
137 /// Dynamic objects that can be created and deleted as required. 149 /// Dynamic objects that can be created and deleted as required.
138 /// </summary> 150 /// </summary>
139 public DOMap DynObjs 151 public DOMap DynObjs
140 { 152 {
141 get 153 get
142 { 154 {
143 if (m_dynObjs == null) 155 if (m_dynObjs == null)
@@ -151,16 +163,16 @@ namespace OpenSim.Region.Framework.Scenes
151 m_dynObjs = value; 163 m_dynObjs = value;
152 } 164 }
153 } 165 }
154 166
155 /// <value> 167 /// <value>
156 /// Is this a root part? 168 /// Is this a root part?
157 /// </value> 169 /// </value>
158 /// <remarks> 170 /// <remarks>
159 /// This will return true even if the whole object is attached to an avatar. 171 /// This will return true even if the whole object is attached to an avatar.
160 /// </remarks> 172 /// </remarks>
161 public bool IsRoot 173 public bool IsRoot
162 { 174 {
163 get { return ParentGroup.RootPart == this; } 175 get { return Object.ReferenceEquals(ParentGroup.RootPart, this); }
164 } 176 }
165 177
166 /// <summary> 178 /// <summary>
@@ -173,19 +185,18 @@ namespace OpenSim.Region.Framework.Scenes
173 return 185 return
174 !(SitTargetPosition == Vector3.Zero 186 !(SitTargetPosition == Vector3.Zero
175 && (SitTargetOrientation == Quaternion.Identity // Valid Zero Rotation quaternion 187 && (SitTargetOrientation == Quaternion.Identity // Valid Zero Rotation quaternion
176 || SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 1f && SitTargetOrientation.W == 0f // W-Z Mapping was invalid at one point 188 || (SitTargetOrientation.W == 0f && SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 0f ))); // Invalid Quaternion
177 || SitTargetOrientation.X == 0f && SitTargetOrientation.Y == 0f && SitTargetOrientation.Z == 0f && SitTargetOrientation.W == 0f)); // Invalid Quaternion
178 } 189 }
179 } 190 }
180 191
181 #region Fields 192 #region Fields
182 193
183 public bool AllowedDrop; 194 public bool AllowedDrop;
184 195
185 public bool DIE_AT_EDGE; 196 public bool DIE_AT_EDGE;
186 197
187 public bool RETURN_AT_EDGE; 198 public bool RETURN_AT_EDGE;
188 199
189 public bool BlockGrab { get; set; } 200 public bool BlockGrab { get; set; }
190 201
191 public bool StatusSandbox; 202 public bool StatusSandbox;
@@ -210,7 +221,7 @@ namespace OpenSim.Region.Framework.Scenes
210 // Note: This isn't persisted in the database right now, as the fields for that aren't just there yet. 221 // Note: This isn't persisted in the database right now, as the fields for that aren't just there yet.
211 // Not a big problem as long as the script that sets it remains in the prim on startup. 222 // Not a big problem as long as the script that sets it remains in the prim on startup.
212 // for SL compatibility it should be persisted though (set sound / displaytext / particlesystem, kill script) 223 // for SL compatibility it should be persisted though (set sound / displaytext / particlesystem, kill script)
213 224
214 public UUID Sound; 225 public UUID Sound;
215 226
216 public byte SoundFlags; 227 public byte SoundFlags;
@@ -227,26 +238,26 @@ namespace OpenSim.Region.Framework.Scenes
227 /// </remarks> 238 /// </remarks>
228 public bool SoundQueueing { get; set; } 239 public bool SoundQueueing { get; set; }
229 240
230 public uint TimeStampFull; 241 [XmlIgnore]
231 242 public Quaternion AttachRotation = Quaternion.Identity;
232 public uint TimeStampLastActivity; // Will be used for AutoReturn
233
234 public uint TimeStampTerse;
235 243
236 public int STATUS_ROTATE_X; 244 [XmlIgnore]
245 public int STATUS_ROTATE_X; // this should not be used
237 246
238 public int STATUS_ROTATE_Y; 247 [XmlIgnore]
248 public int STATUS_ROTATE_Y; // this should not be used
239 249
240 public int STATUS_ROTATE_Z; 250 [XmlIgnore]
251 public int STATUS_ROTATE_Z; // this should not be used
241 252
242 private Dictionary<int, string> m_CollisionFilter = new Dictionary<int, string>(); 253 private Dictionary<int, string> m_CollisionFilter = new Dictionary<int, string>();
243 254
244 /// <value> 255 /// <value>
245 /// The UUID of the user inventory item from which this object was rezzed if this is a root part. 256 /// The UUID of the user inventory item from which this object was rezzed if this is a root part.
246 /// If UUID.Zero then either this is not a root part or there is no connection with a user inventory item. 257 /// If UUID.Zero then either this is not a root part or there is no connection with a user inventory item.
247 /// </value> 258 /// </value>
248 private UUID m_fromUserInventoryItemID; 259 private UUID m_fromUserInventoryItemID;
249 260
250 public UUID FromUserInventoryItemID 261 public UUID FromUserInventoryItemID
251 { 262 {
252 get { return m_fromUserInventoryItemID; } 263 get { return m_fromUserInventoryItemID; }
@@ -255,12 +266,34 @@ namespace OpenSim.Region.Framework.Scenes
255 266
256 public scriptEvents AggregateScriptEvents; 267 public scriptEvents AggregateScriptEvents;
257 268
258 public Vector3 AttachedPos; 269 public Vector3 AttachedPos
270 {
271 get;
272 set;
273 }
259 274
260 public Vector3 RotationAxis = Vector3.One; 275 // rotation locks on local X,Y and or Z axis bit flags
276 // bits are as in llSetStatus defined in SceneObjectGroup.axisSelect enum
277 // but reversed logic: bit cleared means free to rotate
278 public byte RotationAxisLocks = 0;
261 279
262 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 280 // WRONG flag in libOmvPrimFlags
263 // Certainly this must be a persistant setting finally 281 private const uint primFlagVolumeDetect = (uint)PrimFlags.JointLP2P;
282
283 public bool VolumeDetectActive
284 {
285 get
286 {
287 return (Flags & (PrimFlags)primFlagVolumeDetect) != 0;
288 }
289 set
290 {
291 if(value)
292 Flags |= (PrimFlags)primFlagVolumeDetect;
293 else
294 Flags &= (PrimFlags)(~primFlagVolumeDetect);
295 }
296 }
264 297
265 public bool IsWaitingForFirstSpinUpdatePacket; 298 public bool IsWaitingForFirstSpinUpdatePacket;
266 299
@@ -273,7 +306,7 @@ namespace OpenSim.Region.Framework.Scenes
273 306
274 /// <summary> 307 /// <summary>
275 /// This part's inventory 308 /// This part's inventory
276 /// </summary> 309 /// </summary>
277 public IEntityInventory Inventory 310 public IEntityInventory Inventory
278 { 311 {
279 get { return m_inventory; } 312 get { return m_inventory; }
@@ -281,29 +314,31 @@ namespace OpenSim.Region.Framework.Scenes
281 protected SceneObjectPartInventory m_inventory; 314 protected SceneObjectPartInventory m_inventory;
282 315
283 public bool Undoing; 316 public bool Undoing;
284 317
285 public bool IgnoreUndoUpdate = false; 318 public bool IgnoreUndoUpdate = false;
286 319
287 public PrimFlags LocalFlags; 320 public PrimFlags LocalFlags;
288 321
289 private float m_damage = -1.0f; 322 private float m_damage = -1.0f;
290 private byte[] m_TextureAnimation; 323 private byte[] m_TextureAnimation;
291 private byte m_clickAction; 324 private byte m_clickAction;
292 private Color m_color = Color.Black; 325 private Color m_color = Color.Black;
293 private readonly List<uint> m_lastColliders = new List<uint>(); 326 private List<uint> m_lastColliders = new List<uint>();
327 private bool m_lastLandCollide;
294 private int m_linkNum; 328 private int m_linkNum;
295 329
296 private int m_scriptAccessPin; 330 private int m_scriptAccessPin;
297 331
298 private readonly Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>(); 332 private readonly Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>();
299 private string m_sitName = String.Empty; 333 private string m_sitName = String.Empty;
300 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 334 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
301 private Vector3 m_sitTargetPosition; 335 private Vector3 m_sitTargetPosition;
302 private string m_sitAnimation = "SIT"; 336 private string m_sitAnimation = "SIT";
337 private bool m_occupied; // KF if any av is sitting on this prim
303 private string m_text = String.Empty; 338 private string m_text = String.Empty;
304 private string m_touchName = String.Empty; 339 private string m_touchName = String.Empty;
305 private readonly List<UndoState> m_undo = new List<UndoState>(5); 340 private UndoRedoState m_UndoRedo = null;
306 private readonly List<UndoState> m_redo = new List<UndoState>(5); 341 private object m_UndoLock = new object();
307 342
308 private bool m_passTouches = false; 343 private bool m_passTouches = false;
309 private bool m_passCollisions = false; 344 private bool m_passCollisions = false;
@@ -329,16 +364,22 @@ namespace OpenSim.Region.Framework.Scenes
329 protected Vector3 m_lastPosition; 364 protected Vector3 m_lastPosition;
330 protected Quaternion m_lastRotation; 365 protected Quaternion m_lastRotation;
331 protected Vector3 m_lastVelocity; 366 protected Vector3 m_lastVelocity;
332 protected Vector3 m_lastAcceleration; 367 protected Vector3 m_lastAcceleration; // acceleration is a derived var with high noise
333 protected Vector3 m_lastAngularVelocity; 368 protected Vector3 m_lastAngularVelocity;
334 protected int m_lastTerseSent; 369 protected double m_lastUpdateSentTime;
370 protected float m_buoyancy = 0.0f;
371 protected Vector3 m_force;
372 protected Vector3 m_torque;
335 373
336 protected byte m_physicsShapeType = (byte)PhysShapeType.prim; 374 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
337 protected float m_density = 1000.0f; // in kg/m^3 375 protected float m_density = 1000.0f; // in kg/m^3
338 protected float m_gravitymod = 1.0f; 376 protected float m_gravitymod = 1.0f;
339 protected float m_friction = 0.6f; // wood 377 protected float m_friction = 0.6f; // wood
340 protected float m_bounce = 0.5f; // wood 378 protected float m_bounce = 0.5f; // wood
341 379
380
381 protected bool m_isSelected = false;
382
342 /// <summary> 383 /// <summary>
343 /// Stores media texture data 384 /// Stores media texture data
344 /// </summary> 385 /// </summary>
@@ -350,15 +391,24 @@ namespace OpenSim.Region.Framework.Scenes
350 private Vector3 m_cameraAtOffset; 391 private Vector3 m_cameraAtOffset;
351 private bool m_forceMouselook; 392 private bool m_forceMouselook;
352 393
353 // TODO: Collision sound should have default. 394
395 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
396 private sbyte m_collisionSoundType = 0;
354 private UUID m_collisionSound; 397 private UUID m_collisionSound;
355 private float m_collisionSoundVolume; 398 private float m_collisionSoundVolume;
356 399
400 private int LastColSoundSentTime;
401
402 private SOPVehicle m_vehicleParams = null;
403
404 private PhysicsInertiaData m_physicsInertia;
405
357 public KeyframeMotion KeyframeMotion 406 public KeyframeMotion KeyframeMotion
358 { 407 {
359 get; set; 408 get; set;
360 } 409 }
361 410
411
362 #endregion Fields 412 #endregion Fields
363 413
364// ~SceneObjectPart() 414// ~SceneObjectPart()
@@ -388,6 +438,7 @@ namespace OpenSim.Region.Framework.Scenes
388 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from 438 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
389 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log 439 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
390 m_inventory = new SceneObjectPartInventory(this); 440 m_inventory = new SceneObjectPartInventory(this);
441 LastColSoundSentTime = Util.EnvironmentTickCount();
391 } 442 }
392 443
393 /// <summary> 444 /// <summary>
@@ -399,13 +450,13 @@ namespace OpenSim.Region.Framework.Scenes
399 /// <param name="rotationOffset"></param> 450 /// <param name="rotationOffset"></param>
400 /// <param name="offsetPosition"></param> 451 /// <param name="offsetPosition"></param>
401 public SceneObjectPart( 452 public SceneObjectPart(
402 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 453 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
403 Quaternion rotationOffset, Vector3 offsetPosition) : this() 454 Quaternion rotationOffset, Vector3 offsetPosition) : this()
404 { 455 {
405 m_name = "Primitive"; 456 m_name = "Object";
406 457
407 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 458 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
408 LastOwnerID = CreatorID = OwnerID = ownerID; 459 RezzerID = LastOwnerID = CreatorID = OwnerID = ownerID;
409 UUID = UUID.Random(); 460 UUID = UUID.Random();
410 Shape = shape; 461 Shape = shape;
411 OwnershipCost = 0; 462 OwnershipCost = 0;
@@ -418,16 +469,18 @@ namespace OpenSim.Region.Framework.Scenes
418 Velocity = Vector3.Zero; 469 Velocity = Vector3.Zero;
419 AngularVelocity = Vector3.Zero; 470 AngularVelocity = Vector3.Zero;
420 Acceleration = Vector3.Zero; 471 Acceleration = Vector3.Zero;
472 APIDActive = false;
421 Flags = 0; 473 Flags = 0;
422 CreateSelected = true; 474 CreateSelected = true;
423
424 TrimPermissions(); 475 TrimPermissions();
476 AggregateInnerPerms();
425 } 477 }
426 478
427 #endregion Constructors 479 #endregion Constructors
428 480
429 #region XML Schema 481 #region XML Schema
430 482
483 private UUID _rezzerID;
431 private UUID _lastOwnerID; 484 private UUID _lastOwnerID;
432 private UUID _ownerID; 485 private UUID _ownerID;
433 private UUID _groupID; 486 private UUID _groupID;
@@ -441,14 +494,14 @@ namespace OpenSim.Region.Framework.Scenes
441 private uint _ownerMask = (uint)(PermissionMask.All | PermissionMask.Export); 494 private uint _ownerMask = (uint)(PermissionMask.All | PermissionMask.Export);
442 private uint _groupMask = (uint)PermissionMask.None; 495 private uint _groupMask = (uint)PermissionMask.None;
443 private uint _everyoneMask = (uint)PermissionMask.None; 496 private uint _everyoneMask = (uint)PermissionMask.None;
444 private uint _nextOwnerMask = (uint)PermissionMask.All; 497 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Transfer);
445 private PrimFlags _flags = PrimFlags.None; 498 private PrimFlags _flags = PrimFlags.None;
446 private DateTime m_expires; 499 private DateTime m_expires;
447 private DateTime m_rezzed; 500 private DateTime m_rezzed;
448 private bool m_createSelected = false; 501 private bool m_createSelected = false;
449 502
450 private UUID _creatorID; 503 private UUID _creatorID;
451 public UUID CreatorID 504 public UUID CreatorID
452 { 505 {
453 get { return _creatorID; } 506 get { return _creatorID; }
454 set { _creatorID = value; } 507 set { _creatorID = value; }
@@ -458,7 +511,7 @@ namespace OpenSim.Region.Framework.Scenes
458 /// <summary> 511 /// <summary>
459 /// Data about the creator in the form home_url;name 512 /// Data about the creator in the form home_url;name
460 /// </summary> 513 /// </summary>
461 public string CreatorData 514 public string CreatorData
462 { 515 {
463 get { return m_creatorData; } 516 get { return m_creatorData; }
464 set { m_creatorData = value; } 517 set { m_creatorData = value; }
@@ -480,45 +533,35 @@ namespace OpenSim.Region.Framework.Scenes
480 } 533 }
481 set 534 set
482 { 535 {
536 CreatorData = string.Empty;
483 if ((value == null) || (value != null && value == string.Empty)) 537 if ((value == null) || (value != null && value == string.Empty))
484 {
485 CreatorData = string.Empty;
486 return; 538 return;
487 }
488 539
489 if (!value.Contains(";")) // plain UUID 540 // value is uuid or uuid;homeuri;firstname lastname
541 string[] parts = value.Split(';');
542 if (parts.Length > 0)
490 { 543 {
544
491 UUID uuid = UUID.Zero; 545 UUID uuid = UUID.Zero;
492 UUID.TryParse(value, out uuid); 546 UUID.TryParse(parts[0], out uuid);
493 CreatorID = uuid; 547 CreatorID = uuid;
494 } 548
495 else // <uuid>[;<endpoint>[;name]] 549 if (parts.Length > 1)
496 {
497 string name = "Unknown User";
498 string[] parts = value.Split(';');
499 if (parts.Length >= 1)
500 {
501 UUID uuid = UUID.Zero;
502 UUID.TryParse(parts[0], out uuid);
503 CreatorID = uuid;
504 }
505 if (parts.Length >= 2)
506 { 550 {
507 CreatorData = parts[1]; 551 CreatorData = parts[1];
508 if (!CreatorData.EndsWith("/")) 552 if (!CreatorData.EndsWith("/"))
509 CreatorData += "/"; 553 CreatorData += "/";
554 if (parts.Length > 2)
555 CreatorData += ';' + parts[2];
556 else
557 CreatorData += ";Unknown User";
510 } 558 }
511 if (parts.Length >= 3)
512 name = parts[2];
513
514 CreatorData += ';' + name;
515
516 } 559 }
517 } 560 }
518 } 561 }
519 562
520 /// <summary> 563 /// <summary>
521 /// A relic from when we we thought that prims contained folder objects. In 564 /// A relic from when we we thought that prims contained folder objects. In
522 /// reality, prim == folder 565 /// reality, prim == folder
523 /// Exposing this is not particularly good, but it's one of the least evils at the moment to see 566 /// Exposing this is not particularly good, but it's one of the least evils at the moment to see
524 /// folder id from prim inventory item data, since it's not (yet) actually stored with the prim. 567 /// folder id from prim inventory item data, since it's not (yet) actually stored with the prim.
@@ -539,12 +582,16 @@ namespace OpenSim.Region.Framework.Scenes
539 } 582 }
540 583
541 /// <value> 584 /// <value>
542 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 585 /// Get the inventory list
543 /// </value> 586 /// </value>
544 public TaskInventoryDictionary TaskInventory 587 public TaskInventoryDictionary TaskInventory
545 { 588 {
546 get { return m_inventory.Items; } 589 get {
547 set { m_inventory.Items = value; } 590 return m_inventory.Items;
591 }
592 set {
593 m_inventory.Items = value;
594 }
548 } 595 }
549 596
550 /// <summary> 597 /// <summary>
@@ -560,10 +607,10 @@ namespace OpenSim.Region.Framework.Scenes
560 public UUID UUID 607 public UUID UUID
561 { 608 {
562 get { return m_uuid; } 609 get { return m_uuid; }
563 set 610 set
564 { 611 {
565 m_uuid = value; 612 m_uuid = value;
566 613
567 // This is necessary so that TaskInventoryItem parent ids correctly reference the new uuid of this part 614 // This is necessary so that TaskInventoryItem parent ids correctly reference the new uuid of this part
568 if (Inventory != null) 615 if (Inventory != null)
569 Inventory.ResetObjectID(); 616 Inventory.ResetObjectID();
@@ -583,28 +630,16 @@ namespace OpenSim.Region.Framework.Scenes
583 public virtual string Name 630 public virtual string Name
584 { 631 {
585 get { return m_name; } 632 get { return m_name; }
586 set
587 {
588 m_name = value;
589
590 PhysicsActor pa = PhysActor;
591
592 if (pa != null)
593 pa.SOPName = value;
594 }
595 }
596
597 public byte Material
598 {
599 get { return (byte) m_material; }
600 set 633 set
601 { 634 {
602 m_material = (Material)value; 635 m_name = value;
636 if(ParentGroup != null)
637 ParentGroup.InvalidatePartsLinkMaps();
603 638
604 PhysicsActor pa = PhysActor; 639 PhysicsActor pa = PhysActor;
605 640
606 if (pa != null) 641 if (pa != null)
607 pa.SetMaterial((int)value); 642 pa.SOPName = value;
608 } 643 }
609 } 644 }
610 645
@@ -633,6 +668,19 @@ namespace OpenSim.Region.Framework.Scenes
633 } 668 }
634 } 669 }
635 670
671 public bool IsSelected
672 {
673 get { return m_isSelected; }
674 set
675 {
676 m_isSelected = value;
677 if (ParentGroup != null)
678 ParentGroup.PartSelectChanged(value);
679
680 }
681 }
682
683
636 public Dictionary<int, string> CollisionFilter 684 public Dictionary<int, string> CollisionFilter
637 { 685 {
638 get { return m_CollisionFilter; } 686 get { return m_CollisionFilter; }
@@ -654,14 +702,14 @@ namespace OpenSim.Region.Framework.Scenes
654 set { m_APIDTarget = value; } 702 set { m_APIDTarget = value; }
655 } 703 }
656 704
657 705
658 protected float APIDDamp 706 protected float APIDDamp
659 { 707 {
660 get { return m_APIDDamp; } 708 get { return m_APIDDamp; }
661 set { m_APIDDamp = value; } 709 set { m_APIDDamp = value; }
662 } 710 }
663 711
664 712
665 protected float APIDStrength 713 protected float APIDStrength
666 { 714 {
667 get { return m_APIDStrength; } 715 get { return m_APIDStrength; }
@@ -707,53 +755,61 @@ namespace OpenSim.Region.Framework.Scenes
707 set { m_LoopSoundSlavePrims = value; } 755 set { m_LoopSoundSlavePrims = value; }
708 } 756 }
709 757
710
711 public Byte[] TextureAnimation 758 public Byte[] TextureAnimation
712 { 759 {
713 get { return m_TextureAnimation; } 760 get { return m_TextureAnimation; }
714 set { m_TextureAnimation = value; } 761 set { m_TextureAnimation = value; }
715 } 762 }
716 763
717
718 public Byte[] ParticleSystem 764 public Byte[] ParticleSystem
719 { 765 {
720 get { return m_particleSystem; } 766 get { return m_particleSystem; }
721 set { m_particleSystem = value; } 767 set { m_particleSystem = value; }
722 } 768 }
723 769
724 770
725 public DateTime Expires 771 public DateTime Expires
726 { 772 {
727 get { return m_expires; } 773 get { return m_expires; }
728 set { m_expires = value; } 774 set { m_expires = value; }
729 } 775 }
730 776
731 777
732 public DateTime Rezzed 778 public DateTime Rezzed
733 { 779 {
734 get { return m_rezzed; } 780 get { return m_rezzed; }
735 set { m_rezzed = value; } 781 set { m_rezzed = value; }
736 } 782 }
737 783
738 784
739 public float Damage 785 public float Damage
740 { 786 {
741 get { return m_damage; } 787 get { return m_damage; }
742 set { m_damage = value; } 788 set { m_damage = value; }
743 } 789 }
744 790
791 public void setGroupPosition(Vector3 pos)
792 {
793 m_groupPosition = pos;
794 }
795
745 /// <summary> 796 /// <summary>
746 /// The position of the entire group that this prim belongs to. 797 /// The position of the entire group that this prim belongs to.
747 /// </summary> 798 /// </summary>
799 ///
800
748 public Vector3 GroupPosition 801 public Vector3 GroupPosition
749 { 802 {
750 get 803 get
751 { 804 {
752 // If this is a linkset, we don't want the physics engine mucking up our group position here. 805 // If this is a linkset, we don't want the physics engine mucking up our group position here.
753 PhysicsActor actor = PhysActor; 806 PhysicsActor actor = PhysActor;
754 // If physical and the root prim of a linkset, the position of the group is what physics thinks. 807 if (_parentID == 0)
755 if (actor != null && ParentID == 0) 808 {
756 m_groupPosition = actor.Position; 809 if (actor != null)
810 m_groupPosition = actor.Position;
811 return m_groupPosition;
812 }
757 813
758 // If I'm an attachment, my position is reported as the position of who I'm attached to 814 // If I'm an attachment, my position is reported as the position of who I'm attached to
759 if (ParentGroup.IsAttachment) 815 if (ParentGroup.IsAttachment)
@@ -763,19 +819,21 @@ namespace OpenSim.Region.Framework.Scenes
763 return sp.AbsolutePosition; 819 return sp.AbsolutePosition;
764 } 820 }
765 821
822 // use root prim's group position. Physics may have updated it
823 if (ParentGroup.RootPart != this)
824 m_groupPosition = ParentGroup.RootPart.GroupPosition;
766 return m_groupPosition; 825 return m_groupPosition;
767 } 826 }
768 set 827 set
769 { 828 {
770 m_groupPosition = value; 829 m_groupPosition = value;
771
772 PhysicsActor actor = PhysActor; 830 PhysicsActor actor = PhysActor;
773 if (actor != null) 831 if (actor != null && ParentGroup.Scene.PhysicsScene != null)
774 { 832 {
775 try 833 try
776 { 834 {
777 // Root prim actually goes at Position 835 // Root prim actually goes at Position
778 if (ParentID == 0) 836 if (_parentID == 0)
779 { 837 {
780 actor.Position = value; 838 actor.Position = value;
781 } 839 }
@@ -798,27 +856,51 @@ namespace OpenSim.Region.Framework.Scenes
798 } 856 }
799 } 857 }
800 858
859 public void setOffsetPosition(Vector3 pos)
860 {
861 m_offsetPosition = pos;
862 }
863
801 public Vector3 OffsetPosition 864 public Vector3 OffsetPosition
802 { 865 {
803 get { return m_offsetPosition; } 866 get { return m_offsetPosition; }
804 set 867 set
805 { 868 {
806// StoreUndoState(); 869 Vector3 oldpos = m_offsetPosition;
807 m_offsetPosition = value; 870 m_offsetPosition = value;
808 871
809 if (ParentGroup != null && !ParentGroup.IsDeleted) 872 if (ParentGroup != null && !ParentGroup.IsDeleted)
810 { 873 {
874 if((oldpos - m_offsetPosition).LengthSquared() > 1.0f)
875 ParentGroup.InvalidBoundsRadius();
876
811 PhysicsActor actor = PhysActor; 877 PhysicsActor actor = PhysActor;
812 if (ParentID != 0 && actor != null) 878 if (_parentID != 0 && actor != null)
813 { 879 {
814 actor.Position = GetWorldPosition(); 880 actor.Position = GetWorldPosition();
815 actor.Orientation = GetWorldRotation(); 881 actor.Orientation = GetWorldRotation();
816 882
817 // Tell the physics engines that this prim changed. 883 // Tell the physics engines that this prim changed.
818 if (ParentGroup.Scene != null) 884 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null)
819 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 885 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
820 } 886 }
887
888 if (!m_parentGroup.m_dupeInProgress)
889 {
890 List<ScenePresence> avs = ParentGroup.GetSittingAvatars();
891 foreach (ScenePresence av in avs)
892 {
893 if (av.ParentID == m_localId)
894 {
895 Vector3 offset = (m_offsetPosition - oldpos);
896 av.AbsolutePosition += offset;
897// av.SendAvatarDataToAllAgents();
898 av.SendTerseUpdateToAllClients();
899 }
900 }
901 }
821 } 902 }
903 TriggerScriptChangedEvent(Changed.POSITION);
822 } 904 }
823 } 905 }
824 906
@@ -840,6 +922,11 @@ namespace OpenSim.Region.Framework.Scenes
840 } 922 }
841 } 923 }
842 924
925 public void setRotationOffset(Quaternion q)
926 {
927 m_rotationOffset = q;
928 }
929
843 public Quaternion RotationOffset 930 public Quaternion RotationOffset
844 { 931 {
845 get 932 get
@@ -848,28 +935,15 @@ namespace OpenSim.Region.Framework.Scenes
848 PhysicsActor actor = PhysActor; 935 PhysicsActor actor = PhysActor;
849 // If this is a root of a linkset, the real rotation is what the physics engine thinks. 936 // If this is a root of a linkset, the real rotation is what the physics engine thinks.
850 // If not a root prim, the offset rotation is computed by SOG and is relative to the root. 937 // If not a root prim, the offset rotation is computed by SOG and is relative to the root.
851 if (ParentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null) 938 if (_parentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null)
852 { 939 m_rotationOffset = actor.Orientation;
853 if (actor.Orientation.X != 0f || actor.Orientation.Y != 0f
854 || actor.Orientation.Z != 0f || actor.Orientation.W != 0f)
855 {
856 m_rotationOffset = actor.Orientation;
857 }
858 }
859
860// float roll, pitch, yaw = 0;
861// m_rotationOffset.GetEulerAngles(out roll, out pitch, out yaw);
862//
863// m_log.DebugFormat(
864// "[SCENE OBJECT PART]: Got euler {0} for RotationOffset on {1} {2}",
865// new Vector3(roll, pitch, yaw), Name, LocalId);
866 940
867 return m_rotationOffset; 941 return m_rotationOffset;
868 } 942 }
869 943
870 set 944 set
871 { 945 {
872 StoreUndoState(); 946// StoreUndoState();
873 m_rotationOffset = value; 947 m_rotationOffset = value;
874 948
875 PhysicsActor actor = PhysActor; 949 PhysicsActor actor = PhysActor;
@@ -878,7 +952,7 @@ namespace OpenSim.Region.Framework.Scenes
878 try 952 try
879 { 953 {
880 // Root prim gets value directly 954 // Root prim gets value directly
881 if (ParentID == 0) 955 if (_parentID == 0)
882 { 956 {
883 actor.Orientation = value; 957 actor.Orientation = value;
884 //m_log.Info("[PART]: RO1:" + actor.Orientation.ToString()); 958 //m_log.Info("[PART]: RO1:" + actor.Orientation.ToString());
@@ -960,7 +1034,7 @@ namespace OpenSim.Region.Framework.Scenes
960 get 1034 get
961 { 1035 {
962 PhysicsActor actor = PhysActor; 1036 PhysicsActor actor = PhysActor;
963 if ((actor != null) && actor.IsPhysical) 1037 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
964 { 1038 {
965 m_angularVelocity = actor.RotationalVelocity; 1039 m_angularVelocity = actor.RotationalVelocity;
966 } 1040 }
@@ -974,21 +1048,38 @@ namespace OpenSim.Region.Framework.Scenes
974 m_angularVelocity = value; 1048 m_angularVelocity = value;
975 1049
976 PhysicsActor actor = PhysActor; 1050 PhysicsActor actor = PhysActor;
977 if ((actor != null) && actor.IsPhysical) 1051 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
1052 {
978 actor.RotationalVelocity = m_angularVelocity; 1053 actor.RotationalVelocity = m_angularVelocity;
1054 }
979 } 1055 }
980 } 1056 }
981 1057
982 /// <summary></summary> 1058 /// <summary></summary>
983 public Vector3 Acceleration 1059 public Vector3 Acceleration
984 { 1060 {
985 get { return m_acceleration; } 1061 get
986 set 1062 {
1063 PhysicsActor actor = PhysActor;
1064 if (actor != null)
1065 {
1066 m_acceleration = actor.Acceleration;
1067 }
1068 return m_acceleration;
1069 }
1070
1071 set
987 { 1072 {
988 if (Util.IsNanOrInfinity(value)) 1073 if (Util.IsNanOrInfinity(value))
989 m_acceleration = Vector3.Zero; 1074 m_acceleration = Vector3.Zero;
990 else 1075 else
991 m_acceleration = value; 1076 m_acceleration = value;
1077
1078 PhysicsActor actor = PhysActor;
1079 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
1080 {
1081 actor.Acceleration = m_acceleration;
1082 }
992 } 1083 }
993 } 1084 }
994 1085
@@ -1007,8 +1098,8 @@ namespace OpenSim.Region.Framework.Scenes
1007 { 1098 {
1008 get 1099 get
1009 { 1100 {
1010 if (m_text.Length > 255) 1101 if (m_text.Length > 256) // yes > 254
1011 return m_text.Substring(0, 254); 1102 return m_text.Substring(0, 256);
1012 return m_text; 1103 return m_text;
1013 } 1104 }
1014 set { m_text = value; } 1105 set { m_text = value; }
@@ -1056,7 +1147,10 @@ namespace OpenSim.Region.Framework.Scenes
1056 public PrimitiveBaseShape Shape 1147 public PrimitiveBaseShape Shape
1057 { 1148 {
1058 get { return m_shape; } 1149 get { return m_shape; }
1059 set { m_shape = value;} 1150 set
1151 {
1152 m_shape = value;
1153 }
1060 } 1154 }
1061 1155
1062 /// <summary> 1156 /// <summary>
@@ -1069,10 +1163,10 @@ namespace OpenSim.Region.Framework.Scenes
1069 { 1163 {
1070 if (m_shape != null) 1164 if (m_shape != null)
1071 { 1165 {
1072 StoreUndoState(); 1166 Vector3 oldscale = m_shape.Scale;
1073
1074 m_shape.Scale = value; 1167 m_shape.Scale = value;
1075 1168 if (ParentGroup != null && ((value - oldscale).LengthSquared() >1.0f))
1169 ParentGroup.InvalidBoundsRadius();
1076 PhysicsActor actor = PhysActor; 1170 PhysicsActor actor = PhysActor;
1077 if (actor != null) 1171 if (actor != null)
1078 { 1172 {
@@ -1081,11 +1175,7 @@ namespace OpenSim.Region.Framework.Scenes
1081 if (ParentGroup.Scene.PhysicsScene != null) 1175 if (ParentGroup.Scene.PhysicsScene != null)
1082 { 1176 {
1083 actor.Size = m_shape.Scale; 1177 actor.Size = m_shape.Scale;
1084 1178 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
1085// if (Shape.SculptEntry)
1086// CheckSculptAndLoad();
1087// else
1088 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
1089 } 1179 }
1090 } 1180 }
1091 } 1181 }
@@ -1095,20 +1185,47 @@ namespace OpenSim.Region.Framework.Scenes
1095 } 1185 }
1096 } 1186 }
1097 1187
1188 public float maxSimpleArea()
1189 {
1190 float a,b;
1191 float sx = m_shape.Scale.X;
1192 float sy = m_shape.Scale.Y;
1193 float sz = m_shape.Scale.Z;
1194
1195 if( sx > sy)
1196 {
1197 a = sx;
1198 if(sy > sz)
1199 b = sy;
1200 else
1201 b = sz;
1202 }
1203 else
1204 {
1205 a = sy;
1206 if(sx > sz)
1207 b = sx;
1208 else
1209 b = sz;
1210 }
1211
1212 return a * b;
1213 }
1214
1098 public UpdateRequired UpdateFlag { get; set; } 1215 public UpdateRequired UpdateFlag { get; set; }
1099 public bool UpdatePhysRequired { get; set; } 1216 private object UpdateFlagLock = new object();
1100 1217
1101 /// <summary> 1218 /// <summary>
1102 /// Used for media on a prim. 1219 /// Used for media on a prim.
1103 /// </summary> 1220 /// </summary>
1104 /// Do not change this value directly - always do it through an IMoapModule. 1221 /// Do not change this value directly - always do it through an IMoapModule.
1105 public string MediaUrl 1222 public string MediaUrl
1106 { 1223 {
1107 get 1224 get
1108 { 1225 {
1109 return m_mediaUrl; 1226 return m_mediaUrl;
1110 } 1227 }
1111 1228
1112 set 1229 set
1113 { 1230 {
1114 m_mediaUrl = value; 1231 m_mediaUrl = value;
@@ -1121,10 +1238,10 @@ namespace OpenSim.Region.Framework.Scenes
1121 public bool CreateSelected 1238 public bool CreateSelected
1122 { 1239 {
1123 get { return m_createSelected; } 1240 get { return m_createSelected; }
1124 set 1241 set
1125 { 1242 {
1126// m_log.DebugFormat("[SOP]: Setting CreateSelected to {0} for {1} {2}", value, Name, UUID); 1243// m_log.DebugFormat("[SOP]: Setting CreateSelected to {0} for {1} {2}", value, Name, UUID);
1127 m_createSelected = value; 1244 m_createSelected = value;
1128 } 1245 }
1129 } 1246 }
1130 1247
@@ -1137,10 +1254,10 @@ namespace OpenSim.Region.Framework.Scenes
1137 { 1254 {
1138 get 1255 get
1139 { 1256 {
1140 if (ParentGroup.IsAttachment) 1257 if (_parentID == 0)
1141 return GroupPosition; 1258 return GroupPosition;
1142 1259
1143 return m_offsetPosition + m_groupPosition; 1260 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1144 } 1261 }
1145 } 1262 }
1146 1263
@@ -1261,7 +1378,14 @@ namespace OpenSim.Region.Framework.Scenes
1261 public UUID LastOwnerID 1378 public UUID LastOwnerID
1262 { 1379 {
1263 get { return _lastOwnerID; } 1380 get { return _lastOwnerID; }
1264 set { _lastOwnerID = value; } 1381 set {
1382 _lastOwnerID = value; }
1383 }
1384
1385 public UUID RezzerID
1386 {
1387 get { return _rezzerID; }
1388 set { _rezzerID = value; }
1265 } 1389 }
1266 1390
1267 public uint BaseMask 1391 public uint BaseMask
@@ -1295,7 +1419,7 @@ namespace OpenSim.Region.Framework.Scenes
1295 } 1419 }
1296 1420
1297 /// <summary> 1421 /// <summary>
1298 /// Property flags. See OpenMetaverse.PrimFlags 1422 /// Property flags. See OpenMetaverse.PrimFlags
1299 /// </summary> 1423 /// </summary>
1300 /// <remarks> 1424 /// <remarks>
1301 /// Example properties are PrimFlags.Phantom and PrimFlags.DieAtEdge 1425 /// Example properties are PrimFlags.Phantom and PrimFlags.DieAtEdge
@@ -1303,13 +1427,20 @@ namespace OpenSim.Region.Framework.Scenes
1303 public PrimFlags Flags 1427 public PrimFlags Flags
1304 { 1428 {
1305 get { return _flags; } 1429 get { return _flags; }
1306 set 1430 set
1307 { 1431 {
1308// m_log.DebugFormat("[SOP]: Setting flags for {0} {1} to {2}", UUID, Name, value); 1432// m_log.DebugFormat("[SOP]: Setting flags for {0} {1} to {2}", UUID, Name, value);
1309 _flags = value; 1433 _flags = value;
1310 } 1434 }
1311 } 1435 }
1312 1436
1437 [XmlIgnore]
1438 public bool IsOccupied // KF If an av is sittingon this prim
1439 {
1440 get { return m_occupied; }
1441 set { m_occupied = value; }
1442 }
1443
1313 /// <summary> 1444 /// <summary>
1314 /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero 1445 /// ID of the avatar that is sat on us if we have a sit target. If there is no such avatar then is UUID.Zero
1315 /// </summary> 1446 /// </summary>
@@ -1339,7 +1470,7 @@ namespace OpenSim.Region.Framework.Scenes
1339 } 1470 }
1340 1471
1341 private UUID _parentUUID = UUID.Zero; 1472 private UUID _parentUUID = UUID.Zero;
1342 1473
1343 public UUID ParentUUID 1474 public UUID ParentUUID
1344 { 1475 {
1345 get 1476 get
@@ -1352,20 +1483,48 @@ namespace OpenSim.Region.Framework.Scenes
1352 1483
1353 set { _parentUUID = value; } 1484 set { _parentUUID = value; }
1354 } 1485 }
1355 1486
1356 public string SitAnimation 1487 public string SitAnimation
1357 { 1488 {
1358 get { return m_sitAnimation; } 1489 get { return m_sitAnimation; }
1359 set { m_sitAnimation = value; } 1490 set { m_sitAnimation = value; }
1360 } 1491 }
1361 1492
1493 public UUID invalidCollisionSoundUUID = new UUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
1494
1495 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
1496 // runtime thing.. do not persist
1497 [XmlIgnore]
1498 public sbyte CollisionSoundType
1499 {
1500 get
1501 {
1502 return m_collisionSoundType;
1503 }
1504 set
1505 {
1506 m_collisionSoundType = value;
1507 if (value == -1)
1508 m_collisionSound = invalidCollisionSoundUUID;
1509 else if (value == 0)
1510 m_collisionSound = UUID.Zero;
1511 }
1512 }
1513
1362 public UUID CollisionSound 1514 public UUID CollisionSound
1363 { 1515 {
1364 get { return m_collisionSound; } 1516 get { return m_collisionSound; }
1365 set 1517 set
1366 { 1518 {
1367 m_collisionSound = value; 1519 m_collisionSound = value;
1368 aggregateScriptEvents(); 1520
1521 if (value == invalidCollisionSoundUUID)
1522 m_collisionSoundType = -1;
1523 else if (value == UUID.Zero)
1524 m_collisionSoundType = 0;
1525 else
1526 m_collisionSoundType = 1;
1527
1369 } 1528 }
1370 } 1529 }
1371 1530
@@ -1375,6 +1534,126 @@ namespace OpenSim.Region.Framework.Scenes
1375 set { m_collisionSoundVolume = value; } 1534 set { m_collisionSoundVolume = value; }
1376 } 1535 }
1377 1536
1537 public float Buoyancy
1538 {
1539 get
1540 {
1541 if (ParentGroup.RootPart == this)
1542 return m_buoyancy;
1543
1544 return ParentGroup.RootPart.Buoyancy;
1545 }
1546 set
1547 {
1548 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1549 {
1550 ParentGroup.RootPart.Buoyancy = value;
1551 return;
1552 }
1553 m_buoyancy = value;
1554 if (PhysActor != null)
1555 PhysActor.Buoyancy = value;
1556 }
1557 }
1558
1559 public Vector3 Force
1560 {
1561 get
1562 {
1563 if (ParentGroup.RootPart == this)
1564 return m_force;
1565
1566 return ParentGroup.RootPart.Force;
1567 }
1568
1569 set
1570 {
1571 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1572 {
1573 ParentGroup.RootPart.Force = value;
1574 return;
1575 }
1576 m_force = value;
1577 if (PhysActor != null)
1578 PhysActor.Force = value;
1579 }
1580 }
1581
1582 public Vector3 Torque
1583 {
1584 get
1585 {
1586 if (ParentGroup.RootPart == this)
1587 return m_torque;
1588
1589 return ParentGroup.RootPart.Torque;
1590 }
1591
1592 set
1593 {
1594 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1595 {
1596 ParentGroup.RootPart.Torque = value;
1597 return;
1598 }
1599 m_torque = value;
1600 if (PhysActor != null)
1601 PhysActor.Torque = value;
1602 }
1603 }
1604
1605 public byte Material
1606 {
1607 get { return (byte)m_material; }
1608 set
1609 {
1610 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1611 {
1612 bool update = false;
1613
1614 if (m_material != (Material)value)
1615 {
1616 update = true;
1617 m_material = (Material)value;
1618 }
1619
1620 if (m_friction != SOPMaterialData.friction(m_material))
1621 {
1622 update = true;
1623 m_friction = SOPMaterialData.friction(m_material);
1624 }
1625
1626 if (m_bounce != SOPMaterialData.bounce(m_material))
1627 {
1628 update = true;
1629 m_bounce = SOPMaterialData.bounce(m_material);
1630 }
1631
1632 if (update)
1633 {
1634 if (PhysActor != null)
1635 {
1636 PhysActor.SetMaterial((int)value);
1637 }
1638 if(ParentGroup != null)
1639 {
1640 ParentGroup.HasGroupChanged = true;
1641 ScheduleFullUpdate();
1642 }
1643 }
1644 }
1645 }
1646 }
1647
1648 // not a propriety to move to methods place later
1649 private bool HasMesh()
1650 {
1651 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1652 return true;
1653 return false;
1654 }
1655
1656 // not a propriety to move to methods place later
1378 public byte DefaultPhysicsShapeType() 1657 public byte DefaultPhysicsShapeType()
1379 { 1658 {
1380 byte type; 1659 byte type;
@@ -1387,9 +1666,73 @@ namespace OpenSim.Region.Framework.Scenes
1387 return type; 1666 return type;
1388 } 1667 }
1389 1668
1669 [XmlIgnore]
1670 public bool UsesComplexCost
1671 {
1672 get
1673 {
1674 byte pst = PhysicsShapeType;
1675 if(pst == (byte) PhysShapeType.none || HasMesh())
1676 return true;
1677 return false;
1678 }
1679 }
1680
1681 [XmlIgnore]
1682 public float PhysicsCost
1683 {
1684 get
1685 {
1686 if(PhysicsShapeType == (byte)PhysShapeType.none)
1687 return 0;
1688
1689 float cost = 0.1f;
1690 if (PhysActor != null)
1691 cost = PhysActor.PhysicsCost;
1692 else
1693 cost = 0.1f;
1694
1695 if ((Flags & PrimFlags.Physics) != 0)
1696 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1697 return cost;
1698 }
1699 }
1700
1701 [XmlIgnore]
1702 public float StreamingCost
1703 {
1704 get
1705 {
1706 float cost;
1707 if (PhysActor != null)
1708 cost = PhysActor.StreamCost;
1709 else
1710 cost = 1.0f;
1711 return 1.0f;
1712 }
1713 }
1714
1715 [XmlIgnore]
1716 public float SimulationCost
1717 {
1718 get
1719 {
1720 // ignoring scripts. Don't like considering them for this
1721 if((Flags & PrimFlags.Physics) != 0)
1722 return 1.0f;
1723
1724 return 0.5f;
1725 }
1726 }
1727
1390 public byte PhysicsShapeType 1728 public byte PhysicsShapeType
1391 { 1729 {
1392 get { return m_physicsShapeType; } 1730 get
1731 {
1732// if (PhysActor != null)
1733// m_physicsShapeType = PhysActor.PhysicsShapeType;
1734 return m_physicsShapeType;
1735 }
1393 set 1736 set
1394 { 1737 {
1395 byte oldv = m_physicsShapeType; 1738 byte oldv = m_physicsShapeType;
@@ -1410,30 +1753,23 @@ namespace OpenSim.Region.Framework.Scenes
1410 { 1753 {
1411 if (PhysActor != null) 1754 if (PhysActor != null)
1412 { 1755 {
1413 Velocity = new Vector3(0, 0, 0);
1414 Acceleration = new Vector3(0, 0, 0);
1415 if (ParentGroup.RootPart == this)
1416 AngularVelocity = new Vector3(0, 0, 0);
1417 ParentGroup.Scene.RemovePhysicalPrim(1); 1756 ParentGroup.Scene.RemovePhysicalPrim(1);
1418 RemoveFromPhysics(); 1757 RemoveFromPhysics();
1758// Stop();
1419 } 1759 }
1420 } 1760 }
1421 else if (PhysActor == null) 1761 else if (PhysActor == null)
1422 { 1762 {
1423 ApplyPhysics((uint)Flags, VolumeDetectActive); 1763 if(oldv == (byte)PhysShapeType.none)
1764 {
1765 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1766 UpdatePhysicsSubscribedEvents();
1767 }
1424 } 1768 }
1425 else 1769 else
1426 {
1427 PhysActor.PhysicsShapeType = m_physicsShapeType; 1770 PhysActor.PhysicsShapeType = m_physicsShapeType;
1428 }
1429 1771
1430 if (ParentGroup != null) 1772 ParentGroup.HasGroupChanged = true;
1431 ParentGroup.HasGroupChanged = true;
1432 }
1433
1434 if (m_physicsShapeType != value)
1435 {
1436 UpdatePhysRequired = true;
1437 } 1773 }
1438 } 1774 }
1439 } 1775 }
@@ -1446,17 +1782,18 @@ namespace OpenSim.Region.Framework.Scenes
1446 if (value >=1 && value <= 22587.0) 1782 if (value >=1 && value <= 22587.0)
1447 { 1783 {
1448 m_density = value; 1784 m_density = value;
1449 UpdatePhysRequired = true;
1450 }
1451 1785
1452 ScheduleFullUpdateIfNone();
1453 1786
1454 if (ParentGroup != null) 1787 if (ParentGroup != null)
1455 ParentGroup.HasGroupChanged = true; 1788 {
1789 ParentGroup.HasGroupChanged = true;
1790 ScheduleFullUpdate();
1791 }
1456 1792
1457 PhysicsActor pa = PhysActor; 1793 PhysicsActor pa = PhysActor;
1458 if (pa != null) 1794 if (pa != null)
1459 pa.Density = Density; 1795 pa.Density = m_density;
1796 }
1460 } 1797 }
1461 } 1798 }
1462 1799
@@ -1468,17 +1805,17 @@ namespace OpenSim.Region.Framework.Scenes
1468 if( value >= -1 && value <=28.0f) 1805 if( value >= -1 && value <=28.0f)
1469 { 1806 {
1470 m_gravitymod = value; 1807 m_gravitymod = value;
1471 UpdatePhysRequired = true;
1472 }
1473
1474 ScheduleFullUpdateIfNone();
1475 1808
1476 if (ParentGroup != null) 1809 if (ParentGroup != null)
1477 ParentGroup.HasGroupChanged = true; 1810 {
1811 ParentGroup.HasGroupChanged = true;
1812 ScheduleFullUpdate();
1813 }
1478 1814
1479 PhysicsActor pa = PhysActor; 1815 PhysicsActor pa = PhysActor;
1480 if (pa != null) 1816 if (pa != null)
1481 pa.GravModifier = GravityModifier; 1817 pa.GravModifier = m_gravitymod;
1818 }
1482 } 1819 }
1483 } 1820 }
1484 1821
@@ -1490,17 +1827,17 @@ namespace OpenSim.Region.Framework.Scenes
1490 if (value >= 0 && value <= 255.0f) 1827 if (value >= 0 && value <= 255.0f)
1491 { 1828 {
1492 m_friction = value; 1829 m_friction = value;
1493 UpdatePhysRequired = true;
1494 }
1495
1496 ScheduleFullUpdateIfNone();
1497 1830
1498 if (ParentGroup != null) 1831 if (ParentGroup != null)
1499 ParentGroup.HasGroupChanged = true; 1832 {
1833 ParentGroup.HasGroupChanged = true;
1834 ScheduleFullUpdate();
1835 }
1500 1836
1501 PhysicsActor pa = PhysActor; 1837 PhysicsActor pa = PhysActor;
1502 if (pa != null) 1838 if (pa != null)
1503 pa.Friction = Friction; 1839 pa.Friction = m_friction;
1840 }
1504 } 1841 }
1505 } 1842 }
1506 1843
@@ -1512,20 +1849,21 @@ namespace OpenSim.Region.Framework.Scenes
1512 if (value >= 0 && value <= 1.0f) 1849 if (value >= 0 && value <= 1.0f)
1513 { 1850 {
1514 m_bounce = value; 1851 m_bounce = value;
1515 UpdatePhysRequired = true;
1516 }
1517 1852
1518 ScheduleFullUpdateIfNone(); 1853 if (ParentGroup != null)
1519 1854 {
1520 if (ParentGroup != null) 1855 ParentGroup.HasGroupChanged = true;
1521 ParentGroup.HasGroupChanged = true; 1856 ScheduleFullUpdate();
1857 }
1522 1858
1523 PhysicsActor pa = PhysActor; 1859 PhysicsActor pa = PhysActor;
1524 if (pa != null) 1860 if (pa != null)
1525 pa.Restitution = Restitution; 1861 pa.Restitution = m_bounce;
1862 }
1526 } 1863 }
1527 } 1864 }
1528 1865
1866
1529 #endregion Public Properties with only Get 1867 #endregion Public Properties with only Get
1530 1868
1531 private uint ApplyMask(uint val, bool set, uint mask) 1869 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1545,7 +1883,8 @@ namespace OpenSim.Region.Framework.Scenes
1545 /// </summary> 1883 /// </summary>
1546 public void ClearUpdateSchedule() 1884 public void ClearUpdateSchedule()
1547 { 1885 {
1548 UpdateFlag = UpdateRequired.NONE; 1886 lock(UpdateFlagLock)
1887 UpdateFlag = UpdateRequired.NONE;
1549 } 1888 }
1550 1889
1551 /// <summary> 1890 /// <summary>
@@ -1585,7 +1924,7 @@ namespace OpenSim.Region.Framework.Scenes
1585 1924
1586 public void ResetExpire() 1925 public void ResetExpire()
1587 { 1926 {
1588 Expires = DateTime.Now + new TimeSpan(600000000); 1927 Expires = DateTime.UtcNow + new TimeSpan(600000000);
1589 } 1928 }
1590 1929
1591 public void AddFlag(PrimFlags flag) 1930 public void AddFlag(PrimFlags flag)
@@ -1636,8 +1975,8 @@ namespace OpenSim.Region.Framework.Scenes
1636 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos); 1975 Utils.FloatToBytes(pTexAnim.Start).CopyTo(data, pos);
1637 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4); 1976 Utils.FloatToBytes(pTexAnim.Length).CopyTo(data, pos + 4);
1638 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8); 1977 Utils.FloatToBytes(pTexAnim.Rate).CopyTo(data, pos + 8);
1639 }
1640 1978
1979 }
1641 m_TextureAnimation = data; 1980 m_TextureAnimation = data;
1642 } 1981 }
1643 1982
@@ -1680,6 +2019,61 @@ namespace OpenSim.Region.Framework.Scenes
1680 } 2019 }
1681 } 2020 }
1682 2021
2022 // SetVelocity for LSL llSetVelocity.. may need revision if having other uses in future
2023 public void SetVelocity(Vector3 pVel, bool localGlobalTF)
2024 {
2025 if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
2026 return;
2027
2028 if (ParentGroup.IsAttachment)
2029 return; // don't work on attachments (for now ??)
2030
2031 SceneObjectPart root = ParentGroup.RootPart;
2032
2033 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
2034 return;
2035
2036 PhysicsActor pa = root.PhysActor;
2037
2038 if (pa == null || !pa.IsPhysical)
2039 return;
2040
2041 if (localGlobalTF)
2042 {
2043 pVel = pVel * GetWorldRotation();
2044 }
2045
2046 ParentGroup.Velocity = pVel;
2047 }
2048
2049 // SetAngularVelocity for LSL llSetAngularVelocity.. may need revision if having other uses in future
2050 public void SetAngularVelocity(Vector3 pAngVel, bool localGlobalTF)
2051 {
2052 if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
2053 return;
2054
2055 if (ParentGroup.IsAttachment)
2056 return; // don't work on attachments (for now ??)
2057
2058 SceneObjectPart root = ParentGroup.RootPart;
2059
2060 if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles
2061 return;
2062
2063 PhysicsActor pa = root.PhysActor;
2064
2065 if (pa == null || !pa.IsPhysical)
2066 return;
2067
2068 if (localGlobalTF)
2069 {
2070 pAngVel = pAngVel * GetWorldRotation();
2071 }
2072
2073 root.AngularVelocity = pAngVel;
2074 }
2075
2076
1683 /// <summary> 2077 /// <summary>
1684 /// hook to the physics scene to apply angular impulse 2078 /// hook to the physics scene to apply angular impulse
1685 /// This is sent up to the group, which then finds the root prim 2079 /// This is sent up to the group, which then finds the root prim
@@ -1689,6 +2083,9 @@ namespace OpenSim.Region.Framework.Scenes
1689 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 2083 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1690 public void ApplyAngularImpulse(Vector3 impulsei, bool localGlobalTF) 2084 public void ApplyAngularImpulse(Vector3 impulsei, bool localGlobalTF)
1691 { 2085 {
2086 if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
2087 return;
2088
1692 Vector3 impulse = impulsei; 2089 Vector3 impulse = impulsei;
1693 2090
1694 if (localGlobalTF) 2091 if (localGlobalTF)
@@ -1700,7 +2097,7 @@ namespace OpenSim.Region.Framework.Scenes
1700 impulse = newimpulse; 2097 impulse = newimpulse;
1701 } 2098 }
1702 2099
1703 ParentGroup.applyAngularImpulse(impulse); 2100 ParentGroup.ApplyAngularImpulse(impulse);
1704 } 2101 }
1705 2102
1706 /// <summary> 2103 /// <summary>
@@ -1710,20 +2107,18 @@ namespace OpenSim.Region.Framework.Scenes
1710 /// </summary> 2107 /// </summary>
1711 /// <param name="impulsei">Vector force</param> 2108 /// <param name="impulsei">Vector force</param>
1712 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 2109 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1713 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 2110
2111 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
2112 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1714 { 2113 {
1715 Vector3 impulse = impulsei; 2114 Vector3 torque = torquei;
1716 2115
1717 if (localGlobalTF) 2116 if (localGlobalTF)
1718 { 2117 {
1719 Quaternion grot = GetWorldRotation(); 2118 torque *= GetWorldRotation();
1720 Quaternion AXgrot = grot;
1721 Vector3 AXimpulsei = impulsei;
1722 Vector3 newimpulse = AXimpulsei * AXgrot;
1723 impulse = newimpulse;
1724 } 2119 }
1725 2120
1726 ParentGroup.setAngularImpulse(impulse); 2121 Torque = torque;
1727 } 2122 }
1728 2123
1729 /// <summary> 2124 /// <summary>
@@ -1731,7 +2126,9 @@ namespace OpenSim.Region.Framework.Scenes
1731 /// </summary> 2126 /// </summary>
1732 /// <param name="rootObjectFlags"></param> 2127 /// <param name="rootObjectFlags"></param>
1733 /// <param name="VolumeDetectActive"></param> 2128 /// <param name="VolumeDetectActive"></param>
1734 public void ApplyPhysics(uint rootObjectFlags, bool _VolumeDetectActive) 2129 /// <param name="building"></param>
2130
2131 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1735 { 2132 {
1736 VolumeDetectActive = _VolumeDetectActive; 2133 VolumeDetectActive = _VolumeDetectActive;
1737 2134
@@ -1741,8 +2138,8 @@ namespace OpenSim.Region.Framework.Scenes
1741 if (PhysicsShapeType == (byte)PhysShapeType.none) 2138 if (PhysicsShapeType == (byte)PhysShapeType.none)
1742 return; 2139 return;
1743 2140
1744 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 2141 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
1745 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 2142 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
1746 2143
1747 if (_VolumeDetectActive) 2144 if (_VolumeDetectActive)
1748 isPhantom = true; 2145 isPhantom = true;
@@ -1757,10 +2154,14 @@ namespace OpenSim.Region.Framework.Scenes
1757 && !ParentGroup.IsAttachmentCheckFull() 2154 && !ParentGroup.IsAttachmentCheckFull()
1758 && !(Shape.PathCurve == (byte)Extrusion.Flexible)) 2155 && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1759 { 2156 {
1760 AddToPhysics(isPhysical, isPhantom, isPhysical); 2157 AddToPhysics(isPhysical, isPhantom, building, isPhysical);
2158 UpdatePhysicsSubscribedEvents(); // not sure if appliable here
1761 } 2159 }
1762 else 2160 else
2161 {
1763 PhysActor = null; // just to be sure 2162 PhysActor = null; // just to be sure
2163 RemFlag(PrimFlags.CameraDecoupled);
2164 }
1764 } 2165 }
1765 } 2166 }
1766 2167
@@ -1786,9 +2187,9 @@ namespace OpenSim.Region.Framework.Scenes
1786 /// <param name="linkNum"></param> 2187 /// <param name="linkNum"></param>
1787 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param> 2188 /// <param name="userExposed">True if the duplicate will immediately be in the scene, false otherwise</param>
1788 /// <returns></returns> 2189 /// <returns></returns>
1789 public SceneObjectPart Copy(uint localID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed) 2190 public SceneObjectPart Copy(uint plocalID, UUID AgentID, UUID GroupID, int linkNum, bool userExposed)
1790 { 2191 {
1791 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up 2192 // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up
1792 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator 2193 // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator
1793 // but not between regions on different simulators). Really, all copying should be done explicitly. 2194 // but not between regions on different simulators). Really, all copying should be done explicitly.
1794 SceneObjectPart dupe = (SceneObjectPart)MemberwiseClone(); 2195 SceneObjectPart dupe = (SceneObjectPart)MemberwiseClone();
@@ -1816,6 +2217,12 @@ namespace OpenSim.Region.Framework.Scenes
1816 dupe.Category = Category; 2217 dupe.Category = Category;
1817 dupe.m_rezzed = m_rezzed; 2218 dupe.m_rezzed = m_rezzed;
1818 2219
2220 dupe.m_UndoRedo = null;
2221 dupe.m_isSelected = false;
2222
2223 dupe.IgnoreUndoUpdate = false;
2224 dupe.Undoing = false;
2225
1819 dupe.m_inventory = new SceneObjectPartInventory(dupe); 2226 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1820 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 2227 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1821 2228
@@ -1830,60 +2237,45 @@ namespace OpenSim.Region.Framework.Scenes
1830 } 2237 }
1831 2238
1832 // Move afterwards ResetIDs as it clears the localID 2239 // Move afterwards ResetIDs as it clears the localID
1833 dupe.LocalId = localID; 2240 dupe.LocalId = plocalID;
2241
1834 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 2242 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1835 dupe.LastOwnerID = OwnerID; 2243 if(OwnerID != GroupID)
2244 dupe.LastOwnerID = OwnerID;
2245 else
2246 dupe.LastOwnerID = LastOwnerID; // redundant ?
2247
2248 dupe.RezzerID = RezzerID;
1836 2249
1837 byte[] extraP = new byte[Shape.ExtraParams.Length]; 2250 byte[] extraP = new byte[Shape.ExtraParams.Length];
1838 Array.Copy(Shape.ExtraParams, extraP, extraP.Length); 2251 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
1839 dupe.Shape.ExtraParams = extraP; 2252 dupe.Shape.ExtraParams = extraP;
1840 2253
1841 dupe.m_sittingAvatars = new HashSet<ScenePresence>(); 2254 dupe.m_sittingAvatars = new HashSet<ScenePresence>();
1842 2255 dupe.SitTargetAvatar = UUID.Zero;
1843 // safeguard actual copy is done in sog.copy 2256 // safeguard actual copy is done in sog.copy
1844 dupe.KeyframeMotion = null; 2257 dupe.KeyframeMotion = null;
1845 dupe.PayPrice = (int[])PayPrice.Clone(); 2258 dupe.PayPrice = (int[])PayPrice.Clone();
1846 2259
1847 dupe.DynAttrs.CopyFrom(DynAttrs); 2260 dupe.DynAttrs.CopyFrom(DynAttrs);
1848 2261
1849 if (userExposed) 2262 if (userExposed)
1850 { 2263 {
1851/*
1852 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero)
1853 {
1854 ParentGroup.Scene.AssetService.Get(
1855 dupe.m_shape.SculptTexture.ToString(), dupe, dupe.AssetReceived);
1856 }
1857*/
1858 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 2264 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
1859 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 2265 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
1860 } 2266 }
1861 2267
2268 if (dupe.PhysActor != null)
2269 dupe.PhysActor.LocalID = plocalID;
2270
1862 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2271 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1863 2272
1864// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 2273// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
1865 2274
1866 return dupe; 2275 return dupe;
1867 } 2276 }
1868 2277
1869 /// <summary> 2278 /// <summary>
1870 /// Called back by asynchronous asset fetch.
1871 /// </summary>
1872 /// <param name="id">ID of asset received</param>
1873 /// <param name="sender">Register</param>
1874 /// <param name="asset"></param>
1875/*
1876 protected void AssetReceived(string id, Object sender, AssetBase asset)
1877 {
1878 if (asset != null)
1879 SculptTextureCallback(asset);
1880 else
1881 m_log.WarnFormat(
1882 "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
1883 Name, UUID, id);
1884 }
1885*/
1886 /// <summary>
1887 /// Do a physics property update for a NINJA joint. 2279 /// Do a physics property update for a NINJA joint.
1888 /// </summary> 2280 /// </summary>
1889 /// <param name="UsePhysics"></param> 2281 /// <param name="UsePhysics"></param>
@@ -1970,15 +2362,14 @@ namespace OpenSim.Region.Framework.Scenes
1970 ParentGroup.Scene.PhysicsScene.RequestJointDeletion(Name); // FIXME: what if the name changed? 2362 ParentGroup.Scene.PhysicsScene.RequestJointDeletion(Name); // FIXME: what if the name changed?
1971 2363
1972 // make sure client isn't interpolating the joint proxy object 2364 // make sure client isn't interpolating the joint proxy object
1973 Velocity = Vector3.Zero; 2365 Stop();
1974 AngularVelocity = Vector3.Zero;
1975 Acceleration = Vector3.Zero;
1976 } 2366 }
1977 } 2367 }
1978 } 2368 }
1979 2369
1980 /// <summary> 2370 /// <summary>
1981 /// Do a physics propery update for this part. 2371 /// Do a physics propery update for this part.
2372 /// now also updates phantom and volume detector
1982 /// </summary> 2373 /// </summary>
1983 /// <param name="UsePhysics"></param> 2374 /// <param name="UsePhysics"></param>
1984 /// <param name="isNew"></param> 2375 /// <param name="isNew"></param>
@@ -2004,66 +2395,71 @@ namespace OpenSim.Region.Framework.Scenes
2004 { 2395 {
2005 if (pa.IsPhysical) // implies UsePhysics==false for this block 2396 if (pa.IsPhysical) // implies UsePhysics==false for this block
2006 { 2397 {
2007 if (!isNew) 2398 if (!isNew) // implies UsePhysics==false for this block
2399 {
2008 ParentGroup.Scene.RemovePhysicalPrim(1); 2400 ParentGroup.Scene.RemovePhysicalPrim(1);
2009 2401
2010 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2402 Velocity = new Vector3(0, 0, 0);
2011 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2403 Acceleration = new Vector3(0, 0, 0);
2012 pa.delink(); 2404 AngularVelocity = new Vector3(0, 0, 0);
2405 APIDActive = false;
2013 2406
2014 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2407 if (pa.Phantom && !VolumeDetectActive)
2015 { 2408 {
2016 // destroy all joints connected to this now deactivated body 2409 RemoveFromPhysics();
2017 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2410 return;
2018 } 2411 }
2019 2412
2020 // stop client-side interpolation of all joint proxy objects that have just been deleted 2413 pa.IsPhysical = UsePhysics;
2021 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2414 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
2022 // which stops client-side interpolation of deactivated joint proxy objects. 2415 pa.OnOutOfBounds -= PhysicsOutOfBounds;
2416 pa.delink();
2417 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2418 {
2419 // destroy all joints connected to this now deactivated body
2420 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
2421 }
2422 }
2023 } 2423 }
2024 2424
2025 if (!UsePhysics && !isNew) 2425 if (pa.IsPhysical != UsePhysics)
2026 { 2426 pa.IsPhysical = UsePhysics;
2027 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
2028 // prim still has velocity and continues to interpolate its position along the old
2029 // velocity-vector.
2030 Velocity = new Vector3(0, 0, 0);
2031 Acceleration = new Vector3(0, 0, 0);
2032 AngularVelocity = new Vector3(0, 0, 0);
2033 //RotationalVelocity = new Vector3(0, 0, 0);
2034 }
2035 2427
2036 pa.IsPhysical = UsePhysics; 2428 if (UsePhysics)
2429 {
2430 if (ParentGroup.RootPart.KeyframeMotion != null)
2431 ParentGroup.RootPart.KeyframeMotion.Stop();
2432 ParentGroup.RootPart.KeyframeMotion = null;
2433 ParentGroup.Scene.AddPhysicalPrim(1);
2037 2434
2038 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2435 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
2039 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2436 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
2040 /// that's not wholesome. Had to make Scene public
2041 //PhysActor = null;
2042 2437
2043 if ((Flags & PrimFlags.Phantom) == 0) 2438 if (_parentID != 0 && _parentID != LocalId)
2044 {
2045 if (UsePhysics)
2046 { 2439 {
2047 if (ParentGroup.RootPart.KeyframeMotion != null) 2440 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
2048 ParentGroup.RootPart.KeyframeMotion.Stop();
2049 ParentGroup.RootPart.KeyframeMotion = null;
2050 ParentGroup.Scene.AddPhysicalPrim(1);
2051
2052 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
2053 pa.OnOutOfBounds += PhysicsOutOfBounds;
2054 if (ParentID != 0 && ParentID != LocalId)
2055 {
2056 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
2057 2441
2058 if (parentPa != null) 2442 if (parentPa != null)
2059 { 2443 {
2060 pa.link(parentPa); 2444 pa.link(parentPa);
2061 }
2062 } 2445 }
2063 } 2446 }
2064 } 2447 }
2065 } 2448 }
2066 2449
2450 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2451 if (pa.Phantom != phan)
2452 pa.Phantom = phan;
2453
2454// some engines dont' have this check still
2455// if (VolumeDetectActive != pa.IsVolumeDtc)
2456 {
2457 if (VolumeDetectActive)
2458 pa.SetVolumeDetect(1);
2459 else
2460 pa.SetVolumeDetect(0);
2461 }
2462
2067 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2463 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
2068 // mesh data. 2464 // mesh data.
2069// if (Shape.SculptEntry) 2465// if (Shape.SculptEntry)
@@ -2132,13 +2528,8 @@ namespace OpenSim.Region.Framework.Scenes
2132 2528
2133 public int GetAxisRotation(int axis) 2529 public int GetAxisRotation(int axis)
2134 { 2530 {
2135 //Cannot use ScriptBaseClass constants as no referance to it currently. 2531 if (!ParentGroup.IsDeleted)
2136 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) 2532 return ParentGroup.GetAxisRotation(axis);
2137 return STATUS_ROTATE_X;
2138 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y)
2139 return STATUS_ROTATE_Y;
2140 if (axis == (int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z)
2141 return STATUS_ROTATE_Z;
2142 2533
2143 return 0; 2534 return 0;
2144 } 2535 }
@@ -2153,7 +2544,7 @@ namespace OpenSim.Region.Framework.Scenes
2153 2544
2154 public uint GetEffectiveObjectFlags() 2545 public uint GetEffectiveObjectFlags()
2155 { 2546 {
2156 // Commenting this section of code out since it doesn't actually do anything, as enums are handled by 2547 // Commenting this section of code out since it doesn't actually do anything, as enums are handled by
2157 // value rather than reference 2548 // value rather than reference
2158// PrimFlags f = _flags; 2549// PrimFlags f = _flags;
2159// if (m_parentGroup == null || m_parentGroup.RootPart == this) 2550// if (m_parentGroup == null || m_parentGroup.RootPart == this)
@@ -2162,44 +2553,118 @@ namespace OpenSim.Region.Framework.Scenes
2162 return (uint)Flags | (uint)LocalFlags; 2553 return (uint)Flags | (uint)LocalFlags;
2163 } 2554 }
2164 2555
2556 // some of this lines need be moved to other place later
2557
2558 // effective permitions considering only this part inventory contents perms
2559 public uint AggregatedInnerOwnerPerms {get; private set; }
2560 public uint AggregatedInnerGroupPerms {get; private set; }
2561 public uint AggregatedInnerEveryonePerms {get; private set; }
2562 private object InnerPermsLock = new object();
2563
2564 public void AggregateInnerPerms()
2565 {
2566 // assuming child prims permissions masks are irrelevant on a linkset
2567 // root part is handle at SOG since its masks are the sog masks
2568 const uint mask = (uint)PermissionMask.AllEffective;
2569
2570 uint owner = mask;
2571 uint group = mask;
2572 uint everyone = mask;
2573
2574 lock(InnerPermsLock) // do we really need this?
2575 {
2576 if(Inventory != null)
2577 Inventory.AggregateInnerPerms(ref owner, ref group, ref everyone);
2578
2579 AggregatedInnerOwnerPerms = owner & mask;
2580 AggregatedInnerGroupPerms = group & mask;
2581 AggregatedInnerEveryonePerms = everyone & mask;
2582 }
2583 if(ParentGroup != null)
2584 ParentGroup.InvalidateEffectivePerms();
2585 }
2586
2587 // same as above but called during group Effective Permission validation
2588 public void AggregatedInnerPermsForGroup()
2589 {
2590 // assuming child prims permissions masks are irrelevant on a linkset
2591 // root part is handle at SOG since its masks are the sog masks
2592 const uint mask = (uint)PermissionMask.AllEffective;
2593
2594 uint owner = mask;
2595 uint group = mask;
2596 uint everyone = mask;
2597
2598 lock(InnerPermsLock) // do we really need this?
2599 {
2600 if(Inventory != null)
2601 Inventory.AggregateInnerPerms(ref owner, ref group, ref everyone);
2602
2603 AggregatedInnerOwnerPerms = owner & mask;
2604 AggregatedInnerGroupPerms = group & mask;
2605 AggregatedInnerEveryonePerms = everyone & mask;
2606 }
2607 }
2608
2165 public Vector3 GetGeometricCenter() 2609 public Vector3 GetGeometricCenter()
2166 { 2610 {
2611 // this is not real geometric center but a average of positions relative to root prim acording to
2612 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
2613 // ignoring tortured prims details since sl also seems to ignore
2614 // so no real use in doing it on physics
2615 if (ParentGroup.IsDeleted)
2616 return new Vector3(0, 0, 0);
2617
2618 return ParentGroup.GetGeometricCenter();
2619 }
2620
2621 public float GetMass()
2622 {
2167 PhysicsActor pa = PhysActor; 2623 PhysicsActor pa = PhysActor;
2168 2624
2169 if (pa != null) 2625 if (pa != null)
2170 return pa.GeometricCenter; 2626 return pa.Mass;
2171 else 2627 else
2172 return Vector3.Zero; 2628 return 0;
2173 } 2629 }
2174 2630
2175 public Vector3 GetCenterOfMass() 2631 public Vector3 GetCenterOfMass()
2176 { 2632 {
2633 if (ParentGroup.RootPart == this)
2634 {
2635 if (ParentGroup.IsDeleted)
2636 return AbsolutePosition;
2637 return ParentGroup.GetCenterOfMass();
2638 }
2639
2177 PhysicsActor pa = PhysActor; 2640 PhysicsActor pa = PhysActor;
2178 2641
2179 if (pa != null) 2642 if (pa != null)
2180 return pa.CenterOfMass; 2643 {
2644 Vector3 tmp = pa.CenterOfMass;
2645 return tmp;
2646 }
2181 else 2647 else
2182 return Vector3.Zero; 2648 return AbsolutePosition;
2183 } 2649 }
2184 2650
2185 public float GetMass() 2651 public Vector3 GetPartCenterOfMass()
2186 { 2652 {
2187 PhysicsActor pa = PhysActor; 2653 PhysicsActor pa = PhysActor;
2188 2654
2189 if (pa != null) 2655 if (pa != null)
2190 return pa.Mass; 2656 {
2657 Vector3 tmp = pa.CenterOfMass;
2658 return tmp;
2659 }
2191 else 2660 else
2192 return 0; 2661 return AbsolutePosition;
2193 } 2662 }
2194 2663
2664
2195 public Vector3 GetForce() 2665 public Vector3 GetForce()
2196 { 2666 {
2197 PhysicsActor pa = PhysActor; 2667 return Force;
2198
2199 if (pa != null)
2200 return pa.Force;
2201 else
2202 return Vector3.Zero;
2203 } 2668 }
2204 2669
2205 /// <summary> 2670 /// <summary>
@@ -2314,7 +2779,7 @@ namespace OpenSim.Region.Framework.Scenes
2314 detobj.velVector = obj.Velocity; 2779 detobj.velVector = obj.Velocity;
2315 detobj.colliderType = 0; 2780 detobj.colliderType = 0;
2316 detobj.groupUUID = obj.GroupID; 2781 detobj.groupUUID = obj.GroupID;
2317 2782 detobj.linkNumber = LinkNum;
2318 return detobj; 2783 return detobj;
2319 } 2784 }
2320 2785
@@ -2327,8 +2792,13 @@ namespace OpenSim.Region.Framework.Scenes
2327 detobj.posVector = av.AbsolutePosition; 2792 detobj.posVector = av.AbsolutePosition;
2328 detobj.rotQuat = av.Rotation; 2793 detobj.rotQuat = av.Rotation;
2329 detobj.velVector = av.Velocity; 2794 detobj.velVector = av.Velocity;
2330 detobj.colliderType = 0; 2795 detobj.colliderType = av.IsNPC ? 0x20 : 0x1; // OpenSim\Region\ScriptEngine\Shared\Helpers.cs
2796 if(av.IsSatOnObject)
2797 detobj.colliderType |= 0x4; //passive
2798 else if(detobj.velVector != Vector3.Zero)
2799 detobj.colliderType |= 0x2; //active
2331 detobj.groupUUID = av.ControllingClient.ActiveGroupId; 2800 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
2801 detobj.linkNumber = LinkNum;
2332 2802
2333 return detobj; 2803 return detobj;
2334 } 2804 }
@@ -2344,6 +2814,7 @@ namespace OpenSim.Region.Framework.Scenes
2344 detobj.velVector = Vector3.Zero; 2814 detobj.velVector = Vector3.Zero;
2345 detobj.colliderType = 0; 2815 detobj.colliderType = 0;
2346 detobj.groupUUID = UUID.Zero; 2816 detobj.groupUUID = UUID.Zero;
2817 detobj.linkNumber = LinkNum; // pass my link number not sure needed.. but no harm
2347 2818
2348 return detobj; 2819 return detobj;
2349 } 2820 }
@@ -2352,12 +2823,13 @@ namespace OpenSim.Region.Framework.Scenes
2352 { 2823 {
2353 ColliderArgs colliderArgs = new ColliderArgs(); 2824 ColliderArgs colliderArgs = new ColliderArgs();
2354 List<DetectedObject> colliding = new List<DetectedObject>(); 2825 List<DetectedObject> colliding = new List<DetectedObject>();
2826 Scene parentScene = ParentGroup.Scene;
2355 foreach (uint localId in colliders) 2827 foreach (uint localId in colliders)
2356 { 2828 {
2357 if (localId == 0) 2829 if (localId == 0)
2358 continue; 2830 continue;
2359 2831
2360 SceneObjectPart obj = ParentGroup.Scene.GetSceneObjectPart(localId); 2832 SceneObjectPart obj = parentScene.GetSceneObjectPart(localId);
2361 if (obj != null) 2833 if (obj != null)
2362 { 2834 {
2363 if (!dest.CollisionFilteredOut(obj.UUID, obj.Name)) 2835 if (!dest.CollisionFilteredOut(obj.UUID, obj.Name))
@@ -2365,7 +2837,7 @@ namespace OpenSim.Region.Framework.Scenes
2365 } 2837 }
2366 else 2838 else
2367 { 2839 {
2368 ScenePresence av = ParentGroup.Scene.GetScenePresence(localId); 2840 ScenePresence av = parentScene.GetScenePresence(localId);
2369 if (av != null && (!av.IsChildAgent)) 2841 if (av != null && (!av.IsChildAgent))
2370 { 2842 {
2371 if (!dest.CollisionFilteredOut(av.UUID, av.Name)) 2843 if (!dest.CollisionFilteredOut(av.UUID, av.Name))
@@ -2393,7 +2865,7 @@ namespace OpenSim.Region.Framework.Scenes
2393 CollidingMessage = CreateColliderArgs(this, colliders); 2865 CollidingMessage = CreateColliderArgs(this, colliders);
2394 2866
2395 if (CollidingMessage.Colliders.Count > 0) 2867 if (CollidingMessage.Colliders.Count > 0)
2396 DoNotify(notify, LocalId, CollidingMessage); 2868 notify(LocalId, CollidingMessage);
2397 2869
2398 if (PassCollisions) 2870 if (PassCollisions)
2399 sendToRoot = true; 2871 sendToRoot = true;
@@ -2407,109 +2879,205 @@ namespace OpenSim.Region.Framework.Scenes
2407 { 2879 {
2408 CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders); 2880 CollidingMessage = CreateColliderArgs(ParentGroup.RootPart, colliders);
2409 if (CollidingMessage.Colliders.Count > 0) 2881 if (CollidingMessage.Colliders.Count > 0)
2410 DoNotify(notify, ParentGroup.RootPart.LocalId, CollidingMessage); 2882 notify(ParentGroup.RootPart.LocalId, CollidingMessage);
2411 } 2883 }
2412 } 2884 }
2413 } 2885 }
2414 2886
2415 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify) 2887 private void SendLandCollisionEvent(scriptEvents ev, ScriptCollidingNotification notify)
2416 { 2888 {
2417 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0) 2889 bool sendToRoot = true;
2418 {
2419 ColliderArgs LandCollidingMessage = new ColliderArgs();
2420 List<DetectedObject> colliding = new List<DetectedObject>();
2421
2422 colliding.Add(CreateDetObjectForGround());
2423 LandCollidingMessage.Colliders = colliding;
2424 2890
2425 DoNotify(notify, LocalId, LandCollidingMessage); 2891 ColliderArgs LandCollidingMessage = new ColliderArgs();
2426 } 2892 List<DetectedObject> colliding = new List<DetectedObject>();
2427 }
2428 2893
2429 private void DoNotify(ScriptCollidingNotification notify, uint id, ColliderArgs collargs) 2894 colliding.Add(CreateDetObjectForGround());
2430 { 2895 LandCollidingMessage.Colliders = colliding;
2431 if (m_parentGroup != null && ParentGroup.Scene != null && ParentGroup.Scene.ShouldUseFireAndForgetForCollisions)
2432 {
2433 // For those learning C#, FireAndForget takes a function, an object to pass
2434 // to that function and an ID string. The "oo => {}" construct is a lambda expression
2435 // for a function with one arguement ('oo'). The 'new Object[] {}" construct creates an Object
2436 // that is an object array and initializes it with three items (the parameters
2437 // being passed). The parameters passed are the function to call ('notify') and
2438 // its two arguements. Finally, once in the function (called later by the FireAndForget
2439 // thread scheduler), the passed object is cast to an object array and then each
2440 // of its items (aoo[0] to aoo[2]) are individually cast to what they are and
2441 // then used in a call of the passed ScriptCollidingNotification function.
2442 Util.FireAndForget(oo =>
2443 {
2444 Object[] aoo = (Object[])oo;
2445 ((ScriptCollidingNotification)aoo[0])((uint)aoo[1], (ColliderArgs)aoo[2]);
2446 2896
2447 }, new Object[] { notify, id, collargs }, "SOP.Collision"); 2897 if (Inventory.ContainsScripts())
2898 {
2899 if (!PassCollisions)
2900 sendToRoot = false;
2448 } 2901 }
2449 else 2902 if ((ScriptEvents & ev) != 0)
2903 notify(LocalId, LandCollidingMessage);
2904
2905 if ((ParentGroup.RootPart.ScriptEvents & ev) != 0 && sendToRoot)
2450 { 2906 {
2451 notify(id, collargs); 2907 notify(ParentGroup.RootPart.LocalId, LandCollidingMessage);
2452 } 2908 }
2453 } 2909 }
2454 2910
2455 public void PhysicsCollision(EventArgs e) 2911 public void PhysicsCollision(EventArgs e)
2456 { 2912 {
2457 if (ParentGroup.Scene == null || ParentGroup.IsDeleted) 2913 if (ParentGroup.Scene == null || ParentGroup.IsDeleted || ParentGroup.inTransit)
2458 return; 2914 return;
2459 2915
2460 // single threaded here 2916 // this a thread from physics ( heartbeat )
2917 bool thisHitLand = false;
2918 bool startLand = false;
2919 bool endedLand = false;
2920
2461 CollisionEventUpdate a = (CollisionEventUpdate)e; 2921 CollisionEventUpdate a = (CollisionEventUpdate)e;
2462 Dictionary<uint, ContactPoint> collissionswith = a.m_objCollisionList; 2922 Dictionary<uint, ContactPoint> collissionswith = a.m_objCollisionList;
2463 List<uint> thisHitColliders = new List<uint>(); 2923 List<uint> thisHitColliders = new List<uint>();
2464 List<uint> endedColliders = new List<uint>(); 2924 List<uint> endedColliders = new List<uint>();
2465 List<uint> startedColliders = new List<uint>(); 2925 List<uint> startedColliders = new List<uint>();
2466 2926
2467 // calculate things that started colliding this time 2927 if (collissionswith.Count == 0)
2468 // and build up list of colliders this time
2469 foreach (uint localid in collissionswith.Keys)
2470 { 2928 {
2471 thisHitColliders.Add(localid); 2929 if (m_lastColliders.Count == 0 && !m_lastLandCollide)
2472 if (!m_lastColliders.Contains(localid)) 2930 return; // nothing to do
2473 startedColliders.Add(localid);
2474 }
2475 2931
2476 // calculate things that ended colliding 2932 endedLand = m_lastLandCollide;
2477 foreach (uint localID in m_lastColliders) 2933 m_lastLandCollide = false;
2478 { 2934
2479 if (!thisHitColliders.Contains(localID)) 2935 foreach (uint localID in m_lastColliders)
2936 {
2480 endedColliders.Add(localID); 2937 endedColliders.Add(localID);
2938 }
2939
2940 m_lastColliders.Clear();
2481 } 2941 }
2942 else
2943 {
2944 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
2482 2945
2483 //add the items that started colliding this time to the last colliders list. 2946 // calculate things that started colliding this time
2484 foreach (uint localID in startedColliders) 2947 // and build up list of colliders this time
2485 m_lastColliders.Add(localID); 2948 if (!VolumeDetectActive && CollisionSoundType >= 0)
2949 {
2950 CollisionForSoundInfo soundinfo;
2951 ContactPoint curcontact;
2486 2952
2487 // remove things that ended colliding from the last colliders list 2953 foreach (uint id in collissionswith.Keys)
2488 foreach (uint localID in endedColliders) 2954 {
2489 m_lastColliders.Remove(localID); 2955 if(id == 0)
2956 {
2957 thisHitLand = true;
2958 if (!m_lastLandCollide)
2959 {
2960 startLand = true;
2961 curcontact = collissionswith[id];
2962 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2963 {
2964 soundinfo = new CollisionForSoundInfo();
2965 soundinfo.colliderID = id;
2966 soundinfo.position = curcontact.Position;
2967 soundinfo.relativeVel = curcontact.RelativeSpeed;
2968 soundinfolist.Add(soundinfo);
2969 }
2970 }
2971 }
2972 else
2973 {
2974 thisHitColliders.Add(id);
2975 if (!m_lastColliders.Contains(id))
2976 {
2977 startedColliders.Add(id);
2490 2978
2491 // play the sound. 2979 curcontact = collissionswith[id];
2492 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) 2980 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2493 { 2981 {
2494 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>(); 2982 soundinfo = new CollisionForSoundInfo();
2495 if (soundModule != null) 2983 soundinfo.colliderID = id;
2984 soundinfo.position = curcontact.Position;
2985 soundinfo.relativeVel = curcontact.RelativeSpeed;
2986 soundinfolist.Add(soundinfo);
2987 }
2988 }
2989 }
2990 }
2991 }
2992 else
2993 {
2994 foreach (uint id in collissionswith.Keys)
2995 {
2996 if(id == 0)
2997 {
2998 thisHitLand = true;
2999 if (!m_lastLandCollide)
3000 startLand = true;
3001 }
3002 else
3003 {
3004 thisHitColliders.Add(id);
3005 if (!m_lastColliders.Contains(id))
3006 startedColliders.Add(id);
3007 }
3008 }
3009 }
3010
3011 // calculate things that ended colliding
3012 foreach (uint localID in m_lastColliders)
2496 { 3013 {
2497 soundModule.SendSound(UUID, CollisionSound, 3014 if (!thisHitColliders.Contains(localID))
2498 CollisionSoundVolume, true, 0, 0, false, 3015 endedColliders.Add(localID);
2499 false);
2500 } 3016 }
3017
3018 //add the items that started colliding this time to the last colliders list.
3019 foreach (uint localID in startedColliders)
3020 m_lastColliders.Add(localID);
3021
3022 // remove things that ended colliding from the last colliders list
3023 foreach (uint localID in endedColliders)
3024 m_lastColliders.Remove(localID);
3025
3026 if(m_lastLandCollide && !thisHitLand)
3027 endedLand = true;
3028
3029 m_lastLandCollide = thisHitLand;
3030
3031 // play sounds.
3032 if (soundinfolist.Count > 0)
3033 CollisionSounds.PartCollisionSound(this, soundinfolist);
2501 } 3034 }
3035
3036 EventManager eventmanager = ParentGroup.Scene.EventManager;
3037
3038 SendCollisionEvent(scriptEvents.collision_start, startedColliders, eventmanager.TriggerScriptCollidingStart);
3039 if (!VolumeDetectActive)
3040 SendCollisionEvent(scriptEvents.collision , m_lastColliders , eventmanager.TriggerScriptColliding);
3041 SendCollisionEvent(scriptEvents.collision_end , endedColliders , eventmanager.TriggerScriptCollidingEnd);
3042
3043 if (!VolumeDetectActive)
3044 {
3045 if (startLand)
3046 SendLandCollisionEvent(scriptEvents.land_collision_start, eventmanager.TriggerScriptLandCollidingStart);
3047 if (m_lastLandCollide)
3048 SendLandCollisionEvent(scriptEvents.land_collision, eventmanager.TriggerScriptLandColliding);
3049 if (endedLand)
3050 SendLandCollisionEvent(scriptEvents.land_collision_end, eventmanager.TriggerScriptLandCollidingEnd);
3051 }
3052 }
3053
3054 // The Collision sounds code calls this
3055 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
3056 {
3057 if (soundID == UUID.Zero)
3058 return;
2502 3059
2503 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); 3060 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
2504 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); 3061 if (soundModule == null)
2505 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 3062 return;
3063
3064 if (volume > 1)
3065 volume = 1;
3066 if (volume < 0)
3067 volume = 0;
3068
3069 int now = Util.EnvironmentTickCount();
3070 if(Util.EnvironmentTickCountSubtract(now, LastColSoundSentTime) < 200)
3071 return;
3072
3073 LastColSoundSentTime = now;
3074
3075 UUID ownerID = OwnerID;
3076 UUID objectID = ParentGroup.RootPart.UUID;
3077 UUID parentID = ParentGroup.UUID;
3078 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
2506 3079
2507 if (startedColliders.Contains(0)) 3080 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
2508 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2509 if (m_lastColliders.Contains(0))
2510 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding);
2511 if (endedColliders.Contains(0))
2512 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2513 } 3081 }
2514 3082
2515 public void PhysicsOutOfBounds(Vector3 pos) 3083 public void PhysicsOutOfBounds(Vector3 pos)
@@ -2517,9 +3085,9 @@ namespace OpenSim.Region.Framework.Scenes
2517 // Note: This is only being called on the root prim at this time. 3085 // Note: This is only being called on the root prim at this time.
2518 3086
2519 m_log.ErrorFormat( 3087 m_log.ErrorFormat(
2520 "[SCENE OBJECT PART]: Physical object {0}, localID {1} went out of bounds at {2} in {3}. Stopping at {4} and making non-physical.", 3088 "[SCENE OBJECT PART]: Physical object {0}, localID {1} went out of bounds at {2} in {3}. Stopping at {4} and making non-physical.",
2521 Name, LocalId, pos, ParentGroup.Scene.Name, AbsolutePosition); 3089 Name, LocalId, pos, ParentGroup.Scene.Name, AbsolutePosition);
2522 3090
2523 RemFlag(PrimFlags.Physics); 3091 RemFlag(PrimFlags.Physics);
2524 DoPhysicsPropertyUpdate(false, true); 3092 DoPhysicsPropertyUpdate(false, true);
2525 } 3093 }
@@ -2539,8 +3107,8 @@ namespace OpenSim.Region.Framework.Scenes
2539 } 3107 }
2540 //ParentGroup.RootPart.m_groupPosition = newpos; 3108 //ParentGroup.RootPart.m_groupPosition = newpos;
2541 } 3109 }
2542 3110/*
2543 if (pa != null && ParentID != 0 && ParentGroup != null) 3111 if (pa != null && _parentID != 0 && ParentGroup != null)
2544 { 3112 {
2545 // Special case where a child object is requesting property updates. 3113 // Special case where a child object is requesting property updates.
2546 // This happens when linksets are modified to use flexible links rather than 3114 // This happens when linksets are modified to use flexible links rather than
@@ -2559,7 +3127,7 @@ namespace OpenSim.Region.Framework.Scenes
2559 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}", 3127 // m_log.DebugFormat("{0} PhysicsRequestingTerseUpdate child: pos={1}, rot={2}, offPos={3}, offRot={4}",
2560 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset); 3128 // "[SCENE OBJECT PART]", pa.Position, pa.Orientation, m_offsetPosition, RotationOffset);
2561 } 3129 }
2562 3130*/
2563 ScheduleTerseUpdate(); 3131 ScheduleTerseUpdate();
2564 } 3132 }
2565 3133
@@ -2574,7 +3142,7 @@ namespace OpenSim.Region.Framework.Scenes
2574 //m_log.Debug("prev: " + prevflag.ToString() + " curr: " + Flags.ToString()); 3142 //m_log.Debug("prev: " + prevflag.ToString() + " curr: " + Flags.ToString());
2575 //ScheduleFullUpdate(); 3143 //ScheduleFullUpdate();
2576 } 3144 }
2577 3145
2578 public void RemoveScriptEvents(UUID scriptid) 3146 public void RemoveScriptEvents(UUID scriptid)
2579 { 3147 {
2580 lock (m_scriptEvents) 3148 lock (m_scriptEvents)
@@ -2619,18 +3187,17 @@ namespace OpenSim.Region.Framework.Scenes
2619 3187
2620 if (ParentGroup.Scene != null) 3188 if (ParentGroup.Scene != null)
2621 { 3189 {
2622 scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); 3190 float minsize = ParentGroup.Scene.m_minNonphys;
2623 scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); 3191 float maxsize = ParentGroup.Scene.m_maxNonphys;
2624 scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z));
2625
2626 if (pa != null && pa.IsPhysical) 3192 if (pa != null && pa.IsPhysical)
2627 { 3193 {
2628 scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); 3194 minsize = ParentGroup.Scene.m_minPhys;
2629 scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); 3195 maxsize = ParentGroup.Scene.m_maxPhys;
2630 scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); 3196 }
2631 } 3197 scale.X = Util.Clamp(scale.X, minsize, maxsize);
3198 scale.Y = Util.Clamp(scale.Y, minsize, maxsize);
3199 scale.Z = Util.Clamp(scale.Z, minsize, maxsize);
2632 } 3200 }
2633
2634// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); 3201// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
2635 3202
2636 Scale = scale; 3203 Scale = scale;
@@ -2638,58 +3205,68 @@ namespace OpenSim.Region.Framework.Scenes
2638 ParentGroup.HasGroupChanged = true; 3205 ParentGroup.HasGroupChanged = true;
2639 ScheduleFullUpdate(); 3206 ScheduleFullUpdate();
2640 } 3207 }
2641 3208
2642 public void RotLookAt(Quaternion target, float strength, float damping) 3209 public void RotLookAt(Quaternion target, float strength, float damping)
2643 { 3210 {
2644 if (ParentGroup.IsAttachment) 3211 if(ParentGroup.IsDeleted)
3212 return;
3213
3214 // for now we only handle physics case
3215 if(!ParentGroup.UsesPhysics || ParentGroup.IsAttachment)
3216 return;
3217
3218 // physical is SOG
3219 if(ParentGroup.RootPart != this)
2645 { 3220 {
2646 /* 3221 ParentGroup.RotLookAt(target, strength, damping);
2647 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); 3222 return;
2648 if (avatar != null)
2649 {
2650 Rotate the Av?
2651 } */
2652 } 3223 }
2653 else
2654 {
2655 APIDDamp = damping;
2656 APIDStrength = strength;
2657 APIDTarget = target;
2658 3224
2659 if (APIDStrength <= 0) 3225 APIDDamp = damping;
2660 { 3226 APIDStrength = strength;
2661 m_log.WarnFormat("[SceneObjectPart] Invalid rotation strength {0}",APIDStrength); 3227 APIDTarget = target;
2662 return; 3228
2663 } 3229 if (APIDStrength <= 0)
2664 3230 {
2665 APIDActive = true; 3231 m_log.WarnFormat("[SceneObjectPart] Invalid rotation strength {0}",APIDStrength);
3232 return;
2666 } 3233 }
2667 3234
3235 APIDActive = true;
3236
2668 // Necessary to get the lookat deltas applied 3237 // Necessary to get the lookat deltas applied
2669 ParentGroup.QueueForUpdateCheck(); 3238 ParentGroup.QueueForUpdateCheck();
2670 } 3239 }
2671 3240
2672 public void StartLookAt(Quaternion target, float strength, float damping) 3241 public void StartLookAt(Quaternion target, float strength, float damping)
2673 { 3242 {
2674 RotLookAt(target,strength,damping); 3243 if(ParentGroup.IsDeleted)
2675 } 3244 return;
2676
2677 public void StopLookAt()
2678 {
2679 APIDActive = false;
2680 }
2681 3245
3246 // non physical is done on LSL
3247 if(ParentGroup.IsAttachment || !ParentGroup.UsesPhysics)
3248 return;
2682 3249
3250 // physical is SOG
3251 if(ParentGroup.RootPart != this)
3252 ParentGroup.RotLookAt(target, strength, damping);
3253 else
3254 RotLookAt(target,strength,damping);
3255 }
2683 3256
2684 public void ScheduleFullUpdateIfNone() 3257 public void StopLookAt()
2685 { 3258 {
2686 if (ParentGroup == null) 3259 if(ParentGroup.IsDeleted)
2687 return; 3260 return;
2688 3261
2689// ??? ParentGroup.HasGroupChanged = true; 3262 if(ParentGroup.RootPart != this && ParentGroup.UsesPhysics)
3263 ParentGroup.StopLookAt();
2690 3264
2691 if (UpdateFlag != UpdateRequired.FULL) 3265 // just in case do this always
2692 ScheduleFullUpdate(); 3266 if(APIDActive)
3267 AngularVelocity = Vector3.Zero;
3268
3269 APIDActive = false;
2693 } 3270 }
2694 3271
2695 /// <summary> 3272 /// <summary>
@@ -2701,41 +3278,44 @@ namespace OpenSim.Region.Framework.Scenes
2701 3278
2702 if (ParentGroup == null) 3279 if (ParentGroup == null)
2703 return; 3280 return;
3281 if (ParentGroup.Scene == null)
3282 return;
2704 3283
2705 ParentGroup.QueueForUpdateCheck(); 3284 if(ParentGroup.Scene.GetNumberOfClients() == 0)
3285 return;
2706 3286
2707 int timeNow = Util.UnixTimeSinceEpoch(); 3287 ParentGroup.QueueForUpdateCheck(); // just in case
2708 3288
2709 // If multiple updates are scheduled on the same second, we still need to perform all of them 3289 lock(UpdateFlagLock)
2710 // So we'll force the issue by bumping up the timestamp so that later processing sees these need
2711 // to be performed.
2712 if (timeNow <= TimeStampFull)
2713 {
2714 TimeStampFull += 1;
2715 }
2716 else
2717 { 3290 {
2718 TimeStampFull = (uint)timeNow; 3291 if(UpdateFlag != UpdateRequired.FULL)
2719 } 3292 {
2720 3293 UpdateFlag = UpdateRequired.FULL;
2721 UpdateFlag = UpdateRequired.FULL;
2722 3294
2723 // m_log.DebugFormat( 3295 // m_log.DebugFormat(
2724 // "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}", 3296 // "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}",
2725 // UUID, Name, TimeStampFull); 3297 // UUID, Name, TimeStampFull);
2726 3298
2727 if (ParentGroup.Scene != null) 3299 }
2728 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true); 3300 }
3301 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true);
2729 } 3302 }
2730 3303
2731 /// <summary> 3304 /// <summary>
2732 /// Schedule a terse update for this prim. Terse updates only send position, 3305 /// Schedule a terse update for this prim. Terse updates only send position,
2733 /// rotation, velocity and rotational velocity information. 3306 /// rotation, velocity and rotational velocity information. WRONG!!!!
2734 /// </summary> 3307 /// </summary>
2735 public void ScheduleTerseUpdate() 3308 public void ScheduleTerseUpdate()
2736 { 3309 {
2737 if (ParentGroup == null) 3310 if (ParentGroup == null)
2738 return; 3311 return;
3312 if (ParentGroup.Scene == null)
3313 return;
3314
3315 ParentGroup.HasGroupChanged = true;
3316
3317 if(ParentGroup.Scene.GetNumberOfClients() == 0)
3318 return;
2739 3319
2740 // This was pulled from SceneViewer. Attachments always receive full updates. 3320 // This was pulled from SceneViewer. Attachments always receive full updates.
2741 // This is needed because otherwise if only the root prim changes position, then 3321 // This is needed because otherwise if only the root prim changes position, then
@@ -2746,21 +3326,19 @@ namespace OpenSim.Region.Framework.Scenes
2746 return; 3326 return;
2747 } 3327 }
2748 3328
2749 if (UpdateFlag == UpdateRequired.NONE) 3329 ParentGroup.QueueForUpdateCheck();
3330 lock(UpdateFlagLock)
2750 { 3331 {
2751 ParentGroup.HasGroupChanged = true; 3332 if (UpdateFlag == UpdateRequired.NONE)
2752 ParentGroup.QueueForUpdateCheck(); 3333 {
2753 3334 UpdateFlag = UpdateRequired.TERSE;
2754 TimeStampTerse = (uint) Util.UnixTimeSinceEpoch();
2755 UpdateFlag = UpdateRequired.TERSE;
2756 3335
2757 // m_log.DebugFormat( 3336 // m_log.DebugFormat(
2758 // "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}", 3337 // "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1}",
2759 // UUID, Name, TimeStampTerse); 3338 // UUID, Name);
3339 }
2760 } 3340 }
2761 3341 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false);
2762 if (ParentGroup.Scene != null)
2763 ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false);
2764 } 3342 }
2765 3343
2766 public void ScriptSetPhysicsStatus(bool UsePhysics) 3344 public void ScriptSetPhysicsStatus(bool UsePhysics)
@@ -2769,39 +3347,6 @@ namespace OpenSim.Region.Framework.Scenes
2769 } 3347 }
2770 3348
2771 /// <summary> 3349 /// <summary>
2772 /// Set sculpt and mesh data, and tell the physics engine to process the change.
2773 /// </summary>
2774 /// <param name="texture">The mesh itself.</param>
2775/*
2776 public void SculptTextureCallback(AssetBase texture)
2777 {
2778 if (m_shape.SculptEntry)
2779 {
2780 // commented out for sculpt map caching test - null could mean a cached sculpt map has been found
2781 //if (texture != null)
2782 {
2783 if (texture != null)
2784 {
2785// m_log.DebugFormat(
2786// "[SCENE OBJECT PART]: Setting sculpt data for {0} on SculptTextureCallback()", Name);
2787
2788 m_shape.SculptData = texture.Data;
2789 }
2790
2791 PhysicsActor pa = PhysActor;
2792
2793 if (pa != null)
2794 {
2795 // Update the physics actor with the new loaded sculpt data and set the taint signal.
2796 pa.Shape = m_shape;
2797
2798 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
2799 }
2800 }
2801 }
2802 }
2803*/
2804 /// <summary>
2805 /// Send a full update to the client for the given part 3350 /// Send a full update to the client for the given part
2806 /// </summary> 3351 /// </summary>
2807 /// <param name="remoteClient"></param> 3352 /// <param name="remoteClient"></param>
@@ -2812,16 +3357,14 @@ namespace OpenSim.Region.Framework.Scenes
2812 3357
2813// m_log.DebugFormat( 3358// m_log.DebugFormat(
2814// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId); 3359// "[SOG]: Sendinging part full update to {0} for {1} {2}", remoteClient.Name, part.Name, part.LocalId);
2815 3360
2816 if (IsRoot) 3361
3362 if (ParentGroup.IsAttachment)
2817 { 3363 {
2818 if (ParentGroup.IsAttachment) 3364 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3365 if (sp != null)
2819 { 3366 {
2820 SendFullUpdateToClient(remoteClient, AttachedPos); 3367 sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
2821 }
2822 else
2823 {
2824 SendFullUpdateToClient(remoteClient, AbsolutePosition);
2825 } 3368 }
2826 } 3369 }
2827 else 3370 else
@@ -2833,42 +3376,68 @@ namespace OpenSim.Region.Framework.Scenes
2833 /// <summary> 3376 /// <summary>
2834 /// Send a full update for this part to all clients. 3377 /// Send a full update for this part to all clients.
2835 /// </summary> 3378 /// </summary>
2836 public void SendFullUpdateToAllClients() 3379 public void SendFullUpdateToAllClientsInternal()
2837 { 3380 {
2838 if (ParentGroup == null) 3381 if (ParentGroup == null)
2839 return; 3382 return;
2840 3383
3384 // Update the "last" values
3385 lock(UpdateFlagLock)
3386 {
3387 m_lastPosition = AbsolutePosition;
3388 m_lastRotation = RotationOffset;
3389 m_lastVelocity = Velocity;
3390 m_lastAcceleration = Acceleration;
3391 m_lastAngularVelocity = AngularVelocity;
3392 m_lastUpdateSentTime = Util.GetTimeStampMS();
3393 }
3394
2841 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 3395 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
2842 { 3396 {
2843 SendFullUpdate(avatar.ControllingClient); 3397 SendFullUpdate(avatar.ControllingClient);
2844 }); 3398 });
2845 } 3399 }
2846 3400
2847 /// <summary> 3401 public void SendFullUpdateToAllClients()
2848 /// Sends a full update to the client
2849 /// </summary>
2850 /// <param name="remoteClient"></param>
2851 public void SendFullUpdateToClient(IClientAPI remoteClient)
2852 { 3402 {
2853 SendFullUpdateToClient(remoteClient, OffsetPosition); 3403 if (ParentGroup == null)
3404 return;
3405
3406 // Update the "last" values
3407 lock(UpdateFlagLock)
3408 {
3409 m_lastPosition = AbsolutePosition;
3410 m_lastRotation = RotationOffset;
3411 m_lastVelocity = Velocity;
3412 m_lastAcceleration = Acceleration;
3413 m_lastAngularVelocity = AngularVelocity;
3414 m_lastUpdateSentTime = Util.GetTimeStampMS();
3415 }
3416
3417 if (ParentGroup.IsAttachment)
3418 {
3419 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3420 if (sp != null)
3421 {
3422 sp.SendAttachmentUpdate(this, UpdateRequired.FULL);
3423 }
3424 }
3425 else
3426 {
3427 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
3428 {
3429 SendFullUpdate(avatar.ControllingClient);
3430 });
3431 }
2854 } 3432 }
2855 3433
2856 /// <summary> 3434 /// <summary>
2857 /// Sends a full update to the client 3435 /// Sends a full update to the client
2858 /// </summary> 3436 /// </summary>
2859 /// <param name="remoteClient"></param> 3437 /// <param name="remoteClient"></param>
2860 /// <param name="lPos"></param> 3438 public void SendFullUpdateToClient(IClientAPI remoteClient)
2861 public void SendFullUpdateToClient(IClientAPI remoteClient, Vector3 lPos)
2862 { 3439 {
2863 if (ParentGroup == null) 3440 if (ParentGroup == null || ParentGroup.IsDeleted)
2864 return;
2865
2866 // Suppress full updates during attachment editing
2867 //
2868 if (ParentGroup.IsSelected && ParentGroup.IsAttachment)
2869 return;
2870
2871 if (ParentGroup.IsDeleted)
2872 return; 3441 return;
2873 3442
2874 if (ParentGroup.IsAttachment 3443 if (ParentGroup.IsAttachment
@@ -2889,62 +3458,212 @@ namespace OpenSim.Region.Framework.Scenes
2889 ParentGroup.Scene.StatsReporter.AddObjectUpdates(1); 3458 ParentGroup.Scene.StatsReporter.AddObjectUpdates(1);
2890 } 3459 }
2891 3460
3461 private const float ROTATION_TOLERANCE = 0.01f;
3462 private const float VELOCITY_TOLERANCE = 0.1f;
3463 private const float ANGVELOCITY_TOLERANCE = 0.005f;
3464 private const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
3465 private const double TIME_MS_TOLERANCE = 200.0; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
3466
2892 /// <summary> 3467 /// <summary>
2893 /// Tell all the prims which have had updates scheduled 3468 /// Tell all the prims which have had updates scheduled
2894 /// </summary> 3469 /// </summary>
2895 public void SendScheduledUpdates() 3470 public void SendScheduledUpdates(double now)
2896 { 3471 {
2897 const float ROTATION_TOLERANCE = 0.01f; 3472 bool sendterse = false;
2898 const float VELOCITY_TOLERANCE = 0.001f; 3473 bool sendfull = false;
2899 const float POSITION_TOLERANCE = 0.05f;
2900 const int TIME_MS_TOLERANCE = 3000;
2901 3474
2902 switch (UpdateFlag) 3475 lock(UpdateFlagLock)
2903 { 3476 {
2904 case UpdateRequired.TERSE: 3477 switch (UpdateFlag)
2905 { 3478 {
2906 ClearUpdateSchedule(); 3479 case UpdateRequired.NONE:
2907 // Throw away duplicate or insignificant updates 3480 break;
2908 if (!RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) || 3481
2909 !Acceleration.Equals(m_lastAcceleration) || 3482 case UpdateRequired.TERSE:
2910 !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || 3483 sendterse = true;
2911 Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) || 3484
2912 !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) || 3485 Vector3 curvel = Velocity;
2913 !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 3486 Vector3 curacc = Acceleration;
2914 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3487 Vector3 angvel = AngularVelocity;
2915 { 3488
2916 SendTerseUpdateToAllClients(); 3489 while(true) // just to avoid ugly goto
3490 {
3491 double elapsed = now - m_lastUpdateSentTime;
3492 if (elapsed > TIME_MS_TOLERANCE)
3493 break;
3494
3495 if( Math.Abs(curacc.X - m_lastAcceleration.X) > VELOCITY_TOLERANCE ||
3496 Math.Abs(curacc.Y - m_lastAcceleration.Y) > VELOCITY_TOLERANCE ||
3497 Math.Abs(curacc.Z - m_lastAcceleration.Z) > VELOCITY_TOLERANCE)
3498 break;
3499
3500 if( Math.Abs(curvel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE ||
3501 Math.Abs(curvel.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE ||
3502 Math.Abs(curvel.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE)
3503 break;
3504
3505 float vx = Math.Abs(curvel.X);
3506 if(vx > 128.0)
3507 break;
3508 float vy = Math.Abs(curvel.Y);
3509 if(vy > 128.0)
3510 break;
3511 float vz = Math.Abs(curvel.Z);
3512 if(vz > 128.0)
3513 break;
3514
3515 if (
3516 vx < VELOCITY_TOLERANCE &&
3517 vy < VELOCITY_TOLERANCE &&
3518 vz < VELOCITY_TOLERANCE
3519 )
3520 {
3521 if(!AbsolutePosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
3522 break;
3523
3524 if (vx < 1e-4 &&
3525 vy < 1e-4 &&
3526 vz < 1e-4 &&
3527 (
3528 Math.Abs(m_lastVelocity.X) > 1e-4 ||
3529 Math.Abs(m_lastVelocity.Y) > 1e-4 ||
3530 Math.Abs(m_lastVelocity.Z) > 1e-4
3531 ))
3532 break;
3533 }
3534
3535 if( Math.Abs(angvel.X - m_lastAngularVelocity.X) > ANGVELOCITY_TOLERANCE ||
3536 Math.Abs(angvel.Y - m_lastAngularVelocity.Y) > ANGVELOCITY_TOLERANCE ||
3537 Math.Abs(angvel.Z - m_lastAngularVelocity.Z) > ANGVELOCITY_TOLERANCE)
3538 break;
3539
3540 // viewer interpolators have a limit of 64rad/s
3541 float ax = Math.Abs(angvel.X);
3542 if(ax > 64.0)
3543 break;
3544 float ay = Math.Abs(angvel.Y);
3545 if(ay > 64.0)
3546 break;
3547 float az = Math.Abs(angvel.Z);
3548 if(az > 64.0)
3549 break;
3550
3551 if (
3552 ax < ANGVELOCITY_TOLERANCE &&
3553 ay < ANGVELOCITY_TOLERANCE &&
3554 az < ANGVELOCITY_TOLERANCE &&
3555 !RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)
3556 )
3557 break;
3558
3559 sendterse = false;
3560 break;
3561 }
3562
3563 if(sendterse)
3564 {
3565 // Update the "last" values
3566 m_lastPosition = AbsolutePosition;
3567 m_lastRotation = RotationOffset;
3568 m_lastVelocity = curvel;
3569 m_lastAcceleration = curacc;
3570 m_lastAngularVelocity = angvel;
3571 m_lastUpdateSentTime = now;
3572 ClearUpdateSchedule();
3573 }
3574 break;
2917 3575
2918 // Update the "last" values 3576 case UpdateRequired.FULL:
2919 m_lastPosition = OffsetPosition; 3577 m_lastPosition = AbsolutePosition;
2920 m_lastRotation = RotationOffset; 3578 m_lastRotation = RotationOffset;
2921 m_lastVelocity = Velocity; 3579 m_lastVelocity = Velocity;
2922 m_lastAcceleration = Acceleration; 3580 m_lastAcceleration = Acceleration;
2923 m_lastAngularVelocity = AngularVelocity; 3581 m_lastAngularVelocity = AngularVelocity;
2924 m_lastTerseSent = Environment.TickCount; 3582 m_lastUpdateSentTime = now;
2925 } 3583 ClearUpdateSchedule();
2926 break; 3584 sendfull = true;
3585 break;
2927 } 3586 }
2928 case UpdateRequired.FULL: 3587 }
3588 if(sendterse)
3589 {
3590 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
2929 { 3591 {
2930 ClearUpdateSchedule(); 3592 SendTerseUpdateToClient(client);
2931 SendFullUpdateToAllClients(); 3593 });
2932 break; 3594 }
2933 } 3595 else if(sendfull)
3596 {
3597 ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
3598 {
3599 SendFullUpdate(avatar.ControllingClient);
3600 });
2934 } 3601 }
2935 } 3602 }
2936 3603
2937 /// <summary> 3604 /// <summary>
2938 /// Send a terse update to all clients 3605 /// Send a terse update to all clients
2939 /// </summary> 3606 /// </summary>
2940 public void SendTerseUpdateToAllClients() 3607 public void SendTerseUpdateToAllClientsInternal()
2941 { 3608 {
3609 if (ParentGroup == null || ParentGroup.Scene == null)
3610 return;
3611 lock(UpdateFlagLock)
3612 {
3613 if(UpdateFlag != UpdateRequired.NONE)
3614 return;
3615
3616 // Update the "last" values
3617 m_lastPosition = AbsolutePosition;
3618 m_lastRotation = RotationOffset;
3619 m_lastVelocity = Velocity;
3620 m_lastAcceleration = Acceleration;
3621 m_lastAngularVelocity = AngularVelocity;
3622 m_lastUpdateSentTime = Util.GetTimeStampMS();
3623 }
3624
2942 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) 3625 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
2943 { 3626 {
2944 SendTerseUpdateToClient(client); 3627 SendTerseUpdateToClient(client);
2945 }); 3628 });
2946 } 3629 }
2947 3630
3631 public void SendTerseUpdateToAllClients()
3632 {
3633 if (ParentGroup == null || ParentGroup.Scene == null)
3634 return;
3635
3636 lock(UpdateFlagLock)
3637 {
3638 if(UpdateFlag != UpdateRequired.NONE)
3639 return;
3640
3641 // Update the "last" values
3642 m_lastPosition = AbsolutePosition;
3643 m_lastRotation = RotationOffset;
3644 m_lastVelocity = Velocity;
3645 m_lastAcceleration = Acceleration;
3646 m_lastAngularVelocity = AngularVelocity;
3647 m_lastUpdateSentTime = Util.GetTimeStampMS();
3648 }
3649
3650 if (ParentGroup.IsAttachment)
3651 {
3652 ScenePresence sp = ParentGroup.Scene.GetScenePresence(ParentGroup.AttachedAvatar);
3653 if (sp != null)
3654 {
3655 sp.SendAttachmentUpdate(this, UpdateRequired.TERSE);
3656 }
3657 }
3658 else
3659 {
3660 ParentGroup.Scene.ForEachClient(delegate(IClientAPI client)
3661 {
3662 SendTerseUpdateToClient(client);
3663 });
3664 }
3665 }
3666
2948 public void SetAxisRotation(int axis, int rotate) 3667 public void SetAxisRotation(int axis, int rotate)
2949 { 3668 {
2950 ParentGroup.SetAxisRotation(axis, rotate); 3669 ParentGroup.SetAxisRotation(axis, rotate);
@@ -2962,10 +3681,13 @@ namespace OpenSim.Region.Framework.Scenes
2962 3681
2963 public void SetBuoyancy(float fvalue) 3682 public void SetBuoyancy(float fvalue)
2964 { 3683 {
2965 PhysicsActor pa = PhysActor; 3684 Buoyancy = fvalue;
2966 3685/*
2967 if (pa != null) 3686 if (PhysActor != null)
2968 pa.Buoyancy = fvalue; 3687 {
3688 PhysActor.Buoyancy = fvalue;
3689 }
3690 */
2969 } 3691 }
2970 3692
2971 public void SetDieAtEdge(bool p) 3693 public void SetDieAtEdge(bool p)
@@ -2981,47 +3703,123 @@ namespace OpenSim.Region.Framework.Scenes
2981 PhysicsActor pa = PhysActor; 3703 PhysicsActor pa = PhysActor;
2982 3704
2983 if (pa != null) 3705 if (pa != null)
2984 pa.FloatOnWater = floatYN == 1; 3706 pa.FloatOnWater = (floatYN == 1);
2985 } 3707 }
2986 3708
2987 public void SetForce(Vector3 force) 3709 public void SetForce(Vector3 force)
2988 { 3710 {
2989 PhysicsActor pa = PhysActor; 3711 Force = force;
3712 }
2990 3713
2991 if (pa != null) 3714 public PhysicsInertiaData PhysicsInertia
2992 pa.Force = force; 3715 {
3716 get
3717 {
3718 return m_physicsInertia;
3719 }
3720 set
3721 {
3722 m_physicsInertia = value;
3723 }
3724 }
3725
3726 public SOPVehicle VehicleParams
3727 {
3728 get
3729 {
3730 return m_vehicleParams;
3731 }
3732 set
3733 {
3734 m_vehicleParams = value;
3735
3736 }
3737 }
3738
3739 public int VehicleType
3740 {
3741 get
3742 {
3743 if (m_vehicleParams == null)
3744 return (int)Vehicle.TYPE_NONE;
3745 else
3746 return (int)m_vehicleParams.Type;
3747 }
3748 set
3749 {
3750 SetVehicleType(value);
3751 }
2993 } 3752 }
2994 3753
2995 public void SetVehicleType(int type) 3754 public void SetVehicleType(int type)
2996 { 3755 {
2997 PhysicsActor pa = PhysActor; 3756 m_vehicleParams = null;
2998 3757
2999 if (pa != null) 3758 if (type == (int)Vehicle.TYPE_NONE)
3000 pa.VehicleType = type; 3759 {
3760 if (_parentID ==0 && PhysActor != null)
3761 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3762 return;
3763 }
3764 m_vehicleParams = new SOPVehicle();
3765 m_vehicleParams.ProcessTypeChange((Vehicle)type);
3766 {
3767 if (_parentID ==0 && PhysActor != null)
3768 PhysActor.VehicleType = type;
3769 return;
3770 }
3771 }
3772
3773 public void SetVehicleFlags(int param, bool remove)
3774 {
3775 if (m_vehicleParams == null)
3776 return;
3777
3778 m_vehicleParams.ProcessVehicleFlags(param, remove);
3779
3780 if (_parentID == 0 && PhysActor != null)
3781 {
3782 PhysActor.VehicleFlags(param, remove);
3783 }
3001 } 3784 }
3002 3785
3003 public void SetVehicleFloatParam(int param, float value) 3786 public void SetVehicleFloatParam(int param, float value)
3004 { 3787 {
3005 PhysicsActor pa = PhysActor; 3788 if (m_vehicleParams == null)
3789 return;
3006 3790
3007 if (pa != null) 3791 m_vehicleParams.ProcessFloatVehicleParam((Vehicle)param, value);
3008 pa.VehicleFloatParam(param, value); 3792
3793 if (_parentID == 0 && PhysActor != null)
3794 {
3795 PhysActor.VehicleFloatParam(param, value);
3796 }
3009 } 3797 }
3010 3798
3011 public void SetVehicleVectorParam(int param, Vector3 value) 3799 public void SetVehicleVectorParam(int param, Vector3 value)
3012 { 3800 {
3013 PhysicsActor pa = PhysActor; 3801 if (m_vehicleParams == null)
3802 return;
3014 3803
3015 if (pa != null) 3804 m_vehicleParams.ProcessVectorVehicleParam((Vehicle)param, value);
3016 pa.VehicleVectorParam(param, value); 3805
3806 if (_parentID == 0 && PhysActor != null)
3807 {
3808 PhysActor.VehicleVectorParam(param, value);
3809 }
3017 } 3810 }
3018 3811
3019 public void SetVehicleRotationParam(int param, Quaternion rotation) 3812 public void SetVehicleRotationParam(int param, Quaternion rotation)
3020 { 3813 {
3021 PhysicsActor pa = PhysActor; 3814 if (m_vehicleParams == null)
3815 return;
3022 3816
3023 if (pa != null) 3817 m_vehicleParams.ProcessRotationVehicleParam((Vehicle)param, rotation);
3024 pa.VehicleRotationParam(param, rotation); 3818
3819 if (_parentID == 0 && PhysActor != null)
3820 {
3821 PhysActor.VehicleRotationParam(param, rotation);
3822 }
3025 } 3823 }
3026 3824
3027 /// <summary> 3825 /// <summary>
@@ -3041,7 +3839,8 @@ namespace OpenSim.Region.Framework.Scenes
3041 Byte[] buf = Shape.Textures.GetBytes(); 3839 Byte[] buf = Shape.Textures.GetBytes();
3042 Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); 3840 Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length);
3043 Color4 texcolor; 3841 Color4 texcolor;
3044 if (face >= 0 && face < GetNumberOfSides()) 3842 int nsides = GetNumberOfSides();
3843 if (face >= 0 && face < nsides)
3045 { 3844 {
3046 texcolor = tex.CreateFace((uint)face).RGBA; 3845 texcolor = tex.CreateFace((uint)face).RGBA;
3047 texcolor.R = clippedColor.X; 3846 texcolor.R = clippedColor.X;
@@ -3057,7 +3856,7 @@ namespace OpenSim.Region.Framework.Scenes
3057 } 3856 }
3058 else if (face == ALL_SIDES) 3857 else if (face == ALL_SIDES)
3059 { 3858 {
3060 for (uint i = 0; i < GetNumberOfSides(); i++) 3859 for (uint i = 0; i < nsides; i++)
3061 { 3860 {
3062 if (tex.FaceTextures[i] != null) 3861 if (tex.FaceTextures[i] != null)
3063 { 3862 {
@@ -3093,64 +3892,110 @@ namespace OpenSim.Region.Framework.Scenes
3093 public int GetNumberOfSides() 3892 public int GetNumberOfSides()
3094 { 3893 {
3095 int ret = 0; 3894 int ret = 0;
3096 bool hasCut;
3097 bool hasHollow;
3098 bool hasDimple;
3099 bool hasProfileCut;
3100 3895
3101 PrimType primType = GetPrimType(); 3896 if(Shape.SculptEntry)
3102 HasCutHollowDimpleProfileCut(primType, Shape, out hasCut, out hasHollow, out hasDimple, out hasProfileCut); 3897 {
3898 if (Shape.SculptType != (byte)SculptType.Mesh)
3899 return 1; // sculp
3900
3901 //hack to detect new upload with faces data enconded on pbs
3902 if ((Shape.ProfileCurve & 0xf0) != (byte)HollowShape.Triangle)
3903 // old broken upload TODO
3904 return 8;
3905 }
3906
3907 PrimType primType = GetPrimType(true);
3103 3908
3104 switch (primType) 3909 switch (primType)
3105 { 3910 {
3106 case PrimType.BOX: 3911 case PrimType.BOX:
3107 ret = 6; 3912 ret = 6;
3108 if (hasCut) ret += 2; 3913 if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // cut case
3109 if (hasHollow) ret += 1; 3914 {
3110 break; 3915 // removed sides
3111 case PrimType.CYLINDER: 3916 int cut = (Shape.ProfileEnd + Shape.ProfileBegin);
3112 ret = 3; 3917 if(cut > 50000) // range is 0 to 50000
3113 if (hasCut) ret += 2; 3918 cut = 50000;
3114 if (hasHollow) ret += 1; 3919 cut /= 12500; // ie 1/4
3920 ret -= cut;
3921 ret += 2; // both cut faces
3922 }
3115 break; 3923 break;
3116 case PrimType.PRISM: 3924 case PrimType.PRISM:
3117 ret = 5; 3925 ret = 5;
3118 if (hasCut) ret += 2; 3926 if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // cut case
3119 if (hasHollow) ret += 1; 3927 {
3928 // removed faces
3929 int cut = (Shape.ProfileEnd + Shape.ProfileBegin);
3930 if(cut >= 16667 ) // ie 1/3
3931 ret--;
3932 if(cut >= 33333 ) // ie 2/3
3933 ret--;
3934 ret += 2; // both cut faces
3935 }
3936 break;
3937 case PrimType.CYLINDER:
3938 ret = 3;
3939 if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // cut
3940 ret += 2;
3120 break; 3941 break;
3121 case PrimType.SPHERE: 3942 case PrimType.SPHERE:
3122 ret = 1; 3943 ret = 1;
3123 if (hasCut) ret += 2; 3944 // cut faces exist if cut or skew or unequal twist limits
3124 if (hasDimple) ret += 2; 3945 if (Shape.PathBegin > 0 || Shape.PathEnd > 0 || Shape.PathSkew != 0 || (Shape.PathTwistBegin != Shape.PathTwist))
3125 if (hasHollow) ret += 1; 3946 ret += 2;
3947 if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0 || Shape.ProfileHollow > 0) // dimple faces also if hollow
3948 ret += 2;
3126 break; 3949 break;
3127 case PrimType.TORUS: 3950 case PrimType.TORUS:
3128 ret = 1; 3951 ret = 1;
3129 if (hasCut) ret += 2; 3952 if (Shape.PathBegin > 0 || Shape.PathEnd > 0 || Shape.PathSkew != 0
3130 if (hasProfileCut) ret += 2; 3953 || Shape.PathTaperX != 0 || Shape.PathTaperY != 0 || Shape.PathRevolutions > 0
3131 if (hasHollow) ret += 1; 3954 || Shape.PathRadiusOffset != 0 || (Shape.PathTwistBegin != Shape.PathTwist))
3955 ret += 2;
3956 if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // profile cut
3957 ret += 2;
3132 break; 3958 break;
3133 case PrimType.TUBE: 3959 case PrimType.TUBE:
3134 ret = 4; 3960 ret = 4;
3135 if (hasCut) ret += 2; 3961 if (Shape.PathBegin > 0 || Shape.PathEnd > 0 || Shape.PathSkew != 0
3136 if (hasProfileCut) ret += 2; 3962 || Shape.PathTaperX != 0 || Shape.PathTaperY != 0 || Shape.PathRevolutions > 0
3137 if (hasHollow) ret += 1; 3963 || Shape.PathRadiusOffset != 0 || (Shape.PathTwistBegin != Shape.PathTwist))
3964 ret += 2;
3965 if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // profile cut
3966 {
3967 // removed sides
3968 int cut = (Shape.ProfileEnd + Shape.ProfileBegin);
3969 if(cut > 50000)
3970 cut = 50000;
3971 cut /= 12500;
3972 ret -= cut;
3973 ret += 2; // both cut faces
3974 }
3138 break; 3975 break;
3139 case PrimType.RING: 3976 case PrimType.RING:
3140 ret = 3; 3977 ret = 3;
3141 if (hasCut) ret += 2; 3978 if (Shape.PathBegin > 0 || Shape.PathEnd > 0 || Shape.PathSkew != 0
3142 if (hasProfileCut) ret += 2; 3979 || Shape.PathTaperX != 0 || Shape.PathTaperY != 0 || Shape.PathRevolutions > 0
3143 if (hasHollow) ret += 1; 3980 || Shape.PathRadiusOffset != 0 || (Shape.PathTwistBegin != Shape.PathTwist))
3144 break; 3981 ret += 2;
3145 case PrimType.SCULPT: 3982 if (Shape.ProfileBegin > 0 || Shape.ProfileEnd > 0) // profile cut
3146 // Special mesh handling 3983 {
3147 if (Shape.SculptType == (byte)SculptType.Mesh) 3984 // removed faces
3148 ret = 8; // if it's a mesh then max 8 faces 3985 int cut = (Shape.ProfileEnd + Shape.ProfileBegin);
3149 else 3986 if(cut >= 16667 )
3150 ret = 1; // if it's a sculpt then max 1 face 3987 ret--;
3988 if(cut >= 33333 )
3989 ret--;
3990 ret += 2; // both cut faces
3991 }
3151 break; 3992 break;
3152 } 3993 }
3153 3994
3995 // hollow face commum to all
3996 if (Shape.ProfileHollow > 0)
3997 ret += 1;
3998
3154 return ret; 3999 return ret;
3155 } 4000 }
3156 4001
@@ -3159,11 +4004,11 @@ namespace OpenSim.Region.Framework.Scenes
3159 /// </summary> 4004 /// </summary>
3160 /// <param name="primShape"></param> 4005 /// <param name="primShape"></param>
3161 /// <returns></returns> 4006 /// <returns></returns>
3162 public PrimType GetPrimType() 4007 public PrimType GetPrimType(bool ignoreSculpt = false)
3163 { 4008 {
3164 if (Shape.SculptEntry) 4009 if (Shape.SculptEntry && !ignoreSculpt)
3165 return PrimType.SCULPT; 4010 return PrimType.SCULPT;
3166 4011
3167 if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.Square) 4012 if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
3168 { 4013 {
3169 if (Shape.PathCurve == (byte)Extrusion.Straight) 4014 if (Shape.PathCurve == (byte)Extrusion.Straight)
@@ -3173,7 +4018,7 @@ namespace OpenSim.Region.Framework.Scenes
3173 } 4018 }
3174 else if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) 4019 else if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
3175 { 4020 {
3176 if (Shape.PathCurve == (byte)Extrusion.Straight) 4021 if (Shape.PathCurve == (byte)Extrusion.Straight || Shape.PathCurve == (byte)Extrusion.Flexible)
3177 return PrimType.CYLINDER; 4022 return PrimType.CYLINDER;
3178 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits 4023 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
3179 else if (Shape.PathCurve == (byte)Extrusion.Curve1) 4024 else if (Shape.PathCurve == (byte)Extrusion.Curve1)
@@ -3186,48 +4031,13 @@ namespace OpenSim.Region.Framework.Scenes
3186 } 4031 }
3187 else if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) 4032 else if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
3188 { 4033 {
3189 if (Shape.PathCurve == (byte)Extrusion.Straight) 4034 if (Shape.PathCurve == (byte)Extrusion.Straight || Shape.PathCurve == (byte)Extrusion.Flexible)
3190 return PrimType.PRISM; 4035 return PrimType.PRISM;
3191 else if (Shape.PathCurve == (byte)Extrusion.Curve1) 4036 else if (Shape.PathCurve == (byte)Extrusion.Curve1)
3192 return PrimType.RING; 4037 return PrimType.RING;
3193 } 4038 }
3194
3195 return PrimType.BOX;
3196 }
3197
3198 /// <summary>
3199 /// Tell us if this object has cut, hollow, dimple, and other factors affecting the number of faces
3200 /// </summary>
3201 /// <param name="primType"></param>
3202 /// <param name="shape"></param>
3203 /// <param name="hasCut"></param>
3204 /// <param name="hasHollow"></param>
3205 /// <param name="hasDimple"></param>
3206 /// <param name="hasProfileCut"></param>
3207 protected static void HasCutHollowDimpleProfileCut(PrimType primType, PrimitiveBaseShape shape, out bool hasCut, out bool hasHollow,
3208 out bool hasDimple, out bool hasProfileCut)
3209 {
3210 if (primType == PrimType.BOX
3211 ||
3212 primType == PrimType.CYLINDER
3213 ||
3214 primType == PrimType.PRISM)
3215
3216 hasCut = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0);
3217 else
3218 hasCut = (shape.PathBegin > 0) || (shape.PathEnd > 0);
3219
3220 hasHollow = shape.ProfileHollow > 0;
3221 hasDimple = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0); // taken from llSetPrimitiveParms
3222 hasProfileCut = hasDimple; // is it the same thing?
3223 }
3224
3225 public void SetVehicleFlags(int param, bool remove)
3226 {
3227 PhysicsActor pa = PhysActor;
3228 4039
3229 if (pa != null) 4040 return PrimType.BOX;
3230 pa.VehicleFlags(param, remove);
3231 } 4041 }
3232 4042
3233 public void SetGroup(UUID groupID, IClientAPI client) 4043 public void SetGroup(UUID groupID, IClientAPI client)
@@ -3238,8 +4048,8 @@ namespace OpenSim.Region.Framework.Scenes
3238// Name, groupID, OwnerID); 4048// Name, groupID, OwnerID);
3239 4049
3240 GroupID = groupID; 4050 GroupID = groupID;
3241 if (client != null) 4051// if (client != null)
3242 SendPropertiesToClient(client); 4052// SendPropertiesToClient(client);
3243 UpdateFlag = UpdateRequired.FULL; 4053 UpdateFlag = UpdateRequired.FULL;
3244 } 4054 }
3245 4055
@@ -3263,7 +4073,7 @@ namespace OpenSim.Region.Framework.Scenes
3263 4073
3264 if (pa != null) 4074 if (pa != null)
3265 { 4075 {
3266 pa.LockAngularMotion(RotationAxis); 4076 pa.LockAngularMotion(RotationAxisLocks);
3267 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); 4077 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
3268 } 4078 }
3269 } 4079 }
@@ -3276,7 +4086,7 @@ namespace OpenSim.Region.Framework.Scenes
3276 public void SetScriptEvents(UUID scriptid, int events) 4086 public void SetScriptEvents(UUID scriptid, int events)
3277 { 4087 {
3278// m_log.DebugFormat( 4088// m_log.DebugFormat(
3279// "[SCENE OBJECT PART]: Set script events for script with id {0} on {1}/{2} to {3} in {4}", 4089// "[SCENE OBJECT PART]: Set script events for script with id {0} on {1}/{2} to {3} in {4}",
3280// scriptid, Name, ParentGroup.Name, events, ParentGroup.Scene.Name); 4090// scriptid, Name, ParentGroup.Name, events, ParentGroup.Scene.Name);
3281 4091
3282 // scriptEvents oldparts; 4092 // scriptEvents oldparts;
@@ -3313,7 +4123,7 @@ namespace OpenSim.Region.Framework.Scenes
3313 ScheduleFullUpdate(); 4123 ScheduleFullUpdate();
3314 } 4124 }
3315 } 4125 }
3316 4126
3317 /// <summary> 4127 /// <summary>
3318 /// Set the text displayed for this part. 4128 /// Set the text displayed for this part.
3319 /// </summary> 4129 /// </summary>
@@ -3334,67 +4144,16 @@ namespace OpenSim.Region.Framework.Scenes
3334 ParentGroup.StopMoveToTarget(); 4144 ParentGroup.StopMoveToTarget();
3335 } 4145 }
3336 4146
3337 public void StoreUndoState() 4147 public void StoreUndoState(ObjectChangeType change)
3338 { 4148 {
3339 StoreUndoState(false); 4149 lock (m_UndoLock)
3340 }
3341
3342 public void StoreUndoState(bool forGroup)
3343 {
3344 if (ParentGroup == null || ParentGroup.Scene == null)
3345 return;
3346
3347 if (Undoing)
3348 { 4150 {
3349// m_log.DebugFormat( 4151 if (m_UndoRedo == null)
3350// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); 4152 m_UndoRedo = new UndoRedoState(5);
3351 return;
3352 }
3353
3354 if (IgnoreUndoUpdate)
3355 {
3356// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3357 return;
3358 }
3359 4153
3360 lock (m_undo) 4154 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3361 {
3362 if (m_undo.Count > 0)
3363 { 4155 {
3364 UndoState last = m_undo[m_undo.Count - 1]; 4156 m_UndoRedo.StoreUndo(this, change);
3365 if (last != null)
3366 {
3367 // TODO: May need to fix for group comparison
3368 if (last.Compare(this))
3369 {
3370// m_log.DebugFormat(
3371// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3372// Name, LocalId, m_undo.Count);
3373
3374 return;
3375 }
3376 }
3377 }
3378
3379// m_log.DebugFormat(
3380// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3381// Name, LocalId, forGroup, m_undo.Count);
3382
3383 if (ParentGroup.Scene.MaxUndoCount > 0)
3384 {
3385 UndoState nUndo = new UndoState(this, forGroup);
3386
3387 m_undo.Add(nUndo);
3388
3389 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3390 m_undo.RemoveAt(0);
3391
3392 if (m_redo.Count > 0)
3393 m_redo.Clear();
3394
3395// m_log.DebugFormat(
3396// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3397// Name, LocalId, forGroup, m_undo.Count);
3398 } 4157 }
3399 } 4158 }
3400 } 4159 }
@@ -3406,186 +4165,47 @@ namespace OpenSim.Region.Framework.Scenes
3406 { 4165 {
3407 get 4166 get
3408 { 4167 {
3409 lock (m_undo) 4168 if (m_UndoRedo == null)
3410 return m_undo.Count; 4169 return 0;
4170 return m_UndoRedo.Count;
3411 } 4171 }
3412 } 4172 }
3413 4173
3414 public void Undo() 4174 public void Undo()
3415 { 4175 {
3416 lock (m_undo) 4176 lock (m_UndoLock)
3417 { 4177 {
3418// m_log.DebugFormat( 4178 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3419// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}", 4179 return;
3420// Name, LocalId, m_undo.Count);
3421
3422 if (m_undo.Count > 0)
3423 {
3424 UndoState goback = m_undo[m_undo.Count - 1];
3425 m_undo.RemoveAt(m_undo.Count - 1);
3426
3427 UndoState nUndo = null;
3428
3429 if (ParentGroup.Scene.MaxUndoCount > 0)
3430 {
3431 nUndo = new UndoState(this, goback.ForGroup);
3432 }
3433
3434 goback.PlaybackState(this);
3435
3436 if (nUndo != null)
3437 {
3438 m_redo.Add(nUndo);
3439
3440 if (m_redo.Count > ParentGroup.Scene.MaxUndoCount)
3441 m_redo.RemoveAt(0);
3442 }
3443 }
3444 4180
3445// m_log.DebugFormat( 4181 Undoing = true;
3446// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 4182 m_UndoRedo.Undo(this);
3447// Name, LocalId, m_undo.Count); 4183 Undoing = false;
3448 } 4184 }
3449 } 4185 }
3450 4186
3451 public void Redo() 4187 public void Redo()
3452 { 4188 {
3453 lock (m_undo) 4189 lock (m_UndoLock)
3454 { 4190 {
3455// m_log.DebugFormat( 4191 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3456// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}", 4192 return;
3457// Name, LocalId, m_redo.Count);
3458
3459 if (m_redo.Count > 0)
3460 {
3461 UndoState gofwd = m_redo[m_redo.Count - 1];
3462 m_redo.RemoveAt(m_redo.Count - 1);
3463
3464 if (ParentGroup.Scene.MaxUndoCount > 0)
3465 {
3466 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3467
3468 m_undo.Add(nUndo);
3469
3470 if (m_undo.Count > ParentGroup.Scene.MaxUndoCount)
3471 m_undo.RemoveAt(0);
3472 }
3473
3474 gofwd.PlayfwdState(this);
3475 4193
3476// m_log.DebugFormat( 4194 Undoing = true;
3477// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 4195 m_UndoRedo.Redo(this);
3478// Name, LocalId, m_redo.Count); 4196 Undoing = false;
3479 }
3480 } 4197 }
3481 } 4198 }
3482 4199
3483 public void ClearUndoState() 4200 public void ClearUndoState()
3484 { 4201 {
3485// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 4202 lock (m_UndoLock)
3486
3487 lock (m_undo)
3488 {
3489 m_undo.Clear();
3490 m_redo.Clear();
3491 }
3492 }
3493
3494 public EntityIntersection TestIntersection(Ray iray, Quaternion parentrot)
3495 {
3496 // In this case we're using a sphere with a radius of the largest dimension of the prim
3497 // TODO: Change to take shape into account
3498
3499 EntityIntersection result = new EntityIntersection();
3500 Vector3 vAbsolutePosition = AbsolutePosition;
3501 Vector3 vScale = Scale;
3502 Vector3 rOrigin = iray.Origin;
3503 Vector3 rDirection = iray.Direction;
3504
3505 //rDirection = rDirection.Normalize();
3506 // Buidling the first part of the Quadratic equation
3507 Vector3 r2ndDirection = rDirection*rDirection;
3508 float itestPart1 = r2ndDirection.X + r2ndDirection.Y + r2ndDirection.Z;
3509
3510 // Buidling the second part of the Quadratic equation
3511 Vector3 tmVal2 = rOrigin - vAbsolutePosition;
3512 Vector3 r2Direction = rDirection*2.0f;
3513 Vector3 tmVal3 = r2Direction*tmVal2;
3514
3515 float itestPart2 = tmVal3.X + tmVal3.Y + tmVal3.Z;
3516
3517 // Buidling the third part of the Quadratic equation
3518 Vector3 tmVal4 = rOrigin*rOrigin;
3519 Vector3 tmVal5 = vAbsolutePosition*vAbsolutePosition;
3520
3521 Vector3 tmVal6 = vAbsolutePosition*rOrigin;
3522
3523 // Set Radius to the largest dimension of the prim
3524 float radius = 0f;
3525 if (vScale.X > radius)
3526 radius = vScale.X;
3527 if (vScale.Y > radius)
3528 radius = vScale.Y;
3529 if (vScale.Z > radius)
3530 radius = vScale.Z;
3531
3532 // the second part of this is the default prim size
3533 // once we factor in the aabb of the prim we're adding we can
3534 // change this to;
3535 // radius = (radius / 2) - 0.01f;
3536 //
3537 radius = (radius / 2) + (0.5f / 2) - 0.1f;
3538
3539 //radius = radius;
3540
3541 float itestPart3 = tmVal4.X + tmVal4.Y + tmVal4.Z + tmVal5.X + tmVal5.Y + tmVal5.Z -
3542 (2.0f*(tmVal6.X + tmVal6.Y + tmVal6.Z + (radius*radius)));
3543
3544 // Yuk Quadradrics.. Solve first
3545 float rootsqr = (itestPart2*itestPart2) - (4.0f*itestPart1*itestPart3);
3546 if (rootsqr < 0.0f)
3547 {
3548 // No intersection
3549 return result;
3550 }
3551 float root = ((-itestPart2) - (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f);
3552
3553 if (root < 0.0f)
3554 { 4203 {
3555 // perform second quadratic root solution 4204 if (m_UndoRedo == null || Undoing)
3556 root = ((-itestPart2) + (float) Math.Sqrt((double) rootsqr))/(itestPart1*2.0f); 4205 return;
3557 4206
3558 // is there any intersection? 4207 m_UndoRedo.Clear();
3559 if (root < 0.0f)
3560 {
3561 // nope, no intersection
3562 return result;
3563 }
3564 } 4208 }
3565
3566 // We got an intersection. putting together an EntityIntersection object with the
3567 // intersection information
3568 Vector3 ipoint =
3569 new Vector3(iray.Origin.X + (iray.Direction.X*root), iray.Origin.Y + (iray.Direction.Y*root),
3570 iray.Origin.Z + (iray.Direction.Z*root));
3571
3572 result.HitTF = true;
3573 result.ipoint = ipoint;
3574
3575 // Normal is calculated by the difference and then normalizing the result
3576 Vector3 normalpart = ipoint - vAbsolutePosition;
3577 result.normal = normalpart / normalpart.Length();
3578
3579 // It's funny how the Vector3 object has a Distance function, but the Axiom.Math object doesn't.
3580 // I can write a function to do it.. but I like the fact that this one is Static.
3581
3582 Vector3 distanceConvert1 = new Vector3(iray.Origin.X, iray.Origin.Y, iray.Origin.Z);
3583 Vector3 distanceConvert2 = new Vector3(ipoint.X, ipoint.Y, ipoint.Z);
3584 float distance = (float) Util.GetDistanceTo(distanceConvert1, distanceConvert2);
3585
3586 result.distance = distance;
3587
3588 return result;
3589 } 4209 }
3590 4210
3591 public EntityIntersection TestIntersectionOBB(Ray iray, Quaternion parentrot, bool frontFacesOnly, bool faceCenters) 4211 public EntityIntersection TestIntersectionOBB(Ray iray, Quaternion parentrot, bool frontFacesOnly, bool faceCenters)
@@ -3955,15 +4575,7 @@ namespace OpenSim.Region.Framework.Scenes
3955 public void UpdateExtraParam(ushort type, bool inUse, byte[] data) 4575 public void UpdateExtraParam(ushort type, bool inUse, byte[] data)
3956 { 4576 {
3957 m_shape.ReadInUpdateExtraParam(type, inUse, data); 4577 m_shape.ReadInUpdateExtraParam(type, inUse, data);
3958/* 4578
3959 if (type == 0x30)
3960 {
3961 if (m_shape.SculptEntry && m_shape.SculptTexture != UUID.Zero)
3962 {
3963 ParentGroup.Scene.AssetService.Get(m_shape.SculptTexture.ToString(), this, AssetReceived);
3964 }
3965 }
3966*/
3967 if (ParentGroup != null) 4579 if (ParentGroup != null)
3968 { 4580 {
3969 ParentGroup.HasGroupChanged = true; 4581 ParentGroup.HasGroupChanged = true;
@@ -4030,8 +4642,11 @@ namespace OpenSim.Region.Framework.Scenes
4030 if (god) 4642 if (god)
4031 baseMask = 0x7ffffff0; 4643 baseMask = 0x7ffffff0;
4032 4644
4033 // Are we the owner? 4645 bool canChange = (AgentID == OwnerID) || god;
4034 if ((AgentID == OwnerID) || god) 4646 if(!canChange)
4647 canChange = ParentGroup.Scene.Permissions.CanEditObjectPermissions(ParentGroup, AgentID);
4648
4649 if (canChange)
4035 { 4650 {
4036 switch (field) 4651 switch (field)
4037 { 4652 {
@@ -4039,7 +4654,7 @@ namespace OpenSim.Region.Framework.Scenes
4039 if (god) 4654 if (god)
4040 { 4655 {
4041 BaseMask = ApplyMask(BaseMask, set, mask); 4656 BaseMask = ApplyMask(BaseMask, set, mask);
4042 Inventory.ApplyGodPermissions(_baseMask); 4657 Inventory.ApplyGodPermissions(BaseMask);
4043 } 4658 }
4044 4659
4045 break; 4660 break;
@@ -4070,7 +4685,7 @@ namespace OpenSim.Region.Framework.Scenes
4070 } 4685 }
4071 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) & 4686 NextOwnerMask = ApplyMask(NextOwnerMask, set, mask) &
4072 baseMask; 4687 baseMask;
4073 // Prevent the client from creating no mod, no copy 4688 // Prevent the client from creating no copy, no transfer
4074 // objects 4689 // objects
4075 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0) 4690 if ((NextOwnerMask & (uint)PermissionMask.Copy) == 0)
4076 NextOwnerMask |= (uint)PermissionMask.Transfer; 4691 NextOwnerMask |= (uint)PermissionMask.Transfer;
@@ -4079,36 +4694,36 @@ namespace OpenSim.Region.Framework.Scenes
4079 4694
4080 break; 4695 break;
4081 } 4696 }
4082 4697 AggregateInnerPerms();
4083 SendFullUpdateToAllClients(); 4698 SendFullUpdateToAllClients();
4084 } 4699 }
4085 } 4700 }
4086 4701
4087 public void ClonePermissions(SceneObjectPart source) 4702 public void ClonePermissions(SceneObjectPart source)
4088 { 4703 {
4089 bool update = false; 4704 uint prevOwnerMask = OwnerMask;
4705 uint prevGroupMask = GroupMask;
4706 uint prevEveryoneMask = EveryoneMask;
4707 uint prevNextOwnerMask = NextOwnerMask;
4090 4708
4091 if (BaseMask != source.BaseMask || 4709 OwnerMask = source.OwnerMask & BaseMask;
4092 OwnerMask != source.OwnerMask || 4710 GroupMask = source.GroupMask & BaseMask;
4093 GroupMask != source.GroupMask || 4711 EveryoneMask = source.EveryoneMask & BaseMask;
4094 EveryoneMask != source.EveryoneMask || 4712 NextOwnerMask = source.NextOwnerMask & BaseMask;
4095 NextOwnerMask != source.NextOwnerMask)
4096 update = true;
4097 4713
4098 BaseMask = source.BaseMask; 4714 AggregateInnerPerms();
4099 OwnerMask = source.OwnerMask;
4100 GroupMask = source.GroupMask;
4101 EveryoneMask = source.EveryoneMask;
4102 NextOwnerMask = source.NextOwnerMask;
4103 4715
4104 if (update) 4716 if (OwnerMask != prevOwnerMask ||
4717 GroupMask != prevGroupMask ||
4718 EveryoneMask != prevEveryoneMask ||
4719 NextOwnerMask != prevNextOwnerMask)
4105 SendFullUpdateToAllClients(); 4720 SendFullUpdateToAllClients();
4106 } 4721 }
4107 4722
4108 public bool IsHingeJoint() 4723 public bool IsHingeJoint()
4109 { 4724 {
4110 // For now, we use the NINJA naming scheme for identifying joints. 4725 // For now, we use the NINJA naming scheme for identifying joints.
4111 // In the future, we can support other joint specification schemes such as a 4726 // In the future, we can support other joint specification schemes such as a
4112 // custom checkbox in the viewer GUI. 4727 // custom checkbox in the viewer GUI.
4113 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4728 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4114 { 4729 {
@@ -4124,7 +4739,7 @@ namespace OpenSim.Region.Framework.Scenes
4124 public bool IsBallJoint() 4739 public bool IsBallJoint()
4125 { 4740 {
4126 // For now, we use the NINJA naming scheme for identifying joints. 4741 // For now, we use the NINJA naming scheme for identifying joints.
4127 // In the future, we can support other joint specification schemes such as a 4742 // In the future, we can support other joint specification schemes such as a
4128 // custom checkbox in the viewer GUI. 4743 // custom checkbox in the viewer GUI.
4129 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4744 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4130 { 4745 {
@@ -4140,7 +4755,7 @@ namespace OpenSim.Region.Framework.Scenes
4140 public bool IsJoint() 4755 public bool IsJoint()
4141 { 4756 {
4142 // For now, we use the NINJA naming scheme for identifying joints. 4757 // For now, we use the NINJA naming scheme for identifying joints.
4143 // In the future, we can support other joint specification schemes such as a 4758 // In the future, we can support other joint specification schemes such as a
4144 // custom checkbox in the viewer GUI. 4759 // custom checkbox in the viewer GUI.
4145 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints) 4760 if (ParentGroup.Scene != null && ParentGroup.Scene.PhysicsScene != null && ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
4146 { 4761 {
@@ -4157,18 +4772,19 @@ namespace OpenSim.Region.Framework.Scenes
4157 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null) 4772 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
4158 return; 4773 return;
4159 4774
4160 if (PhysicsShapeType != (byte)physdata.PhysShapeType) 4775 byte newtype = (byte)physdata.PhysShapeType;
4161 { 4776 if (PhysicsShapeType != newtype)
4162 PhysicsShapeType = (byte)physdata.PhysShapeType; 4777 PhysicsShapeType = newtype;
4163
4164 }
4165 4778
4166 if(Density != physdata.Density) 4779 if(Density != physdata.Density)
4167 Density = physdata.Density; 4780 Density = physdata.Density;
4781
4168 if(GravityModifier != physdata.GravitationModifier) 4782 if(GravityModifier != physdata.GravitationModifier)
4169 GravityModifier = physdata.GravitationModifier; 4783 GravityModifier = physdata.GravitationModifier;
4784
4170 if(Friction != physdata.Friction) 4785 if(Friction != physdata.Friction)
4171 Friction = physdata.Friction; 4786 Friction = physdata.Friction;
4787
4172 if(Restitution != physdata.Bounce) 4788 if(Restitution != physdata.Bounce)
4173 Restitution = physdata.Bounce; 4789 Restitution = physdata.Bounce;
4174 } 4790 }
@@ -4179,7 +4795,7 @@ namespace OpenSim.Region.Framework.Scenes
4179 /// <param name="SetTemporary"></param> 4795 /// <param name="SetTemporary"></param>
4180 /// <param name="SetPhantom"></param> 4796 /// <param name="SetPhantom"></param>
4181 /// <param name="SetVD"></param> 4797 /// <param name="SetVD"></param>
4182 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4798 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
4183 { 4799 {
4184 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4800 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
4185 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4801 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -4189,134 +4805,85 @@ namespace OpenSim.Region.Framework.Scenes
4189 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4805 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4190 return; 4806 return;
4191 4807
4192 PhysicsActor pa = PhysActor; 4808 VolumeDetectActive = SetVD;
4193
4194 // Special cases for VD. VD can only be called from a script
4195 // and can't be combined with changes to other states. So we can rely
4196 // that...
4197 // ... if VD is changed, all others are not.
4198 // ... if one of the others is changed, VD is not.
4199 if (SetVD) // VD is active, special logic applies
4200 {
4201 // State machine logic for VolumeDetect
4202 // More logic below
4203 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
4204
4205 if (phanReset) // Phantom changes from on to off switch VD off too
4206 {
4207 SetVD = false; // Switch it of for the course of this routine
4208 VolumeDetectActive = false; // and also permanently
4209
4210 if (pa != null)
4211 pa.SetVolumeDetect(0); // Let physics know about it too
4212 }
4213 else
4214 {
4215 // If volumedetect is active we don't want phantom to be applied.
4216 // If this is a new call to VD out of the state "phantom"
4217 // this will also cause the prim to be visible to physics
4218 SetPhantom = false;
4219 }
4220 }
4221 4809
4222 if (UsePhysics && IsJoint()) 4810 // volume detector implies phantom we need to decouple this mess
4223 { 4811 if (SetVD)
4224 SetPhantom = true; 4812 SetPhantom = true;
4225 } 4813 else if(wasVD)
4814 SetPhantom = false;
4226 4815
4227 if (UsePhysics) 4816 if (UsePhysics)
4228 {
4229 AddFlag(PrimFlags.Physics); 4817 AddFlag(PrimFlags.Physics);
4230 if (!wasUsingPhysics)
4231 {
4232 DoPhysicsPropertyUpdate(UsePhysics, false);
4233 }
4234 }
4235 else 4818 else
4236 {
4237 RemFlag(PrimFlags.Physics); 4819 RemFlag(PrimFlags.Physics);
4238 if (wasUsingPhysics)
4239 {
4240 DoPhysicsPropertyUpdate(UsePhysics, false);
4241 }
4242 }
4243 4820
4244 if (SetPhantom 4821 if (SetPhantom)
4245 || ParentGroup.IsAttachmentCheckFull()
4246 || PhysicsShapeType == (byte)PhysShapeType.none
4247 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
4248 {
4249 AddFlag(PrimFlags.Phantom); 4822 AddFlag(PrimFlags.Phantom);
4250 4823 else
4251 if (PhysActor != null)
4252 {
4253 RemoveFromPhysics();
4254 pa = null;
4255 }
4256 }
4257 else // Not phantom
4258 {
4259 RemFlag(PrimFlags.Phantom); 4824 RemFlag(PrimFlags.Phantom);
4260 4825
4261 if (ParentGroup.Scene == null) 4826 if (SetTemporary)
4262 return; 4827 AddFlag(PrimFlags.TemporaryOnRez);
4828 else
4829 RemFlag(PrimFlags.TemporaryOnRez);
4263 4830
4264 if (ParentGroup.Scene.CollidablePrims && pa == null) 4831 if (ParentGroup.Scene == null)
4265 { 4832 return;
4266 AddToPhysics(UsePhysics, SetPhantom, false);
4267 pa = PhysActor;
4268 4833
4269 if (pa != null) 4834 PhysicsActor pa = PhysActor;
4270 {
4271 pa.SetMaterial(Material);
4272 pa.Position = GetWorldPosition();
4273 pa.Orientation = GetWorldRotation();
4274 DoPhysicsPropertyUpdate(UsePhysics, true);
4275 4835
4276 SubscribeForCollisionEvents(); 4836 if (pa != null && building && pa.Building != building)
4277 } 4837 pa.Building = building;
4278 }
4279 else // it already has a physical representation
4280 {
4281 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4282 }
4283 }
4284 4838
4285 if (SetVD) 4839 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4840 || (Shape.PathCurve == (byte)Extrusion.Flexible))
4286 { 4841 {
4287 // If the above logic worked (this is urgent candidate to unit tests!)
4288 // we now have a physicsactor.
4289 // Defensive programming calls for a check here.
4290 // Better would be throwing an exception that could be catched by a unit test as the internal
4291 // logic should make sure, this Physactor is always here.
4292 if (pa != null) 4842 if (pa != null)
4293 { 4843 {
4294 pa.SetVolumeDetect(1); 4844 if(wasUsingPhysics)
4295 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4845 ParentGroup.Scene.RemovePhysicalPrim(1);
4296 VolumeDetectActive = true; 4846 RemoveFromPhysics();
4297 } 4847 }
4298 }
4299 else if (SetVD != wasVD)
4300 {
4301 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like
4302 // (mumbles, well, at least if you have infinte CPU powers :-))
4303 if (pa != null)
4304 pa.SetVolumeDetect(0);
4305 4848
4306 RemFlag(PrimFlags.Phantom); 4849 Stop();
4307 VolumeDetectActive = false;
4308 } 4850 }
4309 4851
4310 if (SetTemporary)
4311 {
4312 AddFlag(PrimFlags.TemporaryOnRez);
4313 }
4314 else 4852 else
4315 { 4853 {
4316 RemFlag(PrimFlags.TemporaryOnRez); 4854 if (ParentGroup.Scene.CollidablePrims)
4855 {
4856 if (pa == null)
4857 {
4858 AddToPhysics(UsePhysics, SetPhantom, building, false);
4859 pa = PhysActor;
4860
4861 if (pa != null)
4862 {
4863 pa.SetMaterial(Material);
4864 DoPhysicsPropertyUpdate(UsePhysics, true);
4865 }
4866 }
4867 else // it already has a physical representation
4868 {
4869
4870 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4871
4872 if(UsePhysics && !SetPhantom && m_localId == ParentGroup.RootPart.LocalId &&
4873 m_vehicleParams != null && m_vehicleParams.CameraDecoupled)
4874 AddFlag(PrimFlags.CameraDecoupled);
4875 else
4876 RemFlag(PrimFlags.CameraDecoupled);
4877
4878 if (pa.Building != building)
4879 pa.Building = building;
4880 }
4881
4882 UpdatePhysicsSubscribedEvents();
4883 }
4317 } 4884 }
4318 4885
4319 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4886 // and last in case we have a new actor and not building
4320 4887
4321 if (ParentGroup != null) 4888 if (ParentGroup != null)
4322 { 4889 {
@@ -4328,58 +4895,14 @@ namespace OpenSim.Region.Framework.Scenes
4328 } 4895 }
4329 4896
4330 /// <summary> 4897 /// <summary>
4331 /// Subscribe for physics collision events if needed for scripts and sounds
4332 /// </summary>
4333 public void SubscribeForCollisionEvents()
4334 {
4335 PhysicsActor pa = PhysActor;
4336
4337 if (pa != null)
4338 {
4339 if (
4340 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4341 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4342 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4343 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4344 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4345 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4346 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4347 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4348 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4349 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4350 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4351 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4352 (CollisionSound != UUID.Zero)
4353 )
4354 {
4355 if (!pa.SubscribedEvents())
4356 {
4357 // If not already subscribed for event, set up for a collision event.
4358 pa.OnCollisionUpdate += PhysicsCollision;
4359 pa.SubscribeEvents(1000);
4360 }
4361 }
4362 else
4363 {
4364 // There is no need to be subscribed to collisions so, if subscribed, remove subscription
4365 if (pa.SubscribedEvents())
4366 {
4367 pa.OnCollisionUpdate -= PhysicsCollision;
4368 pa.UnSubscribeEvents();
4369 }
4370 }
4371 }
4372 }
4373
4374 /// <summary>
4375 /// Adds this part to the physics scene. 4898 /// Adds this part to the physics scene.
4899 /// and sets the PhysActor property
4376 /// </summary> 4900 /// </summary>
4377 /// <remarks>This method also sets the PhysActor property.</remarks> 4901 /// <param name="isPhysical">Add this prim as physical.</param>
4378 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4902 /// <param name="isPhantom">Add this prim as phantom.</param>
4379 /// <returns> 4903 /// <param name="building">tells physics to delay full construction of object</param>
4380 /// The physics actor. null if there was a failure. 4904 /// <param name="applyDynamics">applies velocities, force and torque</param>
4381 /// </returns> 4905 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4382 private void AddToPhysics(bool isPhysical, bool isPhantom, bool applyDynamics)
4383 { 4906 {
4384 PhysicsActor pa; 4907 PhysicsActor pa;
4385 4908
@@ -4389,15 +4912,15 @@ namespace OpenSim.Region.Framework.Scenes
4389 try 4912 try
4390 { 4913 {
4391 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4914 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4392 string.Format("{0}/{1}", Name, UUID), 4915 string.Format("{0}/{1}", Name, UUID),
4393 Shape, 4916 Shape,
4394 AbsolutePosition, 4917 AbsolutePosition,
4395 Scale, 4918 Scale,
4396 GetWorldRotation(), 4919 GetWorldRotation(),
4397 isPhysical, 4920 isPhysical,
4398 isPhantom, 4921 isPhantom,
4399 PhysicsShapeType, 4922 PhysicsShapeType,
4400 m_localId); 4923 m_localId);
4401 } 4924 }
4402 catch (Exception e) 4925 catch (Exception e)
4403 { 4926 {
@@ -4414,12 +4937,37 @@ namespace OpenSim.Region.Framework.Scenes
4414 pa.GravModifier = GravityModifier; 4937 pa.GravModifier = GravityModifier;
4415 pa.Friction = Friction; 4938 pa.Friction = Friction;
4416 pa.Restitution = Restitution; 4939 pa.Restitution = Restitution;
4940 pa.Buoyancy = Buoyancy;
4941
4942 if(LocalId == ParentGroup.RootPart.LocalId)
4943 {
4944 pa.LockAngularMotion(RotationAxisLocks);
4945 }
4417 4946
4418 if (VolumeDetectActive) // change if not the default only 4947 if (VolumeDetectActive) // change if not the default only
4419 pa.SetVolumeDetect(1); 4948 pa.SetVolumeDetect(1);
4949
4950 bool isroot = (m_localId == ParentGroup.RootPart.LocalId);
4951
4952 if(isroot && m_physicsInertia != null)
4953 pa.SetInertiaData(m_physicsInertia);
4954
4955 if (isroot && m_vehicleParams != null )
4956 {
4957 m_vehicleParams.SetVehicle(pa);
4958 if(isPhysical && !isPhantom && m_vehicleParams.CameraDecoupled)
4959 AddFlag(PrimFlags.CameraDecoupled);
4960 else
4961 RemFlag(PrimFlags.CameraDecoupled);
4962 }
4963 else
4964 RemFlag(PrimFlags.CameraDecoupled);
4420 // we are going to tell rest of code about physics so better have this here 4965 // we are going to tell rest of code about physics so better have this here
4421 PhysActor = pa; 4966 PhysActor = pa;
4422 4967
4968 // DoPhysicsPropertyUpdate(isPhysical, true);
4969 // lets expand it here just with what it really needs to do
4970
4423 if (isPhysical) 4971 if (isPhysical)
4424 { 4972 {
4425 if (ParentGroup.RootPart.KeyframeMotion != null) 4973 if (ParentGroup.RootPart.KeyframeMotion != null)
@@ -4430,7 +4978,7 @@ namespace OpenSim.Region.Framework.Scenes
4430 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 4978 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
4431 pa.OnOutOfBounds += PhysicsOutOfBounds; 4979 pa.OnOutOfBounds += PhysicsOutOfBounds;
4432 4980
4433 if (ParentID != 0 && ParentID != LocalId) 4981 if (_parentID != 0 && _parentID != LocalId)
4434 { 4982 {
4435 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; 4983 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
4436 4984
@@ -4441,19 +4989,31 @@ namespace OpenSim.Region.Framework.Scenes
4441 } 4989 }
4442 } 4990 }
4443 4991
4444 if (applyDynamics) 4992 if (applyDynamics && LocalId == ParentGroup.RootPart.LocalId)
4445 // do independent of isphysical so parameters get setted (at least some) 4993 // do independent of isphysical so parameters get setted (at least some)
4446 { 4994 {
4447 Velocity = velocity; 4995 Velocity = velocity;
4448 AngularVelocity = rotationalVelocity; 4996 AngularVelocity = rotationalVelocity;
4449// pa.Velocity = velocity; 4997
4450 pa.RotationalVelocity = rotationalVelocity; 4998 // if not vehicle and root part apply force and torque
4999 if ((m_vehicleParams == null || m_vehicleParams.Type == Vehicle.TYPE_NONE))
5000 {
5001 pa.Force = Force;
5002 pa.Torque = Torque;
5003 }
4451 } 5004 }
4452 5005
4453 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa); 5006// if (Shape.SculptEntry)
5007// CheckSculptAndLoad();
5008// else
5009 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
5010
5011 if (!building)
5012 pa.Building = false;
4454 } 5013 }
4455 5014
4456 PhysActor = pa; 5015 PhysActor = pa;
5016
4457 ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this); 5017 ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this);
4458 } 5018 }
4459 5019
@@ -4462,14 +5022,22 @@ namespace OpenSim.Region.Framework.Scenes
4462 /// </summary> 5022 /// </summary>
4463 /// <remarks> 5023 /// <remarks>
4464 /// This isn't the same as turning off physical, since even without being physical the prim has a physics 5024 /// This isn't the same as turning off physical, since even without being physical the prim has a physics
4465 /// representation for collision detection. Rather, this would be used in situations such as making a prim 5025 /// representation for collision detection.
4466 /// phantom.
4467 /// </remarks> 5026 /// </remarks>
4468 public void RemoveFromPhysics() 5027 public void RemoveFromPhysics()
4469 { 5028 {
4470 ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this); 5029 PhysicsActor pa = PhysActor;
4471 if (ParentGroup.Scene.PhysicsScene != null) 5030 if (pa != null)
4472 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 5031 {
5032 pa.OnCollisionUpdate -= PhysicsCollision;
5033 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
5034 pa.OnOutOfBounds -= PhysicsOutOfBounds;
5035
5036 ParentGroup.Scene.PhysicsScene.RemovePrim(pa);
5037
5038 ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this);
5039 }
5040 RemFlag(PrimFlags.CameraDecoupled);
4473 PhysActor = null; 5041 PhysActor = null;
4474 } 5042 }
4475 5043
@@ -4590,40 +5158,6 @@ namespace OpenSim.Region.Framework.Scenes
4590 } 5158 }
4591 5159
4592 /// <summary> 5160 /// <summary>
4593 /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics
4594 /// engine can use it.
4595 /// </summary>
4596 /// <remarks>
4597 /// When the physics engine has finished with it, the sculpt data is discarded to save memory.
4598 /// </remarks>
4599/*
4600 public void CheckSculptAndLoad()
4601 {
4602// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
4603
4604 if (ParentGroup.IsDeleted)
4605 return;
4606
4607 if ((ParentGroup.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0)
4608 return;
4609
4610 if (Shape.SculptEntry && Shape.SculptTexture != UUID.Zero)
4611 {
4612 // check if a previously decoded sculpt map has been cached
4613 // We don't read the file here - the meshmerizer will do that later.
4614 // TODO: Could we simplify the meshmerizer code by reading and setting the data here?
4615 if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + Shape.SculptTexture.ToString())))
4616 {
4617 SculptTextureCallback(null);
4618 }
4619 else
4620 {
4621 ParentGroup.Scene.AssetService.Get(Shape.SculptTexture.ToString(), this, AssetReceived);
4622 }
4623 }
4624 }
4625*/
4626 /// <summary>
4627 /// Update the texture entry for this part. 5161 /// Update the texture entry for this part.
4628 /// </summary> 5162 /// </summary>
4629 /// <param name="serializedTextureEntry"></param> 5163 /// <param name="serializedTextureEntry"></param>
@@ -4642,41 +5176,42 @@ namespace OpenSim.Region.Framework.Scenes
4642 5176
4643 Changed changeFlags = 0; 5177 Changed changeFlags = 0;
4644 5178
4645 Primitive.TextureEntryFace fallbackNewFace = newTex.DefaultTexture; 5179 Primitive.TextureEntryFace defaultNewFace = newTex.DefaultTexture;
4646 Primitive.TextureEntryFace fallbackOldFace = oldTex.DefaultTexture; 5180 Primitive.TextureEntryFace defaultOldFace = oldTex.DefaultTexture;
4647 5181
4648 // On Incoming packets, sometimes newText.DefaultTexture is null. The assumption is that all 5182 // On Incoming packets, sometimes newText.DefaultTexture is null. The assumption is that all
4649 // other prim-sides are set, but apparently that's not always the case. Lets assume packet/data corruption at this point. 5183 // other prim-sides are set, but apparently that's not always the case. Lets assume packet/data corruption at this point.
4650 if (fallbackNewFace == null) 5184 if (defaultNewFace == null)
4651 { 5185 {
4652 fallbackNewFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0); 5186 defaultNewFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0);
4653 newTex.DefaultTexture = fallbackNewFace; 5187 newTex.DefaultTexture = defaultNewFace;
4654 } 5188 }
4655 if (fallbackOldFace == null) 5189 if (defaultOldFace == null)
4656 { 5190 {
4657 fallbackOldFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0); 5191 defaultOldFace = new Primitive.TextureEntry(Util.BLANK_TEXTURE_UUID).CreateFace(0);
4658 oldTex.DefaultTexture = fallbackOldFace; 5192 oldTex.DefaultTexture = defaultOldFace;
4659 } 5193 }
4660 5194
4661 // Materials capable viewers can send a ObjectImage packet 5195 // Materials capable viewers can send a ObjectImage packet
4662 // when nothing in TE has changed. MaterialID should be updated 5196 // when nothing in TE has changed. MaterialID should be updated
4663 // by the RenderMaterials CAP handler, so updating it here may cause a 5197 // by the RenderMaterials CAP handler, so updating it here may cause a
4664 // race condtion. Therefore, if no non-materials TE fields have changed, 5198 // race condtion. Therefore, if no non-materials TE fields have changed,
4665 // we should ignore any changes and not update Shape.TextureEntry 5199 // we should ignore any changes and not update Shape.TextureEntry
4666 5200
4667 bool otherFieldsChanged = false; 5201 bool otherFieldsChanged = false;
4668 5202 int nsides = GetNumberOfSides();
4669 for (int i = 0 ; i < GetNumberOfSides(); i++) 5203 for (int i = 0 ; i < nsides; i++)
4670 { 5204 {
4671 5205 Primitive.TextureEntryFace newFace = defaultNewFace;
4672 Primitive.TextureEntryFace newFace = newTex.DefaultTexture; 5206 Primitive.TextureEntryFace oldFace = defaultOldFace;
4673 Primitive.TextureEntryFace oldFace = oldTex.DefaultTexture;
4674
4675 if (oldTex.FaceTextures[i] != null) 5207 if (oldTex.FaceTextures[i] != null)
4676 oldFace = oldTex.FaceTextures[i]; 5208 oldFace = oldTex.FaceTextures[i];
4677 if (newTex.FaceTextures[i] != null) 5209 if (newTex.FaceTextures[i] != null)
4678 newFace = newTex.FaceTextures[i]; 5210 newFace = newTex.FaceTextures[i];
4679 5211
5212 if (oldFace.TextureID != newFace.TextureID)
5213 changeFlags |= Changed.TEXTURE;
5214
4680 Color4 oldRGBA = oldFace.RGBA; 5215 Color4 oldRGBA = oldFace.RGBA;
4681 Color4 newRGBA = newFace.RGBA; 5216 Color4 newRGBA = newFace.RGBA;
4682 5217
@@ -4686,9 +5221,6 @@ namespace OpenSim.Region.Framework.Scenes
4686 oldRGBA.A != newRGBA.A) 5221 oldRGBA.A != newRGBA.A)
4687 changeFlags |= Changed.COLOR; 5222 changeFlags |= Changed.COLOR;
4688 5223
4689 if (oldFace.TextureID != newFace.TextureID)
4690 changeFlags |= Changed.TEXTURE;
4691
4692 // Max change, skip the rest of testing 5224 // Max change, skip the rest of testing
4693 if (changeFlags == (Changed.TEXTURE | Changed.COLOR)) 5225 if (changeFlags == (Changed.TEXTURE | Changed.COLOR))
4694 break; 5226 break;
@@ -4706,24 +5238,56 @@ namespace OpenSim.Region.Framework.Scenes
4706 if (oldFace.Rotation != newFace.Rotation) otherFieldsChanged = true; 5238 if (oldFace.Rotation != newFace.Rotation) otherFieldsChanged = true;
4707 if (oldFace.Shiny != newFace.Shiny) otherFieldsChanged = true; 5239 if (oldFace.Shiny != newFace.Shiny) otherFieldsChanged = true;
4708 if (oldFace.TexMapType != newFace.TexMapType) otherFieldsChanged = true; 5240 if (oldFace.TexMapType != newFace.TexMapType) otherFieldsChanged = true;
5241 if(otherFieldsChanged)
5242 changeFlags |= Changed.TEXTURE;
4709 } 5243 }
4710 } 5244 }
4711 5245
4712 if (changeFlags != 0 || otherFieldsChanged) 5246 if (changeFlags == 0)
4713 { 5247 return;
4714 m_shape.TextureEntry = newTex.GetBytes(); 5248 m_shape.TextureEntry = newTex.GetBytes();
4715 if (changeFlags != 0) 5249 TriggerScriptChangedEvent(changeFlags);
4716 TriggerScriptChangedEvent(changeFlags); 5250 ParentGroup.HasGroupChanged = true;
4717 UpdateFlag = UpdateRequired.FULL; 5251 ScheduleFullUpdate();
4718 ParentGroup.HasGroupChanged = true; 5252 }
4719 5253
4720 //This is madness.. 5254 internal void UpdatePhysicsSubscribedEvents()
4721 //ParentGroup.ScheduleGroupForFullUpdate(); 5255 {
4722 //This is sparta 5256 PhysicsActor pa = PhysActor;
4723 ScheduleFullUpdate(); 5257 if (pa == null)
5258 return;
5259
5260 pa.OnCollisionUpdate -= PhysicsCollision;
5261
5262 bool hassound = (!VolumeDetectActive && CollisionSoundType >= 0 && ((Flags & PrimFlags.Physics) != 0));
5263
5264 scriptEvents CombinedEvents = AggregateScriptEvents;
5265
5266 // merge with root part
5267 if (ParentGroup != null && ParentGroup.RootPart != null)
5268 CombinedEvents |= ParentGroup.RootPart.AggregateScriptEvents;
5269
5270 // submit to this part case
5271 if (VolumeDetectActive)
5272 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
5273 else if ((Flags & PrimFlags.Phantom) != 0)
5274 CombinedEvents &= PhyscicsPhantonSubsEvents;
5275 else
5276 CombinedEvents &= PhysicsNeededSubsEvents;
5277
5278 if (hassound || CombinedEvents != 0)
5279 {
5280 // subscribe to physics updates.
5281 pa.OnCollisionUpdate += PhysicsCollision;
5282 pa.SubscribeEvents(50); // 20 reports per second
5283 }
5284 else
5285 {
5286 pa.UnSubscribeEvents();
4724 } 5287 }
4725 } 5288 }
4726 5289
5290
4727 public void aggregateScriptEvents() 5291 public void aggregateScriptEvents()
4728 { 5292 {
4729 if (ParentGroup == null || ParentGroup.RootPart == null) 5293 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4761,17 +5325,6 @@ namespace OpenSim.Region.Framework.Scenes
4761 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 5325 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4762 } 5326 }
4763 5327
4764 SubscribeForCollisionEvents();
4765
4766 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4767 //{
4768 // ParentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting;
4769 //}
4770 //else
4771 //{
4772 // ParentGroup.Scene.EventManager.OnScriptTimerEvent -= handleTimerAccounting;
4773 //}
4774
4775 LocalFlags = (PrimFlags)objectflagupdate; 5328 LocalFlags = (PrimFlags)objectflagupdate;
4776 5329
4777 if (ParentGroup != null && ParentGroup.RootPart == this) 5330 if (ParentGroup != null && ParentGroup.RootPart == this)
@@ -4782,6 +5335,7 @@ namespace OpenSim.Region.Framework.Scenes
4782 { 5335 {
4783// m_log.DebugFormat( 5336// m_log.DebugFormat(
4784// "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents()", Name, LocalId); 5337// "[SCENE OBJECT PART]: Scheduling part {0} {1} for full update in aggregateScriptEvents()", Name, LocalId);
5338 UpdatePhysicsSubscribedEvents();
4785 ScheduleFullUpdate(); 5339 ScheduleFullUpdate();
4786 } 5340 }
4787 } 5341 }
@@ -4815,7 +5369,7 @@ namespace OpenSim.Region.Framework.Scenes
4815 { 5369 {
4816 return m_forceMouselook; 5370 return m_forceMouselook;
4817 } 5371 }
4818 5372
4819 public override string ToString() 5373 public override string ToString()
4820 { 5374 {
4821 return String.Format("{0} {1} (parent {2}))", Name, UUID, ParentGroup); 5375 return String.Format("{0} {1} (parent {2}))", Name, UUID, ParentGroup);
@@ -4832,7 +5386,7 @@ namespace OpenSim.Region.Framework.Scenes
4832 && (ParentGroup.RootPart != this 5386 && (ParentGroup.RootPart != this
4833 || ParentGroup.AttachedAvatar != remoteClient.AgentId && ParentGroup.HasPrivateAttachmentPoint)) 5387 || ParentGroup.AttachedAvatar != remoteClient.AgentId && ParentGroup.HasPrivateAttachmentPoint))
4834 return; 5388 return;
4835 5389
4836 // Causes this thread to dig into the Client Thread Data. 5390 // Causes this thread to dig into the Client Thread Data.
4837 // Remember your locking here! 5391 // Remember your locking here!
4838 remoteClient.SendEntityUpdate( 5392 remoteClient.SendEntityUpdate(
@@ -4840,9 +5394,9 @@ namespace OpenSim.Region.Framework.Scenes
4840 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity 5394 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
4841 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); 5395 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
4842 5396
4843 ParentGroup.Scene.StatsReporter.AddObjectUpdates(1); 5397 ParentGroup.Scene.StatsReporter.AddObjectUpdates(1);
4844 } 5398 }
4845 5399
4846 public void AddScriptLPS(int count) 5400 public void AddScriptLPS(int count)
4847 { 5401 {
4848 ParentGroup.AddScriptLPS(count); 5402 ParentGroup.AddScriptLPS(count);
@@ -4856,7 +5410,7 @@ namespace OpenSim.Region.Framework.Scenes
4856 /// <param name="scene">The scene the prim is being rezzed into</param> 5410 /// <param name="scene">The scene the prim is being rezzed into</param>
4857 public void ApplyPermissionsOnRez(InventoryItemBase item, bool userInventory, Scene scene) 5411 public void ApplyPermissionsOnRez(InventoryItemBase item, bool userInventory, Scene scene)
4858 { 5412 {
4859 if ((OwnerID != item.Owner) || ((item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)) 5413 if ((OwnerID != item.Owner) || ((item.CurrentPermissions & (uint)PermissionMask.Slam) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0))
4860 { 5414 {
4861 if (scene.Permissions.PropagatePermissions()) 5415 if (scene.Permissions.PropagatePermissions())
4862 { 5416 {
@@ -4887,16 +5441,13 @@ namespace OpenSim.Region.Framework.Scenes
4887 5441
4888 if (OwnerID != item.Owner) 5442 if (OwnerID != item.Owner)
4889 { 5443 {
4890 //LogPermissions("Before ApplyNextOwnerPermissions"); 5444 if(OwnerID != GroupID)
5445 LastOwnerID = OwnerID;
5446 OwnerID = item.Owner;
5447 Inventory.ChangeInventoryOwner(item.Owner);
4891 5448
4892 if (scene.Permissions.PropagatePermissions()) 5449 if (scene.Permissions.PropagatePermissions())
4893 ApplyNextOwnerPermissions(); 5450 ApplyNextOwnerPermissions();
4894
4895 //LogPermissions("After ApplyNextOwnerPermissions");
4896
4897 LastOwnerID = OwnerID;
4898 OwnerID = item.Owner;
4899 Inventory.ChangeInventoryOwner(item.Owner);
4900 } 5451 }
4901 } 5452 }
4902 5453
@@ -4908,17 +5459,19 @@ namespace OpenSim.Region.Framework.Scenes
4908 { 5459 {
4909 PermissionsUtil.LogPermissions(Name, message, BaseMask, OwnerMask, NextOwnerMask); 5460 PermissionsUtil.LogPermissions(Name, message, BaseMask, OwnerMask, NextOwnerMask);
4910 } 5461 }
4911 5462
4912 public void ApplyNextOwnerPermissions() 5463 public void ApplyNextOwnerPermissions()
4913 { 5464 {
4914 // Export needs to be preserved in the base and everyone 5465 // Export needs to be preserved in the base and everyone
4915 // mask, but removed in the owner mask as a next owner 5466 // mask, but removed in the owner mask as a next owner
4916 // can never change the export status 5467 // can never change the export status
4917 BaseMask &= NextOwnerMask | (uint)PermissionMask.Export; 5468 BaseMask &= (NextOwnerMask | (uint)PermissionMask.Export);
4918 OwnerMask &= NextOwnerMask; 5469 OwnerMask &= NextOwnerMask;
4919 EveryoneMask &= NextOwnerMask | (uint)PermissionMask.Export; 5470 EveryoneMask &= (NextOwnerMask | (uint)PermissionMask.Export);
5471 GroupMask = 0; // Giving an object zaps group permissions
4920 5472
4921 Inventory.ApplyNextOwnerPermissions(); 5473 Inventory.ApplyNextOwnerPermissions();
5474 AggregateInnerPerms();
4922 } 5475 }
4923 5476
4924 public void UpdateLookAt() 5477 public void UpdateLookAt()
@@ -4970,6 +5523,19 @@ namespace OpenSim.Region.Framework.Scenes
4970 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5523 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4971 } 5524 }
4972 5525
5526 public void ResetOwnerChangeFlag()
5527 {
5528 List<UUID> inv = Inventory.GetInventoryList();
5529
5530 foreach (UUID itemID in inv)
5531 {
5532 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5533 item.OwnerChanged = false;
5534 Inventory.UpdateInventoryItem(item, false, false);
5535 }
5536 AggregateInnerPerms();
5537 }
5538
4973 /// <summary> 5539 /// <summary>
4974 /// Record an avatar sitting on this part. 5540 /// Record an avatar sitting on this part.
4975 /// </summary> 5541 /// </summary>
@@ -4990,7 +5556,8 @@ namespace OpenSim.Region.Framework.Scenes
4990 5556
4991 if (m_sittingAvatars.Add(sp)) 5557 if (m_sittingAvatars.Add(sp))
4992 { 5558 {
4993 ParentGroup.m_sittingAvatars.Add(sp); 5559 if(!ParentGroup.m_sittingAvatars.Contains(sp))
5560 ParentGroup.m_sittingAvatars.Add(sp);
4994 5561
4995 return true; 5562 return true;
4996 } 5563 }
@@ -5062,5 +5629,32 @@ namespace OpenSim.Region.Framework.Scenes
5062 return m_sittingAvatars.Count; 5629 return m_sittingAvatars.Count;
5063 } 5630 }
5064 } 5631 }
5632
5633 public void Stop()
5634 {
5635 Velocity = Vector3.Zero;
5636 AngularVelocity = Vector3.Zero;
5637 Acceleration = Vector3.Zero;
5638 APIDActive = false;
5639 }
5640
5641 // handle osVolumeDetect
5642 public void ScriptSetVolumeDetect(bool makeVolumeDetect)
5643 {
5644 if(_parentID == 0)
5645 {
5646 // if root prim do it via SOG
5647 ParentGroup.ScriptSetVolumeDetect(makeVolumeDetect);
5648 return;
5649 }
5650
5651 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
5652 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
5653 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0);
5654
5655 if(PhysActor != null)
5656 PhysActor.Building = true;
5657 UpdatePrimFlags(wasUsingPhysics,wasTemporary,wasPhantom,makeVolumeDetect,false);
5658 }
5065 } 5659 }
5066} \ No newline at end of file 5660}