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.cs1180
1 files changed, 975 insertions, 205 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 7d14814..5786f48 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; }
@@ -404,14 +478,99 @@ namespace OpenSim.Region.Framework.Scenes
404 478
405 if (Scene != null) 479 if (Scene != null)
406 { 480 {
407 if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) 481 // if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
408 || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) 482 // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
483 // && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
484 if ((Scene.TestBorderCross(val, Cardinals.E) || Scene.TestBorderCross(val, Cardinals.W)
485 || Scene.TestBorderCross(val, Cardinals.N) || Scene.TestBorderCross(val, Cardinals.S))
409 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 486 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
410 { 487 {
411 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 488 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
489 uint x = 0;
490 uint y = 0;
491 string version = String.Empty;
492 Vector3 newpos = Vector3.Zero;
493 OpenSim.Services.Interfaces.GridRegion destination = null;
494
495 bool canCross = true;
496 foreach (ScenePresence av in m_linkedAvatars)
497 {
498 // We need to cross these agents. First, let's find
499 // out if any of them can't cross for some reason.
500 // We have to deny the crossing entirely if any
501 // of them are banned. Alternatively, we could
502 // unsit banned agents....
503
504
505 // We set the avatar position as being the object
506 // position to get the region to send to
507 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null)
508 {
509 canCross = false;
510 break;
511 }
512
513 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
514 }
515
516 if (canCross)
517 {
518 // We unparent the SP quietly so that it won't
519 // be made to stand up
520 foreach (ScenePresence av in m_linkedAvatars)
521 {
522 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
523 if (parentPart != null)
524 av.ParentUUID = parentPart.UUID;
525
526 av.ParentID = 0;
527 }
528
529 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
530
531 // Normalize
532 if (val.X >= Constants.RegionSize)
533 val.X -= Constants.RegionSize;
534 if (val.Y >= Constants.RegionSize)
535 val.Y -= Constants.RegionSize;
536 if (val.X < 0)
537 val.X += Constants.RegionSize;
538 if (val.Y < 0)
539 val.Y += Constants.RegionSize;
540
541 // If it's deleted, crossing was successful
542 if (IsDeleted)
543 {
544 foreach (ScenePresence av in m_linkedAvatars)
545 {
546 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
547
548 av.IsInTransit = true;
549
550 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
551 d.BeginInvoke(av, val, x, y, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
552 }
553
554 return;
555 }
556 }
557 else if (RootPart.PhysActor != null)
558 {
559 RootPart.PhysActor.CrossingFailure();
560 }
561
562 Vector3 oldp = AbsolutePosition;
563 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
564 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
565 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
412 } 566 }
413 } 567 }
414 568/* don't see the need but worse don't see where is restored to false if things stay in
569 foreach (SceneObjectPart part in m_parts.GetArray())
570 {
571 part.IgnoreUndoUpdate = true;
572 }
573 */
415 if (RootPart.GetStatusSandbox()) 574 if (RootPart.GetStatusSandbox())
416 { 575 {
417 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 576 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -425,10 +584,30 @@ namespace OpenSim.Region.Framework.Scenes
425 return; 584 return;
426 } 585 }
427 } 586 }
428
429 SceneObjectPart[] parts = m_parts.GetArray(); 587 SceneObjectPart[] parts = m_parts.GetArray();
430 for (int i = 0; i < parts.Length; i++) 588 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
431 parts[i].GroupPosition = val; 589 if (m_dupeInProgress)
590 triggerScriptEvent = false;
591 foreach (SceneObjectPart part in parts)
592 {
593 part.GroupPosition = val;
594 if (triggerScriptEvent)
595 part.TriggerScriptChangedEvent(Changed.POSITION);
596 }
597 if (!m_dupeInProgress)
598 {
599 foreach (ScenePresence av in m_linkedAvatars)
600 {
601 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
602 if (p != null && m_parts.TryGetValue(p.UUID, out p))
603 {
604 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
605 av.AbsolutePosition += offset;
606 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
607 av.SendAvatarDataToAllAgents();
608 }
609 }
610 }
432 611
433 //if (m_rootPart.PhysActor != null) 612 //if (m_rootPart.PhysActor != null)
434 //{ 613 //{
@@ -443,6 +622,29 @@ namespace OpenSim.Region.Framework.Scenes
443 } 622 }
444 } 623 }
445 624
625 public override Vector3 Velocity
626 {
627 get { return RootPart.Velocity; }
628 set { RootPart.Velocity = value; }
629 }
630
631 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
632 {
633 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
634 ScenePresence agent = icon.EndInvoke(iar);
635
636 //// If the cross was successful, this agent is a child agent
637 //if (agent.IsChildAgent)
638 // agent.Reset();
639 //else // Not successful
640 // agent.RestoreInCurrentScene();
641
642 // In any case
643 agent.IsInTransit = false;
644
645 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
646 }
647
446 public override uint LocalId 648 public override uint LocalId
447 { 649 {
448 get { return m_rootPart.LocalId; } 650 get { return m_rootPart.LocalId; }
@@ -540,6 +742,8 @@ namespace OpenSim.Region.Framework.Scenes
540 childPa.Selected = value; 742 childPa.Selected = value;
541 } 743 }
542 } 744 }
745 if (RootPart.KeyframeMotion != null)
746 RootPart.KeyframeMotion.Selected = value;
543 } 747 }
544 } 748 }
545 749
@@ -617,6 +821,7 @@ namespace OpenSim.Region.Framework.Scenes
617 /// </summary> 821 /// </summary>
618 public SceneObjectGroup() 822 public SceneObjectGroup()
619 { 823 {
824
620 } 825 }
621 826
622 /// <summary> 827 /// <summary>
@@ -633,7 +838,7 @@ namespace OpenSim.Region.Framework.Scenes
633 /// Constructor. This object is added to the scene later via AttachToScene() 838 /// Constructor. This object is added to the scene later via AttachToScene()
634 /// </summary> 839 /// </summary>
635 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 840 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
636 { 841 {
637 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 842 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
638 } 843 }
639 844
@@ -669,6 +874,9 @@ namespace OpenSim.Region.Framework.Scenes
669 /// </summary> 874 /// </summary>
670 public virtual void AttachToBackup() 875 public virtual void AttachToBackup()
671 { 876 {
877 if (IsAttachment) return;
878 m_scene.SceneGraph.FireAttachToBackup(this);
879
672 if (InSceneBackup) 880 if (InSceneBackup)
673 { 881 {
674 //m_log.DebugFormat( 882 //m_log.DebugFormat(
@@ -711,6 +919,13 @@ namespace OpenSim.Region.Framework.Scenes
711 919
712 ApplyPhysics(); 920 ApplyPhysics();
713 921
922 if (RootPart.PhysActor != null)
923 RootPart.Force = RootPart.Force;
924 if (RootPart.PhysActor != null)
925 RootPart.Torque = RootPart.Torque;
926 if (RootPart.PhysActor != null)
927 RootPart.Buoyancy = RootPart.Buoyancy;
928
714 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 929 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
715 // for the same object with very different properties. The caller must schedule the update. 930 // for the same object with very different properties. The caller must schedule the update.
716 //ScheduleGroupForFullUpdate(); 931 //ScheduleGroupForFullUpdate();
@@ -726,6 +941,10 @@ namespace OpenSim.Region.Framework.Scenes
726 EntityIntersection result = new EntityIntersection(); 941 EntityIntersection result = new EntityIntersection();
727 942
728 SceneObjectPart[] parts = m_parts.GetArray(); 943 SceneObjectPart[] parts = m_parts.GetArray();
944
945 // Find closest hit here
946 float idist = float.MaxValue;
947
729 for (int i = 0; i < parts.Length; i++) 948 for (int i = 0; i < parts.Length; i++)
730 { 949 {
731 SceneObjectPart part = parts[i]; 950 SceneObjectPart part = parts[i];
@@ -740,11 +959,6 @@ namespace OpenSim.Region.Framework.Scenes
740 959
741 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 960 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
742 961
743 // This may need to be updated to the maximum draw distance possible..
744 // We might (and probably will) be checking for prim creation from other sims
745 // when the camera crosses the border.
746 float idist = Constants.RegionSize;
747
748 if (inter.HitTF) 962 if (inter.HitTF)
749 { 963 {
750 // We need to find the closest prim to return to the testcaller along the ray 964 // We need to find the closest prim to return to the testcaller along the ray
@@ -755,10 +969,11 @@ namespace OpenSim.Region.Framework.Scenes
755 result.obj = part; 969 result.obj = part;
756 result.normal = inter.normal; 970 result.normal = inter.normal;
757 result.distance = inter.distance; 971 result.distance = inter.distance;
972
973 idist = inter.distance;
758 } 974 }
759 } 975 }
760 } 976 }
761
762 return result; 977 return result;
763 } 978 }
764 979
@@ -770,25 +985,27 @@ namespace OpenSim.Region.Framework.Scenes
770 /// <returns></returns> 985 /// <returns></returns>
771 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 986 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
772 { 987 {
773 maxX = -256f; 988 maxX = float.MinValue;
774 maxY = -256f; 989 maxY = float.MinValue;
775 maxZ = -256f; 990 maxZ = float.MinValue;
776 minX = 256f; 991 minX = float.MaxValue;
777 minY = 256f; 992 minY = float.MaxValue;
778 minZ = 8192f; 993 minZ = float.MaxValue;
779 994
780 SceneObjectPart[] parts = m_parts.GetArray(); 995 SceneObjectPart[] parts = m_parts.GetArray();
781 for (int i = 0; i < parts.Length; i++) 996 foreach (SceneObjectPart part in parts)
782 { 997 {
783 SceneObjectPart part = parts[i];
784
785 Vector3 worldPos = part.GetWorldPosition(); 998 Vector3 worldPos = part.GetWorldPosition();
786 Vector3 offset = worldPos - AbsolutePosition; 999 Vector3 offset = worldPos - AbsolutePosition;
787 Quaternion worldRot; 1000 Quaternion worldRot;
788 if (part.ParentID == 0) 1001 if (part.ParentID == 0)
1002 {
789 worldRot = part.RotationOffset; 1003 worldRot = part.RotationOffset;
1004 }
790 else 1005 else
1006 {
791 worldRot = part.GetWorldRotation(); 1007 worldRot = part.GetWorldRotation();
1008 }
792 1009
793 Vector3 frontTopLeft; 1010 Vector3 frontTopLeft;
794 Vector3 frontTopRight; 1011 Vector3 frontTopRight;
@@ -800,6 +1017,8 @@ namespace OpenSim.Region.Framework.Scenes
800 Vector3 backBottomLeft; 1017 Vector3 backBottomLeft;
801 Vector3 backBottomRight; 1018 Vector3 backBottomRight;
802 1019
1020 // Vector3[] corners = new Vector3[8];
1021
803 Vector3 orig = Vector3.Zero; 1022 Vector3 orig = Vector3.Zero;
804 1023
805 frontTopLeft.X = orig.X - (part.Scale.X / 2); 1024 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -834,6 +1053,38 @@ namespace OpenSim.Region.Framework.Scenes
834 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1053 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
835 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1054 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
836 1055
1056
1057
1058 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1059 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1060 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1061 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1062 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1063 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1064 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1065 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1066
1067 //for (int i = 0; i < 8; i++)
1068 //{
1069 // corners[i] = corners[i] * worldRot;
1070 // corners[i] += offset;
1071
1072 // if (corners[i].X > maxX)
1073 // maxX = corners[i].X;
1074 // if (corners[i].X < minX)
1075 // minX = corners[i].X;
1076
1077 // if (corners[i].Y > maxY)
1078 // maxY = corners[i].Y;
1079 // if (corners[i].Y < minY)
1080 // minY = corners[i].Y;
1081
1082 // if (corners[i].Z > maxZ)
1083 // maxZ = corners[i].Y;
1084 // if (corners[i].Z < minZ)
1085 // minZ = corners[i].Z;
1086 //}
1087
837 frontTopLeft = frontTopLeft * worldRot; 1088 frontTopLeft = frontTopLeft * worldRot;
838 frontTopRight = frontTopRight * worldRot; 1089 frontTopRight = frontTopRight * worldRot;
839 frontBottomLeft = frontBottomLeft * worldRot; 1090 frontBottomLeft = frontBottomLeft * worldRot;
@@ -855,6 +1106,15 @@ namespace OpenSim.Region.Framework.Scenes
855 backTopLeft += offset; 1106 backTopLeft += offset;
856 backTopRight += offset; 1107 backTopRight += offset;
857 1108
1109 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1110 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1111 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1112 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1113 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1114 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1115 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1116 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1117
858 if (frontTopRight.X > maxX) 1118 if (frontTopRight.X > maxX)
859 maxX = frontTopRight.X; 1119 maxX = frontTopRight.X;
860 if (frontTopLeft.X > maxX) 1120 if (frontTopLeft.X > maxX)
@@ -998,17 +1258,118 @@ namespace OpenSim.Region.Framework.Scenes
998 1258
999 #endregion 1259 #endregion
1000 1260
1261 public void GetResourcesCosts(SceneObjectPart apart,
1262 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost)
1263 {
1264 // this information may need to be cached
1265
1266 float cost;
1267 float tmpcost;
1268
1269 bool ComplexCost = false;
1270
1271 SceneObjectPart p;
1272 SceneObjectPart[] parts;
1273
1274 lock (m_parts)
1275 {
1276 parts = m_parts.GetArray();
1277 }
1278
1279 int nparts = parts.Length;
1280
1281
1282 for (int i = 0; i < nparts; i++)
1283 {
1284 p = parts[i];
1285
1286 if (p.UsesComplexCost)
1287 {
1288 ComplexCost = true;
1289 break;
1290 }
1291 }
1292
1293 if (ComplexCost)
1294 {
1295 linksetResCost = 0;
1296 linksetPhysCost = 0;
1297 partCost = 0;
1298 partPhysCost = 0;
1299
1300 for (int i = 0; i < nparts; i++)
1301 {
1302 p = parts[i];
1303
1304 cost = p.StreamingCost;
1305 tmpcost = p.SimulationCost;
1306 if (tmpcost > cost)
1307 cost = tmpcost;
1308 tmpcost = p.PhysicsCost;
1309 if (tmpcost > cost)
1310 cost = tmpcost;
1311
1312 linksetPhysCost += tmpcost;
1313 linksetResCost += cost;
1314
1315 if (p == apart)
1316 {
1317 partCost = cost;
1318 partPhysCost = tmpcost;
1319 }
1320 }
1321 }
1322 else
1323 {
1324 partPhysCost = 1.0f;
1325 partCost = 1.0f;
1326 linksetResCost = (float)nparts;
1327 linksetPhysCost = linksetResCost;
1328 }
1329 }
1330
1331 public void GetSelectedCosts(out float PhysCost, out float StreamCost, out float SimulCost)
1332 {
1333 SceneObjectPart p;
1334 SceneObjectPart[] parts;
1335
1336 lock (m_parts)
1337 {
1338 parts = m_parts.GetArray();
1339 }
1340
1341 int nparts = parts.Length;
1342
1343 PhysCost = 0;
1344 StreamCost = 0;
1345 SimulCost = 0;
1346
1347 for (int i = 0; i < nparts; i++)
1348 {
1349 p = parts[i];
1350
1351 StreamCost += p.StreamingCost;
1352 SimulCost += p.SimulationCost;
1353 PhysCost += p.PhysicsCost;
1354 }
1355 }
1356
1001 public void SaveScriptedState(XmlTextWriter writer) 1357 public void SaveScriptedState(XmlTextWriter writer)
1002 { 1358 {
1359 SaveScriptedState(writer, false);
1360 }
1361
1362 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1363 {
1003 XmlDocument doc = new XmlDocument(); 1364 XmlDocument doc = new XmlDocument();
1004 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1365 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
1005 1366
1006 SceneObjectPart[] parts = m_parts.GetArray(); 1367 SceneObjectPart[] parts = m_parts.GetArray();
1007 for (int i = 0; i < parts.Length; i++) 1368 for (int i = 0; i < parts.Length; i++)
1008 { 1369 {
1009 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1370 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
1010 foreach (KeyValuePair<UUID, string> kvp in pstates) 1371 foreach (KeyValuePair<UUID, string> kvp in pstates)
1011 states.Add(kvp.Key, kvp.Value); 1372 states[kvp.Key] = kvp.Value;
1012 } 1373 }
1013 1374
1014 if (states.Count > 0) 1375 if (states.Count > 0)
@@ -1028,6 +1389,169 @@ namespace OpenSim.Region.Framework.Scenes
1028 } 1389 }
1029 1390
1030 /// <summary> 1391 /// <summary>
1392 /// Add the avatar to this linkset (avatar is sat).
1393 /// </summary>
1394 /// <param name="agentID"></param>
1395 public void AddAvatar(UUID agentID)
1396 {
1397 ScenePresence presence;
1398 if (m_scene.TryGetScenePresence(agentID, out presence))
1399 {
1400 if (!m_linkedAvatars.Contains(presence))
1401 {
1402 m_linkedAvatars.Add(presence);
1403 }
1404 }
1405 }
1406
1407 /// <summary>
1408 /// Delete the avatar from this linkset (avatar is unsat).
1409 /// </summary>
1410 /// <param name="agentID"></param>
1411 public void DeleteAvatar(UUID agentID)
1412 {
1413 ScenePresence presence;
1414 if (m_scene.TryGetScenePresence(agentID, out presence))
1415 {
1416 if (m_linkedAvatars.Contains(presence))
1417 {
1418 m_linkedAvatars.Remove(presence);
1419 }
1420 }
1421 }
1422
1423 /// <summary>
1424 /// Returns the list of linked presences (avatars sat on this group)
1425 /// </summary>
1426 /// <param name="agentID"></param>
1427 public List<ScenePresence> GetLinkedAvatars()
1428 {
1429 return m_linkedAvatars;
1430 }
1431
1432 /// <summary>
1433 /// Attach this scene object to the given avatar.
1434 /// </summary>
1435 /// <param name="agentID"></param>
1436 /// <param name="attachmentpoint"></param>
1437 /// <param name="AttachOffset"></param>
1438 private void AttachToAgent(
1439 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1440 {
1441 if (avatar != null)
1442 {
1443 // don't attach attachments to child agents
1444 if (avatar.IsChildAgent) return;
1445
1446 // Remove from database and parcel prim count
1447 m_scene.DeleteFromStorage(so.UUID);
1448 m_scene.EventManager.TriggerParcelPrimCountTainted();
1449
1450 so.AttachedAvatar = avatar.UUID;
1451
1452 if (so.RootPart.PhysActor != null)
1453 {
1454 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1455 so.RootPart.PhysActor = null;
1456 }
1457
1458 so.AbsolutePosition = attachOffset;
1459 so.RootPart.AttachedPos = attachOffset;
1460 so.IsAttachment = true;
1461 so.RootPart.SetParentLocalId(avatar.LocalId);
1462 so.AttachmentPoint = attachmentpoint;
1463
1464 avatar.AddAttachment(this);
1465
1466 if (!silent)
1467 {
1468 // Killing it here will cause the client to deselect it
1469 // It then reappears on the avatar, deselected
1470 // through the full update below
1471 //
1472 if (IsSelected)
1473 {
1474 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1475 }
1476
1477 IsSelected = false; // fudge....
1478 ScheduleGroupForFullUpdate();
1479 }
1480 }
1481 else
1482 {
1483 m_log.WarnFormat(
1484 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1485 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1486 }
1487 }
1488
1489 public byte GetAttachmentPoint()
1490 {
1491 return m_rootPart.Shape.State;
1492 }
1493
1494 public void DetachToGround()
1495 {
1496 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1497 if (avatar == null)
1498 return;
1499
1500 avatar.RemoveAttachment(this);
1501
1502 Vector3 detachedpos = new Vector3(127f,127f,127f);
1503 if (avatar == null)
1504 return;
1505
1506 detachedpos = avatar.AbsolutePosition;
1507 FromItemID = UUID.Zero;
1508
1509 AbsolutePosition = detachedpos;
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 AttachmentPoint = (byte)0;
1518 // must check if buildind should be true or false here
1519 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1520 HasGroupChanged = true;
1521 RootPart.Rezzed = DateTime.Now;
1522 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1523 AttachToBackup();
1524 m_scene.EventManager.TriggerParcelPrimCountTainted();
1525 m_rootPart.ScheduleFullUpdate();
1526 m_rootPart.ClearUndoState();
1527 }
1528
1529 public void DetachToInventoryPrep()
1530 {
1531 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1532 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1533 if (avatar != null)
1534 {
1535 //detachedpos = avatar.AbsolutePosition;
1536 avatar.RemoveAttachment(this);
1537 }
1538
1539 AttachedAvatar = UUID.Zero;
1540
1541 /*SceneObjectPart[] parts = m_parts.GetArray();
1542 for (int i = 0; i < parts.Length; i++)
1543 parts[i].AttachedAvatar = UUID.Zero;*/
1544
1545 m_rootPart.SetParentLocalId(0);
1546 //m_rootPart.SetAttachmentPoint((byte)0);
1547 IsAttachment = false;
1548 AbsolutePosition = m_rootPart.AttachedPos;
1549 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1550 //AttachToBackup();
1551 //m_rootPart.ScheduleFullUpdate();
1552 }
1553
1554 /// <summary>
1031 /// 1555 ///
1032 /// </summary> 1556 /// </summary>
1033 /// <param name="part"></param> 1557 /// <param name="part"></param>
@@ -1077,7 +1601,10 @@ namespace OpenSim.Region.Framework.Scenes
1077 public void AddPart(SceneObjectPart part) 1601 public void AddPart(SceneObjectPart part)
1078 { 1602 {
1079 part.SetParent(this); 1603 part.SetParent(this);
1080 part.LinkNum = m_parts.Add(part.UUID, part); 1604 m_parts.Add(part.UUID, part);
1605
1606 part.LinkNum = m_parts.Count;
1607
1081 if (part.LinkNum == 2) 1608 if (part.LinkNum == 2)
1082 RootPart.LinkNum = 1; 1609 RootPart.LinkNum = 1;
1083 } 1610 }
@@ -1165,7 +1692,7 @@ namespace OpenSim.Region.Framework.Scenes
1165// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 1692// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1166// remoteClient.Name, part.Name, part.LocalId, offsetPos); 1693// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1167 1694
1168 part.StoreUndoState(); 1695// part.StoreUndoState();
1169 part.OnGrab(offsetPos, remoteClient); 1696 part.OnGrab(offsetPos, remoteClient);
1170 } 1697 }
1171 1698
@@ -1185,6 +1712,11 @@ namespace OpenSim.Region.Framework.Scenes
1185 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1712 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1186 public void DeleteGroupFromScene(bool silent) 1713 public void DeleteGroupFromScene(bool silent)
1187 { 1714 {
1715 // We need to keep track of this state in case this group is still queued for backup.
1716 IsDeleted = true;
1717
1718 DetachFromBackup();
1719
1188 SceneObjectPart[] parts = m_parts.GetArray(); 1720 SceneObjectPart[] parts = m_parts.GetArray();
1189 for (int i = 0; i < parts.Length; i++) 1721 for (int i = 0; i < parts.Length; i++)
1190 { 1722 {
@@ -1207,6 +1739,8 @@ namespace OpenSim.Region.Framework.Scenes
1207 } 1739 }
1208 }); 1740 });
1209 } 1741 }
1742
1743
1210 } 1744 }
1211 1745
1212 public void AddScriptLPS(int count) 1746 public void AddScriptLPS(int count)
@@ -1276,28 +1810,43 @@ namespace OpenSim.Region.Framework.Scenes
1276 /// </summary> 1810 /// </summary>
1277 public void ApplyPhysics() 1811 public void ApplyPhysics()
1278 { 1812 {
1279 // Apply physics to the root prim
1280 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1281
1282 // Apply physics to child prims
1283 SceneObjectPart[] parts = m_parts.GetArray(); 1813 SceneObjectPart[] parts = m_parts.GetArray();
1284 if (parts.Length > 1) 1814 if (parts.Length > 1)
1285 { 1815 {
1816 ResetChildPrimPhysicsPositions();
1817
1818 // Apply physics to the root prim
1819 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
1820
1821
1286 for (int i = 0; i < parts.Length; i++) 1822 for (int i = 0; i < parts.Length; i++)
1287 { 1823 {
1288 SceneObjectPart part = parts[i]; 1824 SceneObjectPart part = parts[i];
1289 if (part.LocalId != m_rootPart.LocalId) 1825 if (part.LocalId != m_rootPart.LocalId)
1290 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 1826 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1291 } 1827 }
1292
1293 // Hack to get the physics scene geometries in the right spot 1828 // Hack to get the physics scene geometries in the right spot
1294 ResetChildPrimPhysicsPositions(); 1829// ResetChildPrimPhysicsPositions();
1830 if (m_rootPart.PhysActor != null)
1831 {
1832 m_rootPart.PhysActor.Building = false;
1833 }
1834 }
1835 else
1836 {
1837 // Apply physics to the root prim
1838 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1295 } 1839 }
1296 } 1840 }
1297 1841
1298 public void SetOwnerId(UUID userId) 1842 public void SetOwnerId(UUID userId)
1299 { 1843 {
1300 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1844 ForEachPart(delegate(SceneObjectPart part)
1845 {
1846
1847 part.OwnerID = userId;
1848
1849 });
1301 } 1850 }
1302 1851
1303 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1852 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1329,11 +1878,17 @@ namespace OpenSim.Region.Framework.Scenes
1329 return; 1878 return;
1330 } 1879 }
1331 1880
1881 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1882 return;
1883
1332 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1884 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1333 // any exception propogate upwards. 1885 // any exception propogate upwards.
1334 try 1886 try
1335 { 1887 {
1336 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1888 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1889 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1890 m_scene.LoadingPrims) // Land may not be valid yet
1891
1337 { 1892 {
1338 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1893 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1339 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1894 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1360,6 +1915,7 @@ namespace OpenSim.Region.Framework.Scenes
1360 } 1915 }
1361 } 1916 }
1362 } 1917 }
1918
1363 } 1919 }
1364 1920
1365 if (m_scene.UseBackup && HasGroupChanged) 1921 if (m_scene.UseBackup && HasGroupChanged)
@@ -1367,6 +1923,20 @@ namespace OpenSim.Region.Framework.Scenes
1367 // don't backup while it's selected or you're asking for changes mid stream. 1923 // don't backup while it's selected or you're asking for changes mid stream.
1368 if (isTimeToPersist() || forcedBackup) 1924 if (isTimeToPersist() || forcedBackup)
1369 { 1925 {
1926 if (m_rootPart.PhysActor != null &&
1927 (!m_rootPart.PhysActor.IsPhysical))
1928 {
1929 // Possible ghost prim
1930 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1931 {
1932 foreach (SceneObjectPart part in m_parts.GetArray())
1933 {
1934 // Re-set physics actor positions and
1935 // orientations
1936 part.GroupPosition = m_rootPart.GroupPosition;
1937 }
1938 }
1939 }
1370// m_log.DebugFormat( 1940// m_log.DebugFormat(
1371// "[SCENE]: Storing {0}, {1} in {2}", 1941// "[SCENE]: Storing {0}, {1} in {2}",
1372// Name, UUID, m_scene.RegionInfo.RegionName); 1942// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1384,6 +1954,11 @@ namespace OpenSim.Region.Framework.Scenes
1384 1954
1385 backup_group.ForEachPart(delegate(SceneObjectPart part) 1955 backup_group.ForEachPart(delegate(SceneObjectPart part)
1386 { 1956 {
1957 if (part.KeyframeMotion != null)
1958 {
1959 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize());
1960 part.KeyframeMotion.UpdateSceneObject(this);
1961 }
1387 part.Inventory.ProcessInventoryBackup(datastore); 1962 part.Inventory.ProcessInventoryBackup(datastore);
1388 }); 1963 });
1389 1964
@@ -1436,6 +2011,7 @@ namespace OpenSim.Region.Framework.Scenes
1436 /// <returns></returns> 2011 /// <returns></returns>
1437 public SceneObjectGroup Copy(bool userExposed) 2012 public SceneObjectGroup Copy(bool userExposed)
1438 { 2013 {
2014 m_dupeInProgress = true;
1439 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 2015 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1440 dupe.m_isBackedUp = false; 2016 dupe.m_isBackedUp = false;
1441 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 2017 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
@@ -1450,7 +2026,7 @@ namespace OpenSim.Region.Framework.Scenes
1450 // This is only necessary when userExposed is false! 2026 // This is only necessary when userExposed is false!
1451 2027
1452 bool previousAttachmentStatus = dupe.IsAttachment; 2028 bool previousAttachmentStatus = dupe.IsAttachment;
1453 2029
1454 if (!userExposed) 2030 if (!userExposed)
1455 dupe.IsAttachment = true; 2031 dupe.IsAttachment = true;
1456 2032
@@ -1468,11 +2044,11 @@ namespace OpenSim.Region.Framework.Scenes
1468 dupe.m_rootPart.TrimPermissions(); 2044 dupe.m_rootPart.TrimPermissions();
1469 2045
1470 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 2046 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1471 2047
1472 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 2048 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1473 { 2049 {
1474 return p1.LinkNum.CompareTo(p2.LinkNum); 2050 return p1.LinkNum.CompareTo(p2.LinkNum);
1475 } 2051 }
1476 ); 2052 );
1477 2053
1478 foreach (SceneObjectPart part in partList) 2054 foreach (SceneObjectPart part in partList)
@@ -1482,41 +2058,53 @@ namespace OpenSim.Region.Framework.Scenes
1482 { 2058 {
1483 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2059 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1484 newPart.LinkNum = part.LinkNum; 2060 newPart.LinkNum = part.LinkNum;
1485 } 2061 if (userExposed)
2062 newPart.ParentID = dupe.m_rootPart.LocalId;
2063 }
1486 else 2064 else
1487 { 2065 {
1488 newPart = dupe.m_rootPart; 2066 newPart = dupe.m_rootPart;
1489 } 2067 }
2068/*
2069 bool isphys = ((newPart.Flags & PrimFlags.Physics) != 0);
2070 bool isphan = ((newPart.Flags & PrimFlags.Phantom) != 0);
1490 2071
1491 // Need to duplicate the physics actor as well 2072 // Need to duplicate the physics actor as well
1492 PhysicsActor originalPartPa = part.PhysActor; 2073 if (userExposed && (isphys || !isphan || newPart.VolumeDetectActive))
1493 if (originalPartPa != null && userExposed)
1494 { 2074 {
1495 PrimitiveBaseShape pbs = newPart.Shape; 2075 PrimitiveBaseShape pbs = newPart.Shape;
1496
1497 newPart.PhysActor 2076 newPart.PhysActor
1498 = m_scene.PhysicsScene.AddPrimShape( 2077 = m_scene.PhysicsScene.AddPrimShape(
1499 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 2078 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1500 pbs, 2079 pbs,
1501 newPart.AbsolutePosition, 2080 newPart.AbsolutePosition,
1502 newPart.Scale, 2081 newPart.Scale,
1503 newPart.RotationOffset, 2082 newPart.GetWorldRotation(),
1504 originalPartPa.IsPhysical, 2083 isphys,
2084 isphan,
1505 newPart.LocalId); 2085 newPart.LocalId);
1506 2086
1507 newPart.DoPhysicsPropertyUpdate(originalPartPa.IsPhysical, true); 2087 newPart.DoPhysicsPropertyUpdate(isphys, true);
1508 } 2088 */
2089 if (userExposed)
2090 newPart.ApplyPhysics((uint)newPart.Flags,newPart.VolumeDetectActive,true);
2091// }
1509 } 2092 }
1510 2093
1511 if (userExposed) 2094 if (userExposed)
1512 { 2095 {
1513 dupe.UpdateParentIDs(); 2096// done above dupe.UpdateParentIDs();
2097
2098 if (dupe.m_rootPart.PhysActor != null)
2099 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
2100
1514 dupe.HasGroupChanged = true; 2101 dupe.HasGroupChanged = true;
1515 dupe.AttachToBackup(); 2102 dupe.AttachToBackup();
1516 2103
1517 ScheduleGroupForFullUpdate(); 2104 ScheduleGroupForFullUpdate();
1518 } 2105 }
1519 2106
2107 m_dupeInProgress = false;
1520 return dupe; 2108 return dupe;
1521 } 2109 }
1522 2110
@@ -1528,11 +2116,24 @@ namespace OpenSim.Region.Framework.Scenes
1528 /// <param name="cGroupID"></param> 2116 /// <param name="cGroupID"></param>
1529 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2117 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1530 { 2118 {
1531 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2119 // SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed));
2120 // give newpart a new local ID lettng old part keep same
2121 SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2122 newpart.LocalId = m_scene.AllocateLocalId();
2123
2124 SetRootPart(newpart);
2125 if (userExposed)
2126 RootPart.Velocity = Vector3.Zero; // In case source is moving
1532 } 2127 }
1533 2128
1534 public void ScriptSetPhysicsStatus(bool usePhysics) 2129 public void ScriptSetPhysicsStatus(bool usePhysics)
1535 { 2130 {
2131 if (usePhysics)
2132 {
2133 if (RootPart.KeyframeMotion != null)
2134 RootPart.KeyframeMotion.Stop();
2135 RootPart.KeyframeMotion = null;
2136 }
1536 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2137 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1537 } 2138 }
1538 2139
@@ -1586,7 +2187,7 @@ namespace OpenSim.Region.Framework.Scenes
1586 } 2187 }
1587 } 2188 }
1588 2189
1589 public void applyAngularImpulse(Vector3 impulse) 2190 public void ApplyAngularImpulse(Vector3 impulse)
1590 { 2191 {
1591 PhysicsActor pa = RootPart.PhysActor; 2192 PhysicsActor pa = RootPart.PhysActor;
1592 2193
@@ -1600,36 +2201,12 @@ namespace OpenSim.Region.Framework.Scenes
1600 } 2201 }
1601 } 2202 }
1602 2203
1603 public void setAngularImpulse(Vector3 impulse)
1604 {
1605 PhysicsActor pa = RootPart.PhysActor;
1606
1607 if (pa != null)
1608 {
1609 if (!IsAttachment)
1610 {
1611 pa.Torque = impulse;
1612 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1613 }
1614 }
1615 }
1616
1617 public Vector3 GetTorque() 2204 public Vector3 GetTorque()
1618 { 2205 {
1619 PhysicsActor pa = RootPart.PhysActor; 2206 return RootPart.Torque;
1620
1621 if (pa != null)
1622 {
1623 if (!IsAttachment)
1624 {
1625 Vector3 torque = pa.Torque;
1626 return torque;
1627 }
1628 }
1629
1630 return Vector3.Zero;
1631 } 2207 }
1632 2208
2209 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1633 public void moveToTarget(Vector3 target, float tau) 2210 public void moveToTarget(Vector3 target, float tau)
1634 { 2211 {
1635 if (IsAttachment) 2212 if (IsAttachment)
@@ -1661,6 +2238,46 @@ namespace OpenSim.Region.Framework.Scenes
1661 pa.PIDActive = false; 2238 pa.PIDActive = false;
1662 } 2239 }
1663 2240
2241 public void rotLookAt(Quaternion target, float strength, float damping)
2242 {
2243 SceneObjectPart rootpart = m_rootPart;
2244 if (rootpart != null)
2245 {
2246 if (IsAttachment)
2247 {
2248 /*
2249 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2250 if (avatar != null)
2251 {
2252 Rotate the Av?
2253 } */
2254 }
2255 else
2256 {
2257 if (rootpart.PhysActor != null)
2258 { // APID must be implemented in your physics system for this to function.
2259 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2260 rootpart.PhysActor.APIDStrength = strength;
2261 rootpart.PhysActor.APIDDamping = damping;
2262 rootpart.PhysActor.APIDActive = true;
2263 }
2264 }
2265 }
2266 }
2267
2268 public void stopLookAt()
2269 {
2270 SceneObjectPart rootpart = m_rootPart;
2271 if (rootpart != null)
2272 {
2273 if (rootpart.PhysActor != null)
2274 { // APID must be implemented in your physics system for this to function.
2275 rootpart.PhysActor.APIDActive = false;
2276 }
2277 }
2278
2279 }
2280
1664 /// <summary> 2281 /// <summary>
1665 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2282 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1666 /// </summary> 2283 /// </summary>
@@ -1717,7 +2334,12 @@ namespace OpenSim.Region.Framework.Scenes
1717 /// <param name="cGroupID"></param> 2334 /// <param name="cGroupID"></param>
1718 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2335 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1719 { 2336 {
1720 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2337 // give new ID to the new part, letting old keep original
2338 // SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2339 SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2340 newPart.LocalId = m_scene.AllocateLocalId();
2341 newPart.SetParent(this);
2342
1721 AddPart(newPart); 2343 AddPart(newPart);
1722 2344
1723 SetPartAsNonRoot(newPart); 2345 SetPartAsNonRoot(newPart);
@@ -1846,11 +2468,11 @@ namespace OpenSim.Region.Framework.Scenes
1846 /// Immediately send a full update for this scene object. 2468 /// Immediately send a full update for this scene object.
1847 /// </summary> 2469 /// </summary>
1848 public void SendGroupFullUpdate() 2470 public void SendGroupFullUpdate()
1849 { 2471 {
1850 if (IsDeleted) 2472 if (IsDeleted)
1851 return; 2473 return;
1852 2474
1853// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2475// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1854 2476
1855 RootPart.SendFullUpdateToAllClients(); 2477 RootPart.SendFullUpdateToAllClients();
1856 2478
@@ -1965,6 +2587,11 @@ namespace OpenSim.Region.Framework.Scenes
1965 /// <param name="objectGroup">The group of prims which should be linked to this group</param> 2587 /// <param name="objectGroup">The group of prims which should be linked to this group</param>
1966 public void LinkToGroup(SceneObjectGroup objectGroup) 2588 public void LinkToGroup(SceneObjectGroup objectGroup)
1967 { 2589 {
2590 LinkToGroup(objectGroup, false);
2591 }
2592
2593 public void LinkToGroup(SceneObjectGroup objectGroup, bool insert)
2594 {
1968// m_log.DebugFormat( 2595// m_log.DebugFormat(
1969// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", 2596// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
1970// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); 2597// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
@@ -1975,6 +2602,15 @@ namespace OpenSim.Region.Framework.Scenes
1975 2602
1976 SceneObjectPart linkPart = objectGroup.m_rootPart; 2603 SceneObjectPart linkPart = objectGroup.m_rootPart;
1977 2604
2605 if (m_rootPart.PhysActor != null)
2606 m_rootPart.PhysActor.Building = true;
2607 if (linkPart.PhysActor != null)
2608 linkPart.PhysActor.Building = true;
2609
2610 // physics flags from group to be applied to linked parts
2611 bool grpusephys = UsesPhysics;
2612 bool grptemporary = IsTemporary;
2613
1978 Vector3 oldGroupPosition = linkPart.GroupPosition; 2614 Vector3 oldGroupPosition = linkPart.GroupPosition;
1979 Quaternion oldRootRotation = linkPart.RotationOffset; 2615 Quaternion oldRootRotation = linkPart.RotationOffset;
1980 2616
@@ -1998,13 +2634,34 @@ namespace OpenSim.Region.Framework.Scenes
1998 2634
1999 lock (m_parts.SyncRoot) 2635 lock (m_parts.SyncRoot)
2000 { 2636 {
2001 int linkNum = PrimCount + 1; 2637 int linkNum;
2638 if (insert)
2639 {
2640 linkNum = 2;
2641 foreach (SceneObjectPart part in Parts)
2642 {
2643 if (part.LinkNum > 1)
2644 part.LinkNum++;
2645 }
2646 }
2647 else
2648 {
2649 linkNum = PrimCount + 1;
2650 }
2002 2651
2003 m_parts.Add(linkPart.UUID, linkPart); 2652 m_parts.Add(linkPart.UUID, linkPart);
2004 2653
2005 linkPart.SetParent(this); 2654 linkPart.SetParent(this);
2006 linkPart.CreateSelected = true; 2655 linkPart.CreateSelected = true;
2007 2656
2657 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
2658 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true);
2659 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2660 {
2661 linkPart.PhysActor.link(m_rootPart.PhysActor);
2662 this.Scene.PhysicsScene.AddPhysicsActorTaint(linkPart.PhysActor);
2663 }
2664
2008 linkPart.LinkNum = linkNum++; 2665 linkPart.LinkNum = linkNum++;
2009 2666
2010 SceneObjectPart[] ogParts = objectGroup.Parts; 2667 SceneObjectPart[] ogParts = objectGroup.Parts;
@@ -2017,7 +2674,16 @@ namespace OpenSim.Region.Framework.Scenes
2017 { 2674 {
2018 SceneObjectPart part = ogParts[i]; 2675 SceneObjectPart part = ogParts[i];
2019 if (part.UUID != objectGroup.m_rootPart.UUID) 2676 if (part.UUID != objectGroup.m_rootPart.UUID)
2677 {
2020 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); 2678 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2679 // let physics know
2680 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true);
2681 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2682 {
2683 part.PhysActor.link(m_rootPart.PhysActor);
2684 this.Scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2685 }
2686 }
2021 part.ClearUndoState(); 2687 part.ClearUndoState();
2022 } 2688 }
2023 } 2689 }
@@ -2026,7 +2692,7 @@ namespace OpenSim.Region.Framework.Scenes
2026 objectGroup.IsDeleted = true; 2692 objectGroup.IsDeleted = true;
2027 2693
2028 objectGroup.m_parts.Clear(); 2694 objectGroup.m_parts.Clear();
2029 2695
2030 // Can't do this yet since backup still makes use of the root part without any synchronization 2696 // Can't do this yet since backup still makes use of the root part without any synchronization
2031// objectGroup.m_rootPart = null; 2697// objectGroup.m_rootPart = null;
2032 2698
@@ -2037,6 +2703,9 @@ namespace OpenSim.Region.Framework.Scenes
2037 // unmoved prims! 2703 // unmoved prims!
2038 ResetChildPrimPhysicsPositions(); 2704 ResetChildPrimPhysicsPositions();
2039 2705
2706 if (m_rootPart.PhysActor != null)
2707 m_rootPart.PhysActor.Building = false;
2708
2040 //HasGroupChanged = true; 2709 //HasGroupChanged = true;
2041 //ScheduleGroupForFullUpdate(); 2710 //ScheduleGroupForFullUpdate();
2042 } 2711 }
@@ -2089,7 +2758,10 @@ namespace OpenSim.Region.Framework.Scenes
2089// m_log.DebugFormat( 2758// m_log.DebugFormat(
2090// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", 2759// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2091// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); 2760// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2092 2761
2762 if (m_rootPart.PhysActor != null)
2763 m_rootPart.PhysActor.Building = true;
2764
2093 linkPart.ClearUndoState(); 2765 linkPart.ClearUndoState();
2094 2766
2095 Quaternion worldRot = linkPart.GetWorldRotation(); 2767 Quaternion worldRot = linkPart.GetWorldRotation();
@@ -2149,6 +2821,14 @@ namespace OpenSim.Region.Framework.Scenes
2149 2821
2150 // When we delete a group, we currently have to force persist to the database if the object id has changed 2822 // When we delete a group, we currently have to force persist to the database if the object id has changed
2151 // (since delete works by deleting all rows which have a given object id) 2823 // (since delete works by deleting all rows which have a given object id)
2824
2825 // this is as it seems to be in sl now
2826 if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none)
2827 linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now
2828
2829 if (m_rootPart.PhysActor != null)
2830 m_rootPart.PhysActor.Building = false;
2831
2152 objectGroup.HasGroupChangedDueToDelink = true; 2832 objectGroup.HasGroupChangedDueToDelink = true;
2153 2833
2154 return objectGroup; 2834 return objectGroup;
@@ -2160,6 +2840,7 @@ namespace OpenSim.Region.Framework.Scenes
2160 /// <param name="objectGroup"></param> 2840 /// <param name="objectGroup"></param>
2161 public virtual void DetachFromBackup() 2841 public virtual void DetachFromBackup()
2162 { 2842 {
2843 m_scene.SceneGraph.FireDetachFromBackup(this);
2163 if (m_isBackedUp && Scene != null) 2844 if (m_isBackedUp && Scene != null)
2164 m_scene.EventManager.OnBackup -= ProcessBackup; 2845 m_scene.EventManager.OnBackup -= ProcessBackup;
2165 2846
@@ -2178,7 +2859,8 @@ namespace OpenSim.Region.Framework.Scenes
2178 2859
2179 axPos *= parentRot; 2860 axPos *= parentRot;
2180 part.OffsetPosition = axPos; 2861 part.OffsetPosition = axPos;
2181 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2862 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2863 part.GroupPosition = newPos;
2182 part.OffsetPosition = Vector3.Zero; 2864 part.OffsetPosition = Vector3.Zero;
2183 part.RotationOffset = worldRot; 2865 part.RotationOffset = worldRot;
2184 2866
@@ -2189,7 +2871,7 @@ namespace OpenSim.Region.Framework.Scenes
2189 2871
2190 part.LinkNum = linkNum; 2872 part.LinkNum = linkNum;
2191 2873
2192 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2874 part.OffsetPosition = newPos - AbsolutePosition;
2193 2875
2194 Quaternion rootRotation = m_rootPart.RotationOffset; 2876 Quaternion rootRotation = m_rootPart.RotationOffset;
2195 2877
@@ -2199,7 +2881,7 @@ namespace OpenSim.Region.Framework.Scenes
2199 2881
2200 parentRot = m_rootPart.RotationOffset; 2882 parentRot = m_rootPart.RotationOffset;
2201 oldRot = part.RotationOffset; 2883 oldRot = part.RotationOffset;
2202 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2884 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2203 part.RotationOffset = newRot; 2885 part.RotationOffset = newRot;
2204 } 2886 }
2205 2887
@@ -2451,8 +3133,31 @@ namespace OpenSim.Region.Framework.Scenes
2451 } 3133 }
2452 } 3134 }
2453 3135
3136/*
3137 RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2454 for (int i = 0; i < parts.Length; i++) 3138 for (int i = 0; i < parts.Length; i++)
2455 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 3139 {
3140 if (parts[i] != RootPart)
3141 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
3142 }
3143*/
3144 if (parts.Length > 1)
3145 {
3146 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3147
3148 for (int i = 0; i < parts.Length; i++)
3149 {
3150
3151 if (parts[i].UUID != m_rootPart.UUID)
3152 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3153 }
3154
3155 if (m_rootPart.PhysActor != null)
3156 m_rootPart.PhysActor.Building = false;
3157 }
3158 else
3159 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
3160
2456 } 3161 }
2457 } 3162 }
2458 3163
@@ -2465,6 +3170,17 @@ namespace OpenSim.Region.Framework.Scenes
2465 } 3170 }
2466 } 3171 }
2467 3172
3173
3174
3175 /// <summary>
3176 /// Gets the number of parts
3177 /// </summary>
3178 /// <returns></returns>
3179 public int GetPartCount()
3180 {
3181 return Parts.Count();
3182 }
3183
2468 /// <summary> 3184 /// <summary>
2469 /// Update the texture entry for this part 3185 /// Update the texture entry for this part
2470 /// </summary> 3186 /// </summary>
@@ -2526,11 +3242,6 @@ namespace OpenSim.Region.Framework.Scenes
2526 /// <param name="scale"></param> 3242 /// <param name="scale"></param>
2527 public void GroupResize(Vector3 scale) 3243 public void GroupResize(Vector3 scale)
2528 { 3244 {
2529// m_log.DebugFormat(
2530// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2531
2532 RootPart.StoreUndoState(true);
2533
2534 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3245 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
2535 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); 3246 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
2536 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); 3247 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
@@ -2557,7 +3268,6 @@ namespace OpenSim.Region.Framework.Scenes
2557 SceneObjectPart obPart = parts[i]; 3268 SceneObjectPart obPart = parts[i];
2558 if (obPart.UUID != m_rootPart.UUID) 3269 if (obPart.UUID != m_rootPart.UUID)
2559 { 3270 {
2560// obPart.IgnoreUndoUpdate = true;
2561 Vector3 oldSize = new Vector3(obPart.Scale); 3271 Vector3 oldSize = new Vector3(obPart.Scale);
2562 3272
2563 float f = 1.0f; 3273 float f = 1.0f;
@@ -2621,8 +3331,6 @@ namespace OpenSim.Region.Framework.Scenes
2621 z *= a; 3331 z *= a;
2622 } 3332 }
2623 } 3333 }
2624
2625// obPart.IgnoreUndoUpdate = false;
2626 } 3334 }
2627 } 3335 }
2628 } 3336 }
@@ -2632,9 +3340,7 @@ namespace OpenSim.Region.Framework.Scenes
2632 prevScale.Y *= y; 3340 prevScale.Y *= y;
2633 prevScale.Z *= z; 3341 prevScale.Z *= z;
2634 3342
2635// RootPart.IgnoreUndoUpdate = true;
2636 RootPart.Resize(prevScale); 3343 RootPart.Resize(prevScale);
2637// RootPart.IgnoreUndoUpdate = false;
2638 3344
2639 parts = m_parts.GetArray(); 3345 parts = m_parts.GetArray();
2640 for (int i = 0; i < parts.Length; i++) 3346 for (int i = 0; i < parts.Length; i++)
@@ -2643,8 +3349,6 @@ namespace OpenSim.Region.Framework.Scenes
2643 3349
2644 if (obPart.UUID != m_rootPart.UUID) 3350 if (obPart.UUID != m_rootPart.UUID)
2645 { 3351 {
2646 obPart.IgnoreUndoUpdate = true;
2647
2648 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3352 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2649 currentpos.X *= x; 3353 currentpos.X *= x;
2650 currentpos.Y *= y; 3354 currentpos.Y *= y;
@@ -2657,16 +3361,12 @@ namespace OpenSim.Region.Framework.Scenes
2657 3361
2658 obPart.Resize(newSize); 3362 obPart.Resize(newSize);
2659 obPart.UpdateOffSet(currentpos); 3363 obPart.UpdateOffSet(currentpos);
2660
2661 obPart.IgnoreUndoUpdate = false;
2662 } 3364 }
2663 3365
2664// obPart.IgnoreUndoUpdate = false; 3366 HasGroupChanged = true;
2665// obPart.StoreUndoState(); 3367 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3368 ScheduleGroupForTerseUpdate();
2666 } 3369 }
2667
2668// m_log.DebugFormat(
2669// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale);
2670 } 3370 }
2671 3371
2672 #endregion 3372 #endregion
@@ -2679,14 +3379,6 @@ namespace OpenSim.Region.Framework.Scenes
2679 /// <param name="pos"></param> 3379 /// <param name="pos"></param>
2680 public void UpdateGroupPosition(Vector3 pos) 3380 public void UpdateGroupPosition(Vector3 pos)
2681 { 3381 {
2682// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
2683
2684 RootPart.StoreUndoState(true);
2685
2686// SceneObjectPart[] parts = m_parts.GetArray();
2687// for (int i = 0; i < parts.Length; i++)
2688// parts[i].StoreUndoState();
2689
2690 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3382 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2691 { 3383 {
2692 if (IsAttachment) 3384 if (IsAttachment)
@@ -2719,21 +3411,17 @@ namespace OpenSim.Region.Framework.Scenes
2719 /// </summary> 3411 /// </summary>
2720 /// <param name="pos"></param> 3412 /// <param name="pos"></param>
2721 /// <param name="localID"></param> 3413 /// <param name="localID"></param>
3414 ///
3415
2722 public void UpdateSinglePosition(Vector3 pos, uint localID) 3416 public void UpdateSinglePosition(Vector3 pos, uint localID)
2723 { 3417 {
2724 SceneObjectPart part = GetPart(localID); 3418 SceneObjectPart part = GetPart(localID);
2725 3419
2726// SceneObjectPart[] parts = m_parts.GetArray();
2727// for (int i = 0; i < parts.Length; i++)
2728// parts[i].StoreUndoState();
2729
2730 if (part != null) 3420 if (part != null)
2731 { 3421 {
2732// m_log.DebugFormat( 3422// unlock parts position change
2733// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); 3423 if (m_rootPart.PhysActor != null)
2734 3424 m_rootPart.PhysActor.Building = true;
2735 part.StoreUndoState(false);
2736 part.IgnoreUndoUpdate = true;
2737 3425
2738 if (part.UUID == m_rootPart.UUID) 3426 if (part.UUID == m_rootPart.UUID)
2739 { 3427 {
@@ -2744,8 +3432,10 @@ namespace OpenSim.Region.Framework.Scenes
2744 part.UpdateOffSet(pos); 3432 part.UpdateOffSet(pos);
2745 } 3433 }
2746 3434
3435 if (m_rootPart.PhysActor != null)
3436 m_rootPart.PhysActor.Building = false;
3437
2747 HasGroupChanged = true; 3438 HasGroupChanged = true;
2748 part.IgnoreUndoUpdate = false;
2749 } 3439 }
2750 } 3440 }
2751 3441
@@ -2755,13 +3445,7 @@ namespace OpenSim.Region.Framework.Scenes
2755 /// <param name="pos"></param> 3445 /// <param name="pos"></param>
2756 public void UpdateRootPosition(Vector3 pos) 3446 public void UpdateRootPosition(Vector3 pos)
2757 { 3447 {
2758// m_log.DebugFormat( 3448 // needs to be called with phys building true
2759// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
2760
2761// SceneObjectPart[] parts = m_parts.GetArray();
2762// for (int i = 0; i < parts.Length; i++)
2763// parts[i].StoreUndoState();
2764
2765 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3449 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2766 Vector3 oldPos = 3450 Vector3 oldPos =
2767 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3451 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
@@ -2784,7 +3468,14 @@ namespace OpenSim.Region.Framework.Scenes
2784 AbsolutePosition = newPos; 3468 AbsolutePosition = newPos;
2785 3469
2786 HasGroupChanged = true; 3470 HasGroupChanged = true;
2787 ScheduleGroupForTerseUpdate(); 3471 if (m_rootPart.Undoing)
3472 {
3473 ScheduleGroupForFullUpdate();
3474 }
3475 else
3476 {
3477 ScheduleGroupForTerseUpdate();
3478 }
2788 } 3479 }
2789 3480
2790 #endregion 3481 #endregion
@@ -2797,17 +3488,6 @@ namespace OpenSim.Region.Framework.Scenes
2797 /// <param name="rot"></param> 3488 /// <param name="rot"></param>
2798 public void UpdateGroupRotationR(Quaternion rot) 3489 public void UpdateGroupRotationR(Quaternion rot)
2799 { 3490 {
2800// m_log.DebugFormat(
2801// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
2802
2803// SceneObjectPart[] parts = m_parts.GetArray();
2804// for (int i = 0; i < parts.Length; i++)
2805// parts[i].StoreUndoState();
2806
2807 m_rootPart.StoreUndoState(true);
2808
2809 m_rootPart.UpdateRotation(rot);
2810
2811 PhysicsActor actor = m_rootPart.PhysActor; 3491 PhysicsActor actor = m_rootPart.PhysActor;
2812 if (actor != null) 3492 if (actor != null)
2813 { 3493 {
@@ -2826,16 +3506,6 @@ namespace OpenSim.Region.Framework.Scenes
2826 /// <param name="rot"></param> 3506 /// <param name="rot"></param>
2827 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 3507 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
2828 { 3508 {
2829// m_log.DebugFormat(
2830// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
2831
2832// SceneObjectPart[] parts = m_parts.GetArray();
2833// for (int i = 0; i < parts.Length; i++)
2834// parts[i].StoreUndoState();
2835
2836 RootPart.StoreUndoState(true);
2837 RootPart.IgnoreUndoUpdate = true;
2838
2839 m_rootPart.UpdateRotation(rot); 3509 m_rootPart.UpdateRotation(rot);
2840 3510
2841 PhysicsActor actor = m_rootPart.PhysActor; 3511 PhysicsActor actor = m_rootPart.PhysActor;
@@ -2849,8 +3519,6 @@ namespace OpenSim.Region.Framework.Scenes
2849 3519
2850 HasGroupChanged = true; 3520 HasGroupChanged = true;
2851 ScheduleGroupForTerseUpdate(); 3521 ScheduleGroupForTerseUpdate();
2852
2853 RootPart.IgnoreUndoUpdate = false;
2854 } 3522 }
2855 3523
2856 /// <summary> 3524 /// <summary>
@@ -2863,13 +3531,11 @@ namespace OpenSim.Region.Framework.Scenes
2863 SceneObjectPart part = GetPart(localID); 3531 SceneObjectPart part = GetPart(localID);
2864 3532
2865 SceneObjectPart[] parts = m_parts.GetArray(); 3533 SceneObjectPart[] parts = m_parts.GetArray();
2866 for (int i = 0; i < parts.Length; i++)
2867 parts[i].StoreUndoState();
2868 3534
2869 if (part != null) 3535 if (part != null)
2870 { 3536 {
2871// m_log.DebugFormat( 3537 if (m_rootPart.PhysActor != null)
2872// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); 3538 m_rootPart.PhysActor.Building = true;
2873 3539
2874 if (part.UUID == m_rootPart.UUID) 3540 if (part.UUID == m_rootPart.UUID)
2875 { 3541 {
@@ -2879,6 +3545,9 @@ namespace OpenSim.Region.Framework.Scenes
2879 { 3545 {
2880 part.UpdateRotation(rot); 3546 part.UpdateRotation(rot);
2881 } 3547 }
3548
3549 if (m_rootPart.PhysActor != null)
3550 m_rootPart.PhysActor.Building = false;
2882 } 3551 }
2883 } 3552 }
2884 3553
@@ -2892,12 +3561,8 @@ namespace OpenSim.Region.Framework.Scenes
2892 SceneObjectPart part = GetPart(localID); 3561 SceneObjectPart part = GetPart(localID);
2893 if (part != null) 3562 if (part != null)
2894 { 3563 {
2895// m_log.DebugFormat( 3564 if (m_rootPart.PhysActor != null)
2896// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", 3565 m_rootPart.PhysActor.Building = true;
2897// part.Name, part.LocalId, rot);
2898
2899 part.StoreUndoState();
2900 part.IgnoreUndoUpdate = true;
2901 3566
2902 if (part.UUID == m_rootPart.UUID) 3567 if (part.UUID == m_rootPart.UUID)
2903 { 3568 {
@@ -2910,7 +3575,8 @@ namespace OpenSim.Region.Framework.Scenes
2910 part.OffsetPosition = pos; 3575 part.OffsetPosition = pos;
2911 } 3576 }
2912 3577
2913 part.IgnoreUndoUpdate = false; 3578 if (m_rootPart.PhysActor != null)
3579 m_rootPart.PhysActor.Building = false;
2914 } 3580 }
2915 } 3581 }
2916 3582
@@ -2920,15 +3586,12 @@ namespace OpenSim.Region.Framework.Scenes
2920 /// <param name="rot"></param> 3586 /// <param name="rot"></param>
2921 public void UpdateRootRotation(Quaternion rot) 3587 public void UpdateRootRotation(Quaternion rot)
2922 { 3588 {
2923// m_log.DebugFormat( 3589 // needs to be called with phys building true
2924// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
2925// Name, LocalId, rot);
2926
2927 Quaternion axRot = rot; 3590 Quaternion axRot = rot;
2928 Quaternion oldParentRot = m_rootPart.RotationOffset; 3591 Quaternion oldParentRot = m_rootPart.RotationOffset;
2929 3592
2930 m_rootPart.StoreUndoState(); 3593 //Don't use UpdateRotation because it schedules an update prematurely
2931 m_rootPart.UpdateRotation(rot); 3594 m_rootPart.RotationOffset = rot;
2932 3595
2933 PhysicsActor pa = m_rootPart.PhysActor; 3596 PhysicsActor pa = m_rootPart.PhysActor;
2934 3597
@@ -2944,35 +3607,135 @@ namespace OpenSim.Region.Framework.Scenes
2944 SceneObjectPart prim = parts[i]; 3607 SceneObjectPart prim = parts[i];
2945 if (prim.UUID != m_rootPart.UUID) 3608 if (prim.UUID != m_rootPart.UUID)
2946 { 3609 {
2947 prim.IgnoreUndoUpdate = true; 3610 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3611 NewRot = Quaternion.Inverse(axRot) * NewRot;
3612 prim.RotationOffset = NewRot;
3613
2948 Vector3 axPos = prim.OffsetPosition; 3614 Vector3 axPos = prim.OffsetPosition;
3615
2949 axPos *= oldParentRot; 3616 axPos *= oldParentRot;
2950 axPos *= Quaternion.Inverse(axRot); 3617 axPos *= Quaternion.Inverse(axRot);
2951 prim.OffsetPosition = axPos; 3618 prim.OffsetPosition = axPos;
2952 Quaternion primsRot = prim.RotationOffset; 3619 }
2953 Quaternion newRot = oldParentRot * primsRot; 3620 }
2954 newRot = Quaternion.Inverse(axRot) * newRot;
2955 prim.RotationOffset = newRot;
2956 prim.ScheduleTerseUpdate();
2957 prim.IgnoreUndoUpdate = false;
2958 }
2959 }
2960
2961// for (int i = 0; i < parts.Length; i++)
2962// {
2963// SceneObjectPart childpart = parts[i];
2964// if (childpart != m_rootPart)
2965// {
2966//// childpart.IgnoreUndoUpdate = false;
2967//// childpart.StoreUndoState();
2968// }
2969// }
2970 3621
2971 m_rootPart.ScheduleTerseUpdate(); 3622 HasGroupChanged = true;
3623 ScheduleGroupForFullUpdate();
3624 }
2972 3625
2973// m_log.DebugFormat( 3626 private enum updatetype :int
2974// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3627 {
2975// Name, LocalId, rot); 3628 none = 0,
3629 partterse = 1,
3630 partfull = 2,
3631 groupterse = 3,
3632 groupfull = 4
3633 }
3634
3635 public void doChangeObject(SceneObjectPart part, ObjectChangeData data)
3636 {
3637 // TODO this still as excessive *.Schedule*Update()s
3638
3639 if (part != null && part.ParentGroup != null)
3640 {
3641 ObjectChangeType change = data.change;
3642 bool togroup = ((change & ObjectChangeType.Group) != 0);
3643 // bool uniform = ((what & ObjectChangeType.UniformScale) != 0); not in use
3644
3645 SceneObjectGroup group = part.ParentGroup;
3646 PhysicsActor pha = group.RootPart.PhysActor;
3647
3648 updatetype updateType = updatetype.none;
3649
3650 if (togroup)
3651 {
3652 // related to group
3653 if ((change & ObjectChangeType.Position) != 0)
3654 {
3655 group.AbsolutePosition = data.position;
3656 updateType = updatetype.groupterse;
3657 }
3658 if ((change & ObjectChangeType.Rotation) != 0)
3659 {
3660 group.RootPart.UpdateRotation(data.rotation);
3661 updateType = updatetype.none;
3662 }
3663 if ((change & ObjectChangeType.Scale) != 0)
3664 {
3665 if (pha != null)
3666 pha.Building = true;
3667
3668 group.GroupResize(data.scale);
3669 updateType = updatetype.none;
3670
3671 if (pha != null)
3672 pha.Building = false;
3673 }
3674 }
3675 else
3676 {
3677 // related to single prim in a link-set ( ie group)
3678 if (pha != null)
3679 pha.Building = true;
3680
3681 // root part is special
3682 // parts offset positions or rotations need to change also
3683
3684 if (part == group.RootPart)
3685 {
3686 if ((change & ObjectChangeType.Position) != 0)
3687 group.UpdateRootPosition(data.position);
3688 if ((change & ObjectChangeType.Rotation) != 0)
3689 group.UpdateRootRotation(data.rotation);
3690 if ((change & ObjectChangeType.Scale) != 0)
3691 part.Resize(data.scale);
3692 }
3693 else
3694 {
3695 if ((change & ObjectChangeType.Position) != 0)
3696 {
3697 part.OffsetPosition = data.position;
3698 updateType = updatetype.partterse;
3699 }
3700 if ((change & ObjectChangeType.Rotation) != 0)
3701 {
3702 part.UpdateRotation(data.rotation);
3703 updateType = updatetype.none;
3704 }
3705 if ((change & ObjectChangeType.Scale) != 0)
3706 {
3707 part.Resize(data.scale);
3708 updateType = updatetype.none;
3709 }
3710 }
3711
3712 if (pha != null)
3713 pha.Building = false;
3714 }
3715
3716 if (updateType != updatetype.none)
3717 {
3718 group.HasGroupChanged = true;
3719
3720 switch (updateType)
3721 {
3722 case updatetype.partterse:
3723 part.ScheduleTerseUpdate();
3724 break;
3725 case updatetype.partfull:
3726 part.ScheduleFullUpdate();
3727 break;
3728 case updatetype.groupterse:
3729 group.ScheduleGroupForTerseUpdate();
3730 break;
3731 case updatetype.groupfull:
3732 group.ScheduleGroupForFullUpdate();
3733 break;
3734 default:
3735 break;
3736 }
3737 }
3738 }
2976 } 3739 }
2977 3740
2978 #endregion 3741 #endregion
@@ -3196,7 +3959,6 @@ namespace OpenSim.Region.Framework.Scenes
3196 public float GetMass() 3959 public float GetMass()
3197 { 3960 {
3198 float retmass = 0f; 3961 float retmass = 0f;
3199
3200 SceneObjectPart[] parts = m_parts.GetArray(); 3962 SceneObjectPart[] parts = m_parts.GetArray();
3201 for (int i = 0; i < parts.Length; i++) 3963 for (int i = 0; i < parts.Length; i++)
3202 retmass += parts[i].GetMass(); 3964 retmass += parts[i].GetMass();
@@ -3318,6 +4080,14 @@ namespace OpenSim.Region.Framework.Scenes
3318 FromItemID = uuid; 4080 FromItemID = uuid;
3319 } 4081 }
3320 4082
4083 public void ResetOwnerChangeFlag()
4084 {
4085 ForEachPart(delegate(SceneObjectPart part)
4086 {
4087 part.ResetOwnerChangeFlag();
4088 });
4089 }
4090
3321 #endregion 4091 #endregion
3322 } 4092 }
3323} 4093}