diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectPart.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 2966 |
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 | } |