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.cs1176
1 files changed, 975 insertions, 201 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index afb5ccf..90ad098 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -24,11 +24,12 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Drawing; 30using System.Drawing;
31using System.IO; 31using System.IO;
32using System.Diagnostics;
32using System.Linq; 33using System.Linq;
33using System.Threading; 34using System.Threading;
34using System.Xml; 35using System.Xml;
@@ -42,6 +43,7 @@ using OpenSim.Region.Framework.Scenes.Serialization;
42 43
43namespace OpenSim.Region.Framework.Scenes 44namespace OpenSim.Region.Framework.Scenes
44{ 45{
46
45 [Flags] 47 [Flags]
46 public enum scriptEvents 48 public enum scriptEvents
47 { 49 {
@@ -105,8 +107,29 @@ namespace OpenSim.Region.Framework.Scenes
105 /// since the group's last persistent backup 107 /// since the group's last persistent backup
106 /// </summary> 108 /// </summary>
107 private bool m_hasGroupChanged = false; 109 private bool m_hasGroupChanged = false;
108 private long timeFirstChanged; 110 private long timeFirstChanged = 0;
109 private long timeLastChanged; 111 private long timeLastChanged = 0;
112 private long m_maxPersistTime = 0;
113 private long m_minPersistTime = 0;
114 private Random m_rand;
115 private bool m_suspendUpdates;
116 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
117
118 public bool areUpdatesSuspended
119 {
120 get
121 {
122 return m_suspendUpdates;
123 }
124 set
125 {
126 m_suspendUpdates = value;
127 if (!value)
128 {
129 QueueForUpdateCheck();
130 }
131 }
132 }
110 133
111 public bool HasGroupChanged 134 public bool HasGroupChanged
112 { 135 {
@@ -114,9 +137,39 @@ namespace OpenSim.Region.Framework.Scenes
114 { 137 {
115 if (value) 138 if (value)
116 { 139 {
140 if (m_isBackedUp)
141 {
142 m_scene.SceneGraph.FireChangeBackup(this);
143 }
117 timeLastChanged = DateTime.Now.Ticks; 144 timeLastChanged = DateTime.Now.Ticks;
118 if (!m_hasGroupChanged) 145 if (!m_hasGroupChanged)
119 timeFirstChanged = DateTime.Now.Ticks; 146 timeFirstChanged = DateTime.Now.Ticks;
147 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
148 {
149 if (m_rand == null)
150 {
151 byte[] val = new byte[16];
152 m_rootPart.UUID.ToBytes(val, 0);
153 m_rand = new Random(BitConverter.ToInt32(val, 0));
154 }
155
156 if (m_scene.GetRootAgentCount() == 0)
157 {
158 //If the region is empty, this change has been made by an automated process
159 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
160
161 float factor = 1.5f + (float)(m_rand.NextDouble());
162 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
163 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
164 }
165 else
166 {
167 //If the region is not empty, we want to obey the minimum and maximum persist times
168 //but add a random factor so we stagger the object persistance a little
169 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
170 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
171 }
172 }
120 } 173 }
121 m_hasGroupChanged = value; 174 m_hasGroupChanged = value;
122 175
@@ -131,7 +184,7 @@ namespace OpenSim.Region.Framework.Scenes
131 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since 184 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since
132 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation. 185 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation.
133 /// </summary> 186 /// </summary>
134 public bool HasGroupChangedDueToDelink { get; private set; } 187 public bool HasGroupChangedDueToDelink { get; set; }
135 188
136 private bool isTimeToPersist() 189 private bool isTimeToPersist()
137 { 190 {
@@ -141,8 +194,19 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 194 return false;
142 if (m_scene.ShuttingDown) 195 if (m_scene.ShuttingDown)
143 return true; 196 return true;
197
198 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
199 {
200 m_maxPersistTime = m_scene.m_persistAfter;
201 m_minPersistTime = m_scene.m_dontPersistBefore;
202 }
203
144 long currentTime = DateTime.Now.Ticks; 204 long currentTime = DateTime.Now.Ticks;
145 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 205
206 if (timeLastChanged == 0) timeLastChanged = currentTime;
207 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
208
209 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
146 return true; 210 return true;
147 return false; 211 return false;
148 } 212 }
@@ -245,10 +309,10 @@ namespace OpenSim.Region.Framework.Scenes
245 309
246 private bool m_scriptListens_atTarget; 310 private bool m_scriptListens_atTarget;
247 private bool m_scriptListens_notAtTarget; 311 private bool m_scriptListens_notAtTarget;
248
249 private bool m_scriptListens_atRotTarget; 312 private bool m_scriptListens_atRotTarget;
250 private bool m_scriptListens_notAtRotTarget; 313 private bool m_scriptListens_notAtRotTarget;
251 314
315 public bool m_dupeInProgress = false;
252 internal Dictionary<UUID, string> m_savedScriptState; 316 internal Dictionary<UUID, string> m_savedScriptState;
253 317
254 #region Properties 318 #region Properties
@@ -285,6 +349,16 @@ namespace OpenSim.Region.Framework.Scenes
285 get { return m_parts.Count; } 349 get { return m_parts.Count; }
286 } 350 }
287 351
352// protected Quaternion m_rotation = Quaternion.Identity;
353//
354// public virtual Quaternion Rotation
355// {
356// get { return m_rotation; }
357// set {
358// m_rotation = value;
359// }
360// }
361
288 public Quaternion GroupRotation 362 public Quaternion GroupRotation
289 { 363 {
290 get { return m_rootPart.RotationOffset; } 364 get { return m_rootPart.RotationOffset; }
@@ -386,14 +460,99 @@ namespace OpenSim.Region.Framework.Scenes
386 460
387 if (Scene != null) 461 if (Scene != null)
388 { 462 {
389 if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) 463 // if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
390 || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) 464 // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
465 // && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
466 if ((Scene.TestBorderCross(val, Cardinals.E) || Scene.TestBorderCross(val, Cardinals.W)
467 || Scene.TestBorderCross(val, Cardinals.N) || Scene.TestBorderCross(val, Cardinals.S))
391 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 468 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
392 { 469 {
393 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 470 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
471 uint x = 0;
472 uint y = 0;
473 string version = String.Empty;
474 Vector3 newpos = Vector3.Zero;
475 OpenSim.Services.Interfaces.GridRegion destination = null;
476
477 bool canCross = true;
478 foreach (ScenePresence av in m_linkedAvatars)
479 {
480 // We need to cross these agents. First, let's find
481 // out if any of them can't cross for some reason.
482 // We have to deny the crossing entirely if any
483 // of them are banned. Alternatively, we could
484 // unsit banned agents....
485
486
487 // We set the avatar position as being the object
488 // position to get the region to send to
489 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null)
490 {
491 canCross = false;
492 break;
493 }
494
495 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
496 }
497
498 if (canCross)
499 {
500 // We unparent the SP quietly so that it won't
501 // be made to stand up
502 foreach (ScenePresence av in m_linkedAvatars)
503 {
504 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
505 if (parentPart != null)
506 av.ParentUUID = parentPart.UUID;
507
508 av.ParentID = 0;
509 }
510
511 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
512
513 // Normalize
514 if (val.X >= Constants.RegionSize)
515 val.X -= Constants.RegionSize;
516 if (val.Y >= Constants.RegionSize)
517 val.Y -= Constants.RegionSize;
518 if (val.X < 0)
519 val.X += Constants.RegionSize;
520 if (val.Y < 0)
521 val.Y += Constants.RegionSize;
522
523 // If it's deleted, crossing was successful
524 if (IsDeleted)
525 {
526 foreach (ScenePresence av in m_linkedAvatars)
527 {
528 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
529
530 av.IsInTransit = true;
531
532 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
533 d.BeginInvoke(av, val, x, y, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
534 }
535
536 return;
537 }
538 }
539 else if (RootPart.PhysActor != null)
540 {
541 RootPart.PhysActor.CrossingFailure();
542 }
543
544 Vector3 oldp = AbsolutePosition;
545 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
546 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
547 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
394 } 548 }
395 } 549 }
396 550/* don't see the need but worse don't see where is restored to false if things stay in
551 foreach (SceneObjectPart part in m_parts.GetArray())
552 {
553 part.IgnoreUndoUpdate = true;
554 }
555 */
397 if (RootPart.GetStatusSandbox()) 556 if (RootPart.GetStatusSandbox())
398 { 557 {
399 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 558 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -407,10 +566,30 @@ namespace OpenSim.Region.Framework.Scenes
407 return; 566 return;
408 } 567 }
409 } 568 }
410
411 SceneObjectPart[] parts = m_parts.GetArray(); 569 SceneObjectPart[] parts = m_parts.GetArray();
412 for (int i = 0; i < parts.Length; i++) 570 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
413 parts[i].GroupPosition = val; 571 if (m_dupeInProgress)
572 triggerScriptEvent = false;
573 foreach (SceneObjectPart part in parts)
574 {
575 part.GroupPosition = val;
576 if (triggerScriptEvent)
577 part.TriggerScriptChangedEvent(Changed.POSITION);
578 }
579 if (!m_dupeInProgress)
580 {
581 foreach (ScenePresence av in m_linkedAvatars)
582 {
583 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
584 if (p != null && m_parts.TryGetValue(p.UUID, out p))
585 {
586 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
587 av.AbsolutePosition += offset;
588 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
589 av.SendAvatarDataToAllAgents();
590 }
591 }
592 }
414 593
415 //if (m_rootPart.PhysActor != null) 594 //if (m_rootPart.PhysActor != null)
416 //{ 595 //{
@@ -425,6 +604,29 @@ namespace OpenSim.Region.Framework.Scenes
425 } 604 }
426 } 605 }
427 606
607 public override Vector3 Velocity
608 {
609 get { return RootPart.Velocity; }
610 set { RootPart.Velocity = value; }
611 }
612
613 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
614 {
615 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
616 ScenePresence agent = icon.EndInvoke(iar);
617
618 //// If the cross was successful, this agent is a child agent
619 //if (agent.IsChildAgent)
620 // agent.Reset();
621 //else // Not successful
622 // agent.RestoreInCurrentScene();
623
624 // In any case
625 agent.IsInTransit = false;
626
627 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
628 }
629
428 public override uint LocalId 630 public override uint LocalId
429 { 631 {
430 get { return m_rootPart.LocalId; } 632 get { return m_rootPart.LocalId; }
@@ -517,6 +719,8 @@ namespace OpenSim.Region.Framework.Scenes
517 child.PhysActor.Selected = value; 719 child.PhysActor.Selected = value;
518 } 720 }
519 } 721 }
722 if (RootPart.KeyframeMotion != null)
723 RootPart.KeyframeMotion.Selected = value;
520 } 724 }
521 } 725 }
522 726
@@ -576,6 +780,7 @@ namespace OpenSim.Region.Framework.Scenes
576 /// </summary> 780 /// </summary>
577 public SceneObjectGroup() 781 public SceneObjectGroup()
578 { 782 {
783
579 } 784 }
580 785
581 /// <summary> 786 /// <summary>
@@ -592,7 +797,7 @@ namespace OpenSim.Region.Framework.Scenes
592 /// Constructor. This object is added to the scene later via AttachToScene() 797 /// Constructor. This object is added to the scene later via AttachToScene()
593 /// </summary> 798 /// </summary>
594 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 799 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
595 { 800 {
596 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 801 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
597 } 802 }
598 803
@@ -640,6 +845,9 @@ namespace OpenSim.Region.Framework.Scenes
640 /// </summary> 845 /// </summary>
641 public virtual void AttachToBackup() 846 public virtual void AttachToBackup()
642 { 847 {
848 if (IsAttachment) return;
849 m_scene.SceneGraph.FireAttachToBackup(this);
850
643 if (InSceneBackup) 851 if (InSceneBackup)
644 { 852 {
645 //m_log.DebugFormat( 853 //m_log.DebugFormat(
@@ -682,6 +890,13 @@ namespace OpenSim.Region.Framework.Scenes
682 890
683 ApplyPhysics(); 891 ApplyPhysics();
684 892
893 if (RootPart.PhysActor != null)
894 RootPart.Force = RootPart.Force;
895 if (RootPart.PhysActor != null)
896 RootPart.Torque = RootPart.Torque;
897 if (RootPart.PhysActor != null)
898 RootPart.Buoyancy = RootPart.Buoyancy;
899
685 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 900 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
686 // for the same object with very different properties. The caller must schedule the update. 901 // for the same object with very different properties. The caller must schedule the update.
687 //ScheduleGroupForFullUpdate(); 902 //ScheduleGroupForFullUpdate();
@@ -697,6 +912,10 @@ namespace OpenSim.Region.Framework.Scenes
697 EntityIntersection result = new EntityIntersection(); 912 EntityIntersection result = new EntityIntersection();
698 913
699 SceneObjectPart[] parts = m_parts.GetArray(); 914 SceneObjectPart[] parts = m_parts.GetArray();
915
916 // Find closest hit here
917 float idist = float.MaxValue;
918
700 for (int i = 0; i < parts.Length; i++) 919 for (int i = 0; i < parts.Length; i++)
701 { 920 {
702 SceneObjectPart part = parts[i]; 921 SceneObjectPart part = parts[i];
@@ -711,11 +930,6 @@ namespace OpenSim.Region.Framework.Scenes
711 930
712 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 931 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
713 932
714 // This may need to be updated to the maximum draw distance possible..
715 // We might (and probably will) be checking for prim creation from other sims
716 // when the camera crosses the border.
717 float idist = Constants.RegionSize;
718
719 if (inter.HitTF) 933 if (inter.HitTF)
720 { 934 {
721 // We need to find the closest prim to return to the testcaller along the ray 935 // We need to find the closest prim to return to the testcaller along the ray
@@ -726,10 +940,11 @@ namespace OpenSim.Region.Framework.Scenes
726 result.obj = part; 940 result.obj = part;
727 result.normal = inter.normal; 941 result.normal = inter.normal;
728 result.distance = inter.distance; 942 result.distance = inter.distance;
943
944 idist = inter.distance;
729 } 945 }
730 } 946 }
731 } 947 }
732
733 return result; 948 return result;
734 } 949 }
735 950
@@ -741,25 +956,27 @@ namespace OpenSim.Region.Framework.Scenes
741 /// <returns></returns> 956 /// <returns></returns>
742 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 957 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
743 { 958 {
744 maxX = -256f; 959 maxX = float.MinValue;
745 maxY = -256f; 960 maxY = float.MinValue;
746 maxZ = -256f; 961 maxZ = float.MinValue;
747 minX = 256f; 962 minX = float.MaxValue;
748 minY = 256f; 963 minY = float.MaxValue;
749 minZ = 8192f; 964 minZ = float.MaxValue;
750 965
751 SceneObjectPart[] parts = m_parts.GetArray(); 966 SceneObjectPart[] parts = m_parts.GetArray();
752 for (int i = 0; i < parts.Length; i++) 967 foreach (SceneObjectPart part in parts)
753 { 968 {
754 SceneObjectPart part = parts[i];
755
756 Vector3 worldPos = part.GetWorldPosition(); 969 Vector3 worldPos = part.GetWorldPosition();
757 Vector3 offset = worldPos - AbsolutePosition; 970 Vector3 offset = worldPos - AbsolutePosition;
758 Quaternion worldRot; 971 Quaternion worldRot;
759 if (part.ParentID == 0) 972 if (part.ParentID == 0)
973 {
760 worldRot = part.RotationOffset; 974 worldRot = part.RotationOffset;
975 }
761 else 976 else
977 {
762 worldRot = part.GetWorldRotation(); 978 worldRot = part.GetWorldRotation();
979 }
763 980
764 Vector3 frontTopLeft; 981 Vector3 frontTopLeft;
765 Vector3 frontTopRight; 982 Vector3 frontTopRight;
@@ -771,6 +988,8 @@ namespace OpenSim.Region.Framework.Scenes
771 Vector3 backBottomLeft; 988 Vector3 backBottomLeft;
772 Vector3 backBottomRight; 989 Vector3 backBottomRight;
773 990
991 // Vector3[] corners = new Vector3[8];
992
774 Vector3 orig = Vector3.Zero; 993 Vector3 orig = Vector3.Zero;
775 994
776 frontTopLeft.X = orig.X - (part.Scale.X / 2); 995 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -805,6 +1024,38 @@ namespace OpenSim.Region.Framework.Scenes
805 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1024 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
806 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1025 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
807 1026
1027
1028
1029 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1030 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1031 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1032 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1033 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1034 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1035 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1036 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1037
1038 //for (int i = 0; i < 8; i++)
1039 //{
1040 // corners[i] = corners[i] * worldRot;
1041 // corners[i] += offset;
1042
1043 // if (corners[i].X > maxX)
1044 // maxX = corners[i].X;
1045 // if (corners[i].X < minX)
1046 // minX = corners[i].X;
1047
1048 // if (corners[i].Y > maxY)
1049 // maxY = corners[i].Y;
1050 // if (corners[i].Y < minY)
1051 // minY = corners[i].Y;
1052
1053 // if (corners[i].Z > maxZ)
1054 // maxZ = corners[i].Y;
1055 // if (corners[i].Z < minZ)
1056 // minZ = corners[i].Z;
1057 //}
1058
808 frontTopLeft = frontTopLeft * worldRot; 1059 frontTopLeft = frontTopLeft * worldRot;
809 frontTopRight = frontTopRight * worldRot; 1060 frontTopRight = frontTopRight * worldRot;
810 frontBottomLeft = frontBottomLeft * worldRot; 1061 frontBottomLeft = frontBottomLeft * worldRot;
@@ -826,6 +1077,15 @@ namespace OpenSim.Region.Framework.Scenes
826 backTopLeft += offset; 1077 backTopLeft += offset;
827 backTopRight += offset; 1078 backTopRight += offset;
828 1079
1080 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1081 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1082 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1083 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1084 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1085 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1086 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1087 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1088
829 if (frontTopRight.X > maxX) 1089 if (frontTopRight.X > maxX)
830 maxX = frontTopRight.X; 1090 maxX = frontTopRight.X;
831 if (frontTopLeft.X > maxX) 1091 if (frontTopLeft.X > maxX)
@@ -969,17 +1229,118 @@ namespace OpenSim.Region.Framework.Scenes
969 1229
970 #endregion 1230 #endregion
971 1231
1232 public void GetResourcesCosts(SceneObjectPart apart,
1233 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost)
1234 {
1235 // this information may need to be cached
1236
1237 float cost;
1238 float tmpcost;
1239
1240 bool ComplexCost = false;
1241
1242 SceneObjectPart p;
1243 SceneObjectPart[] parts;
1244
1245 lock (m_parts)
1246 {
1247 parts = m_parts.GetArray();
1248 }
1249
1250 int nparts = parts.Length;
1251
1252
1253 for (int i = 0; i < nparts; i++)
1254 {
1255 p = parts[i];
1256
1257 if (p.UsesComplexCost)
1258 {
1259 ComplexCost = true;
1260 break;
1261 }
1262 }
1263
1264 if (ComplexCost)
1265 {
1266 linksetResCost = 0;
1267 linksetPhysCost = 0;
1268 partCost = 0;
1269 partPhysCost = 0;
1270
1271 for (int i = 0; i < nparts; i++)
1272 {
1273 p = parts[i];
1274
1275 cost = p.StreamingCost;
1276 tmpcost = p.SimulationCost;
1277 if (tmpcost > cost)
1278 cost = tmpcost;
1279 tmpcost = p.PhysicsCost;
1280 if (tmpcost > cost)
1281 cost = tmpcost;
1282
1283 linksetPhysCost += tmpcost;
1284 linksetResCost += cost;
1285
1286 if (p == apart)
1287 {
1288 partCost = cost;
1289 partPhysCost = tmpcost;
1290 }
1291 }
1292 }
1293 else
1294 {
1295 partPhysCost = 1.0f;
1296 partCost = 1.0f;
1297 linksetResCost = (float)nparts;
1298 linksetPhysCost = linksetResCost;
1299 }
1300 }
1301
1302 public void GetSelectedCosts(out float PhysCost, out float StreamCost, out float SimulCost)
1303 {
1304 SceneObjectPart p;
1305 SceneObjectPart[] parts;
1306
1307 lock (m_parts)
1308 {
1309 parts = m_parts.GetArray();
1310 }
1311
1312 int nparts = parts.Length;
1313
1314 PhysCost = 0;
1315 StreamCost = 0;
1316 SimulCost = 0;
1317
1318 for (int i = 0; i < nparts; i++)
1319 {
1320 p = parts[i];
1321
1322 StreamCost += p.StreamingCost;
1323 SimulCost += p.SimulationCost;
1324 PhysCost += p.PhysicsCost;
1325 }
1326 }
1327
972 public void SaveScriptedState(XmlTextWriter writer) 1328 public void SaveScriptedState(XmlTextWriter writer)
973 { 1329 {
1330 SaveScriptedState(writer, false);
1331 }
1332
1333 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1334 {
974 XmlDocument doc = new XmlDocument(); 1335 XmlDocument doc = new XmlDocument();
975 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1336 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
976 1337
977 SceneObjectPart[] parts = m_parts.GetArray(); 1338 SceneObjectPart[] parts = m_parts.GetArray();
978 for (int i = 0; i < parts.Length; i++) 1339 for (int i = 0; i < parts.Length; i++)
979 { 1340 {
980 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1341 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
981 foreach (KeyValuePair<UUID, string> kvp in pstates) 1342 foreach (KeyValuePair<UUID, string> kvp in pstates)
982 states.Add(kvp.Key, kvp.Value); 1343 states[kvp.Key] = kvp.Value;
983 } 1344 }
984 1345
985 if (states.Count > 0) 1346 if (states.Count > 0)
@@ -999,6 +1360,169 @@ namespace OpenSim.Region.Framework.Scenes
999 } 1360 }
1000 1361
1001 /// <summary> 1362 /// <summary>
1363 /// Add the avatar to this linkset (avatar is sat).
1364 /// </summary>
1365 /// <param name="agentID"></param>
1366 public void AddAvatar(UUID agentID)
1367 {
1368 ScenePresence presence;
1369 if (m_scene.TryGetScenePresence(agentID, out presence))
1370 {
1371 if (!m_linkedAvatars.Contains(presence))
1372 {
1373 m_linkedAvatars.Add(presence);
1374 }
1375 }
1376 }
1377
1378 /// <summary>
1379 /// Delete the avatar from this linkset (avatar is unsat).
1380 /// </summary>
1381 /// <param name="agentID"></param>
1382 public void DeleteAvatar(UUID agentID)
1383 {
1384 ScenePresence presence;
1385 if (m_scene.TryGetScenePresence(agentID, out presence))
1386 {
1387 if (m_linkedAvatars.Contains(presence))
1388 {
1389 m_linkedAvatars.Remove(presence);
1390 }
1391 }
1392 }
1393
1394 /// <summary>
1395 /// Returns the list of linked presences (avatars sat on this group)
1396 /// </summary>
1397 /// <param name="agentID"></param>
1398 public List<ScenePresence> GetLinkedAvatars()
1399 {
1400 return m_linkedAvatars;
1401 }
1402
1403 /// <summary>
1404 /// Attach this scene object to the given avatar.
1405 /// </summary>
1406 /// <param name="agentID"></param>
1407 /// <param name="attachmentpoint"></param>
1408 /// <param name="AttachOffset"></param>
1409 private void AttachToAgent(
1410 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1411 {
1412 if (avatar != null)
1413 {
1414 // don't attach attachments to child agents
1415 if (avatar.IsChildAgent) return;
1416
1417 // Remove from database and parcel prim count
1418 m_scene.DeleteFromStorage(so.UUID);
1419 m_scene.EventManager.TriggerParcelPrimCountTainted();
1420
1421 so.AttachedAvatar = avatar.UUID;
1422
1423 if (so.RootPart.PhysActor != null)
1424 {
1425 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1426 so.RootPart.PhysActor = null;
1427 }
1428
1429 so.AbsolutePosition = attachOffset;
1430 so.RootPart.AttachedPos = attachOffset;
1431 so.IsAttachment = true;
1432 so.RootPart.SetParentLocalId(avatar.LocalId);
1433 so.AttachmentPoint = attachmentpoint;
1434
1435 avatar.AddAttachment(this);
1436
1437 if (!silent)
1438 {
1439 // Killing it here will cause the client to deselect it
1440 // It then reappears on the avatar, deselected
1441 // through the full update below
1442 //
1443 if (IsSelected)
1444 {
1445 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1446 }
1447
1448 IsSelected = false; // fudge....
1449 ScheduleGroupForFullUpdate();
1450 }
1451 }
1452 else
1453 {
1454 m_log.WarnFormat(
1455 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1456 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1457 }
1458 }
1459
1460 public byte GetAttachmentPoint()
1461 {
1462 return m_rootPart.Shape.State;
1463 }
1464
1465 public void DetachToGround()
1466 {
1467 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1468 if (avatar == null)
1469 return;
1470
1471 avatar.RemoveAttachment(this);
1472
1473 Vector3 detachedpos = new Vector3(127f,127f,127f);
1474 if (avatar == null)
1475 return;
1476
1477 detachedpos = avatar.AbsolutePosition;
1478 RootPart.FromItemID = UUID.Zero;
1479
1480 AbsolutePosition = detachedpos;
1481 AttachedAvatar = UUID.Zero;
1482
1483 //SceneObjectPart[] parts = m_parts.GetArray();
1484 //for (int i = 0; i < parts.Length; i++)
1485 // parts[i].AttachedAvatar = UUID.Zero;
1486
1487 m_rootPart.SetParentLocalId(0);
1488 AttachmentPoint = (byte)0;
1489 // must check if buildind should be true or false here
1490 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1491 HasGroupChanged = true;
1492 RootPart.Rezzed = DateTime.Now;
1493 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1494 AttachToBackup();
1495 m_scene.EventManager.TriggerParcelPrimCountTainted();
1496 m_rootPart.ScheduleFullUpdate();
1497 m_rootPart.ClearUndoState();
1498 }
1499
1500 public void DetachToInventoryPrep()
1501 {
1502 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1503 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1504 if (avatar != null)
1505 {
1506 //detachedpos = avatar.AbsolutePosition;
1507 avatar.RemoveAttachment(this);
1508 }
1509
1510 AttachedAvatar = UUID.Zero;
1511
1512 /*SceneObjectPart[] parts = m_parts.GetArray();
1513 for (int i = 0; i < parts.Length; i++)
1514 parts[i].AttachedAvatar = UUID.Zero;*/
1515
1516 m_rootPart.SetParentLocalId(0);
1517 //m_rootPart.SetAttachmentPoint((byte)0);
1518 IsAttachment = false;
1519 AbsolutePosition = m_rootPart.AttachedPos;
1520 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1521 //AttachToBackup();
1522 //m_rootPart.ScheduleFullUpdate();
1523 }
1524
1525 /// <summary>
1002 /// 1526 ///
1003 /// </summary> 1527 /// </summary>
1004 /// <param name="part"></param> 1528 /// <param name="part"></param>
@@ -1048,7 +1572,10 @@ namespace OpenSim.Region.Framework.Scenes
1048 public void AddPart(SceneObjectPart part) 1572 public void AddPart(SceneObjectPart part)
1049 { 1573 {
1050 part.SetParent(this); 1574 part.SetParent(this);
1051 part.LinkNum = m_parts.Add(part.UUID, part); 1575 m_parts.Add(part.UUID, part);
1576
1577 part.LinkNum = m_parts.Count;
1578
1052 if (part.LinkNum == 2) 1579 if (part.LinkNum == 2)
1053 RootPart.LinkNum = 1; 1580 RootPart.LinkNum = 1;
1054 } 1581 }
@@ -1136,7 +1663,7 @@ namespace OpenSim.Region.Framework.Scenes
1136// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 1663// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1137// remoteClient.Name, part.Name, part.LocalId, offsetPos); 1664// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1138 1665
1139 part.StoreUndoState(); 1666// part.StoreUndoState();
1140 part.OnGrab(offsetPos, remoteClient); 1667 part.OnGrab(offsetPos, remoteClient);
1141 } 1668 }
1142 1669
@@ -1156,6 +1683,11 @@ namespace OpenSim.Region.Framework.Scenes
1156 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1683 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1157 public void DeleteGroupFromScene(bool silent) 1684 public void DeleteGroupFromScene(bool silent)
1158 { 1685 {
1686 // We need to keep track of this state in case this group is still queued for backup.
1687 IsDeleted = true;
1688
1689 DetachFromBackup();
1690
1159 SceneObjectPart[] parts = m_parts.GetArray(); 1691 SceneObjectPart[] parts = m_parts.GetArray();
1160 for (int i = 0; i < parts.Length; i++) 1692 for (int i = 0; i < parts.Length; i++)
1161 { 1693 {
@@ -1178,6 +1710,8 @@ namespace OpenSim.Region.Framework.Scenes
1178 } 1710 }
1179 }); 1711 });
1180 } 1712 }
1713
1714
1181 } 1715 }
1182 1716
1183 public void AddScriptLPS(int count) 1717 public void AddScriptLPS(int count)
@@ -1247,28 +1781,43 @@ namespace OpenSim.Region.Framework.Scenes
1247 /// </summary> 1781 /// </summary>
1248 public void ApplyPhysics() 1782 public void ApplyPhysics()
1249 { 1783 {
1250 // Apply physics to the root prim
1251 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1252
1253 // Apply physics to child prims
1254 SceneObjectPart[] parts = m_parts.GetArray(); 1784 SceneObjectPart[] parts = m_parts.GetArray();
1255 if (parts.Length > 1) 1785 if (parts.Length > 1)
1256 { 1786 {
1787 ResetChildPrimPhysicsPositions();
1788
1789 // Apply physics to the root prim
1790 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
1791
1792
1257 for (int i = 0; i < parts.Length; i++) 1793 for (int i = 0; i < parts.Length; i++)
1258 { 1794 {
1259 SceneObjectPart part = parts[i]; 1795 SceneObjectPart part = parts[i];
1260 if (part.LocalId != m_rootPart.LocalId) 1796 if (part.LocalId != m_rootPart.LocalId)
1261 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 1797 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1262 } 1798 }
1263
1264 // Hack to get the physics scene geometries in the right spot 1799 // Hack to get the physics scene geometries in the right spot
1265 ResetChildPrimPhysicsPositions(); 1800// ResetChildPrimPhysicsPositions();
1801 if (m_rootPart.PhysActor != null)
1802 {
1803 m_rootPart.PhysActor.Building = false;
1804 }
1805 }
1806 else
1807 {
1808 // Apply physics to the root prim
1809 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1266 } 1810 }
1267 } 1811 }
1268 1812
1269 public void SetOwnerId(UUID userId) 1813 public void SetOwnerId(UUID userId)
1270 { 1814 {
1271 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1815 ForEachPart(delegate(SceneObjectPart part)
1816 {
1817
1818 part.OwnerID = userId;
1819
1820 });
1272 } 1821 }
1273 1822
1274 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1823 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1300,11 +1849,17 @@ namespace OpenSim.Region.Framework.Scenes
1300 return; 1849 return;
1301 } 1850 }
1302 1851
1852 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1853 return;
1854
1303 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1855 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1304 // any exception propogate upwards. 1856 // any exception propogate upwards.
1305 try 1857 try
1306 { 1858 {
1307 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1859 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1860 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1861 m_scene.LoadingPrims) // Land may not be valid yet
1862
1308 { 1863 {
1309 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1864 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1310 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1865 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1331,6 +1886,7 @@ namespace OpenSim.Region.Framework.Scenes
1331 } 1886 }
1332 } 1887 }
1333 } 1888 }
1889
1334 } 1890 }
1335 1891
1336 if (m_scene.UseBackup && HasGroupChanged) 1892 if (m_scene.UseBackup && HasGroupChanged)
@@ -1338,6 +1894,20 @@ namespace OpenSim.Region.Framework.Scenes
1338 // don't backup while it's selected or you're asking for changes mid stream. 1894 // don't backup while it's selected or you're asking for changes mid stream.
1339 if (isTimeToPersist() || forcedBackup) 1895 if (isTimeToPersist() || forcedBackup)
1340 { 1896 {
1897 if (m_rootPart.PhysActor != null &&
1898 (!m_rootPart.PhysActor.IsPhysical))
1899 {
1900 // Possible ghost prim
1901 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1902 {
1903 foreach (SceneObjectPart part in m_parts.GetArray())
1904 {
1905 // Re-set physics actor positions and
1906 // orientations
1907 part.GroupPosition = m_rootPart.GroupPosition;
1908 }
1909 }
1910 }
1341// m_log.DebugFormat( 1911// m_log.DebugFormat(
1342// "[SCENE]: Storing {0}, {1} in {2}", 1912// "[SCENE]: Storing {0}, {1} in {2}",
1343// Name, UUID, m_scene.RegionInfo.RegionName); 1913// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1355,6 +1925,11 @@ namespace OpenSim.Region.Framework.Scenes
1355 1925
1356 backup_group.ForEachPart(delegate(SceneObjectPart part) 1926 backup_group.ForEachPart(delegate(SceneObjectPart part)
1357 { 1927 {
1928 if (part.KeyframeMotion != null)
1929 {
1930 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize());
1931 part.KeyframeMotion.UpdateSceneObject(this);
1932 }
1358 part.Inventory.ProcessInventoryBackup(datastore); 1933 part.Inventory.ProcessInventoryBackup(datastore);
1359 }); 1934 });
1360 1935
@@ -1407,6 +1982,7 @@ namespace OpenSim.Region.Framework.Scenes
1407 /// <returns></returns> 1982 /// <returns></returns>
1408 public SceneObjectGroup Copy(bool userExposed) 1983 public SceneObjectGroup Copy(bool userExposed)
1409 { 1984 {
1985 m_dupeInProgress = true;
1410 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1986 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1411 dupe.m_isBackedUp = false; 1987 dupe.m_isBackedUp = false;
1412 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 1988 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
@@ -1421,7 +1997,7 @@ namespace OpenSim.Region.Framework.Scenes
1421 // This is only necessary when userExposed is false! 1997 // This is only necessary when userExposed is false!
1422 1998
1423 bool previousAttachmentStatus = dupe.IsAttachment; 1999 bool previousAttachmentStatus = dupe.IsAttachment;
1424 2000
1425 if (!userExposed) 2001 if (!userExposed)
1426 dupe.IsAttachment = true; 2002 dupe.IsAttachment = true;
1427 2003
@@ -1439,11 +2015,11 @@ namespace OpenSim.Region.Framework.Scenes
1439 dupe.m_rootPart.TrimPermissions(); 2015 dupe.m_rootPart.TrimPermissions();
1440 2016
1441 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 2017 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1442 2018
1443 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 2019 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1444 { 2020 {
1445 return p1.LinkNum.CompareTo(p2.LinkNum); 2021 return p1.LinkNum.CompareTo(p2.LinkNum);
1446 } 2022 }
1447 ); 2023 );
1448 2024
1449 foreach (SceneObjectPart part in partList) 2025 foreach (SceneObjectPart part in partList)
@@ -1453,40 +2029,53 @@ namespace OpenSim.Region.Framework.Scenes
1453 { 2029 {
1454 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2030 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1455 newPart.LinkNum = part.LinkNum; 2031 newPart.LinkNum = part.LinkNum;
1456 } 2032 if (userExposed)
2033 newPart.ParentID = dupe.m_rootPart.LocalId;
2034 }
1457 else 2035 else
1458 { 2036 {
1459 newPart = dupe.m_rootPart; 2037 newPart = dupe.m_rootPart;
1460 } 2038 }
2039/*
2040 bool isphys = ((newPart.Flags & PrimFlags.Physics) != 0);
2041 bool isphan = ((newPart.Flags & PrimFlags.Phantom) != 0);
1461 2042
1462 // Need to duplicate the physics actor as well 2043 // Need to duplicate the physics actor as well
1463 if (part.PhysActor != null && userExposed) 2044 if (userExposed && (isphys || !isphan || newPart.VolumeDetectActive))
1464 { 2045 {
1465 PrimitiveBaseShape pbs = newPart.Shape; 2046 PrimitiveBaseShape pbs = newPart.Shape;
1466
1467 newPart.PhysActor 2047 newPart.PhysActor
1468 = m_scene.PhysicsScene.AddPrimShape( 2048 = m_scene.PhysicsScene.AddPrimShape(
1469 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 2049 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1470 pbs, 2050 pbs,
1471 newPart.AbsolutePosition, 2051 newPart.AbsolutePosition,
1472 newPart.Scale, 2052 newPart.Scale,
1473 newPart.RotationOffset, 2053 newPart.GetWorldRotation(),
1474 part.PhysActor.IsPhysical, 2054 isphys,
2055 isphan,
1475 newPart.LocalId); 2056 newPart.LocalId);
1476 2057
1477 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 2058 newPart.DoPhysicsPropertyUpdate(isphys, true);
1478 } 2059 */
2060 if (userExposed)
2061 newPart.ApplyPhysics((uint)newPart.Flags,newPart.VolumeDetectActive,true);
2062// }
1479 } 2063 }
1480 2064
1481 if (userExposed) 2065 if (userExposed)
1482 { 2066 {
1483 dupe.UpdateParentIDs(); 2067// done above dupe.UpdateParentIDs();
2068
2069 if (dupe.m_rootPart.PhysActor != null)
2070 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
2071
1484 dupe.HasGroupChanged = true; 2072 dupe.HasGroupChanged = true;
1485 dupe.AttachToBackup(); 2073 dupe.AttachToBackup();
1486 2074
1487 ScheduleGroupForFullUpdate(); 2075 ScheduleGroupForFullUpdate();
1488 } 2076 }
1489 2077
2078 m_dupeInProgress = false;
1490 return dupe; 2079 return dupe;
1491 } 2080 }
1492 2081
@@ -1498,11 +2087,24 @@ namespace OpenSim.Region.Framework.Scenes
1498 /// <param name="cGroupID"></param> 2087 /// <param name="cGroupID"></param>
1499 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2088 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1500 { 2089 {
1501 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2090 // SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed));
2091 // give newpart a new local ID lettng old part keep same
2092 SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2093 newpart.LocalId = m_scene.AllocateLocalId();
2094
2095 SetRootPart(newpart);
2096 if (userExposed)
2097 RootPart.Velocity = Vector3.Zero; // In case source is moving
1502 } 2098 }
1503 2099
1504 public void ScriptSetPhysicsStatus(bool usePhysics) 2100 public void ScriptSetPhysicsStatus(bool usePhysics)
1505 { 2101 {
2102 if (usePhysics)
2103 {
2104 if (RootPart.KeyframeMotion != null)
2105 RootPart.KeyframeMotion.Stop();
2106 RootPart.KeyframeMotion = null;
2107 }
1506 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2108 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1507 } 2109 }
1508 2110
@@ -1566,32 +2168,12 @@ namespace OpenSim.Region.Framework.Scenes
1566 } 2168 }
1567 } 2169 }
1568 2170
1569 public void setAngularImpulse(Vector3 impulse)
1570 {
1571 if (RootPart.PhysActor != null)
1572 {
1573 if (!IsAttachment)
1574 {
1575 RootPart.PhysActor.Torque = impulse;
1576 m_scene.PhysicsScene.AddPhysicsActorTaint(RootPart.PhysActor);
1577 }
1578 }
1579 }
1580
1581 public Vector3 GetTorque() 2171 public Vector3 GetTorque()
1582 { 2172 {
1583 if (RootPart.PhysActor != null) 2173 return RootPart.Torque;
1584 {
1585 if (!IsAttachment)
1586 {
1587 Vector3 torque = RootPart.PhysActor.Torque;
1588 return torque;
1589 }
1590 }
1591
1592 return Vector3.Zero;
1593 } 2174 }
1594 2175
2176 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1595 public void moveToTarget(Vector3 target, float tau) 2177 public void moveToTarget(Vector3 target, float tau)
1596 { 2178 {
1597 if (IsAttachment) 2179 if (IsAttachment)
@@ -1619,6 +2201,46 @@ namespace OpenSim.Region.Framework.Scenes
1619 RootPart.PhysActor.PIDActive = false; 2201 RootPart.PhysActor.PIDActive = false;
1620 } 2202 }
1621 2203
2204 public void rotLookAt(Quaternion target, float strength, float damping)
2205 {
2206 SceneObjectPart rootpart = m_rootPart;
2207 if (rootpart != null)
2208 {
2209 if (IsAttachment)
2210 {
2211 /*
2212 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2213 if (avatar != null)
2214 {
2215 Rotate the Av?
2216 } */
2217 }
2218 else
2219 {
2220 if (rootpart.PhysActor != null)
2221 { // APID must be implemented in your physics system for this to function.
2222 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2223 rootpart.PhysActor.APIDStrength = strength;
2224 rootpart.PhysActor.APIDDamping = damping;
2225 rootpart.PhysActor.APIDActive = true;
2226 }
2227 }
2228 }
2229 }
2230
2231 public void stopLookAt()
2232 {
2233 SceneObjectPart rootpart = m_rootPart;
2234 if (rootpart != null)
2235 {
2236 if (rootpart.PhysActor != null)
2237 { // APID must be implemented in your physics system for this to function.
2238 rootpart.PhysActor.APIDActive = false;
2239 }
2240 }
2241
2242 }
2243
1622 /// <summary> 2244 /// <summary>
1623 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2245 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1624 /// </summary> 2246 /// </summary>
@@ -1673,7 +2295,12 @@ namespace OpenSim.Region.Framework.Scenes
1673 /// <param name="cGroupID"></param> 2295 /// <param name="cGroupID"></param>
1674 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2296 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1675 { 2297 {
1676 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2298 // give new ID to the new part, letting old keep original
2299 // SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2300 SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2301 newPart.LocalId = m_scene.AllocateLocalId();
2302 newPart.SetParent(this);
2303
1677 AddPart(newPart); 2304 AddPart(newPart);
1678 2305
1679 SetPartAsNonRoot(newPart); 2306 SetPartAsNonRoot(newPart);
@@ -1802,11 +2429,11 @@ namespace OpenSim.Region.Framework.Scenes
1802 /// Immediately send a full update for this scene object. 2429 /// Immediately send a full update for this scene object.
1803 /// </summary> 2430 /// </summary>
1804 public void SendGroupFullUpdate() 2431 public void SendGroupFullUpdate()
1805 { 2432 {
1806 if (IsDeleted) 2433 if (IsDeleted)
1807 return; 2434 return;
1808 2435
1809// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2436// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1810 2437
1811 RootPart.SendFullUpdateToAllClients(); 2438 RootPart.SendFullUpdateToAllClients();
1812 2439
@@ -1950,6 +2577,11 @@ namespace OpenSim.Region.Framework.Scenes
1950 /// <param name="objectGroup">The group of prims which should be linked to this group</param> 2577 /// <param name="objectGroup">The group of prims which should be linked to this group</param>
1951 public void LinkToGroup(SceneObjectGroup objectGroup) 2578 public void LinkToGroup(SceneObjectGroup objectGroup)
1952 { 2579 {
2580 LinkToGroup(objectGroup, false);
2581 }
2582
2583 public void LinkToGroup(SceneObjectGroup objectGroup, bool insert)
2584 {
1953// m_log.DebugFormat( 2585// m_log.DebugFormat(
1954// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", 2586// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
1955// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); 2587// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
@@ -1960,6 +2592,15 @@ namespace OpenSim.Region.Framework.Scenes
1960 2592
1961 SceneObjectPart linkPart = objectGroup.m_rootPart; 2593 SceneObjectPart linkPart = objectGroup.m_rootPart;
1962 2594
2595 if (m_rootPart.PhysActor != null)
2596 m_rootPart.PhysActor.Building = true;
2597 if (linkPart.PhysActor != null)
2598 linkPart.PhysActor.Building = true;
2599
2600 // physics flags from group to be applied to linked parts
2601 bool grpusephys = UsesPhysics;
2602 bool grptemporary = IsTemporary;
2603
1963 Vector3 oldGroupPosition = linkPart.GroupPosition; 2604 Vector3 oldGroupPosition = linkPart.GroupPosition;
1964 Quaternion oldRootRotation = linkPart.RotationOffset; 2605 Quaternion oldRootRotation = linkPart.RotationOffset;
1965 2606
@@ -1983,13 +2624,34 @@ namespace OpenSim.Region.Framework.Scenes
1983 2624
1984 lock (m_parts.SyncRoot) 2625 lock (m_parts.SyncRoot)
1985 { 2626 {
1986 int linkNum = PrimCount + 1; 2627 int linkNum;
2628 if (insert)
2629 {
2630 linkNum = 2;
2631 foreach (SceneObjectPart part in Parts)
2632 {
2633 if (part.LinkNum > 1)
2634 part.LinkNum++;
2635 }
2636 }
2637 else
2638 {
2639 linkNum = PrimCount + 1;
2640 }
1987 2641
1988 m_parts.Add(linkPart.UUID, linkPart); 2642 m_parts.Add(linkPart.UUID, linkPart);
1989 2643
1990 linkPart.SetParent(this); 2644 linkPart.SetParent(this);
1991 linkPart.CreateSelected = true; 2645 linkPart.CreateSelected = true;
1992 2646
2647 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
2648 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true);
2649 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2650 {
2651 linkPart.PhysActor.link(m_rootPart.PhysActor);
2652 this.Scene.PhysicsScene.AddPhysicsActorTaint(linkPart.PhysActor);
2653 }
2654
1993 linkPart.LinkNum = linkNum++; 2655 linkPart.LinkNum = linkNum++;
1994 2656
1995 SceneObjectPart[] ogParts = objectGroup.Parts; 2657 SceneObjectPart[] ogParts = objectGroup.Parts;
@@ -2002,7 +2664,16 @@ namespace OpenSim.Region.Framework.Scenes
2002 { 2664 {
2003 SceneObjectPart part = ogParts[i]; 2665 SceneObjectPart part = ogParts[i];
2004 if (part.UUID != objectGroup.m_rootPart.UUID) 2666 if (part.UUID != objectGroup.m_rootPart.UUID)
2667 {
2005 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); 2668 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2669 // let physics know
2670 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true);
2671 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2672 {
2673 part.PhysActor.link(m_rootPart.PhysActor);
2674 this.Scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2675 }
2676 }
2006 part.ClearUndoState(); 2677 part.ClearUndoState();
2007 } 2678 }
2008 } 2679 }
@@ -2011,7 +2682,7 @@ namespace OpenSim.Region.Framework.Scenes
2011 objectGroup.IsDeleted = true; 2682 objectGroup.IsDeleted = true;
2012 2683
2013 objectGroup.m_parts.Clear(); 2684 objectGroup.m_parts.Clear();
2014 2685
2015 // Can't do this yet since backup still makes use of the root part without any synchronization 2686 // Can't do this yet since backup still makes use of the root part without any synchronization
2016// objectGroup.m_rootPart = null; 2687// objectGroup.m_rootPart = null;
2017 2688
@@ -2022,6 +2693,9 @@ namespace OpenSim.Region.Framework.Scenes
2022 // unmoved prims! 2693 // unmoved prims!
2023 ResetChildPrimPhysicsPositions(); 2694 ResetChildPrimPhysicsPositions();
2024 2695
2696 if (m_rootPart.PhysActor != null)
2697 m_rootPart.PhysActor.Building = false;
2698
2025 //HasGroupChanged = true; 2699 //HasGroupChanged = true;
2026 //ScheduleGroupForFullUpdate(); 2700 //ScheduleGroupForFullUpdate();
2027 } 2701 }
@@ -2074,7 +2748,10 @@ namespace OpenSim.Region.Framework.Scenes
2074// m_log.DebugFormat( 2748// m_log.DebugFormat(
2075// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", 2749// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2076// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); 2750// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2077 2751
2752 if (m_rootPart.PhysActor != null)
2753 m_rootPart.PhysActor.Building = true;
2754
2078 linkPart.ClearUndoState(); 2755 linkPart.ClearUndoState();
2079 2756
2080 Quaternion worldRot = linkPart.GetWorldRotation(); 2757 Quaternion worldRot = linkPart.GetWorldRotation();
@@ -2134,6 +2811,14 @@ namespace OpenSim.Region.Framework.Scenes
2134 2811
2135 // When we delete a group, we currently have to force persist to the database if the object id has changed 2812 // When we delete a group, we currently have to force persist to the database if the object id has changed
2136 // (since delete works by deleting all rows which have a given object id) 2813 // (since delete works by deleting all rows which have a given object id)
2814
2815 // this is as it seems to be in sl now
2816 if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none)
2817 linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now
2818
2819 if (m_rootPart.PhysActor != null)
2820 m_rootPart.PhysActor.Building = false;
2821
2137 objectGroup.HasGroupChangedDueToDelink = true; 2822 objectGroup.HasGroupChangedDueToDelink = true;
2138 2823
2139 return objectGroup; 2824 return objectGroup;
@@ -2145,6 +2830,7 @@ namespace OpenSim.Region.Framework.Scenes
2145 /// <param name="objectGroup"></param> 2830 /// <param name="objectGroup"></param>
2146 public virtual void DetachFromBackup() 2831 public virtual void DetachFromBackup()
2147 { 2832 {
2833 m_scene.SceneGraph.FireDetachFromBackup(this);
2148 if (m_isBackedUp && Scene != null) 2834 if (m_isBackedUp && Scene != null)
2149 m_scene.EventManager.OnBackup -= ProcessBackup; 2835 m_scene.EventManager.OnBackup -= ProcessBackup;
2150 2836
@@ -2163,7 +2849,8 @@ namespace OpenSim.Region.Framework.Scenes
2163 2849
2164 axPos *= parentRot; 2850 axPos *= parentRot;
2165 part.OffsetPosition = axPos; 2851 part.OffsetPosition = axPos;
2166 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2852 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2853 part.GroupPosition = newPos;
2167 part.OffsetPosition = Vector3.Zero; 2854 part.OffsetPosition = Vector3.Zero;
2168 part.RotationOffset = worldRot; 2855 part.RotationOffset = worldRot;
2169 2856
@@ -2174,7 +2861,7 @@ namespace OpenSim.Region.Framework.Scenes
2174 2861
2175 part.LinkNum = linkNum; 2862 part.LinkNum = linkNum;
2176 2863
2177 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2864 part.OffsetPosition = newPos - AbsolutePosition;
2178 2865
2179 Quaternion rootRotation = m_rootPart.RotationOffset; 2866 Quaternion rootRotation = m_rootPart.RotationOffset;
2180 2867
@@ -2184,7 +2871,7 @@ namespace OpenSim.Region.Framework.Scenes
2184 2871
2185 parentRot = m_rootPart.RotationOffset; 2872 parentRot = m_rootPart.RotationOffset;
2186 oldRot = part.RotationOffset; 2873 oldRot = part.RotationOffset;
2187 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2874 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2188 part.RotationOffset = newRot; 2875 part.RotationOffset = newRot;
2189 } 2876 }
2190 2877
@@ -2431,8 +3118,31 @@ namespace OpenSim.Region.Framework.Scenes
2431 } 3118 }
2432 } 3119 }
2433 3120
3121/*
3122 RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2434 for (int i = 0; i < parts.Length; i++) 3123 for (int i = 0; i < parts.Length; i++)
2435 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 3124 {
3125 if (parts[i] != RootPart)
3126 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
3127 }
3128*/
3129 if (parts.Length > 1)
3130 {
3131 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3132
3133 for (int i = 0; i < parts.Length; i++)
3134 {
3135
3136 if (parts[i].UUID != m_rootPart.UUID)
3137 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3138 }
3139
3140 if (m_rootPart.PhysActor != null)
3141 m_rootPart.PhysActor.Building = false;
3142 }
3143 else
3144 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
3145
2436 } 3146 }
2437 } 3147 }
2438 3148
@@ -2445,6 +3155,17 @@ namespace OpenSim.Region.Framework.Scenes
2445 } 3155 }
2446 } 3156 }
2447 3157
3158
3159
3160 /// <summary>
3161 /// Gets the number of parts
3162 /// </summary>
3163 /// <returns></returns>
3164 public int GetPartCount()
3165 {
3166 return Parts.Count();
3167 }
3168
2448 /// <summary> 3169 /// <summary>
2449 /// Update the texture entry for this part 3170 /// Update the texture entry for this part
2450 /// </summary> 3171 /// </summary>
@@ -2504,11 +3225,6 @@ namespace OpenSim.Region.Framework.Scenes
2504 /// <param name="scale"></param> 3225 /// <param name="scale"></param>
2505 public void GroupResize(Vector3 scale) 3226 public void GroupResize(Vector3 scale)
2506 { 3227 {
2507// m_log.DebugFormat(
2508// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2509
2510 RootPart.StoreUndoState(true);
2511
2512 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3228 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
2513 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); 3229 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
2514 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); 3230 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
@@ -2533,7 +3249,6 @@ namespace OpenSim.Region.Framework.Scenes
2533 SceneObjectPart obPart = parts[i]; 3249 SceneObjectPart obPart = parts[i];
2534 if (obPart.UUID != m_rootPart.UUID) 3250 if (obPart.UUID != m_rootPart.UUID)
2535 { 3251 {
2536// obPart.IgnoreUndoUpdate = true;
2537 Vector3 oldSize = new Vector3(obPart.Scale); 3252 Vector3 oldSize = new Vector3(obPart.Scale);
2538 3253
2539 float f = 1.0f; 3254 float f = 1.0f;
@@ -2597,8 +3312,6 @@ namespace OpenSim.Region.Framework.Scenes
2597 z *= a; 3312 z *= a;
2598 } 3313 }
2599 } 3314 }
2600
2601// obPart.IgnoreUndoUpdate = false;
2602 } 3315 }
2603 } 3316 }
2604 } 3317 }
@@ -2608,9 +3321,7 @@ namespace OpenSim.Region.Framework.Scenes
2608 prevScale.Y *= y; 3321 prevScale.Y *= y;
2609 prevScale.Z *= z; 3322 prevScale.Z *= z;
2610 3323
2611// RootPart.IgnoreUndoUpdate = true;
2612 RootPart.Resize(prevScale); 3324 RootPart.Resize(prevScale);
2613// RootPart.IgnoreUndoUpdate = false;
2614 3325
2615 parts = m_parts.GetArray(); 3326 parts = m_parts.GetArray();
2616 for (int i = 0; i < parts.Length; i++) 3327 for (int i = 0; i < parts.Length; i++)
@@ -2619,8 +3330,6 @@ namespace OpenSim.Region.Framework.Scenes
2619 3330
2620 if (obPart.UUID != m_rootPart.UUID) 3331 if (obPart.UUID != m_rootPart.UUID)
2621 { 3332 {
2622 obPart.IgnoreUndoUpdate = true;
2623
2624 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3333 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2625 currentpos.X *= x; 3334 currentpos.X *= x;
2626 currentpos.Y *= y; 3335 currentpos.Y *= y;
@@ -2633,16 +3342,12 @@ namespace OpenSim.Region.Framework.Scenes
2633 3342
2634 obPart.Resize(newSize); 3343 obPart.Resize(newSize);
2635 obPart.UpdateOffSet(currentpos); 3344 obPart.UpdateOffSet(currentpos);
2636
2637 obPart.IgnoreUndoUpdate = false;
2638 } 3345 }
2639 3346
2640// obPart.IgnoreUndoUpdate = false; 3347 HasGroupChanged = true;
2641// obPart.StoreUndoState(); 3348 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3349 ScheduleGroupForTerseUpdate();
2642 } 3350 }
2643
2644// m_log.DebugFormat(
2645// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale);
2646 } 3351 }
2647 3352
2648 #endregion 3353 #endregion
@@ -2655,14 +3360,6 @@ namespace OpenSim.Region.Framework.Scenes
2655 /// <param name="pos"></param> 3360 /// <param name="pos"></param>
2656 public void UpdateGroupPosition(Vector3 pos) 3361 public void UpdateGroupPosition(Vector3 pos)
2657 { 3362 {
2658// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
2659
2660 RootPart.StoreUndoState(true);
2661
2662// SceneObjectPart[] parts = m_parts.GetArray();
2663// for (int i = 0; i < parts.Length; i++)
2664// parts[i].StoreUndoState();
2665
2666 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3363 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2667 { 3364 {
2668 if (IsAttachment) 3365 if (IsAttachment)
@@ -2694,21 +3391,17 @@ namespace OpenSim.Region.Framework.Scenes
2694 /// </summary> 3391 /// </summary>
2695 /// <param name="pos"></param> 3392 /// <param name="pos"></param>
2696 /// <param name="localID"></param> 3393 /// <param name="localID"></param>
3394 ///
3395
2697 public void UpdateSinglePosition(Vector3 pos, uint localID) 3396 public void UpdateSinglePosition(Vector3 pos, uint localID)
2698 { 3397 {
2699 SceneObjectPart part = GetChildPart(localID); 3398 SceneObjectPart part = GetChildPart(localID);
2700 3399
2701// SceneObjectPart[] parts = m_parts.GetArray();
2702// for (int i = 0; i < parts.Length; i++)
2703// parts[i].StoreUndoState();
2704
2705 if (part != null) 3400 if (part != null)
2706 { 3401 {
2707// m_log.DebugFormat( 3402// unlock parts position change
2708// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); 3403 if (m_rootPart.PhysActor != null)
2709 3404 m_rootPart.PhysActor.Building = true;
2710 part.StoreUndoState(false);
2711 part.IgnoreUndoUpdate = true;
2712 3405
2713 if (part.UUID == m_rootPart.UUID) 3406 if (part.UUID == m_rootPart.UUID)
2714 { 3407 {
@@ -2719,8 +3412,10 @@ namespace OpenSim.Region.Framework.Scenes
2719 part.UpdateOffSet(pos); 3412 part.UpdateOffSet(pos);
2720 } 3413 }
2721 3414
3415 if (m_rootPart.PhysActor != null)
3416 m_rootPart.PhysActor.Building = false;
3417
2722 HasGroupChanged = true; 3418 HasGroupChanged = true;
2723 part.IgnoreUndoUpdate = false;
2724 } 3419 }
2725 } 3420 }
2726 3421
@@ -2730,13 +3425,7 @@ namespace OpenSim.Region.Framework.Scenes
2730 /// <param name="pos"></param> 3425 /// <param name="pos"></param>
2731 public void UpdateRootPosition(Vector3 pos) 3426 public void UpdateRootPosition(Vector3 pos)
2732 { 3427 {
2733// m_log.DebugFormat( 3428 // needs to be called with phys building true
2734// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
2735
2736// SceneObjectPart[] parts = m_parts.GetArray();
2737// for (int i = 0; i < parts.Length; i++)
2738// parts[i].StoreUndoState();
2739
2740 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3429 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2741 Vector3 oldPos = 3430 Vector3 oldPos =
2742 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3431 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
@@ -2759,7 +3448,14 @@ namespace OpenSim.Region.Framework.Scenes
2759 AbsolutePosition = newPos; 3448 AbsolutePosition = newPos;
2760 3449
2761 HasGroupChanged = true; 3450 HasGroupChanged = true;
2762 ScheduleGroupForTerseUpdate(); 3451 if (m_rootPart.Undoing)
3452 {
3453 ScheduleGroupForFullUpdate();
3454 }
3455 else
3456 {
3457 ScheduleGroupForTerseUpdate();
3458 }
2763 } 3459 }
2764 3460
2765 #endregion 3461 #endregion
@@ -2772,17 +3468,6 @@ namespace OpenSim.Region.Framework.Scenes
2772 /// <param name="rot"></param> 3468 /// <param name="rot"></param>
2773 public void UpdateGroupRotationR(Quaternion rot) 3469 public void UpdateGroupRotationR(Quaternion rot)
2774 { 3470 {
2775// m_log.DebugFormat(
2776// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
2777
2778// SceneObjectPart[] parts = m_parts.GetArray();
2779// for (int i = 0; i < parts.Length; i++)
2780// parts[i].StoreUndoState();
2781
2782 m_rootPart.StoreUndoState(true);
2783
2784 m_rootPart.UpdateRotation(rot);
2785
2786 PhysicsActor actor = m_rootPart.PhysActor; 3471 PhysicsActor actor = m_rootPart.PhysActor;
2787 if (actor != null) 3472 if (actor != null)
2788 { 3473 {
@@ -2801,16 +3486,6 @@ namespace OpenSim.Region.Framework.Scenes
2801 /// <param name="rot"></param> 3486 /// <param name="rot"></param>
2802 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 3487 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
2803 { 3488 {
2804// m_log.DebugFormat(
2805// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
2806
2807// SceneObjectPart[] parts = m_parts.GetArray();
2808// for (int i = 0; i < parts.Length; i++)
2809// parts[i].StoreUndoState();
2810
2811 RootPart.StoreUndoState(true);
2812 RootPart.IgnoreUndoUpdate = true;
2813
2814 m_rootPart.UpdateRotation(rot); 3489 m_rootPart.UpdateRotation(rot);
2815 3490
2816 PhysicsActor actor = m_rootPart.PhysActor; 3491 PhysicsActor actor = m_rootPart.PhysActor;
@@ -2824,8 +3499,6 @@ namespace OpenSim.Region.Framework.Scenes
2824 3499
2825 HasGroupChanged = true; 3500 HasGroupChanged = true;
2826 ScheduleGroupForTerseUpdate(); 3501 ScheduleGroupForTerseUpdate();
2827
2828 RootPart.IgnoreUndoUpdate = false;
2829 } 3502 }
2830 3503
2831 /// <summary> 3504 /// <summary>
@@ -2836,15 +3509,12 @@ namespace OpenSim.Region.Framework.Scenes
2836 public void UpdateSingleRotation(Quaternion rot, uint localID) 3509 public void UpdateSingleRotation(Quaternion rot, uint localID)
2837 { 3510 {
2838 SceneObjectPart part = GetChildPart(localID); 3511 SceneObjectPart part = GetChildPart(localID);
2839
2840 SceneObjectPart[] parts = m_parts.GetArray(); 3512 SceneObjectPart[] parts = m_parts.GetArray();
2841 for (int i = 0; i < parts.Length; i++)
2842 parts[i].StoreUndoState();
2843 3513
2844 if (part != null) 3514 if (part != null)
2845 { 3515 {
2846// m_log.DebugFormat( 3516 if (m_rootPart.PhysActor != null)
2847// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); 3517 m_rootPart.PhysActor.Building = true;
2848 3518
2849 if (part.UUID == m_rootPart.UUID) 3519 if (part.UUID == m_rootPart.UUID)
2850 { 3520 {
@@ -2854,6 +3524,9 @@ namespace OpenSim.Region.Framework.Scenes
2854 { 3524 {
2855 part.UpdateRotation(rot); 3525 part.UpdateRotation(rot);
2856 } 3526 }
3527
3528 if (m_rootPart.PhysActor != null)
3529 m_rootPart.PhysActor.Building = false;
2857 } 3530 }
2858 } 3531 }
2859 3532
@@ -2867,12 +3540,8 @@ namespace OpenSim.Region.Framework.Scenes
2867 SceneObjectPart part = GetChildPart(localID); 3540 SceneObjectPart part = GetChildPart(localID);
2868 if (part != null) 3541 if (part != null)
2869 { 3542 {
2870// m_log.DebugFormat( 3543 if (m_rootPart.PhysActor != null)
2871// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", 3544 m_rootPart.PhysActor.Building = true;
2872// part.Name, part.LocalId, rot);
2873
2874 part.StoreUndoState();
2875 part.IgnoreUndoUpdate = true;
2876 3545
2877 if (part.UUID == m_rootPart.UUID) 3546 if (part.UUID == m_rootPart.UUID)
2878 { 3547 {
@@ -2885,7 +3554,8 @@ namespace OpenSim.Region.Framework.Scenes
2885 part.OffsetPosition = pos; 3554 part.OffsetPosition = pos;
2886 } 3555 }
2887 3556
2888 part.IgnoreUndoUpdate = false; 3557 if (m_rootPart.PhysActor != null)
3558 m_rootPart.PhysActor.Building = false;
2889 } 3559 }
2890 } 3560 }
2891 3561
@@ -2895,15 +3565,12 @@ namespace OpenSim.Region.Framework.Scenes
2895 /// <param name="rot"></param> 3565 /// <param name="rot"></param>
2896 public void UpdateRootRotation(Quaternion rot) 3566 public void UpdateRootRotation(Quaternion rot)
2897 { 3567 {
2898// m_log.DebugFormat( 3568 // needs to be called with phys building true
2899// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
2900// Name, LocalId, rot);
2901
2902 Quaternion axRot = rot; 3569 Quaternion axRot = rot;
2903 Quaternion oldParentRot = m_rootPart.RotationOffset; 3570 Quaternion oldParentRot = m_rootPart.RotationOffset;
2904 3571
2905 m_rootPart.StoreUndoState(); 3572 //Don't use UpdateRotation because it schedules an update prematurely
2906 m_rootPart.UpdateRotation(rot); 3573 m_rootPart.RotationOffset = rot;
2907 if (m_rootPart.PhysActor != null) 3574 if (m_rootPart.PhysActor != null)
2908 { 3575 {
2909 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3576 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2916,35 +3583,135 @@ namespace OpenSim.Region.Framework.Scenes
2916 SceneObjectPart prim = parts[i]; 3583 SceneObjectPart prim = parts[i];
2917 if (prim.UUID != m_rootPart.UUID) 3584 if (prim.UUID != m_rootPart.UUID)
2918 { 3585 {
2919 prim.IgnoreUndoUpdate = true; 3586 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3587 NewRot = Quaternion.Inverse(axRot) * NewRot;
3588 prim.RotationOffset = NewRot;
3589
2920 Vector3 axPos = prim.OffsetPosition; 3590 Vector3 axPos = prim.OffsetPosition;
3591
2921 axPos *= oldParentRot; 3592 axPos *= oldParentRot;
2922 axPos *= Quaternion.Inverse(axRot); 3593 axPos *= Quaternion.Inverse(axRot);
2923 prim.OffsetPosition = axPos; 3594 prim.OffsetPosition = axPos;
2924 Quaternion primsRot = prim.RotationOffset; 3595 }
2925 Quaternion newRot = oldParentRot * primsRot; 3596 }
2926 newRot = Quaternion.Inverse(axRot) * newRot;
2927 prim.RotationOffset = newRot;
2928 prim.ScheduleTerseUpdate();
2929 prim.IgnoreUndoUpdate = false;
2930 }
2931 }
2932
2933// for (int i = 0; i < parts.Length; i++)
2934// {
2935// SceneObjectPart childpart = parts[i];
2936// if (childpart != m_rootPart)
2937// {
2938//// childpart.IgnoreUndoUpdate = false;
2939//// childpart.StoreUndoState();
2940// }
2941// }
2942 3597
2943 m_rootPart.ScheduleTerseUpdate(); 3598 HasGroupChanged = true;
3599 ScheduleGroupForFullUpdate();
3600 }
2944 3601
2945// m_log.DebugFormat( 3602 private enum updatetype :int
2946// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3603 {
2947// Name, LocalId, rot); 3604 none = 0,
3605 partterse = 1,
3606 partfull = 2,
3607 groupterse = 3,
3608 groupfull = 4
3609 }
3610
3611 public void doChangeObject(SceneObjectPart part, ObjectChangeData data)
3612 {
3613 // TODO this still as excessive *.Schedule*Update()s
3614
3615 if (part != null && part.ParentGroup != null)
3616 {
3617 ObjectChangeType change = data.change;
3618 bool togroup = ((change & ObjectChangeType.Group) != 0);
3619 // bool uniform = ((what & ObjectChangeType.UniformScale) != 0); not in use
3620
3621 SceneObjectGroup group = part.ParentGroup;
3622 PhysicsActor pha = group.RootPart.PhysActor;
3623
3624 updatetype updateType = updatetype.none;
3625
3626 if (togroup)
3627 {
3628 // related to group
3629 if ((change & ObjectChangeType.Position) != 0)
3630 {
3631 group.AbsolutePosition = data.position;
3632 updateType = updatetype.groupterse;
3633 }
3634 if ((change & ObjectChangeType.Rotation) != 0)
3635 {
3636 group.RootPart.UpdateRotation(data.rotation);
3637 updateType = updatetype.none;
3638 }
3639 if ((change & ObjectChangeType.Scale) != 0)
3640 {
3641 if (pha != null)
3642 pha.Building = true;
3643
3644 group.GroupResize(data.scale);
3645 updateType = updatetype.none;
3646
3647 if (pha != null)
3648 pha.Building = false;
3649 }
3650 }
3651 else
3652 {
3653 // related to single prim in a link-set ( ie group)
3654 if (pha != null)
3655 pha.Building = true;
3656
3657 // root part is special
3658 // parts offset positions or rotations need to change also
3659
3660 if (part == group.RootPart)
3661 {
3662 if ((change & ObjectChangeType.Position) != 0)
3663 group.UpdateRootPosition(data.position);
3664 if ((change & ObjectChangeType.Rotation) != 0)
3665 group.UpdateRootRotation(data.rotation);
3666 if ((change & ObjectChangeType.Scale) != 0)
3667 part.Resize(data.scale);
3668 }
3669 else
3670 {
3671 if ((change & ObjectChangeType.Position) != 0)
3672 {
3673 part.OffsetPosition = data.position;
3674 updateType = updatetype.partterse;
3675 }
3676 if ((change & ObjectChangeType.Rotation) != 0)
3677 {
3678 part.UpdateRotation(data.rotation);
3679 updateType = updatetype.none;
3680 }
3681 if ((change & ObjectChangeType.Scale) != 0)
3682 {
3683 part.Resize(data.scale);
3684 updateType = updatetype.none;
3685 }
3686 }
3687
3688 if (pha != null)
3689 pha.Building = false;
3690 }
3691
3692 if (updateType != updatetype.none)
3693 {
3694 group.HasGroupChanged = true;
3695
3696 switch (updateType)
3697 {
3698 case updatetype.partterse:
3699 part.ScheduleTerseUpdate();
3700 break;
3701 case updatetype.partfull:
3702 part.ScheduleFullUpdate();
3703 break;
3704 case updatetype.groupterse:
3705 group.ScheduleGroupForTerseUpdate();
3706 break;
3707 case updatetype.groupfull:
3708 group.ScheduleGroupForFullUpdate();
3709 break;
3710 default:
3711 break;
3712 }
3713 }
3714 }
2948 } 3715 }
2949 3716
2950 #endregion 3717 #endregion
@@ -3168,7 +3935,6 @@ namespace OpenSim.Region.Framework.Scenes
3168 public float GetMass() 3935 public float GetMass()
3169 { 3936 {
3170 float retmass = 0f; 3937 float retmass = 0f;
3171
3172 SceneObjectPart[] parts = m_parts.GetArray(); 3938 SceneObjectPart[] parts = m_parts.GetArray();
3173 for (int i = 0; i < parts.Length; i++) 3939 for (int i = 0; i < parts.Length; i++)
3174 retmass += parts[i].GetMass(); 3940 retmass += parts[i].GetMass();
@@ -3264,6 +4030,14 @@ namespace OpenSim.Region.Framework.Scenes
3264 SetFromItemID(uuid); 4030 SetFromItemID(uuid);
3265 } 4031 }
3266 4032
4033 public void ResetOwnerChangeFlag()
4034 {
4035 ForEachPart(delegate(SceneObjectPart part)
4036 {
4037 part.ResetOwnerChangeFlag();
4038 });
4039 }
4040
3267 #endregion 4041 #endregion
3268 } 4042 }
3269} 4043}