aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs1064
1 files changed, 504 insertions, 560 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 58f2586..3e1439d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -209,27 +209,89 @@ namespace OpenSim.Region.Framework.Scenes
209 return true; 209 return true;
210 return false; 210 return false;
211 } 211 }
212 212
213 /// <value> 213 /// <summary>
214 /// Is this scene object acting as an attachment? 214 /// Is this scene object acting as an attachment?
215 /// 215 /// </summary>
216 /// We return false if the group has already been deleted. 216 public bool IsAttachment { get; set; }
217 /// 217
218 /// TODO: At the moment set must be done on the part itself. There may be a case for doing it here since I 218 /// <summary>
219 /// presume either all or no parts in a linkset can be part of an attachment (in which 219 /// The avatar to which this scene object is attached.
220 /// case the value would get proprogated down into all the descendent parts). 220 /// </summary>
221 /// </value> 221 /// <remarks>
222 public bool IsAttachment 222 /// If we're not attached to an avatar then this is UUID.Zero
223 /// </remarks>
224 public UUID AttachedAvatar { get; set; }
225
226 /// <summary>
227 /// Attachment point of this scene object to an avatar.
228 /// </summary>
229 /// <remarks>
230 /// 0 if we're not attached to anything
231 /// </remarks>
232 public uint AttachmentPoint
223 { 233 {
224 get 234 get
225 { 235 {
226 if (!IsDeleted) 236 return m_rootPart.Shape.State;
227 return m_rootPart.IsAttachment; 237 }
228 238
229 return false; 239 set
240 {
241 IsAttachment = value != 0;
242 m_rootPart.Shape.State = (byte)value;
230 } 243 }
231 } 244 }
232 245
246 public void ClearPartAttachmentData()
247 {
248 AttachmentPoint = 0;
249
250 // Even though we don't use child part state parameters for attachments any more, we still need to set
251 // these to zero since having them non-zero in rezzed scene objects will crash some clients. Even if
252 // we store them correctly, scene objects that we receive from elsewhere might not.
253 foreach (SceneObjectPart part in Parts)
254 part.Shape.State = 0;
255 }
256
257 /// <summary>
258 /// Is this scene object phantom?
259 /// </summary>
260 /// <remarks>
261 /// Updating must currently take place through UpdatePrimFlags()
262 /// </remarks>
263 public bool IsPhantom
264 {
265 get { return (RootPart.Flags & PrimFlags.Phantom) != 0; }
266 }
267
268 /// <summary>
269 /// Does this scene object use physics?
270 /// </summary>
271 /// <remarks>
272 /// Updating must currently take place through UpdatePrimFlags()
273 /// </remarks>
274 public bool UsesPhysics
275 {
276 get { return (RootPart.Flags & PrimFlags.TemporaryOnRez) != 0; }
277 }
278
279 /// <summary>
280 /// Is this scene object temporary?
281 /// </summary>
282 /// <remarks>
283 /// Updating must currently take place through UpdatePrimFlags()
284 /// </remarks>
285 public bool IsTemporary
286 {
287 get { return (RootPart.Flags & PrimFlags.TemporaryOnRez) != 0; }
288 }
289
290 public bool IsVolumeDetect
291 {
292 get { return RootPart.VolumeDetectActive; }
293 }
294
233 public float scriptScore; 295 public float scriptScore;
234 296
235 private Vector3 lastPhysGroupPos; 297 private Vector3 lastPhysGroupPos;
@@ -261,11 +323,7 @@ namespace OpenSim.Region.Framework.Scenes
261 /// </summary> 323 /// </summary>
262 public override string Name 324 public override string Name
263 { 325 {
264 get { 326 get { return RootPart.Name; }
265 if (RootPart == null)
266 return String.Empty;
267 return RootPart.Name;
268 }
269 set { RootPart.Name = value; } 327 set { RootPart.Name = value; }
270 } 328 }
271 329
@@ -292,10 +350,6 @@ namespace OpenSim.Region.Framework.Scenes
292 { 350 {
293 get { return m_rotation; } 351 get { return m_rotation; }
294 set { 352 set {
295 foreach(SceneObjectPart p in m_parts.GetArray())
296 {
297 p.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
298 }
299 m_rotation = value; 353 m_rotation = value;
300 } 354 }
301 } 355 }
@@ -305,6 +359,38 @@ namespace OpenSim.Region.Framework.Scenes
305 get { return m_rootPart.RotationOffset; } 359 get { return m_rootPart.RotationOffset; }
306 } 360 }
307 361
362 public Vector3 GroupScale
363 {
364 get
365 {
366 Vector3 minScale = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionSize);
367 Vector3 maxScale = Vector3.Zero;
368 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
369
370 SceneObjectPart[] parts = m_parts.GetArray();
371 for (int i = 0; i < parts.Length; i++)
372 {
373 SceneObjectPart part = parts[i];
374 Vector3 partscale = part.Scale;
375 Vector3 partoffset = part.OffsetPosition;
376
377 minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X;
378 minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.Y + partoffset.Y : minScale.Y;
379 minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.Z + partoffset.Z : minScale.Z;
380
381 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
382 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
383 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
384 }
385
386 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
387 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
388 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
389
390 return finalScale;
391 }
392 }
393
308 public UUID GroupID 394 public UUID GroupID
309 { 395 {
310 get { return m_rootPart.GroupID; } 396 get { return m_rootPart.GroupID; }
@@ -344,11 +430,13 @@ namespace OpenSim.Region.Framework.Scenes
344 /// <summary> 430 /// <summary>
345 /// Check both the attachment property and the relevant properties of the underlying root part. 431 /// Check both the attachment property and the relevant properties of the underlying root part.
346 /// </summary> 432 /// </summary>
433 /// <remarks>
347 /// This is necessary in some cases, particularly when a scene object has just crossed into a region and doesn't 434 /// This is necessary in some cases, particularly when a scene object has just crossed into a region and doesn't
348 /// have the IsAttachment property yet checked. 435 /// have the IsAttachment property yet checked.
349 /// 436 ///
350 /// FIXME: However, this should be fixed so that this property 437 /// FIXME: However, this should be fixed so that this property
351 /// propertly reflects the underlying status. 438 /// propertly reflects the underlying status.
439 /// </remarks>
352 /// <returns></returns> 440 /// <returns></returns>
353 public bool IsAttachmentCheckFull() 441 public bool IsAttachmentCheckFull()
354 { 442 {
@@ -395,8 +483,6 @@ namespace OpenSim.Region.Framework.Scenes
395 SceneObjectPart[] parts = m_parts.GetArray(); 483 SceneObjectPart[] parts = m_parts.GetArray();
396 foreach (SceneObjectPart part in parts) 484 foreach (SceneObjectPart part in parts)
397 { 485 {
398 part.IgnoreUndoUpdate = false;
399 part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
400 part.GroupPosition = val; 486 part.GroupPosition = val;
401 if (!m_dupeInProgress) 487 if (!m_dupeInProgress)
402 { 488 {
@@ -682,7 +768,7 @@ namespace OpenSim.Region.Framework.Scenes
682 part.ParentID = m_rootPart.LocalId; 768 part.ParentID = m_rootPart.LocalId;
683 //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID); 769 //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID);
684 } 770 }
685 771
686 ApplyPhysics(m_scene.m_physicalPrim); 772 ApplyPhysics(m_scene.m_physicalPrim);
687 773
688 if (RootPart.PhysActor != null) 774 if (RootPart.PhysActor != null)
@@ -693,34 +779,6 @@ namespace OpenSim.Region.Framework.Scenes
693 //ScheduleGroupForFullUpdate(); 779 //ScheduleGroupForFullUpdate();
694 } 780 }
695 781
696 public Vector3 GroupScale()
697 {
698 Vector3 minScale = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionSize);
699 Vector3 maxScale = Vector3.Zero;
700 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
701
702 SceneObjectPart[] parts = m_parts.GetArray();
703 for (int i = 0; i < parts.Length; i++)
704 {
705 SceneObjectPart part = parts[i];
706 Vector3 partscale = part.Scale;
707 Vector3 partoffset = part.OffsetPosition;
708
709 minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X;
710 minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.Y + partoffset.Y : minScale.Y;
711 minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.Z + partoffset.Z : minScale.Z;
712
713 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
714 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
715 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
716 }
717
718 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
719 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
720 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
721 return finalScale;
722
723 }
724 public EntityIntersection TestIntersection(Ray hRay, bool frontFacesOnly, bool faceCenters) 782 public EntityIntersection TestIntersection(Ray hRay, bool frontFacesOnly, bool faceCenters)
725 { 783 {
726 // We got a request from the inner_scene to raytrace along the Ray hRay 784 // We got a request from the inner_scene to raytrace along the Ray hRay
@@ -1129,45 +1187,31 @@ namespace OpenSim.Region.Framework.Scenes
1129 /// <param name="agentID"></param> 1187 /// <param name="agentID"></param>
1130 /// <param name="attachmentpoint"></param> 1188 /// <param name="attachmentpoint"></param>
1131 /// <param name="AttachOffset"></param> 1189 /// <param name="AttachOffset"></param>
1132 public void AttachToAgent(UUID agentID, uint attachmentpoint, Vector3 AttachOffset, bool silent) 1190 private void AttachToAgent(
1191 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1133 { 1192 {
1134 ScenePresence avatar = m_scene.GetScenePresence(agentID);
1135 if (avatar != null) 1193 if (avatar != null)
1136 { 1194 {
1137 // don't attach attachments to child agents 1195 // don't attach attachments to child agents
1138 if (avatar.IsChildAgent) return; 1196 if (avatar.IsChildAgent) return;
1139 1197
1140// m_log.DebugFormat("[SOG]: Adding attachment {0} to avatar {1}", Name, avatar.Name);
1141
1142 DetachFromBackup();
1143
1144 // Remove from database and parcel prim count 1198 // Remove from database and parcel prim count
1145 m_scene.DeleteFromStorage(UUID); 1199 m_scene.DeleteFromStorage(so.UUID);
1146 m_scene.EventManager.TriggerParcelPrimCountTainted(); 1200 m_scene.EventManager.TriggerParcelPrimCountTainted();
1147 1201
1148 m_rootPart.AttachedAvatar = agentID; 1202 so.AttachedAvatar = avatar.UUID;
1149
1150 //Anakin Lohner bug #3839
1151 lock (m_parts)
1152 {
1153 foreach (SceneObjectPart p in m_parts.GetArray())
1154 {
1155 p.AttachedAvatar = agentID;
1156 }
1157 }
1158 1203
1159 if (m_rootPart.PhysActor != null) 1204 if (so.RootPart.PhysActor != null)
1160 { 1205 {
1161 m_scene.PhysicsScene.RemovePrim(m_rootPart.PhysActor); 1206 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1162 m_rootPart.PhysActor = null; 1207 so.RootPart.PhysActor = null;
1163 } 1208 }
1164 1209
1165 AbsolutePosition = AttachOffset; 1210 so.AbsolutePosition = attachOffset;
1166 m_rootPart.AttachedPos = AttachOffset; 1211 so.RootPart.AttachedPos = attachOffset;
1167 m_rootPart.IsAttachment = true; 1212 so.IsAttachment = true;
1168 1213 so.RootPart.SetParentLocalId(avatar.LocalId);
1169 m_rootPart.SetParentLocalId(avatar.LocalId); 1214 so.AttachmentPoint = attachmentpoint;
1170 SetAttachmentPoint(Convert.ToByte(attachmentpoint));
1171 1215
1172 avatar.AddAttachment(this); 1216 avatar.AddAttachment(this);
1173 1217
@@ -1190,7 +1234,7 @@ namespace OpenSim.Region.Framework.Scenes
1190 { 1234 {
1191 m_log.WarnFormat( 1235 m_log.WarnFormat(
1192 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present", 1236 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1193 UUID, agentID, Scene.RegionInfo.RegionName); 1237 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1194 } 1238 }
1195 } 1239 }
1196 1240
@@ -1199,14 +1243,9 @@ namespace OpenSim.Region.Framework.Scenes
1199 return m_rootPart.Shape.State; 1243 return m_rootPart.Shape.State;
1200 } 1244 }
1201 1245
1202 public void ClearPartAttachmentData()
1203 {
1204 SetAttachmentPoint((Byte)0);
1205 }
1206
1207 public void DetachToGround() 1246 public void DetachToGround()
1208 { 1247 {
1209 ScenePresence avatar = m_scene.GetScenePresence(m_rootPart.AttachedAvatar); 1248 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1210 if (avatar == null) 1249 if (avatar == null)
1211 return; 1250 return;
1212 1251
@@ -1220,14 +1259,14 @@ namespace OpenSim.Region.Framework.Scenes
1220 RootPart.FromItemID = UUID.Zero; 1259 RootPart.FromItemID = UUID.Zero;
1221 1260
1222 AbsolutePosition = detachedpos; 1261 AbsolutePosition = detachedpos;
1223 m_rootPart.AttachedAvatar = UUID.Zero; 1262 AttachedAvatar = UUID.Zero;
1224 1263
1225 SceneObjectPart[] parts = m_parts.GetArray(); 1264 //SceneObjectPart[] parts = m_parts.GetArray();
1226 for (int i = 0; i < parts.Length; i++) 1265 //for (int i = 0; i < parts.Length; i++)
1227 parts[i].AttachedAvatar = UUID.Zero; 1266 // parts[i].AttachedAvatar = UUID.Zero;
1228 1267
1229 m_rootPart.SetParentLocalId(0); 1268 m_rootPart.SetParentLocalId(0);
1230 SetAttachmentPoint((byte)0); 1269 AttachmentPoint = (byte)0;
1231 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_scene.m_physicalPrim); 1270 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_scene.m_physicalPrim);
1232 HasGroupChanged = true; 1271 HasGroupChanged = true;
1233 RootPart.Rezzed = DateTime.Now; 1272 RootPart.Rezzed = DateTime.Now;
@@ -1240,7 +1279,7 @@ namespace OpenSim.Region.Framework.Scenes
1240 1279
1241 public void DetachToInventoryPrep() 1280 public void DetachToInventoryPrep()
1242 { 1281 {
1243 ScenePresence avatar = m_scene.GetScenePresence(m_rootPart.AttachedAvatar); 1282 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1244 //Vector3 detachedpos = new Vector3(127f, 127f, 127f); 1283 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1245 if (avatar != null) 1284 if (avatar != null)
1246 { 1285 {
@@ -1248,15 +1287,15 @@ namespace OpenSim.Region.Framework.Scenes
1248 avatar.RemoveAttachment(this); 1287 avatar.RemoveAttachment(this);
1249 } 1288 }
1250 1289
1251 m_rootPart.AttachedAvatar = UUID.Zero; 1290 AttachedAvatar = UUID.Zero;
1252 1291
1253 SceneObjectPart[] parts = m_parts.GetArray(); 1292 /*SceneObjectPart[] parts = m_parts.GetArray();
1254 for (int i = 0; i < parts.Length; i++) 1293 for (int i = 0; i < parts.Length; i++)
1255 parts[i].AttachedAvatar = UUID.Zero; 1294 parts[i].AttachedAvatar = UUID.Zero;*/
1256 1295
1257 m_rootPart.SetParentLocalId(0); 1296 m_rootPart.SetParentLocalId(0);
1258 //m_rootPart.SetAttachmentPoint((byte)0); 1297 //m_rootPart.SetAttachmentPoint((byte)0);
1259 m_rootPart.IsAttachment = false; 1298 IsAttachment = false;
1260 AbsolutePosition = m_rootPart.AttachedPos; 1299 AbsolutePosition = m_rootPart.AttachedPos;
1261 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim); 1300 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1262 //AttachToBackup(); 1301 //AttachToBackup();
@@ -1324,7 +1363,7 @@ namespace OpenSim.Region.Framework.Scenes
1324 1363
1325 part.LinkNum = m_parts.Count; 1364 part.LinkNum = m_parts.Count;
1326 1365
1327 if (part.LinkNum == 2 && RootPart != null) 1366 if (part.LinkNum == 2)
1328 RootPart.LinkNum = 1; 1367 RootPart.LinkNum = 1;
1329 } 1368 }
1330 1369
@@ -1407,7 +1446,11 @@ namespace OpenSim.Region.Framework.Scenes
1407 1446
1408 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1447 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1409 { 1448 {
1410 part.StoreUndoState(UndoType.STATE_PRIM_ALL); 1449// m_log.DebugFormat(
1450// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1451// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1452
1453 part.StoreUndoState();
1411 part.OnGrab(offsetPos, remoteClient); 1454 part.OnGrab(offsetPos, remoteClient);
1412 } 1455 }
1413 1456
@@ -1428,7 +1471,7 @@ namespace OpenSim.Region.Framework.Scenes
1428 public void DeleteGroupFromScene(bool silent) 1471 public void DeleteGroupFromScene(bool silent)
1429 { 1472 {
1430 // We need to keep track of this state in case this group is still queued for backup. 1473 // We need to keep track of this state in case this group is still queued for backup.
1431 m_isDeleted = true; 1474 IsDeleted = true;
1432 1475
1433 DetachFromBackup(); 1476 DetachFromBackup();
1434 1477
@@ -1703,91 +1746,86 @@ namespace OpenSim.Region.Framework.Scenes
1703 /// <returns></returns> 1746 /// <returns></returns>
1704 public SceneObjectGroup Copy(bool userExposed) 1747 public SceneObjectGroup Copy(bool userExposed)
1705 { 1748 {
1706 SceneObjectGroup dupe; 1749 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1707 try 1750 dupe.m_isBackedUp = false;
1708 { 1751 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1709 m_dupeInProgress = true;
1710 dupe = (SceneObjectGroup)MemberwiseClone();
1711 dupe.m_isBackedUp = false;
1712 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1713 1752
1714 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 1753 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1715 // attachments do not bordercross while they're being duplicated. This is hacktastic! 1754 // attachments do not bordercross while they're being duplicated. This is hacktastic!
1716 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! 1755 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
1717 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state 1756 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1718 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, 1757 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1719 // then restore it's attachment state 1758 // then restore it's attachment state
1720 1759
1721 // This is only necessary when userExposed is false! 1760 // This is only necessary when userExposed is false!
1722 1761
1723 bool previousAttachmentStatus = dupe.RootPart.IsAttachment; 1762 bool previousAttachmentStatus = dupe.IsAttachment;
1724 1763
1725 if (!userExposed) 1764 if (!userExposed)
1726 dupe.RootPart.IsAttachment = true; 1765 dupe.IsAttachment = true;
1727 1766
1728 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 1767 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
1729 1768
1730 if (!userExposed) 1769 if (!userExposed)
1731 { 1770 {
1732 dupe.RootPart.IsAttachment = previousAttachmentStatus; 1771 dupe.IsAttachment = previousAttachmentStatus;
1733 } 1772 }
1734 1773
1735 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 1774 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1736 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 1775 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1737 1776
1738 if (userExposed) 1777 if (userExposed)
1739 dupe.m_rootPart.TrimPermissions(); 1778 dupe.m_rootPart.TrimPermissions();
1740 1779
1741 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1780 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1742 1781
1743 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1782 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1744 { 1783 {
1745 return p1.LinkNum.CompareTo(p2.LinkNum); 1784 return p1.LinkNum.CompareTo(p2.LinkNum);
1746 } 1785 }
1747 ); 1786 );
1748 1787
1749 foreach (SceneObjectPart part in partList) 1788 foreach (SceneObjectPart part in partList)
1789 {
1790 SceneObjectPart newPart;
1791 if (part.UUID != m_rootPart.UUID)
1750 { 1792 {
1751 if (part.UUID != m_rootPart.UUID) 1793 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1752 { 1794 newPart.LinkNum = part.LinkNum;
1753 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1754
1755 newPart.LinkNum = part.LinkNum;
1756 }
1757
1758 // Need to duplicate the physics actor as well
1759 if (part.PhysActor != null && userExposed)
1760 {
1761 PrimitiveBaseShape pbs = part.Shape;
1762
1763 part.PhysActor
1764 = m_scene.PhysicsScene.AddPrimShape(
1765 string.Format("{0}/{1}", part.Name, part.UUID),
1766 pbs,
1767 part.AbsolutePosition,
1768 part.Scale,
1769 part.RotationOffset,
1770 part.PhysActor.IsPhysical,
1771 m_localId);
1772 part.PhysActor.SetMaterial((int)part.Material);
1773
1774 part.PhysActor.LocalID = part.LocalId;
1775 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1776 }
1777 } 1795 }
1778 if (userExposed) 1796 else
1779 { 1797 {
1780 dupe.UpdateParentIDs(); 1798 newPart = dupe.m_rootPart;
1781 dupe.HasGroupChanged = true; 1799 }
1782 dupe.AttachToBackup();
1783 1800
1784 ScheduleGroupForFullUpdate(); 1801 // Need to duplicate the physics actor as well
1802 if (part.PhysActor != null && userExposed)
1803 {
1804 PrimitiveBaseShape pbs = newPart.Shape;
1805
1806 newPart.PhysActor
1807 = m_scene.PhysicsScene.AddPrimShape(
1808 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1809 pbs,
1810 newPart.AbsolutePosition,
1811 newPart.Scale,
1812 newPart.RotationOffset,
1813 part.PhysActor.IsPhysical,
1814 newPart.LocalId);
1815
1816 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1785 } 1817 }
1786 } 1818 }
1787 finally 1819
1820 if (userExposed)
1788 { 1821 {
1789 m_dupeInProgress = false; 1822 dupe.UpdateParentIDs();
1823 dupe.HasGroupChanged = true;
1824 dupe.AttachToBackup();
1825
1826 ScheduleGroupForFullUpdate();
1790 } 1827 }
1828
1791 return dupe; 1829 return dupe;
1792 } 1830 }
1793 1831
@@ -1802,36 +1840,24 @@ namespace OpenSim.Region.Framework.Scenes
1802 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 1840 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed));
1803 } 1841 }
1804 1842
1805 public void ScriptSetPhysicsStatus(bool UsePhysics) 1843 public void ScriptSetPhysicsStatus(bool usePhysics)
1806 { 1844 {
1807 bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0); 1845 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1808 bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
1809 bool IsVolumeDetect = RootPart.VolumeDetectActive;
1810 UpdatePrimFlags(RootPart.LocalId, UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1811 } 1846 }
1812 1847
1813 public void ScriptSetTemporaryStatus(bool TemporaryStatus) 1848 public void ScriptSetTemporaryStatus(bool makeTemporary)
1814 { 1849 {
1815 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 1850 UpdatePrimFlags(RootPart.LocalId, UsesPhysics, makeTemporary, IsPhantom, IsVolumeDetect);
1816 bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
1817 bool IsVolumeDetect = RootPart.VolumeDetectActive;
1818 UpdatePrimFlags(RootPart.LocalId, UsePhysics, TemporaryStatus, IsPhantom, IsVolumeDetect);
1819 } 1851 }
1820 1852
1821 public void ScriptSetPhantomStatus(bool PhantomStatus) 1853 public void ScriptSetPhantomStatus(bool makePhantom)
1822 { 1854 {
1823 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 1855 UpdatePrimFlags(RootPart.LocalId, UsesPhysics, IsTemporary, makePhantom, IsVolumeDetect);
1824 bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0);
1825 bool IsVolumeDetect = RootPart.VolumeDetectActive;
1826 UpdatePrimFlags(RootPart.LocalId, UsePhysics, IsTemporary, PhantomStatus, IsVolumeDetect);
1827 } 1856 }
1828 1857
1829 public void ScriptSetVolumeDetect(bool VDStatus) 1858 public void ScriptSetVolumeDetect(bool makeVolumeDetect)
1830 { 1859 {
1831 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); 1860 UpdatePrimFlags(RootPart.LocalId, UsesPhysics, IsTemporary, IsPhantom, makeVolumeDetect);
1832 bool IsTemporary = ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0);
1833 bool IsPhantom = ((RootPart.Flags & PrimFlags.Phantom) != 0);
1834 UpdatePrimFlags(RootPart.LocalId, UsePhysics, IsTemporary, IsPhantom, VDStatus);
1835 1861
1836 /* 1862 /*
1837 ScriptSetPhantomStatus(false); // What ever it was before, now it's not phantom anymore 1863 ScriptSetPhantomStatus(false); // What ever it was before, now it's not phantom anymore
@@ -1849,142 +1875,88 @@ namespace OpenSim.Region.Framework.Scenes
1849 1875
1850 public void applyImpulse(Vector3 impulse) 1876 public void applyImpulse(Vector3 impulse)
1851 { 1877 {
1852 // We check if rootpart is null here because scripts don't delete if you delete the host. 1878 if (IsAttachment)
1853 // This means that unfortunately, we can pass a null physics actor to Simulate!
1854 // Make sure we don't do that!
1855 SceneObjectPart rootpart = m_rootPart;
1856 if (rootpart != null)
1857 { 1879 {
1858 if (IsAttachment) 1880 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1881 if (avatar != null)
1859 { 1882 {
1860 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); 1883 avatar.PushForce(impulse);
1861 if (avatar != null)
1862 {
1863 avatar.PushForce(impulse);
1864 }
1865 } 1884 }
1866 else 1885 }
1886 else
1887 {
1888 if (RootPart.PhysActor != null)
1867 { 1889 {
1868 if (rootpart.PhysActor != null) 1890 RootPart.PhysActor.AddForce(impulse, true);
1869 { 1891 m_scene.PhysicsScene.AddPhysicsActorTaint(RootPart.PhysActor);
1870 rootpart.PhysActor.AddForce(impulse, true);
1871 m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor);
1872 }
1873 } 1892 }
1874 } 1893 }
1875 } 1894 }
1876 1895
1877 public void applyAngularImpulse(Vector3 impulse) 1896 public void applyAngularImpulse(Vector3 impulse)
1878 { 1897 {
1879 // We check if rootpart is null here because scripts don't delete if you delete the host. 1898 if (RootPart.PhysActor != null)
1880 // This means that unfortunately, we can pass a null physics actor to Simulate!
1881 // Make sure we don't do that!
1882 SceneObjectPart rootpart = m_rootPart;
1883 if (rootpart != null)
1884 { 1899 {
1885 if (rootpart.PhysActor != null) 1900 if (!IsAttachment)
1886 { 1901 {
1887 if (!IsAttachment) 1902 RootPart.PhysActor.AddAngularForce(impulse, true);
1888 { 1903 m_scene.PhysicsScene.AddPhysicsActorTaint(RootPart.PhysActor);
1889 rootpart.PhysActor.AddAngularForce(impulse, true);
1890 m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor);
1891 }
1892 } 1904 }
1893 } 1905 }
1894 } 1906 }
1895 1907
1896 public void setAngularImpulse(Vector3 impulse) 1908 public void setAngularImpulse(Vector3 impulse)
1897 { 1909 {
1898 // We check if rootpart is null here because scripts don't delete if you delete the host. 1910 if (RootPart.PhysActor != null)
1899 // This means that unfortunately, we can pass a null physics actor to Simulate!
1900 // Make sure we don't do that!
1901 SceneObjectPart rootpart = m_rootPart;
1902 if (rootpart != null)
1903 { 1911 {
1904 if (rootpart.PhysActor != null) 1912 if (!IsAttachment)
1905 { 1913 {
1906 if (!IsAttachment) 1914 RootPart.PhysActor.Torque = impulse;
1907 { 1915 m_scene.PhysicsScene.AddPhysicsActorTaint(RootPart.PhysActor);
1908 rootpart.PhysActor.Torque = impulse;
1909 m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor);
1910 }
1911 } 1916 }
1912 } 1917 }
1913 } 1918 }
1914 1919
1915 public Vector3 GetTorque() 1920 public Vector3 GetTorque()
1916 { 1921 {
1917 // We check if rootpart is null here because scripts don't delete if you delete the host. 1922 if (RootPart.PhysActor != null)
1918 // This means that unfortunately, we can pass a null physics actor to Simulate!
1919 // Make sure we don't do that!
1920 SceneObjectPart rootpart = m_rootPart;
1921 if (rootpart != null)
1922 { 1923 {
1923 if (rootpart.PhysActor != null) 1924 if (!IsAttachment)
1924 { 1925 {
1925 if (!IsAttachment) 1926 Vector3 torque = RootPart.PhysActor.Torque;
1926 { 1927 return torque;
1927 Vector3 torque = rootpart.PhysActor.Torque;
1928 return torque;
1929 }
1930 } 1928 }
1931 } 1929 }
1930
1932 return Vector3.Zero; 1931 return Vector3.Zero;
1933 } 1932 }
1934 1933
1935 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object 1934 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1936 public void moveToTarget(Vector3 target, float tau) 1935 public void moveToTarget(Vector3 target, float tau)
1937 { 1936 {
1938 SceneObjectPart rootpart = m_rootPart; 1937 if (IsAttachment)
1939 if (rootpart != null)
1940 { 1938 {
1941 if (IsAttachment) 1939 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1940 if (avatar != null)
1942 { 1941 {
1943 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); 1942 avatar.MoveToTarget(target, false);
1944 if (avatar != null)
1945 {
1946 List<string> coords = new List<string>();
1947 uint regionX = 0;
1948 uint regionY = 0;
1949 Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY);
1950 target.X += regionX;
1951 target.Y += regionY;
1952 coords.Add(target.X.ToString());
1953 coords.Add(target.Y.ToString());
1954 coords.Add(target.Z.ToString());
1955 avatar.DoMoveToPosition(avatar, "", coords);
1956 }
1957 } 1943 }
1958 else 1944 }
1945 else
1946 {
1947 if (RootPart.PhysActor != null)
1959 { 1948 {
1960 if (rootpart.PhysActor != null) 1949 RootPart.PhysActor.PIDTarget = target;
1961 { 1950 RootPart.PhysActor.PIDTau = tau;
1962 rootpart.PhysActor.PIDTarget = target; 1951 RootPart.PhysActor.PIDActive = true;
1963 rootpart.PhysActor.PIDTau = tau;
1964 rootpart.PhysActor.PIDActive = true;
1965 }
1966 } 1952 }
1967 } 1953 }
1968 } 1954 }
1969 1955
1970 public void stopMoveToTarget() 1956 public void stopMoveToTarget()
1971 { 1957 {
1972 SceneObjectPart rootpart = m_rootPart; 1958 if (RootPart.PhysActor != null)
1973 if (rootpart != null) 1959 RootPart.PhysActor.PIDActive = false;
1974 {
1975 if (IsAttachment)
1976 {
1977 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1978 if (avatar != null) avatar.StopMoveToPosition();
1979 }
1980 else
1981 {
1982 if (rootpart.PhysActor != null)
1983 {
1984 rootpart.PhysActor.PIDActive = false;
1985 }
1986 }
1987 }
1988 } 1960 }
1989 1961
1990 public void rotLookAt(Quaternion target, float strength, float damping) 1962 public void rotLookAt(Quaternion target, float strength, float damping)
@@ -2035,22 +2007,18 @@ namespace OpenSim.Region.Framework.Scenes
2035 /// <param name="tau">Number of seconds over which to reach target</param> 2007 /// <param name="tau">Number of seconds over which to reach target</param>
2036 public void SetHoverHeight(float height, PIDHoverType hoverType, float tau) 2008 public void SetHoverHeight(float height, PIDHoverType hoverType, float tau)
2037 { 2009 {
2038 SceneObjectPart rootpart = m_rootPart; 2010 if (RootPart.PhysActor != null)
2039 if (rootpart != null)
2040 { 2011 {
2041 if (rootpart.PhysActor != null) 2012 if (height != 0f)
2042 { 2013 {
2043 if (height != 0f) 2014 RootPart.PhysActor.PIDHoverHeight = height;
2044 { 2015 RootPart.PhysActor.PIDHoverType = hoverType;
2045 rootpart.PhysActor.PIDHoverHeight = height; 2016 RootPart.PhysActor.PIDTau = tau;
2046 rootpart.PhysActor.PIDHoverType = hoverType; 2017 RootPart.PhysActor.PIDHoverActive = true;
2047 rootpart.PhysActor.PIDTau = tau; 2018 }
2048 rootpart.PhysActor.PIDHoverActive = true; 2019 else
2049 } 2020 {
2050 else 2021 RootPart.PhysActor.PIDHoverActive = false;
2051 {
2052 rootpart.PhysActor.PIDHoverActive = false;
2053 }
2054 } 2022 }
2055 } 2023 }
2056 } 2024 }
@@ -2145,7 +2113,7 @@ namespace OpenSim.Region.Framework.Scenes
2145 // an object has been deleted from a scene before update was processed. 2113 // an object has been deleted from a scene before update was processed.
2146 // A more fundamental overhaul of the update mechanism is required to eliminate all 2114 // A more fundamental overhaul of the update mechanism is required to eliminate all
2147 // the race conditions. 2115 // the race conditions.
2148 if (m_isDeleted) 2116 if (IsDeleted)
2149 return; 2117 return;
2150 2118
2151 // Even temporary objects take part in physics (e.g. temp-on-rez bullets) 2119 // Even temporary objects take part in physics (e.g. temp-on-rez bullets)
@@ -2459,7 +2427,7 @@ namespace OpenSim.Region.Framework.Scenes
2459 } 2427 }
2460 2428
2461 m_scene.UnlinkSceneObject(objectGroup, true); 2429 m_scene.UnlinkSceneObject(objectGroup, true);
2462 objectGroup.m_isDeleted = true; 2430 objectGroup.IsDeleted = true;
2463 2431
2464 objectGroup.m_parts.Clear(); 2432 objectGroup.m_parts.Clear();
2465 2433
@@ -2597,8 +2565,7 @@ namespace OpenSim.Region.Framework.Scenes
2597 public virtual void DetachFromBackup() 2565 public virtual void DetachFromBackup()
2598 { 2566 {
2599 m_scene.SceneGraph.FireDetachFromBackup(this); 2567 m_scene.SceneGraph.FireDetachFromBackup(this);
2600 2568 if (m_isBackedUp && Scene != null)
2601 if (m_isBackedUp)
2602 m_scene.EventManager.OnBackup -= ProcessBackup; 2569 m_scene.EventManager.OnBackup -= ProcessBackup;
2603 2570
2604 m_isBackedUp = false; 2571 m_isBackedUp = false;
@@ -2858,14 +2825,15 @@ namespace OpenSim.Region.Framework.Scenes
2858 /// Update prim flags for this group. 2825 /// Update prim flags for this group.
2859 /// </summary> 2826 /// </summary>
2860 /// <param name="localID"></param> 2827 /// <param name="localID"></param>
2861 /// <param name="type"></param> 2828 /// <param name="UsePhysics"></param>
2862 /// <param name="inUse"></param> 2829 /// <param name="SetTemporary"></param>
2863 /// <param name="data"></param> 2830 /// <param name="SetPhantom"></param>
2864 public void UpdatePrimFlags(uint localID, bool UsePhysics, bool IsTemporary, bool IsPhantom, bool IsVolumeDetect) 2831 /// <param name="SetVolumeDetect"></param>
2832 public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect)
2865 { 2833 {
2866 SceneObjectPart selectionPart = GetChildPart(localID); 2834 SceneObjectPart selectionPart = GetChildPart(localID);
2867 2835
2868 if (IsTemporary) 2836 if (SetTemporary && Scene != null)
2869 { 2837 {
2870 DetachFromBackup(); 2838 DetachFromBackup();
2871 // Remove from database and parcel prim count 2839 // Remove from database and parcel prim count
@@ -2877,23 +2845,27 @@ namespace OpenSim.Region.Framework.Scenes
2877 if (selectionPart != null) 2845 if (selectionPart != null)
2878 { 2846 {
2879 SceneObjectPart[] parts = m_parts.GetArray(); 2847 SceneObjectPart[] parts = m_parts.GetArray();
2880 for (int i = 0; i < parts.Length; i++) 2848
2849 if (Scene != null)
2881 { 2850 {
2882 SceneObjectPart part = parts[i]; 2851 for (int i = 0; i < parts.Length; i++)
2883 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2884 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
2885 part.Scale.Z > m_scene.RegionInfo.PhysPrimMax)
2886 { 2852 {
2887 UsePhysics = false; // Reset physics 2853 SceneObjectPart part = parts[i];
2888 break; 2854 if (part.Scale.X > m_scene.RegionInfo.PhysPrimMax ||
2855 part.Scale.Y > m_scene.RegionInfo.PhysPrimMax ||
2856 part.Scale.Z > m_scene.RegionInfo.PhysPrimMax)
2857 {
2858 UsePhysics = false; // Reset physics
2859 break;
2860 }
2889 } 2861 }
2890 } 2862 }
2891 2863
2892 RootPart.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2864 RootPart.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, SetVolumeDetect);
2893 for (int i = 0; i < parts.Length; i++) 2865 for (int i = 0; i < parts.Length; i++)
2894 { 2866 {
2895 if (parts[i] != RootPart) 2867 if (parts[i] != RootPart)
2896 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2868 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, SetVolumeDetect);
2897 } 2869 }
2898 } 2870 }
2899 } 2871 }
@@ -2967,202 +2939,150 @@ namespace OpenSim.Region.Framework.Scenes
2967 #region Resize 2939 #region Resize
2968 2940
2969 /// <summary> 2941 /// <summary>
2970 /// Resize the given part 2942 /// Resize the entire group of prims.
2971 /// </summary> 2943 /// </summary>
2972 /// <param name="scale"></param> 2944 /// <param name="scale"></param>
2973 /// <param name="localID"></param> 2945 public void GroupResize(Vector3 scale)
2974 public void Resize(Vector3 scale, uint localID) 2946 {
2975 { 2947// m_log.DebugFormat(
2976 if (scale.X > m_scene.m_maxNonphys) 2948// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2977 scale.X = m_scene.m_maxNonphys; 2949 RootPart.StoreUndoState(true);
2978 if (scale.Y > m_scene.m_maxNonphys)
2979 scale.Y = m_scene.m_maxNonphys;
2980 if (scale.Z > m_scene.m_maxNonphys)
2981 scale.Z = m_scene.m_maxNonphys;
2982 SceneObjectPart part = GetChildPart(localID);
2983 if (part != null)
2984 {
2985 if (part.PhysActor != null)
2986 {
2987 if (part.PhysActor.IsPhysical)
2988 {
2989 if (scale.X > m_scene.m_maxPhys)
2990 scale.X = m_scene.m_maxPhys;
2991 if (scale.Y > m_scene.m_maxPhys)
2992 scale.Y = m_scene.m_maxPhys;
2993 if (scale.Z > m_scene.m_maxPhys)
2994 scale.Z = m_scene.m_maxPhys;
2995 }
2996 part.PhysActor.Size = scale;
2997 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2998 }
2999 part.Resize(scale);
3000 2950
3001 HasGroupChanged = true; 2951 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
3002 part.TriggerScriptChangedEvent(Changed.SCALE); 2952 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
3003 ScheduleGroupForFullUpdate(); 2953 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
3004 2954
3005 //if (part.UUID == m_rootPart.UUID) 2955 if (RootPart.PhysActor != null && RootPart.PhysActor.IsPhysical)
3006 //{ 2956 {
3007 //if (m_rootPart.PhysActor != null) 2957 scale.X = Math.Min(scale.X, Scene.m_maxPhys);
3008 //{ 2958 scale.Y = Math.Min(scale.Y, Scene.m_maxPhys);
3009 //m_rootPart.PhysActor.Size = 2959 scale.Z = Math.Min(scale.Z, Scene.m_maxPhys);
3010 //new PhysicsVector(m_rootPart.Scale.X, m_rootPart.Scale.Y, m_rootPart.Scale.Z);
3011 //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
3012 //}
3013 //}
3014 } 2960 }
3015 }
3016 2961
3017 public void GroupResize(Vector3 scale, uint localID) 2962 float x = (scale.X / RootPart.Scale.X);
3018 { 2963 float y = (scale.Y / RootPart.Scale.Y);
3019 SceneObjectPart part = GetChildPart(localID); 2964 float z = (scale.Z / RootPart.Scale.Z);
3020 if (part != null)
3021 {
3022 if (scale.X > m_scene.m_maxNonphys)
3023 scale.X = m_scene.m_maxNonphys;
3024 if (scale.Y > m_scene.m_maxNonphys)
3025 scale.Y = m_scene.m_maxNonphys;
3026 if (scale.Z > m_scene.m_maxNonphys)
3027 scale.Z = m_scene.m_maxNonphys;
3028 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3029 {
3030 if (scale.X > m_scene.m_maxPhys)
3031 scale.X = m_scene.m_maxPhys;
3032 if (scale.Y > m_scene.m_maxPhys)
3033 scale.Y = m_scene.m_maxPhys;
3034 if (scale.Z > m_scene.m_maxPhys)
3035 scale.Z = m_scene.m_maxPhys;
3036 }
3037 float x = (scale.X / part.Scale.X);
3038 float y = (scale.Y / part.Scale.Y);
3039 float z = (scale.Z / part.Scale.Z);
3040 2965
3041 SceneObjectPart[] parts; 2966 SceneObjectPart[] parts;
3042 if (x > 1.0f || y > 1.0f || z > 1.0f) 2967 if (x > 1.0f || y > 1.0f || z > 1.0f)
2968 {
2969 parts = m_parts.GetArray();
2970 for (int i = 0; i < parts.Length; i++)
3043 { 2971 {
3044 parts = m_parts.GetArray(); 2972 SceneObjectPart obPart = parts[i];
3045 for (int i = 0; i < parts.Length; i++) 2973 if (obPart.UUID != m_rootPart.UUID)
3046 { 2974 {
3047 SceneObjectPart obPart = parts[i]; 2975// obPart.IgnoreUndoUpdate = true;
3048 if (obPart.UUID != m_rootPart.UUID) 2976 Vector3 oldSize = new Vector3(obPart.Scale);
2977
2978 float f = 1.0f;
2979 float a = 1.0f;
2980
2981 if (RootPart.PhysActor != null && RootPart.PhysActor.IsPhysical)
3049 { 2982 {
3050 obPart.IgnoreUndoUpdate = true; 2983 if (oldSize.X * x > m_scene.m_maxPhys)
3051 Vector3 oldSize = new Vector3(obPart.Scale); 2984 {
2985 f = m_scene.m_maxPhys / oldSize.X;
2986 a = f / x;
2987 x *= a;
2988 y *= a;
2989 z *= a;
2990 }
3052 2991
3053 float f = 1.0f; 2992 if (oldSize.Y * y > m_scene.m_maxPhys)
3054 float a = 1.0f; 2993 {
2994 f = m_scene.m_maxPhys / oldSize.Y;
2995 a = f / y;
2996 x *= a;
2997 y *= a;
2998 z *= a;
2999 }
3055 3000
3056 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3001 if (oldSize.Z * z > m_scene.m_maxPhys)
3057 { 3002 {
3058 if (oldSize.X*x > m_scene.m_maxPhys) 3003 f = m_scene.m_maxPhys / oldSize.Z;
3059 { 3004 a = f / z;
3060 f = m_scene.m_maxPhys / oldSize.X; 3005 x *= a;
3061 a = f / x; 3006 y *= a;
3062 x *= a; 3007 z *= a;
3063 y *= a;
3064 z *= a;
3065 }
3066 if (oldSize.Y*y > m_scene.m_maxPhys)
3067 {
3068 f = m_scene.m_maxPhys / oldSize.Y;
3069 a = f / y;
3070 x *= a;
3071 y *= a;
3072 z *= a;
3073 }
3074 if (oldSize.Z*z > m_scene.m_maxPhys)
3075 {
3076 f = m_scene.m_maxPhys / oldSize.Z;
3077 a = f / z;
3078 x *= a;
3079 y *= a;
3080 z *= a;
3081 }
3082 } 3008 }
3083 else 3009 }
3010 else
3011 {
3012 if (oldSize.X * x > m_scene.m_maxNonphys)
3084 { 3013 {
3085 if (oldSize.X*x > m_scene.m_maxNonphys) 3014 f = m_scene.m_maxNonphys / oldSize.X;
3086 { 3015 a = f / x;
3087 f = m_scene.m_maxNonphys / oldSize.X; 3016 x *= a;
3088 a = f / x; 3017 y *= a;
3089 x *= a; 3018 z *= a;
3090 y *= a; 3019 }
3091 z *= a; 3020
3092 } 3021 if (oldSize.Y * y > m_scene.m_maxNonphys)
3093 if (oldSize.Y*y > m_scene.m_maxNonphys) 3022 {
3094 { 3023 f = m_scene.m_maxNonphys / oldSize.Y;
3095 f = m_scene.m_maxNonphys / oldSize.Y; 3024 a = f / y;
3096 a = f / y; 3025 x *= a;
3097 x *= a; 3026 y *= a;
3098 y *= a; 3027 z *= a;
3099 z *= a; 3028 }
3100 } 3029
3101 if (oldSize.Z*z > m_scene.m_maxNonphys) 3030 if (oldSize.Z * z > m_scene.m_maxNonphys)
3102 { 3031 {
3103 f = m_scene.m_maxNonphys / oldSize.Z; 3032 f = m_scene.m_maxNonphys / oldSize.Z;
3104 a = f / z; 3033 a = f / z;
3105 x *= a; 3034 x *= a;
3106 y *= a; 3035 y *= a;
3107 z *= a; 3036 z *= a;
3108 }
3109 } 3037 }
3110 obPart.IgnoreUndoUpdate = false;
3111 } 3038 }
3039
3040// obPart.IgnoreUndoUpdate = false;
3112 } 3041 }
3113 } 3042 }
3043 }
3114 3044
3115 Vector3 prevScale = part.Scale; 3045 Vector3 prevScale = RootPart.Scale;
3116 prevScale.X *= x; 3046 prevScale.X *= x;
3117 prevScale.Y *= y; 3047 prevScale.Y *= y;
3118 prevScale.Z *= z;; 3048 prevScale.Z *= z;
3049// RootPart.IgnoreUndoUpdate = true;
3050 RootPart.Resize(prevScale);
3051// RootPart.IgnoreUndoUpdate = false;
3119 3052
3120 part.IgnoreUndoUpdate = false; 3053 parts = m_parts.GetArray();
3121 part.StoreUndoState(UndoType.STATE_GROUP_SCALE); 3054 for (int i = 0; i < parts.Length; i++)
3122 part.IgnoreUndoUpdate = true; 3055 {
3123 part.Resize(prevScale); 3056 SceneObjectPart obPart = parts[i];
3124 part.IgnoreUndoUpdate = false;
3125 3057
3126 parts = m_parts.GetArray(); 3058 if (obPart.UUID != m_rootPart.UUID)
3127 for (int i = 0; i < parts.Length; i++)
3128 { 3059 {
3129 SceneObjectPart obPart = parts[i];
3130 obPart.IgnoreUndoUpdate = true; 3060 obPart.IgnoreUndoUpdate = true;
3131 if (obPart.UUID != m_rootPart.UUID)
3132 {
3133 if (obPart.UUID != m_rootPart.UUID)
3134 {
3135 obPart.IgnoreUndoUpdate = false;
3136 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3137 obPart.IgnoreUndoUpdate = true;
3138
3139 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
3140 currentpos.X *= x;
3141 currentpos.Y *= y;
3142 currentpos.Z *= z;
3143 Vector3 newSize = new Vector3(obPart.Scale);
3144 newSize.X *= x;
3145 newSize.Y *= y;
3146 newSize.Z *= z;
3147 obPart.Resize(newSize);
3148 obPart.UpdateOffSet(currentpos);
3149 }
3150 obPart.IgnoreUndoUpdate = false;
3151 }
3152 obPart.IgnoreUndoUpdate = false;
3153 }
3154 3061
3155 if (part.PhysActor != null) 3062 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
3156 { 3063 currentpos.X *= x;
3157 part.PhysActor.Size = prevScale; 3064 currentpos.Y *= y;
3158 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 3065 currentpos.Z *= z;
3066
3067 Vector3 newSize = new Vector3(obPart.Scale);
3068 newSize.X *= x;
3069 newSize.Y *= y;
3070 newSize.Z *= z;
3071
3072 obPart.Resize(newSize);
3073 obPart.UpdateOffSet(currentpos);
3074
3075 obPart.IgnoreUndoUpdate = false;
3159 } 3076 }
3160 3077
3161 part.IgnoreUndoUpdate = false; 3078// obPart.IgnoreUndoUpdate = false;
3162 HasGroupChanged = true; 3079 HasGroupChanged = true;
3163 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE); 3080 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3164 ScheduleGroupForTerseUpdate(); 3081 ScheduleGroupForTerseUpdate();
3165 } 3082 }
3083
3084// m_log.DebugFormat(
3085// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale);
3166 } 3086 }
3167 3087
3168 #endregion 3088 #endregion
@@ -3175,11 +3095,18 @@ namespace OpenSim.Region.Framework.Scenes
3175 /// <param name="pos"></param> 3095 /// <param name="pos"></param>
3176 public void UpdateGroupPosition(Vector3 pos) 3096 public void UpdateGroupPosition(Vector3 pos)
3177 { 3097 {
3098// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
3099
3100 RootPart.StoreUndoState(true);
3101
3102// SceneObjectPart[] parts = m_parts.GetArray();
3103// for (int i = 0; i < parts.Length; i++)
3104// parts[i].StoreUndoState();
3105
3178 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3106 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
3179 { 3107 {
3180 if (IsAttachment) 3108 if (IsAttachment)
3181 { 3109 {
3182 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
3183 m_rootPart.AttachedPos = pos; 3110 m_rootPart.AttachedPos = pos;
3184 } 3111 }
3185 if (RootPart.GetStatusSandbox()) 3112 if (RootPart.GetStatusSandbox())
@@ -3213,10 +3140,16 @@ namespace OpenSim.Region.Framework.Scenes
3213 3140
3214 SceneObjectPart[] parts = m_parts.GetArray(); 3141 SceneObjectPart[] parts = m_parts.GetArray();
3215 for (int i = 0; i < parts.Length; i++) 3142 for (int i = 0; i < parts.Length; i++)
3216 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION); 3143 parts[i].StoreUndoState();
3217 3144
3218 if (part != null) 3145 if (part != null)
3219 { 3146 {
3147// m_log.DebugFormat(
3148// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos);
3149
3150 part.StoreUndoState(false);
3151 part.IgnoreUndoUpdate = true;
3152
3220 if (part.UUID == m_rootPart.UUID) 3153 if (part.UUID == m_rootPart.UUID)
3221 { 3154 {
3222 UpdateRootPosition(pos); 3155 UpdateRootPosition(pos);
@@ -3227,18 +3160,22 @@ namespace OpenSim.Region.Framework.Scenes
3227 } 3160 }
3228 3161
3229 HasGroupChanged = true; 3162 HasGroupChanged = true;
3163 part.IgnoreUndoUpdate = false;
3230 } 3164 }
3231 } 3165 }
3232 3166
3233 /// <summary> 3167 /// <summary>
3234 /// 3168 /// Update just the root prim position in a linkset
3235 /// </summary> 3169 /// </summary>
3236 /// <param name="pos"></param> 3170 /// <param name="pos"></param>
3237 private void UpdateRootPosition(Vector3 pos) 3171 public void UpdateRootPosition(Vector3 pos)
3238 { 3172 {
3239 SceneObjectPart[] parts = m_parts.GetArray(); 3173// m_log.DebugFormat(
3240 for (int i = 0; i < parts.Length; i++) 3174// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
3241 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION); 3175
3176// SceneObjectPart[] parts = m_parts.GetArray();
3177// for (int i = 0; i < parts.Length; i++)
3178// parts[i].StoreUndoState();
3242 3179
3243 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3180 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
3244 Vector3 oldPos = 3181 Vector3 oldPos =
@@ -3251,7 +3188,7 @@ namespace OpenSim.Region.Framework.Scenes
3251 axDiff *= Quaternion.Inverse(partRotation); 3188 axDiff *= Quaternion.Inverse(partRotation);
3252 diff = axDiff; 3189 diff = axDiff;
3253 3190
3254 parts = m_parts.GetArray(); 3191 SceneObjectPart[] parts = m_parts.GetArray();
3255 for (int i = 0; i < parts.Length; i++) 3192 for (int i = 0; i < parts.Length; i++)
3256 { 3193 {
3257 SceneObjectPart obPart = parts[i]; 3194 SceneObjectPart obPart = parts[i];
@@ -3297,9 +3234,14 @@ namespace OpenSim.Region.Framework.Scenes
3297 /// <param name="rot"></param> 3234 /// <param name="rot"></param>
3298 public void UpdateGroupRotationR(Quaternion rot) 3235 public void UpdateGroupRotationR(Quaternion rot)
3299 { 3236 {
3300 SceneObjectPart[] parts = m_parts.GetArray(); 3237// m_log.DebugFormat(
3301 for (int i = 0; i < parts.Length; i++) 3238// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
3302 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION); 3239
3240// SceneObjectPart[] parts = m_parts.GetArray();
3241// for (int i = 0; i < parts.Length; i++)
3242// parts[i].StoreUndoState();
3243
3244 m_rootPart.StoreUndoState(true);
3303 3245
3304 m_rootPart.UpdateRotation(rot); 3246 m_rootPart.UpdateRotation(rot);
3305 3247
@@ -3321,9 +3263,15 @@ namespace OpenSim.Region.Framework.Scenes
3321 /// <param name="rot"></param> 3263 /// <param name="rot"></param>
3322 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 3264 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
3323 { 3265 {
3324 SceneObjectPart[] parts = m_parts.GetArray(); 3266// m_log.DebugFormat(
3325 for (int i = 0; i < parts.Length; i++) 3267// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
3326 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION); 3268
3269// SceneObjectPart[] parts = m_parts.GetArray();
3270// for (int i = 0; i < parts.Length; i++)
3271// parts[i].StoreUndoState();
3272
3273 RootPart.StoreUndoState(true);
3274 RootPart.IgnoreUndoUpdate = true;
3327 3275
3328 m_rootPart.UpdateRotation(rot); 3276 m_rootPart.UpdateRotation(rot);
3329 3277
@@ -3338,6 +3286,8 @@ namespace OpenSim.Region.Framework.Scenes
3338 3286
3339 HasGroupChanged = true; 3287 HasGroupChanged = true;
3340 ScheduleGroupForTerseUpdate(); 3288 ScheduleGroupForTerseUpdate();
3289
3290 RootPart.IgnoreUndoUpdate = false;
3341 } 3291 }
3342 3292
3343 /// <summary> 3293 /// <summary>
@@ -3349,11 +3299,12 @@ namespace OpenSim.Region.Framework.Scenes
3349 { 3299 {
3350 SceneObjectPart part = GetChildPart(localID); 3300 SceneObjectPart part = GetChildPart(localID);
3351 SceneObjectPart[] parts = m_parts.GetArray(); 3301 SceneObjectPart[] parts = m_parts.GetArray();
3352 for (int i = 0; i < parts.Length; i++)
3353 parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3354 3302
3355 if (part != null) 3303 if (part != null)
3356 { 3304 {
3305// m_log.DebugFormat(
3306// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot);
3307
3357 if (part.UUID == m_rootPart.UUID) 3308 if (part.UUID == m_rootPart.UUID)
3358 { 3309 {
3359 UpdateRootRotation(rot); 3310 UpdateRootRotation(rot);
@@ -3375,6 +3326,13 @@ namespace OpenSim.Region.Framework.Scenes
3375 SceneObjectPart part = GetChildPart(localID); 3326 SceneObjectPart part = GetChildPart(localID);
3376 if (part != null) 3327 if (part != null)
3377 { 3328 {
3329// m_log.DebugFormat(
3330// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}",
3331// part.Name, part.LocalId, rot);
3332
3333 part.StoreUndoState();
3334 part.IgnoreUndoUpdate = true;
3335
3378 if (part.UUID == m_rootPart.UUID) 3336 if (part.UUID == m_rootPart.UUID)
3379 { 3337 {
3380 UpdateRootRotation(rot); 3338 UpdateRootRotation(rot);
@@ -3391,12 +3349,11 @@ namespace OpenSim.Region.Framework.Scenes
3391 } 3349 }
3392 else 3350 else
3393 { 3351 {
3394 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3395 part.IgnoreUndoUpdate = true;
3396 part.UpdateRotation(rot); 3352 part.UpdateRotation(rot);
3397 part.OffsetPosition = pos; 3353 part.OffsetPosition = pos;
3398 part.IgnoreUndoUpdate = false;
3399 } 3354 }
3355
3356 part.IgnoreUndoUpdate = false;
3400 } 3357 }
3401 } 3358 }
3402 3359
@@ -3404,18 +3361,15 @@ namespace OpenSim.Region.Framework.Scenes
3404 /// 3361 ///
3405 /// </summary> 3362 /// </summary>
3406 /// <param name="rot"></param> 3363 /// <param name="rot"></param>
3407 private void UpdateRootRotation(Quaternion rot) 3364 public void UpdateRootRotation(Quaternion rot)
3408 { 3365 {
3366// m_log.DebugFormat(
3367// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
3368// Name, LocalId, rot);
3369
3409 Quaternion axRot = rot; 3370 Quaternion axRot = rot;
3410 Quaternion oldParentRot = m_rootPart.RotationOffset; 3371 Quaternion oldParentRot = m_rootPart.RotationOffset;
3411 3372 m_rootPart.StoreUndoState();
3412 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3413 bool cancelUndo = false;
3414 if (!m_rootPart.Undoing)
3415 {
3416 m_rootPart.Undoing = true;
3417 cancelUndo = true;
3418 }
3419 3373
3420 //Don't use UpdateRotation because it schedules an update prematurely 3374 //Don't use UpdateRotation because it schedules an update prematurely
3421 m_rootPart.RotationOffset = rot; 3375 m_rootPart.RotationOffset = rot;
@@ -3444,14 +3398,25 @@ namespace OpenSim.Region.Framework.Scenes
3444 prim.OffsetPosition = axPos; 3398 prim.OffsetPosition = axPos;
3445 3399
3446 prim.IgnoreUndoUpdate = false; 3400 prim.IgnoreUndoUpdate = false;
3401 prim.IgnoreUndoUpdate = false;
3447 } 3402 }
3448 } 3403 }
3449 if (cancelUndo == true) 3404
3450 { 3405// for (int i = 0; i < parts.Length; i++)
3451 m_rootPart.Undoing = false; 3406// {
3452 } 3407// SceneObjectPart childpart = parts[i];
3408// if (childpart != m_rootPart)
3409// {
3410//// childpart.IgnoreUndoUpdate = false;
3411//// childpart.StoreUndoState();
3412// }
3413// }
3453 HasGroupChanged = true; 3414 HasGroupChanged = true;
3454 ScheduleGroupForFullUpdate(); 3415 ScheduleGroupForFullUpdate();
3416
3417// m_log.DebugFormat(
3418// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
3419// Name, LocalId, rot);
3455 } 3420 }
3456 3421
3457 #endregion 3422 #endregion
@@ -3466,28 +3431,23 @@ namespace OpenSim.Region.Framework.Scenes
3466 int yaxis = 4; 3431 int yaxis = 4;
3467 int zaxis = 8; 3432 int zaxis = 8;
3468 3433
3469 if (m_rootPart != null) 3434 setX = ((axis & xaxis) != 0) ? true : false;
3470 { 3435 setY = ((axis & yaxis) != 0) ? true : false;
3471 setX = ((axis & xaxis) != 0) ? true : false; 3436 setZ = ((axis & zaxis) != 0) ? true : false;
3472 setY = ((axis & yaxis) != 0) ? true : false;
3473 setZ = ((axis & zaxis) != 0) ? true : false;
3474
3475 float setval = (rotate10 > 0) ? 1f : 0f;
3476 3437
3477 if (setX) 3438 float setval = (rotate10 > 0) ? 1f : 0f;
3478 m_rootPart.RotationAxis.X = setval;
3479 if (setY)
3480 m_rootPart.RotationAxis.Y = setval;
3481 if (setZ)
3482 m_rootPart.RotationAxis.Z = setval;
3483 3439
3484 if (setX || setY || setZ) 3440 if (setX)
3485 { 3441 RootPart.RotationAxis.X = setval;
3486 m_rootPart.SetPhysicsAxisRotation(); 3442 if (setY)
3487 } 3443 RootPart.RotationAxis.Y = setval;
3444 if (setZ)
3445 RootPart.RotationAxis.Z = setval;
3488 3446
3489 } 3447 if (setX || setY || setZ)
3448 RootPart.SetPhysicsAxisRotation();
3490 } 3449 }
3450
3491 public int registerRotTargetWaypoint(Quaternion target, float tolerance) 3451 public int registerRotTargetWaypoint(Quaternion target, float tolerance)
3492 { 3452 {
3493 scriptRotTarget waypoint = new scriptRotTarget(); 3453 scriptRotTarget waypoint = new scriptRotTarget();
@@ -3615,7 +3575,13 @@ namespace OpenSim.Region.Framework.Scenes
3615 foreach (uint idx in m_rotTargets.Keys) 3575 foreach (uint idx in m_rotTargets.Keys)
3616 { 3576 {
3617 scriptRotTarget target = m_rotTargets[idx]; 3577 scriptRotTarget target = m_rotTargets[idx];
3618 double angle = Math.Acos(target.targetRot.X * m_rootPart.RotationOffset.X + target.targetRot.Y * m_rootPart.RotationOffset.Y + target.targetRot.Z * m_rootPart.RotationOffset.Z + target.targetRot.W * m_rootPart.RotationOffset.W) * 2; 3578 double angle
3579 = Math.Acos(
3580 target.targetRot.X * m_rootPart.RotationOffset.X
3581 + target.targetRot.Y * m_rootPart.RotationOffset.Y
3582 + target.targetRot.Z * m_rootPart.RotationOffset.Z
3583 + target.targetRot.W * m_rootPart.RotationOffset.W)
3584 * 2;
3619 if (angle < 0) angle = -angle; 3585 if (angle < 0) angle = -angle;
3620 if (angle > Math.PI) angle = (Math.PI * 2 - angle); 3586 if (angle > Math.PI) angle = (Math.PI * 2 - angle);
3621 if (angle <= target.tolerance) 3587 if (angle <= target.tolerance)
@@ -3680,43 +3646,28 @@ namespace OpenSim.Region.Framework.Scenes
3680 3646
3681 return retmass; 3647 return retmass;
3682 } 3648 }
3683 3649
3650 /// <summary>
3651 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that
3652 /// the physics engine can use it.
3653 /// </summary>
3654 /// <remarks>
3655 /// When the physics engine has finished with it, the sculpt data is discarded to save memory.
3656 /// </remarks>
3684 public void CheckSculptAndLoad() 3657 public void CheckSculptAndLoad()
3685 { 3658 {
3686 if (IsDeleted) 3659 if (IsDeleted)
3687 return; 3660 return;
3661
3688 if ((RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) 3662 if ((RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0)
3689 return; 3663 return;
3690 3664
3691 SceneObjectPart[] parts = m_parts.GetArray(); 3665// m_log.Debug("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
3692 for (int i = 0; i < parts.Length; i++)
3693 {
3694 SceneObjectPart part = parts[i];
3695 if (part.Shape.SculptEntry && part.Shape.SculptTexture != UUID.Zero)
3696 {
3697 // check if a previously decoded sculpt map has been cached
3698 if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + part.Shape.SculptTexture.ToString())))
3699 {
3700 part.SculptTextureCallback(part.Shape.SculptTexture, null);
3701 }
3702 else
3703 {
3704 m_scene.AssetService.Get(
3705 part.Shape.SculptTexture.ToString(), part, AssetReceived);
3706 }
3707 }
3708 }
3709 }
3710 3666
3711 protected void AssetReceived(string id, Object sender, AssetBase asset) 3667 SceneObjectPart[] parts = m_parts.GetArray();
3712 {
3713 SceneObjectPart sop = (SceneObjectPart)sender;
3714 3668
3715 if (sop != null) 3669 for (int i = 0; i < parts.Length; i++)
3716 { 3670 parts[i].CheckSculptAndLoad();
3717 if (asset != null)
3718 sop.SculptTextureCallback(asset.FullID, asset);
3719 }
3720 } 3671 }
3721 3672
3722 /// <summary> 3673 /// <summary>
@@ -3751,19 +3702,12 @@ namespace OpenSim.Region.Framework.Scenes
3751 return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition); 3702 return String.Format("{0} {1} ({2})", Name, UUID, AbsolutePosition);
3752 } 3703 }
3753 3704
3754 public void SetAttachmentPoint(byte point)
3755 {
3756 SceneObjectPart[] parts = m_parts.GetArray();
3757 for (int i = 0; i < parts.Length; i++)
3758 parts[i].SetAttachmentPoint(point);
3759 }
3760
3761 #region ISceneObject 3705 #region ISceneObject
3762 3706
3763 public virtual ISceneObject CloneForNewScene() 3707 public virtual ISceneObject CloneForNewScene()
3764 { 3708 {
3765 SceneObjectGroup sog = Copy(false); 3709 SceneObjectGroup sog = Copy(false);
3766 sog.m_isDeleted = false; 3710 sog.IsDeleted = false;
3767 return sog; 3711 return sog;
3768 } 3712 }
3769 3713