diff options
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs')
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 1703 |
1 files changed, 1433 insertions, 270 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 866a43c..a703377 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -24,12 +24,13 @@ | |||
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 | ||
28 | using System; | 28 | using System; |
29 | using System.ComponentModel; | 29 | using System.ComponentModel; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Drawing; | 31 | using System.Drawing; |
32 | using System.IO; | 32 | using System.IO; |
33 | using System.Diagnostics; | ||
33 | using System.Linq; | 34 | using System.Linq; |
34 | using System.Threading; | 35 | using System.Threading; |
35 | using System.Xml; | 36 | using System.Xml; |
@@ -44,6 +45,7 @@ using PermissionMask = OpenSim.Framework.PermissionMask; | |||
44 | 45 | ||
45 | namespace OpenSim.Region.Framework.Scenes | 46 | namespace OpenSim.Region.Framework.Scenes |
46 | { | 47 | { |
48 | |||
47 | [Flags] | 49 | [Flags] |
48 | public enum scriptEvents | 50 | public enum scriptEvents |
49 | { | 51 | { |
@@ -79,14 +81,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
79 | object_rez = 4194304 | 81 | object_rez = 4194304 |
80 | } | 82 | } |
81 | 83 | ||
82 | struct scriptPosTarget | 84 | public struct scriptPosTarget |
83 | { | 85 | { |
84 | public Vector3 targetPos; | 86 | public Vector3 targetPos; |
85 | public float tolerance; | 87 | public float tolerance; |
86 | public uint handle; | 88 | public uint handle; |
87 | } | 89 | } |
88 | 90 | ||
89 | struct scriptRotTarget | 91 | public struct scriptRotTarget |
90 | { | 92 | { |
91 | public Quaternion targetRot; | 93 | public Quaternion targetRot; |
92 | public float tolerance; | 94 | public float tolerance; |
@@ -120,8 +122,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
120 | /// since the group's last persistent backup | 122 | /// since the group's last persistent backup |
121 | /// </summary> | 123 | /// </summary> |
122 | private bool m_hasGroupChanged = false; | 124 | private bool m_hasGroupChanged = false; |
125 | <<<<<<< HEAD | ||
123 | private long timeFirstChanged; | 126 | private long timeFirstChanged; |
124 | private long timeLastChanged; | 127 | private long timeLastChanged; |
128 | ======= | ||
129 | private long timeFirstChanged = 0; | ||
130 | private long timeLastChanged = 0; | ||
131 | private long m_maxPersistTime = 0; | ||
132 | private long m_minPersistTime = 0; | ||
133 | // private Random m_rand; | ||
134 | private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>(); | ||
135 | >>>>>>> avn/ubitvar | ||
125 | 136 | ||
126 | /// <summary> | 137 | /// <summary> |
127 | /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage | 138 | /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage |
@@ -138,9 +149,44 @@ namespace OpenSim.Region.Framework.Scenes | |||
138 | { | 149 | { |
139 | if (value) | 150 | if (value) |
140 | { | 151 | { |
152 | |||
153 | if (m_isBackedUp) | ||
154 | { | ||
155 | m_scene.SceneGraph.FireChangeBackup(this); | ||
156 | } | ||
141 | timeLastChanged = DateTime.Now.Ticks; | 157 | timeLastChanged = DateTime.Now.Ticks; |
142 | if (!m_hasGroupChanged) | 158 | if (!m_hasGroupChanged) |
143 | timeFirstChanged = DateTime.Now.Ticks; | 159 | timeFirstChanged = DateTime.Now.Ticks; |
160 | if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null) | ||
161 | { | ||
162 | /* | ||
163 | if (m_rand == null) | ||
164 | { | ||
165 | byte[] val = new byte[16]; | ||
166 | m_rootPart.UUID.ToBytes(val, 0); | ||
167 | m_rand = new Random(BitConverter.ToInt32(val, 0)); | ||
168 | } | ||
169 | */ | ||
170 | if (m_scene.GetRootAgentCount() == 0) | ||
171 | { | ||
172 | //If the region is empty, this change has been made by an automated process | ||
173 | //and thus we delay the persist time by a random amount between 1.5 and 2.5. | ||
174 | |||
175 | // float factor = 1.5f + (float)(m_rand.NextDouble()); | ||
176 | float factor = 2.0f; | ||
177 | m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor); | ||
178 | m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor); | ||
179 | } | ||
180 | else | ||
181 | { | ||
182 | //If the region is not empty, we want to obey the minimum and maximum persist times | ||
183 | //but add a random factor so we stagger the object persistance a little | ||
184 | // m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5 | ||
185 | // m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0 | ||
186 | m_maxPersistTime = m_scene.m_persistAfter; | ||
187 | m_minPersistTime = m_scene.m_dontPersistBefore; | ||
188 | } | ||
189 | } | ||
144 | } | 190 | } |
145 | m_hasGroupChanged = value; | 191 | m_hasGroupChanged = value; |
146 | 192 | ||
@@ -159,6 +205,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
159 | /// the prims in the database still use the old SceneGroupID. That's a problem if the group | 205 | /// the prims in the database still use the old SceneGroupID. That's a problem if the group |
160 | /// is deleted, because we delete groups by searching for prims by their SceneGroupID. | 206 | /// is deleted, because we delete groups by searching for prims by their SceneGroupID. |
161 | /// </summary> | 207 | /// </summary> |
208 | <<<<<<< HEAD | ||
162 | public bool GroupContainsForeignPrims | 209 | public bool GroupContainsForeignPrims |
163 | { | 210 | { |
164 | private set | 211 | private set |
@@ -171,6 +218,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
171 | get { return m_groupContainsForeignPrims; } | 218 | get { return m_groupContainsForeignPrims; } |
172 | } | 219 | } |
173 | 220 | ||
221 | ======= | ||
222 | public bool HasGroupChangedDueToDelink { get; set; } | ||
223 | >>>>>>> avn/ubitvar | ||
174 | 224 | ||
175 | private bool isTimeToPersist() | 225 | private bool isTimeToPersist() |
176 | { | 226 | { |
@@ -180,8 +230,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
180 | return false; | 230 | return false; |
181 | if (m_scene.ShuttingDown) | 231 | if (m_scene.ShuttingDown) |
182 | return true; | 232 | return true; |
233 | |||
234 | if (m_minPersistTime == 0 || m_maxPersistTime == 0) | ||
235 | { | ||
236 | m_maxPersistTime = m_scene.m_persistAfter; | ||
237 | m_minPersistTime = m_scene.m_dontPersistBefore; | ||
238 | } | ||
239 | |||
183 | long currentTime = DateTime.Now.Ticks; | 240 | long currentTime = DateTime.Now.Ticks; |
184 | if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) | 241 | |
242 | if (timeLastChanged == 0) timeLastChanged = currentTime; | ||
243 | if (timeFirstChanged == 0) timeFirstChanged = currentTime; | ||
244 | |||
245 | if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime) | ||
185 | return true; | 246 | return true; |
186 | return false; | 247 | return false; |
187 | } | 248 | } |
@@ -239,6 +300,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
239 | { | 300 | { |
240 | AttachmentPoint = 0; | 301 | AttachmentPoint = 0; |
241 | 302 | ||
303 | // Don't zap trees | ||
304 | if (RootPart.Shape.PCode == (byte)PCode.Tree || | ||
305 | RootPart.Shape.PCode == (byte)PCode.NewTree) | ||
306 | return; | ||
307 | |||
242 | // Even though we don't use child part state parameters for attachments any more, we still need to set | 308 | // Even though we don't use child part state parameters for attachments any more, we still need to set |
243 | // these to zero since having them non-zero in rezzed scene objects will crash some clients. Even if | 309 | // these to zero since having them non-zero in rezzed scene objects will crash some clients. Even if |
244 | // we store them correctly, scene objects that we receive from elsewhere might not. | 310 | // we store them correctly, scene objects that we receive from elsewhere might not. |
@@ -284,6 +350,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
284 | get { return RootPart.VolumeDetectActive; } | 350 | get { return RootPart.VolumeDetectActive; } |
285 | } | 351 | } |
286 | 352 | ||
353 | <<<<<<< HEAD | ||
287 | private Vector3 lastPhysGroupPos; | 354 | private Vector3 lastPhysGroupPos; |
288 | private Quaternion lastPhysGroupRot; | 355 | private Quaternion lastPhysGroupRot; |
289 | 356 | ||
@@ -291,6 +358,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
291 | /// Is this entity set to be saved in persistent storage? | 358 | /// Is this entity set to be saved in persistent storage? |
292 | /// </summary> | 359 | /// </summary> |
293 | public bool Backup { get; private set; } | 360 | public bool Backup { get; private set; } |
361 | ======= | ||
362 | private bool m_isBackedUp; | ||
363 | >>>>>>> avn/ubitvar | ||
364 | |||
365 | public bool IsBackedUp | ||
366 | { | ||
367 | get { return m_isBackedUp; } | ||
368 | } | ||
294 | 369 | ||
295 | protected MapAndArray<UUID, SceneObjectPart> m_parts = new MapAndArray<UUID, SceneObjectPart>(); | 370 | protected MapAndArray<UUID, SceneObjectPart> m_parts = new MapAndArray<UUID, SceneObjectPart>(); |
296 | 371 | ||
@@ -298,15 +373,25 @@ namespace OpenSim.Region.Framework.Scenes | |||
298 | protected SceneObjectPart m_rootPart; | 373 | protected SceneObjectPart m_rootPart; |
299 | // private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>(); | 374 | // private Dictionary<UUID, scriptEvents> m_scriptEvents = new Dictionary<UUID, scriptEvents>(); |
300 | 375 | ||
301 | private Dictionary<uint, scriptPosTarget> m_targets = new Dictionary<uint, scriptPosTarget>(); | 376 | private SortedDictionary<uint, scriptPosTarget> m_targets = new SortedDictionary<uint, scriptPosTarget>(); |
302 | private Dictionary<uint, scriptRotTarget> m_rotTargets = new Dictionary<uint, scriptRotTarget>(); | 377 | private SortedDictionary<uint, scriptRotTarget> m_rotTargets = new SortedDictionary<uint, scriptRotTarget>(); |
378 | |||
379 | public SortedDictionary<uint, scriptPosTarget> AtTargets | ||
380 | { | ||
381 | get { return m_targets; } | ||
382 | } | ||
383 | |||
384 | public SortedDictionary<uint, scriptRotTarget> RotTargets | ||
385 | { | ||
386 | get { return m_rotTargets; } | ||
387 | } | ||
303 | 388 | ||
304 | private bool m_scriptListens_atTarget; | 389 | private bool m_scriptListens_atTarget; |
305 | private bool m_scriptListens_notAtTarget; | 390 | private bool m_scriptListens_notAtTarget; |
306 | |||
307 | private bool m_scriptListens_atRotTarget; | 391 | private bool m_scriptListens_atRotTarget; |
308 | private bool m_scriptListens_notAtRotTarget; | 392 | private bool m_scriptListens_notAtRotTarget; |
309 | 393 | ||
394 | public bool m_dupeInProgress = false; | ||
310 | internal Dictionary<UUID, string> m_savedScriptState; | 395 | internal Dictionary<UUID, string> m_savedScriptState; |
311 | 396 | ||
312 | #region Properties | 397 | #region Properties |
@@ -343,6 +428,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
343 | get { return m_parts.Count; } | 428 | get { return m_parts.Count; } |
344 | } | 429 | } |
345 | 430 | ||
431 | // protected Quaternion m_rotation = Quaternion.Identity; | ||
432 | // | ||
433 | // public virtual Quaternion Rotation | ||
434 | // { | ||
435 | // get { return m_rotation; } | ||
436 | // set { | ||
437 | // m_rotation = value; | ||
438 | // } | ||
439 | // } | ||
440 | |||
346 | public Quaternion GroupRotation | 441 | public Quaternion GroupRotation |
347 | { | 442 | { |
348 | get { return m_rootPart.RotationOffset; } | 443 | get { return m_rootPart.RotationOffset; } |
@@ -456,6 +551,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
456 | public uint ParentID; | 551 | public uint ParentID; |
457 | } | 552 | } |
458 | 553 | ||
554 | |||
555 | public bool inTransit = false; | ||
556 | public delegate SceneObjectGroup SOGCrossDelegate(SceneObjectGroup sog,Vector3 pos); | ||
557 | |||
459 | /// <summary> | 558 | /// <summary> |
460 | /// The absolute position of this scene object in the scene | 559 | /// The absolute position of this scene object in the scene |
461 | /// </summary> | 560 | /// </summary> |
@@ -465,9 +564,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
465 | set | 564 | set |
466 | { | 565 | { |
467 | Vector3 val = value; | 566 | Vector3 val = value; |
468 | 567 | if (Scene != null | |
469 | if (Scene != null) | 568 | && !Scene.PositionIsInCurrentRegion(val) |
569 | && !IsAttachmentCheckFull() | ||
570 | && !Scene.LoadingPrims | ||
571 | ) | ||
470 | { | 572 | { |
573 | <<<<<<< HEAD | ||
471 | if ( | 574 | if ( |
472 | !Scene.PositionIsInCurrentRegion(val) | 575 | !Scene.PositionIsInCurrentRegion(val) |
473 | && !IsAttachmentCheckFull() | 576 | && !IsAttachmentCheckFull() |
@@ -600,7 +703,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
600 | val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)m_scene.RegionInfo.RegionSizeX - 0.5f); | 703 | val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)m_scene.RegionInfo.RegionSizeX - 0.5f); |
601 | val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)m_scene.RegionInfo.RegionSizeY - 0.5f); | 704 | val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)m_scene.RegionInfo.RegionSizeY - 0.5f); |
602 | val.Z = Util.Clamp<float>(oldp.Z, 0.5f, Constants.RegionHeight); | 705 | val.Z = Util.Clamp<float>(oldp.Z, 0.5f, Constants.RegionHeight); |
706 | ======= | ||
707 | if (!inTransit) | ||
708 | { | ||
709 | inTransit = true; | ||
710 | SOGCrossDelegate d = CrossAsync; | ||
711 | d.BeginInvoke(this, val, CrossAsyncCompleted, d); | ||
712 | >>>>>>> avn/ubitvar | ||
603 | } | 713 | } |
714 | return; | ||
604 | } | 715 | } |
605 | 716 | ||
606 | if (RootPart.GetStatusSandbox()) | 717 | if (RootPart.GetStatusSandbox()) |
@@ -608,38 +719,235 @@ namespace OpenSim.Region.Framework.Scenes | |||
608 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) | 719 | if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) |
609 | { | 720 | { |
610 | RootPart.ScriptSetPhysicsStatus(false); | 721 | RootPart.ScriptSetPhysicsStatus(false); |
611 | 722 | ||
612 | if (Scene != null) | 723 | if (Scene != null) |
613 | Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), | 724 | Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), |
614 | ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); | 725 | ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); |
615 | 726 | ||
616 | return; | 727 | return; |
617 | } | 728 | } |
618 | } | 729 | } |
619 | 730 | ||
620 | // Restuff the new GroupPosition into each SOP of the linkset. | 731 | bool triggerScriptEvent = m_rootPart.GroupPosition != val; |
621 | // This has the affect of resetting and tainting the physics actors. | 732 | if (m_dupeInProgress || IsDeleted) |
733 | triggerScriptEvent = false; | ||
734 | |||
735 | m_rootPart.GroupPosition = val; | ||
736 | |||
737 | // Restuff the new GroupPosition into each child SOP of the linkset. | ||
738 | // this is needed because physics may not have linksets but just loose SOPs in world | ||
739 | |||
622 | SceneObjectPart[] parts = m_parts.GetArray(); | 740 | SceneObjectPart[] parts = m_parts.GetArray(); |
623 | for (int i = 0; i < parts.Length; i++) | ||
624 | parts[i].GroupPosition = val; | ||
625 | 741 | ||
626 | //if (m_rootPart.PhysActor != null) | 742 | foreach (SceneObjectPart part in parts) |
627 | //{ | 743 | { |
628 | //m_rootPart.PhysActor.Position = | 744 | if (part != m_rootPart) |
629 | //new PhysicsVector(m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y, | 745 | part.GroupPosition = val; |
630 | //m_rootPart.GroupPosition.Z); | 746 | } |
631 | //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); | 747 | |
632 | //} | 748 | foreach (ScenePresence av in m_linkedAvatars) |
633 | 749 | { | |
750 | av.sitSOGmoved(); | ||
751 | } | ||
752 | |||
753 | |||
754 | // now that position is changed tell it to scripts | ||
755 | if (triggerScriptEvent) | ||
756 | { | ||
757 | foreach (SceneObjectPart part in parts) | ||
758 | { | ||
759 | part.TriggerScriptChangedEvent(Changed.POSITION); | ||
760 | } | ||
761 | } | ||
762 | |||
634 | if (Scene != null) | 763 | if (Scene != null) |
635 | Scene.EventManager.TriggerParcelPrimCountTainted(); | 764 | Scene.EventManager.TriggerParcelPrimCountTainted(); |
765 | |||
636 | } | 766 | } |
637 | } | 767 | } |
638 | 768 | ||
639 | public override Vector3 Velocity | 769 | public SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val) |
640 | { | 770 | { |
641 | get { return RootPart.Velocity; } | 771 | Scene sogScene = sog.m_scene; |
642 | set { RootPart.Velocity = value; } | 772 | IEntityTransferModule entityTransfer = sogScene.RequestModuleInterface<IEntityTransferModule>(); |
773 | |||
774 | Vector3 newpos = Vector3.Zero; | ||
775 | OpenSim.Services.Interfaces.GridRegion destination = null; | ||
776 | |||
777 | if (sog.RootPart.DIE_AT_EDGE) | ||
778 | { | ||
779 | try | ||
780 | { | ||
781 | sogScene.DeleteSceneObject(sog, false); | ||
782 | } | ||
783 | catch (Exception) | ||
784 | { | ||
785 | m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border."); | ||
786 | } | ||
787 | return sog; | ||
788 | } | ||
789 | |||
790 | if (sog.RootPart.RETURN_AT_EDGE) | ||
791 | { | ||
792 | // We remove the object here | ||
793 | try | ||
794 | { | ||
795 | List<uint> localIDs = new List<uint>(); | ||
796 | localIDs.Add(sog.RootPart.LocalId); | ||
797 | sogScene.AddReturn(sog.OwnerID, sog.Name, sog.AbsolutePosition, | ||
798 | "Returned at region cross"); | ||
799 | sogScene.DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, UUID.Zero); | ||
800 | } | ||
801 | catch (Exception) | ||
802 | { | ||
803 | m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border."); | ||
804 | } | ||
805 | return sog; | ||
806 | } | ||
807 | |||
808 | if (sog.m_rootPart.KeyframeMotion != null) | ||
809 | sog.m_rootPart.KeyframeMotion.StartCrossingCheck(); | ||
810 | |||
811 | if (entityTransfer == null) | ||
812 | return sog; | ||
813 | |||
814 | destination = entityTransfer.GetObjectDestination(sog, val, out newpos); | ||
815 | if (destination == null) | ||
816 | return sog; | ||
817 | |||
818 | if (sog.m_linkedAvatars.Count == 0) | ||
819 | { | ||
820 | entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true); | ||
821 | return sog; | ||
822 | } | ||
823 | |||
824 | string reason = String.Empty; | ||
825 | string version = String.Empty; | ||
826 | |||
827 | foreach (ScenePresence av in sog.m_linkedAvatars) | ||
828 | { | ||
829 | // We need to cross these agents. First, let's find | ||
830 | // out if any of them can't cross for some reason. | ||
831 | // We have to deny the crossing entirely if any | ||
832 | // of them are banned. Alternatively, we could | ||
833 | // unsit banned agents.... | ||
834 | |||
835 | // We set the avatar position as being the object | ||
836 | // position to get the region to send to | ||
837 | if(!entityTransfer.checkAgentAccessToRegion(av, destination, newpos, out version, out reason)) | ||
838 | { | ||
839 | return sog; | ||
840 | } | ||
841 | m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); | ||
842 | } | ||
843 | |||
844 | // We unparent the SP quietly so that it won't | ||
845 | // be made to stand up | ||
846 | |||
847 | List<avtocrossInfo> avsToCross = new List<avtocrossInfo>(); | ||
848 | |||
849 | foreach (ScenePresence av in sog.m_linkedAvatars) | ||
850 | { | ||
851 | avtocrossInfo avinfo = new avtocrossInfo(); | ||
852 | SceneObjectPart parentPart = sogScene.GetSceneObjectPart(av.ParentID); | ||
853 | if (parentPart != null) | ||
854 | av.ParentUUID = parentPart.UUID; | ||
855 | |||
856 | avinfo.av = av; | ||
857 | avinfo.ParentID = av.ParentID; | ||
858 | avsToCross.Add(avinfo); | ||
859 | |||
860 | av.PrevSitOffset = av.OffsetPosition; | ||
861 | av.ParentID = 0; | ||
862 | } | ||
863 | |||
864 | if (entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true)) | ||
865 | { | ||
866 | foreach (avtocrossInfo avinfo in avsToCross) | ||
867 | { | ||
868 | ScenePresence av = avinfo.av; | ||
869 | if (!av.IsInTransit) // just in case... | ||
870 | { | ||
871 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val); | ||
872 | |||
873 | av.IsInTransit = true; | ||
874 | |||
875 | // CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync; | ||
876 | // d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d); | ||
877 | entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, av.Flying, version); | ||
878 | if(av.IsChildAgent) | ||
879 | { | ||
880 | if (av.ParentUUID != UUID.Zero) | ||
881 | { | ||
882 | av.ClearControls(); | ||
883 | av.ParentPart = null; | ||
884 | } | ||
885 | } | ||
886 | av.ParentUUID = UUID.Zero; | ||
887 | // In any case | ||
888 | av.IsInTransit = false; | ||
889 | |||
890 | m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname); | ||
891 | } | ||
892 | else | ||
893 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar already in transit {0} to {1}", av.Name, val); | ||
894 | } | ||
895 | avsToCross.Clear(); | ||
896 | return sog; | ||
897 | } | ||
898 | else // cross failed, put avas back ?? | ||
899 | { | ||
900 | foreach (avtocrossInfo avinfo in avsToCross) | ||
901 | { | ||
902 | ScenePresence av = avinfo.av; | ||
903 | av.ParentUUID = UUID.Zero; | ||
904 | av.ParentID = avinfo.ParentID; | ||
905 | } | ||
906 | } | ||
907 | avsToCross.Clear(); | ||
908 | |||
909 | return sog; | ||
910 | } | ||
911 | |||
912 | public void CrossAsyncCompleted(IAsyncResult iar) | ||
913 | { | ||
914 | SOGCrossDelegate icon = (SOGCrossDelegate)iar.AsyncState; | ||
915 | SceneObjectGroup sog = icon.EndInvoke(iar); | ||
916 | |||
917 | if (!sog.IsDeleted) | ||
918 | { | ||
919 | SceneObjectPart rootp = sog.m_rootPart; | ||
920 | Vector3 oldp = rootp.GroupPosition; | ||
921 | oldp.X = Util.Clamp<float>(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f); | ||
922 | oldp.Y = Util.Clamp<float>(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f); | ||
923 | rootp.GroupPosition = oldp; | ||
924 | |||
925 | SceneObjectPart[] parts = sog.m_parts.GetArray(); | ||
926 | |||
927 | foreach (SceneObjectPart part in parts) | ||
928 | { | ||
929 | if (part != rootp) | ||
930 | part.GroupPosition = oldp; | ||
931 | } | ||
932 | |||
933 | foreach (ScenePresence av in sog.m_linkedAvatars) | ||
934 | { | ||
935 | av.sitSOGmoved(); | ||
936 | } | ||
937 | |||
938 | sog.Velocity = Vector3.Zero; | ||
939 | |||
940 | if (sog.m_rootPart.KeyframeMotion != null) | ||
941 | sog.m_rootPart.KeyframeMotion.CrossingFailure(); | ||
942 | |||
943 | if (sog.RootPart.PhysActor != null) | ||
944 | { | ||
945 | sog.RootPart.PhysActor.CrossingFailure(); | ||
946 | } | ||
947 | |||
948 | sog.inTransit = false; | ||
949 | sog.ScheduleGroupForFullUpdate(); | ||
950 | } | ||
643 | } | 951 | } |
644 | 952 | ||
645 | private void CrossAgentToNewRegionCompleted(ScenePresence agent) | 953 | private void CrossAgentToNewRegionCompleted(ScenePresence agent) |
@@ -649,6 +957,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
649 | { | 957 | { |
650 | if (agent.ParentUUID != UUID.Zero) | 958 | if (agent.ParentUUID != UUID.Zero) |
651 | { | 959 | { |
960 | agent.HandleForceReleaseControls(agent.ControllingClient,agent.UUID); | ||
652 | agent.ParentPart = null; | 961 | agent.ParentPart = null; |
653 | // agent.ParentPosition = Vector3.Zero; | 962 | // agent.ParentPosition = Vector3.Zero; |
654 | // agent.ParentUUID = UUID.Zero; | 963 | // agent.ParentUUID = UUID.Zero; |
@@ -666,6 +975,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
666 | m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); | 975 | m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); |
667 | } | 976 | } |
668 | 977 | ||
978 | public override Vector3 Velocity | ||
979 | { | ||
980 | get { return RootPart.Velocity; } | ||
981 | set { RootPart.Velocity = value; } | ||
982 | } | ||
983 | |||
669 | public override uint LocalId | 984 | public override uint LocalId |
670 | { | 985 | { |
671 | get { return m_rootPart.LocalId; } | 986 | get { return m_rootPart.LocalId; } |
@@ -740,6 +1055,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
740 | m_isSelected = value; | 1055 | m_isSelected = value; |
741 | // Tell physics engine that group is selected | 1056 | // Tell physics engine that group is selected |
742 | 1057 | ||
1058 | // this is not right | ||
1059 | // but ode engines should only really need to know about root part | ||
1060 | // so they can put entire object simulation on hold and not colliding | ||
1061 | // keep as was for now | ||
1062 | |||
743 | PhysicsActor pa = m_rootPart.PhysActor; | 1063 | PhysicsActor pa = m_rootPart.PhysActor; |
744 | if (pa != null) | 1064 | if (pa != null) |
745 | { | 1065 | { |
@@ -761,13 +1081,47 @@ namespace OpenSim.Region.Framework.Scenes | |||
761 | } | 1081 | } |
762 | } | 1082 | } |
763 | 1083 | ||
1084 | public void PartSelectChanged(bool partSelect) | ||
1085 | { | ||
1086 | // any part selected makes group selected | ||
1087 | if (m_isSelected == partSelect) | ||
1088 | return; | ||
1089 | |||
1090 | if (partSelect) | ||
1091 | { | ||
1092 | IsSelected = partSelect; | ||
1093 | // if (!IsAttachment) | ||
1094 | // ScheduleGroupForFullUpdate(); | ||
1095 | } | ||
1096 | else | ||
1097 | { | ||
1098 | // bad bad bad 2 heavy for large linksets | ||
1099 | // since viewer does send lot of (un)selects | ||
1100 | // this needs to be replaced by a specific list or count ? | ||
1101 | // but that will require extra code in several places | ||
1102 | |||
1103 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
1104 | for (int i = 0; i < parts.Length; i++) | ||
1105 | { | ||
1106 | SceneObjectPart part = parts[i]; | ||
1107 | if (part.IsSelected) | ||
1108 | return; | ||
1109 | } | ||
1110 | IsSelected = partSelect; | ||
1111 | // if (!IsAttachment) | ||
1112 | // { | ||
1113 | // ScheduleGroupForFullUpdate(); | ||
1114 | // } | ||
1115 | } | ||
1116 | } | ||
1117 | // PlaySoundMasterPrim no longer in use to remove | ||
764 | private SceneObjectPart m_PlaySoundMasterPrim = null; | 1118 | private SceneObjectPart m_PlaySoundMasterPrim = null; |
765 | public SceneObjectPart PlaySoundMasterPrim | 1119 | public SceneObjectPart PlaySoundMasterPrim |
766 | { | 1120 | { |
767 | get { return m_PlaySoundMasterPrim; } | 1121 | get { return m_PlaySoundMasterPrim; } |
768 | set { m_PlaySoundMasterPrim = value; } | 1122 | set { m_PlaySoundMasterPrim = value; } |
769 | } | 1123 | } |
770 | 1124 | // PlaySoundSlavePrims no longer in use to remove | |
771 | private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>(); | 1125 | private List<SceneObjectPart> m_PlaySoundSlavePrims = new List<SceneObjectPart>(); |
772 | public List<SceneObjectPart> PlaySoundSlavePrims | 1126 | public List<SceneObjectPart> PlaySoundSlavePrims |
773 | { | 1127 | { |
@@ -775,6 +1129,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
775 | set { m_PlaySoundSlavePrims = value; } | 1129 | set { m_PlaySoundSlavePrims = value; } |
776 | } | 1130 | } |
777 | 1131 | ||
1132 | // LoopSoundMasterPrim no longer in use to remove | ||
778 | private SceneObjectPart m_LoopSoundMasterPrim = null; | 1133 | private SceneObjectPart m_LoopSoundMasterPrim = null; |
779 | public SceneObjectPart LoopSoundMasterPrim | 1134 | public SceneObjectPart LoopSoundMasterPrim |
780 | { | 1135 | { |
@@ -782,6 +1137,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
782 | set { m_LoopSoundMasterPrim = value; } | 1137 | set { m_LoopSoundMasterPrim = value; } |
783 | } | 1138 | } |
784 | 1139 | ||
1140 | // m_LoopSoundSlavePrims no longer in use to remove | ||
785 | private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>(); | 1141 | private List<SceneObjectPart> m_LoopSoundSlavePrims = new List<SceneObjectPart>(); |
786 | public List<SceneObjectPart> LoopSoundSlavePrims | 1142 | public List<SceneObjectPart> LoopSoundSlavePrims |
787 | { | 1143 | { |
@@ -861,6 +1217,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
861 | /// </summary> | 1217 | /// </summary> |
862 | public SceneObjectGroup() | 1218 | public SceneObjectGroup() |
863 | { | 1219 | { |
1220 | |||
864 | } | 1221 | } |
865 | 1222 | ||
866 | /// <summary> | 1223 | /// <summary> |
@@ -878,8 +1235,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
878 | /// Constructor. This object is added to the scene later via AttachToScene() | 1235 | /// Constructor. This object is added to the scene later via AttachToScene() |
879 | /// </summary> | 1236 | /// </summary> |
880 | public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) | 1237 | public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) |
881 | :this(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)) | 1238 | { |
882 | { | 1239 | SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); |
883 | } | 1240 | } |
884 | 1241 | ||
885 | /// <summary> | 1242 | /// <summary> |
@@ -954,7 +1311,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
954 | /// </summary> | 1311 | /// </summary> |
955 | public virtual void AttachToBackup() | 1312 | public virtual void AttachToBackup() |
956 | { | 1313 | { |
1314 | <<<<<<< HEAD | ||
957 | if (CanBeBackedUp) | 1315 | if (CanBeBackedUp) |
1316 | ======= | ||
1317 | if (IsAttachment) return; | ||
1318 | m_scene.SceneGraph.FireAttachToBackup(this); | ||
1319 | |||
1320 | if (InSceneBackup) | ||
1321 | >>>>>>> avn/ubitvar | ||
958 | { | 1322 | { |
959 | // m_log.DebugFormat( | 1323 | // m_log.DebugFormat( |
960 | // "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID); | 1324 | // "[SCENE OBJECT GROUP]: Attaching object {0} {1} to scene presistence sweep", Name, UUID); |
@@ -1001,6 +1365,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1001 | 1365 | ||
1002 | ApplyPhysics(); | 1366 | ApplyPhysics(); |
1003 | 1367 | ||
1368 | if (RootPart.PhysActor != null) | ||
1369 | RootPart.Force = RootPart.Force; | ||
1370 | if (RootPart.PhysActor != null) | ||
1371 | RootPart.Torque = RootPart.Torque; | ||
1372 | if (RootPart.PhysActor != null) | ||
1373 | RootPart.Buoyancy = RootPart.Buoyancy; | ||
1374 | |||
1004 | // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled | 1375 | // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled |
1005 | // for the same object with very different properties. The caller must schedule the update. | 1376 | // for the same object with very different properties. The caller must schedule the update. |
1006 | //ScheduleGroupForFullUpdate(); | 1377 | //ScheduleGroupForFullUpdate(); |
@@ -1016,6 +1387,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
1016 | EntityIntersection result = new EntityIntersection(); | 1387 | EntityIntersection result = new EntityIntersection(); |
1017 | 1388 | ||
1018 | SceneObjectPart[] parts = m_parts.GetArray(); | 1389 | SceneObjectPart[] parts = m_parts.GetArray(); |
1390 | |||
1391 | // Find closest hit here | ||
1392 | float idist = float.MaxValue; | ||
1393 | |||
1019 | for (int i = 0; i < parts.Length; i++) | 1394 | for (int i = 0; i < parts.Length; i++) |
1020 | { | 1395 | { |
1021 | SceneObjectPart part = parts[i]; | 1396 | SceneObjectPart part = parts[i]; |
@@ -1030,11 +1405,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
1030 | 1405 | ||
1031 | EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); | 1406 | EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); |
1032 | 1407 | ||
1033 | // This may need to be updated to the maximum draw distance possible.. | ||
1034 | // We might (and probably will) be checking for prim creation from other sims | ||
1035 | // when the camera crosses the border. | ||
1036 | float idist = Constants.RegionSize; | ||
1037 | |||
1038 | if (inter.HitTF) | 1408 | if (inter.HitTF) |
1039 | { | 1409 | { |
1040 | // We need to find the closest prim to return to the testcaller along the ray | 1410 | // We need to find the closest prim to return to the testcaller along the ray |
@@ -1045,10 +1415,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
1045 | result.obj = part; | 1415 | result.obj = part; |
1046 | result.normal = inter.normal; | 1416 | result.normal = inter.normal; |
1047 | result.distance = inter.distance; | 1417 | result.distance = inter.distance; |
1418 | |||
1419 | idist = inter.distance; | ||
1048 | } | 1420 | } |
1049 | } | 1421 | } |
1050 | } | 1422 | } |
1051 | |||
1052 | return result; | 1423 | return result; |
1053 | } | 1424 | } |
1054 | 1425 | ||
@@ -1060,25 +1431,36 @@ namespace OpenSim.Region.Framework.Scenes | |||
1060 | /// <returns></returns> | 1431 | /// <returns></returns> |
1061 | public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) | 1432 | public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) |
1062 | { | 1433 | { |
1434 | <<<<<<< HEAD | ||
1063 | maxX = -256f; | 1435 | maxX = -256f; |
1064 | maxY = -256f; | 1436 | maxY = -256f; |
1065 | maxZ = -256f; | 1437 | maxZ = -256f; |
1066 | minX = 10000f; | 1438 | minX = 10000f; |
1067 | minY = 10000f; | 1439 | minY = 10000f; |
1068 | minZ = 10000f; | 1440 | minZ = 10000f; |
1441 | ======= | ||
1442 | maxX = float.MinValue; | ||
1443 | maxY = float.MinValue; | ||
1444 | maxZ = float.MinValue; | ||
1445 | minX = float.MaxValue; | ||
1446 | minY = float.MaxValue; | ||
1447 | minZ = float.MaxValue; | ||
1448 | >>>>>>> avn/ubitvar | ||
1069 | 1449 | ||
1070 | SceneObjectPart[] parts = m_parts.GetArray(); | 1450 | SceneObjectPart[] parts = m_parts.GetArray(); |
1071 | for (int i = 0; i < parts.Length; i++) | 1451 | foreach (SceneObjectPart part in parts) |
1072 | { | 1452 | { |
1073 | SceneObjectPart part = parts[i]; | ||
1074 | |||
1075 | Vector3 worldPos = part.GetWorldPosition(); | 1453 | Vector3 worldPos = part.GetWorldPosition(); |
1076 | Vector3 offset = worldPos - AbsolutePosition; | 1454 | Vector3 offset = worldPos - AbsolutePosition; |
1077 | Quaternion worldRot; | 1455 | Quaternion worldRot; |
1078 | if (part.ParentID == 0) | 1456 | if (part.ParentID == 0) |
1457 | { | ||
1079 | worldRot = part.RotationOffset; | 1458 | worldRot = part.RotationOffset; |
1459 | } | ||
1080 | else | 1460 | else |
1461 | { | ||
1081 | worldRot = part.GetWorldRotation(); | 1462 | worldRot = part.GetWorldRotation(); |
1463 | } | ||
1082 | 1464 | ||
1083 | Vector3 frontTopLeft; | 1465 | Vector3 frontTopLeft; |
1084 | Vector3 frontTopRight; | 1466 | Vector3 frontTopRight; |
@@ -1090,6 +1472,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1090 | Vector3 backBottomLeft; | 1472 | Vector3 backBottomLeft; |
1091 | Vector3 backBottomRight; | 1473 | Vector3 backBottomRight; |
1092 | 1474 | ||
1475 | // Vector3[] corners = new Vector3[8]; | ||
1476 | |||
1093 | Vector3 orig = Vector3.Zero; | 1477 | Vector3 orig = Vector3.Zero; |
1094 | 1478 | ||
1095 | frontTopLeft.X = orig.X - (part.Scale.X / 2); | 1479 | frontTopLeft.X = orig.X - (part.Scale.X / 2); |
@@ -1124,6 +1508,38 @@ namespace OpenSim.Region.Framework.Scenes | |||
1124 | backBottomRight.Y = orig.Y + (part.Scale.Y / 2); | 1508 | backBottomRight.Y = orig.Y + (part.Scale.Y / 2); |
1125 | backBottomRight.Z = orig.Z - (part.Scale.Z / 2); | 1509 | backBottomRight.Z = orig.Z - (part.Scale.Z / 2); |
1126 | 1510 | ||
1511 | |||
1512 | |||
1513 | //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); | ||
1514 | //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); | ||
1515 | //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); | ||
1516 | //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z); | ||
1517 | //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z); | ||
1518 | //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z); | ||
1519 | //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z); | ||
1520 | //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z); | ||
1521 | |||
1522 | //for (int i = 0; i < 8; i++) | ||
1523 | //{ | ||
1524 | // corners[i] = corners[i] * worldRot; | ||
1525 | // corners[i] += offset; | ||
1526 | |||
1527 | // if (corners[i].X > maxX) | ||
1528 | // maxX = corners[i].X; | ||
1529 | // if (corners[i].X < minX) | ||
1530 | // minX = corners[i].X; | ||
1531 | |||
1532 | // if (corners[i].Y > maxY) | ||
1533 | // maxY = corners[i].Y; | ||
1534 | // if (corners[i].Y < minY) | ||
1535 | // minY = corners[i].Y; | ||
1536 | |||
1537 | // if (corners[i].Z > maxZ) | ||
1538 | // maxZ = corners[i].Y; | ||
1539 | // if (corners[i].Z < minZ) | ||
1540 | // minZ = corners[i].Z; | ||
1541 | //} | ||
1542 | |||
1127 | frontTopLeft = frontTopLeft * worldRot; | 1543 | frontTopLeft = frontTopLeft * worldRot; |
1128 | frontTopRight = frontTopRight * worldRot; | 1544 | frontTopRight = frontTopRight * worldRot; |
1129 | frontBottomLeft = frontBottomLeft * worldRot; | 1545 | frontBottomLeft = frontBottomLeft * worldRot; |
@@ -1145,6 +1561,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
1145 | backTopLeft += offset; | 1561 | backTopLeft += offset; |
1146 | backTopRight += offset; | 1562 | backTopRight += offset; |
1147 | 1563 | ||
1564 | //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z); | ||
1565 | //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z); | ||
1566 | //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z); | ||
1567 | //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z); | ||
1568 | //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z); | ||
1569 | //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z); | ||
1570 | //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z); | ||
1571 | //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z); | ||
1572 | |||
1148 | if (frontTopRight.X > maxX) | 1573 | if (frontTopRight.X > maxX) |
1149 | maxX = frontTopRight.X; | 1574 | maxX = frontTopRight.X; |
1150 | if (frontTopLeft.X > maxX) | 1575 | if (frontTopLeft.X > maxX) |
@@ -1288,17 +1713,118 @@ namespace OpenSim.Region.Framework.Scenes | |||
1288 | 1713 | ||
1289 | #endregion | 1714 | #endregion |
1290 | 1715 | ||
1716 | public void GetResourcesCosts(SceneObjectPart apart, | ||
1717 | out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost) | ||
1718 | { | ||
1719 | // this information may need to be cached | ||
1720 | |||
1721 | float cost; | ||
1722 | float tmpcost; | ||
1723 | |||
1724 | bool ComplexCost = false; | ||
1725 | |||
1726 | SceneObjectPart p; | ||
1727 | SceneObjectPart[] parts; | ||
1728 | |||
1729 | lock (m_parts) | ||
1730 | { | ||
1731 | parts = m_parts.GetArray(); | ||
1732 | } | ||
1733 | |||
1734 | int nparts = parts.Length; | ||
1735 | |||
1736 | |||
1737 | for (int i = 0; i < nparts; i++) | ||
1738 | { | ||
1739 | p = parts[i]; | ||
1740 | |||
1741 | if (p.UsesComplexCost) | ||
1742 | { | ||
1743 | ComplexCost = true; | ||
1744 | break; | ||
1745 | } | ||
1746 | } | ||
1747 | |||
1748 | if (ComplexCost) | ||
1749 | { | ||
1750 | linksetResCost = 0; | ||
1751 | linksetPhysCost = 0; | ||
1752 | partCost = 0; | ||
1753 | partPhysCost = 0; | ||
1754 | |||
1755 | for (int i = 0; i < nparts; i++) | ||
1756 | { | ||
1757 | p = parts[i]; | ||
1758 | |||
1759 | cost = p.StreamingCost; | ||
1760 | tmpcost = p.SimulationCost; | ||
1761 | if (tmpcost > cost) | ||
1762 | cost = tmpcost; | ||
1763 | tmpcost = p.PhysicsCost; | ||
1764 | if (tmpcost > cost) | ||
1765 | cost = tmpcost; | ||
1766 | |||
1767 | linksetPhysCost += tmpcost; | ||
1768 | linksetResCost += cost; | ||
1769 | |||
1770 | if (p == apart) | ||
1771 | { | ||
1772 | partCost = cost; | ||
1773 | partPhysCost = tmpcost; | ||
1774 | } | ||
1775 | } | ||
1776 | } | ||
1777 | else | ||
1778 | { | ||
1779 | partPhysCost = 1.0f; | ||
1780 | partCost = 1.0f; | ||
1781 | linksetResCost = (float)nparts; | ||
1782 | linksetPhysCost = linksetResCost; | ||
1783 | } | ||
1784 | } | ||
1785 | |||
1786 | public void GetSelectedCosts(out float PhysCost, out float StreamCost, out float SimulCost) | ||
1787 | { | ||
1788 | SceneObjectPart p; | ||
1789 | SceneObjectPart[] parts; | ||
1790 | |||
1791 | lock (m_parts) | ||
1792 | { | ||
1793 | parts = m_parts.GetArray(); | ||
1794 | } | ||
1795 | |||
1796 | int nparts = parts.Length; | ||
1797 | |||
1798 | PhysCost = 0; | ||
1799 | StreamCost = 0; | ||
1800 | SimulCost = 0; | ||
1801 | |||
1802 | for (int i = 0; i < nparts; i++) | ||
1803 | { | ||
1804 | p = parts[i]; | ||
1805 | |||
1806 | StreamCost += p.StreamingCost; | ||
1807 | SimulCost += p.SimulationCost; | ||
1808 | PhysCost += p.PhysicsCost; | ||
1809 | } | ||
1810 | } | ||
1811 | |||
1291 | public void SaveScriptedState(XmlTextWriter writer) | 1812 | public void SaveScriptedState(XmlTextWriter writer) |
1292 | { | 1813 | { |
1814 | SaveScriptedState(writer, false); | ||
1815 | } | ||
1816 | |||
1817 | public void SaveScriptedState(XmlTextWriter writer, bool oldIDs) | ||
1818 | { | ||
1293 | XmlDocument doc = new XmlDocument(); | 1819 | XmlDocument doc = new XmlDocument(); |
1294 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); | 1820 | Dictionary<UUID,string> states = new Dictionary<UUID,string>(); |
1295 | 1821 | ||
1296 | SceneObjectPart[] parts = m_parts.GetArray(); | 1822 | SceneObjectPart[] parts = m_parts.GetArray(); |
1297 | for (int i = 0; i < parts.Length; i++) | 1823 | for (int i = 0; i < parts.Length; i++) |
1298 | { | 1824 | { |
1299 | Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); | 1825 | Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs); |
1300 | foreach (KeyValuePair<UUID, string> kvp in pstates) | 1826 | foreach (KeyValuePair<UUID, string> kvp in pstates) |
1301 | states.Add(kvp.Key, kvp.Value); | 1827 | states[kvp.Key] = kvp.Value; |
1302 | } | 1828 | } |
1303 | 1829 | ||
1304 | if (states.Count > 0) | 1830 | if (states.Count > 0) |
@@ -1317,6 +1843,183 @@ namespace OpenSim.Region.Framework.Scenes | |||
1317 | } | 1843 | } |
1318 | } | 1844 | } |
1319 | 1845 | ||
1846 | <<<<<<< HEAD | ||
1847 | |||
1848 | /// <summary> | ||
1849 | /// | ||
1850 | /// </summary> | ||
1851 | /// <param name="part"></param> | ||
1852 | private void SetPartAsNonRoot(SceneObjectPart part) | ||
1853 | { | ||
1854 | part.ParentID = m_rootPart.LocalId; | ||
1855 | part.ClearUndoState(); | ||
1856 | ======= | ||
1857 | /// <summary> | ||
1858 | /// Add the avatar to this linkset (avatar is sat). | ||
1859 | /// </summary> | ||
1860 | /// <param name="agentID"></param> | ||
1861 | public void AddAvatar(UUID agentID) | ||
1862 | { | ||
1863 | ScenePresence presence; | ||
1864 | if (m_scene.TryGetScenePresence(agentID, out presence)) | ||
1865 | { | ||
1866 | if (!m_linkedAvatars.Contains(presence)) | ||
1867 | { | ||
1868 | m_linkedAvatars.Add(presence); | ||
1869 | } | ||
1870 | } | ||
1871 | } | ||
1872 | |||
1873 | /// <summary> | ||
1874 | /// Delete the avatar from this linkset (avatar is unsat). | ||
1875 | /// </summary> | ||
1876 | /// <param name="agentID"></param> | ||
1877 | public void DeleteAvatar(UUID agentID) | ||
1878 | { | ||
1879 | ScenePresence presence; | ||
1880 | if (m_scene.TryGetScenePresence(agentID, out presence)) | ||
1881 | { | ||
1882 | if (m_linkedAvatars.Contains(presence)) | ||
1883 | { | ||
1884 | m_linkedAvatars.Remove(presence); | ||
1885 | } | ||
1886 | } | ||
1887 | } | ||
1888 | |||
1889 | /// <summary> | ||
1890 | /// Returns the list of linked presences (avatars sat on this group) | ||
1891 | /// </summary> | ||
1892 | /// <param name="agentID"></param> | ||
1893 | public List<ScenePresence> GetLinkedAvatars() | ||
1894 | { | ||
1895 | return m_linkedAvatars; | ||
1896 | >>>>>>> avn/ubitvar | ||
1897 | } | ||
1898 | |||
1899 | /// <summary> | ||
1900 | /// Attach this scene object to the given avatar. | ||
1901 | /// </summary> | ||
1902 | /// <param name="agentID"></param> | ||
1903 | /// <param name="attachmentpoint"></param> | ||
1904 | /// <param name="AttachOffset"></param> | ||
1905 | private void AttachToAgent( | ||
1906 | ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) | ||
1907 | { | ||
1908 | if (avatar != null) | ||
1909 | { | ||
1910 | // don't attach attachments to child agents | ||
1911 | if (avatar.IsChildAgent) return; | ||
1912 | |||
1913 | // Remove from database and parcel prim count | ||
1914 | m_scene.DeleteFromStorage(so.UUID); | ||
1915 | m_scene.EventManager.TriggerParcelPrimCountTainted(); | ||
1916 | |||
1917 | so.AttachedAvatar = avatar.UUID; | ||
1918 | |||
1919 | if (so.RootPart.PhysActor != null) | ||
1920 | { | ||
1921 | m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor); | ||
1922 | so.RootPart.PhysActor = null; | ||
1923 | } | ||
1924 | |||
1925 | so.AbsolutePosition = attachOffset; | ||
1926 | so.RootPart.AttachedPos = attachOffset; | ||
1927 | so.IsAttachment = true; | ||
1928 | so.RootPart.SetParentLocalId(avatar.LocalId); | ||
1929 | so.AttachmentPoint = attachmentpoint; | ||
1930 | |||
1931 | avatar.AddAttachment(this); | ||
1932 | |||
1933 | if (!silent) | ||
1934 | { | ||
1935 | // Killing it here will cause the client to deselect it | ||
1936 | // It then reappears on the avatar, deselected | ||
1937 | // through the full update below | ||
1938 | // | ||
1939 | if (IsSelected) | ||
1940 | { | ||
1941 | m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId }); | ||
1942 | } | ||
1943 | |||
1944 | IsSelected = false; // fudge.... | ||
1945 | ScheduleGroupForFullUpdate(); | ||
1946 | } | ||
1947 | } | ||
1948 | else | ||
1949 | { | ||
1950 | m_log.WarnFormat( | ||
1951 | "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present", | ||
1952 | UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName); | ||
1953 | } | ||
1954 | } | ||
1955 | |||
1956 | public byte GetAttachmentPoint() | ||
1957 | { | ||
1958 | return m_rootPart.Shape.State; | ||
1959 | } | ||
1960 | |||
1961 | public void DetachToGround() | ||
1962 | { | ||
1963 | ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); | ||
1964 | if (avatar == null) | ||
1965 | return; | ||
1966 | m_rootPart.Shape.LastAttachPoint = m_rootPart.Shape.State; | ||
1967 | m_rootPart.AttachedPos = m_rootPart.OffsetPosition; | ||
1968 | avatar.RemoveAttachment(this); | ||
1969 | |||
1970 | Vector3 detachedpos = new Vector3(127f,127f,127f); | ||
1971 | if (avatar == null) | ||
1972 | return; | ||
1973 | |||
1974 | detachedpos = avatar.AbsolutePosition; | ||
1975 | FromItemID = UUID.Zero; | ||
1976 | |||
1977 | AbsolutePosition = detachedpos; | ||
1978 | AttachedAvatar = UUID.Zero; | ||
1979 | |||
1980 | //SceneObjectPart[] parts = m_parts.GetArray(); | ||
1981 | //for (int i = 0; i < parts.Length; i++) | ||
1982 | // parts[i].AttachedAvatar = UUID.Zero; | ||
1983 | |||
1984 | m_rootPart.SetParentLocalId(0); | ||
1985 | AttachmentPoint = (byte)0; | ||
1986 | // must check if buildind should be true or false here | ||
1987 | // m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false); | ||
1988 | ApplyPhysics(); | ||
1989 | |||
1990 | HasGroupChanged = true; | ||
1991 | RootPart.Rezzed = DateTime.Now; | ||
1992 | RootPart.RemFlag(PrimFlags.TemporaryOnRez); | ||
1993 | AttachToBackup(); | ||
1994 | m_scene.EventManager.TriggerParcelPrimCountTainted(); | ||
1995 | m_rootPart.ScheduleFullUpdate(); | ||
1996 | m_rootPart.ClearUndoState(); | ||
1997 | } | ||
1998 | |||
1999 | public void DetachToInventoryPrep() | ||
2000 | { | ||
2001 | ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); | ||
2002 | //Vector3 detachedpos = new Vector3(127f, 127f, 127f); | ||
2003 | if (avatar != null) | ||
2004 | { | ||
2005 | //detachedpos = avatar.AbsolutePosition; | ||
2006 | avatar.RemoveAttachment(this); | ||
2007 | } | ||
2008 | |||
2009 | AttachedAvatar = UUID.Zero; | ||
2010 | |||
2011 | /*SceneObjectPart[] parts = m_parts.GetArray(); | ||
2012 | for (int i = 0; i < parts.Length; i++) | ||
2013 | parts[i].AttachedAvatar = UUID.Zero;*/ | ||
2014 | |||
2015 | m_rootPart.SetParentLocalId(0); | ||
2016 | //m_rootPart.SetAttachmentPoint((byte)0); | ||
2017 | IsAttachment = false; | ||
2018 | AbsolutePosition = m_rootPart.AttachedPos; | ||
2019 | //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim); | ||
2020 | //AttachToBackup(); | ||
2021 | //m_rootPart.ScheduleFullUpdate(); | ||
2022 | } | ||
1320 | 2023 | ||
1321 | /// <summary> | 2024 | /// <summary> |
1322 | /// | 2025 | /// |
@@ -1358,7 +2061,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
1358 | public void AddPart(SceneObjectPart part) | 2061 | public void AddPart(SceneObjectPart part) |
1359 | { | 2062 | { |
1360 | part.SetParent(this); | 2063 | part.SetParent(this); |
1361 | part.LinkNum = m_parts.Add(part.UUID, part); | 2064 | m_parts.Add(part.UUID, part); |
2065 | |||
2066 | part.LinkNum = m_parts.Count; | ||
2067 | |||
1362 | if (part.LinkNum == 2) | 2068 | if (part.LinkNum == 2) |
1363 | RootPart.LinkNum = 1; | 2069 | RootPart.LinkNum = 1; |
1364 | } | 2070 | } |
@@ -1384,6 +2090,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1384 | parts[i].UUID = UUID.Random(); | 2090 | parts[i].UUID = UUID.Random(); |
1385 | } | 2091 | } |
1386 | 2092 | ||
2093 | // helper provided for parts. | ||
2094 | public int GetSceneMaxUndo() | ||
2095 | { | ||
2096 | if (m_scene != null) | ||
2097 | return m_scene.MaxUndoCount; | ||
2098 | return 5; | ||
2099 | } | ||
2100 | |||
1387 | // justincc: I don't believe this hack is needed any longer, especially since the physics | 2101 | // justincc: I don't believe this hack is needed any longer, especially since the physics |
1388 | // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false | 2102 | // parts of set AbsolutePosition were already commented out. By changing HasGroupChanged to false |
1389 | // this method was preventing proper reload of scene objects. | 2103 | // this method was preventing proper reload of scene objects. |
@@ -1405,11 +2119,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
1405 | // Setting this SOG's absolute position also loops through and sets the positions | 2119 | // Setting this SOG's absolute position also loops through and sets the positions |
1406 | // of the SOP's in this SOG's linkset. This has the side affect of making sure | 2120 | // of the SOP's in this SOG's linkset. This has the side affect of making sure |
1407 | // the physics world matches the simulated world. | 2121 | // the physics world matches the simulated world. |
1408 | AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works? | 2122 | // AbsolutePosition = AbsolutePosition; // could someone in the know please explain how this works? |
1409 | 2123 | ||
1410 | // teravus: AbsolutePosition is NOT a normal property! | 2124 | // teravus: AbsolutePosition is NOT a normal property! |
1411 | // the code in the getter of AbsolutePosition is significantly different then the code in the setter! | 2125 | // the code in the getter of AbsolutePosition is significantly different then the code in the setter! |
1412 | // jhurliman: Then why is it a property instead of two methods? | 2126 | // jhurliman: Then why is it a property instead of two methods? |
2127 | |||
2128 | // do only what is supposed to do | ||
2129 | Vector3 groupPosition = m_rootPart.GroupPosition; | ||
2130 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
2131 | |||
2132 | foreach (SceneObjectPart part in parts) | ||
2133 | { | ||
2134 | if (part != m_rootPart) | ||
2135 | part.GroupPosition = groupPosition; | ||
2136 | } | ||
1413 | } | 2137 | } |
1414 | 2138 | ||
1415 | public UUID GetPartsFullID(uint localID) | 2139 | public UUID GetPartsFullID(uint localID) |
@@ -1441,7 +2165,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1441 | // "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", | 2165 | // "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", |
1442 | // remoteClient.Name, part.Name, part.LocalId, offsetPos); | 2166 | // remoteClient.Name, part.Name, part.LocalId, offsetPos); |
1443 | 2167 | ||
1444 | part.StoreUndoState(); | 2168 | // part.StoreUndoState(); |
1445 | part.OnGrab(offsetPos, remoteClient); | 2169 | part.OnGrab(offsetPos, remoteClient); |
1446 | } | 2170 | } |
1447 | 2171 | ||
@@ -1461,28 +2185,43 @@ namespace OpenSim.Region.Framework.Scenes | |||
1461 | /// <param name="silent">If true then deletion is not broadcast to clients</param> | 2185 | /// <param name="silent">If true then deletion is not broadcast to clients</param> |
1462 | public void DeleteGroupFromScene(bool silent) | 2186 | public void DeleteGroupFromScene(bool silent) |
1463 | { | 2187 | { |
2188 | // We need to keep track of this state in case this group is still queued for backup. | ||
2189 | IsDeleted = true; | ||
2190 | |||
2191 | DetachFromBackup(); | ||
2192 | |||
1464 | SceneObjectPart[] parts = m_parts.GetArray(); | 2193 | SceneObjectPart[] parts = m_parts.GetArray(); |
1465 | for (int i = 0; i < parts.Length; i++) | 2194 | for (int i = 0; i < parts.Length; i++) |
1466 | { | 2195 | { |
1467 | SceneObjectPart part = parts[i]; | 2196 | SceneObjectPart part = parts[i]; |
1468 | 2197 | ||
1469 | Scene.ForEachScenePresence(sp => | 2198 | if (Scene != null) |
1470 | { | 2199 | { |
2200 | <<<<<<< HEAD | ||
1471 | if (!sp.IsChildAgent && sp.ParentID == part.LocalId) | 2201 | if (!sp.IsChildAgent && sp.ParentID == part.LocalId) |
1472 | sp.StandUp(); | 2202 | sp.StandUp(); |
1473 | 2203 | ||
1474 | if (!silent) | 2204 | if (!silent) |
2205 | ======= | ||
2206 | Scene.ForEachRootScenePresence(delegate(ScenePresence avatar) | ||
2207 | >>>>>>> avn/ubitvar | ||
1475 | { | 2208 | { |
1476 | part.ClearUpdateSchedule(); | 2209 | if (avatar.ParentID == LocalId) |
1477 | if (part == m_rootPart) | 2210 | avatar.StandUp(); |
2211 | |||
2212 | if (!silent) | ||
1478 | { | 2213 | { |
1479 | if (!IsAttachment | 2214 | part.ClearUpdateSchedule(); |
1480 | || AttachedAvatar == sp.UUID | 2215 | if (part == m_rootPart) |
1481 | || !HasPrivateAttachmentPoint) | 2216 | { |
1482 | sp.ControllingClient.SendKillObject(new List<uint> { part.LocalId }); | 2217 | if (!IsAttachment |
2218 | || AttachedAvatar == avatar.ControllingClient.AgentId | ||
2219 | || !HasPrivateAttachmentPoint) | ||
2220 | avatar.ControllingClient.SendKillObject(new List<uint> { part.LocalId }); | ||
2221 | } | ||
1483 | } | 2222 | } |
1484 | } | 2223 | }); |
1485 | }); | 2224 | } |
1486 | } | 2225 | } |
1487 | } | 2226 | } |
1488 | 2227 | ||
@@ -1553,28 +2292,43 @@ namespace OpenSim.Region.Framework.Scenes | |||
1553 | /// </summary> | 2292 | /// </summary> |
1554 | public void ApplyPhysics() | 2293 | public void ApplyPhysics() |
1555 | { | 2294 | { |
1556 | // Apply physics to the root prim | ||
1557 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive); | ||
1558 | |||
1559 | // Apply physics to child prims | ||
1560 | SceneObjectPart[] parts = m_parts.GetArray(); | 2295 | SceneObjectPart[] parts = m_parts.GetArray(); |
1561 | if (parts.Length > 1) | 2296 | if (parts.Length > 1) |
1562 | { | 2297 | { |
2298 | ResetChildPrimPhysicsPositions(); | ||
2299 | |||
2300 | // Apply physics to the root prim | ||
2301 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true); | ||
2302 | |||
2303 | |||
1563 | for (int i = 0; i < parts.Length; i++) | 2304 | for (int i = 0; i < parts.Length; i++) |
1564 | { | 2305 | { |
1565 | SceneObjectPart part = parts[i]; | 2306 | SceneObjectPart part = parts[i]; |
1566 | if (part.LocalId != m_rootPart.LocalId) | 2307 | if (part.LocalId != m_rootPart.LocalId) |
1567 | part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); | 2308 | part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true); |
1568 | } | 2309 | } |
1569 | |||
1570 | // Hack to get the physics scene geometries in the right spot | 2310 | // Hack to get the physics scene geometries in the right spot |
1571 | ResetChildPrimPhysicsPositions(); | 2311 | // ResetChildPrimPhysicsPositions(); |
2312 | if (m_rootPart.PhysActor != null) | ||
2313 | { | ||
2314 | m_rootPart.PhysActor.Building = false; | ||
2315 | } | ||
2316 | } | ||
2317 | else | ||
2318 | { | ||
2319 | // Apply physics to the root prim | ||
2320 | m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false); | ||
1572 | } | 2321 | } |
1573 | } | 2322 | } |
1574 | 2323 | ||
1575 | public void SetOwnerId(UUID userId) | 2324 | public void SetOwnerId(UUID userId) |
1576 | { | 2325 | { |
1577 | ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); | 2326 | ForEachPart(delegate(SceneObjectPart part) |
2327 | { | ||
2328 | |||
2329 | part.OwnerID = userId; | ||
2330 | |||
2331 | }); | ||
1578 | } | 2332 | } |
1579 | 2333 | ||
1580 | public void ForEachPart(Action<SceneObjectPart> whatToDo) | 2334 | public void ForEachPart(Action<SceneObjectPart> whatToDo) |
@@ -1599,18 +2353,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
1599 | return; | 2353 | return; |
1600 | } | 2354 | } |
1601 | 2355 | ||
1602 | if (IsDeleted || UUID == UUID.Zero) | 2356 | if (IsDeleted || inTransit || UUID == UUID.Zero) |
1603 | { | 2357 | { |
1604 | // m_log.DebugFormat( | 2358 | // m_log.DebugFormat( |
1605 | // "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID); | 2359 | // "[WATER WARS]: Ignoring backup of {0} {1} since object is marked as already deleted", Name, UUID); |
1606 | return; | 2360 | return; |
1607 | } | 2361 | } |
1608 | 2362 | ||
2363 | if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) | ||
2364 | return; | ||
2365 | |||
1609 | // Since this is the top of the section of call stack for backing up a particular scene object, don't let | 2366 | // Since this is the top of the section of call stack for backing up a particular scene object, don't let |
1610 | // any exception propogate upwards. | 2367 | // any exception propogate upwards. |
1611 | try | 2368 | try |
1612 | { | 2369 | { |
1613 | if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart | 2370 | if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart |
2371 | !m_scene.LoginsEnabled || // We're starting up or doing maintenance, don't mess with things | ||
2372 | m_scene.LoadingPrims) // Land may not be valid yet | ||
2373 | |||
1614 | { | 2374 | { |
1615 | ILandObject parcel = m_scene.LandChannel.GetLandObject( | 2375 | ILandObject parcel = m_scene.LandChannel.GetLandObject( |
1616 | m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); | 2376 | m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); |
@@ -1637,6 +2397,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1637 | } | 2397 | } |
1638 | } | 2398 | } |
1639 | } | 2399 | } |
2400 | |||
1640 | } | 2401 | } |
1641 | 2402 | ||
1642 | if (m_scene.UseBackup && HasGroupChanged) | 2403 | if (m_scene.UseBackup && HasGroupChanged) |
@@ -1644,10 +2405,31 @@ namespace OpenSim.Region.Framework.Scenes | |||
1644 | // don't backup while it's selected or you're asking for changes mid stream. | 2405 | // don't backup while it's selected or you're asking for changes mid stream. |
1645 | if (isTimeToPersist() || forcedBackup) | 2406 | if (isTimeToPersist() || forcedBackup) |
1646 | { | 2407 | { |
2408 | if (m_rootPart.PhysActor != null && | ||
2409 | (!m_rootPart.PhysActor.IsPhysical)) | ||
2410 | { | ||
2411 | // Possible ghost prim | ||
2412 | if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition) | ||
2413 | { | ||
2414 | foreach (SceneObjectPart part in m_parts.GetArray()) | ||
2415 | { | ||
2416 | // Re-set physics actor positions and | ||
2417 | // orientations | ||
2418 | part.GroupPosition = m_rootPart.GroupPosition; | ||
2419 | } | ||
2420 | } | ||
2421 | } | ||
1647 | // m_log.DebugFormat( | 2422 | // m_log.DebugFormat( |
1648 | // "[SCENE]: Storing {0}, {1} in {2}", | 2423 | // "[SCENE]: Storing {0}, {1} in {2}", |
1649 | // Name, UUID, m_scene.RegionInfo.RegionName); | 2424 | // Name, UUID, m_scene.RegionInfo.RegionName); |
1650 | 2425 | ||
2426 | if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0) | ||
2427 | { | ||
2428 | RootPart.Shape.LastAttachPoint = RootPart.Shape.State; | ||
2429 | RootPart.Shape.State = 0; | ||
2430 | ScheduleGroupForFullUpdate(); | ||
2431 | } | ||
2432 | |||
1651 | SceneObjectGroup backup_group = Copy(false); | 2433 | SceneObjectGroup backup_group = Copy(false); |
1652 | backup_group.RootPart.Velocity = RootPart.Velocity; | 2434 | backup_group.RootPart.Velocity = RootPart.Velocity; |
1653 | backup_group.RootPart.Acceleration = RootPart.Acceleration; | 2435 | backup_group.RootPart.Acceleration = RootPart.Acceleration; |
@@ -1657,13 +2439,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
1657 | GroupContainsForeignPrims = false; | 2439 | GroupContainsForeignPrims = false; |
1658 | 2440 | ||
1659 | m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); | 2441 | m_scene.EventManager.TriggerOnSceneObjectPreSave(backup_group, this); |
2442 | |||
1660 | datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); | 2443 | datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); |
1661 | 2444 | ||
1662 | backup_group.ForEachPart(delegate(SceneObjectPart part) | 2445 | backup_group.ForEachPart(delegate(SceneObjectPart part) |
1663 | { | 2446 | { |
1664 | part.Inventory.ProcessInventoryBackup(datastore); | 2447 | part.Inventory.ProcessInventoryBackup(datastore); |
2448 | |||
2449 | // take the change to delete things | ||
2450 | if(part.KeyframeMotion != null) | ||
2451 | { | ||
2452 | part.KeyframeMotion.Delete(); | ||
2453 | part.KeyframeMotion = null; | ||
2454 | } | ||
1665 | }); | 2455 | }); |
1666 | 2456 | ||
2457 | |||
1667 | backup_group = null; | 2458 | backup_group = null; |
1668 | } | 2459 | } |
1669 | // else | 2460 | // else |
@@ -1713,6 +2504,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1713 | /// <returns></returns> | 2504 | /// <returns></returns> |
1714 | public SceneObjectGroup Copy(bool userExposed) | 2505 | public SceneObjectGroup Copy(bool userExposed) |
1715 | { | 2506 | { |
2507 | <<<<<<< HEAD | ||
1716 | // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up | 2508 | // FIXME: This is dangerous since it's easy to forget to reset some references when necessary and end up |
1717 | // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator | 2509 | // with bugs that only occur in some circumstances (e.g. crossing between regions on the same simulator |
1718 | // but not between regions on different simulators). Really, all copying should be done explicitly. | 2510 | // but not between regions on different simulators). Really, all copying should be done explicitly. |
@@ -1721,18 +2513,32 @@ namespace OpenSim.Region.Framework.Scenes | |||
1721 | dupe.Backup = false; | 2513 | dupe.Backup = false; |
1722 | dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); | 2514 | dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); |
1723 | dupe.m_sittingAvatars = new List<ScenePresence>(); | 2515 | dupe.m_sittingAvatars = new List<ScenePresence>(); |
2516 | ======= | ||
2517 | m_dupeInProgress = true; | ||
2518 | SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); | ||
2519 | dupe.m_isBackedUp = false; | ||
2520 | dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); | ||
2521 | |||
2522 | dupe.inTransit = inTransit; // this shouldn't be needed TEST | ||
2523 | |||
2524 | // new group as no sitting avatars | ||
2525 | dupe.m_linkedAvatars = new List<ScenePresence>(); | ||
2526 | dupe.m_sittingAvatars = new List<UUID>(); | ||
2527 | |||
2528 | >>>>>>> avn/ubitvar | ||
1724 | dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); | 2529 | dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); |
1725 | dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; | 2530 | dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; |
2531 | |||
1726 | 2532 | ||
1727 | if (userExposed) | 2533 | if (userExposed) |
1728 | dupe.m_rootPart.TrimPermissions(); | 2534 | dupe.m_rootPart.TrimPermissions(); |
1729 | 2535 | ||
1730 | List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); | 2536 | List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); |
1731 | 2537 | ||
1732 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) | 2538 | partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) |
1733 | { | 2539 | { |
1734 | return p1.LinkNum.CompareTo(p2.LinkNum); | 2540 | return p1.LinkNum.CompareTo(p2.LinkNum); |
1735 | } | 2541 | } |
1736 | ); | 2542 | ); |
1737 | 2543 | ||
1738 | foreach (SceneObjectPart part in partList) | 2544 | foreach (SceneObjectPart part in partList) |
@@ -1742,43 +2548,56 @@ namespace OpenSim.Region.Framework.Scenes | |||
1742 | { | 2548 | { |
1743 | newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); | 2549 | newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); |
1744 | newPart.LinkNum = part.LinkNum; | 2550 | newPart.LinkNum = part.LinkNum; |
1745 | } | 2551 | // if (userExposed) |
2552 | newPart.ParentID = dupe.m_rootPart.LocalId; | ||
2553 | } | ||
1746 | else | 2554 | else |
1747 | { | 2555 | { |
1748 | newPart = dupe.m_rootPart; | 2556 | newPart = dupe.m_rootPart; |
1749 | } | 2557 | } |
2558 | /* | ||
2559 | bool isphys = ((newPart.Flags & PrimFlags.Physics) != 0); | ||
2560 | bool isphan = ((newPart.Flags & PrimFlags.Phantom) != 0); | ||
1750 | 2561 | ||
1751 | // Need to duplicate the physics actor as well | 2562 | // Need to duplicate the physics actor as well |
1752 | PhysicsActor originalPartPa = part.PhysActor; | 2563 | if (userExposed && (isphys || !isphan || newPart.VolumeDetectActive)) |
1753 | if (originalPartPa != null && userExposed) | ||
1754 | { | 2564 | { |
1755 | PrimitiveBaseShape pbs = newPart.Shape; | 2565 | PrimitiveBaseShape pbs = newPart.Shape; |
1756 | |||
1757 | newPart.PhysActor | 2566 | newPart.PhysActor |
1758 | = m_scene.PhysicsScene.AddPrimShape( | 2567 | = m_scene.PhysicsScene.AddPrimShape( |
1759 | string.Format("{0}/{1}", newPart.Name, newPart.UUID), | 2568 | string.Format("{0}/{1}", newPart.Name, newPart.UUID), |
1760 | pbs, | 2569 | pbs, |
1761 | newPart.AbsolutePosition, | 2570 | newPart.AbsolutePosition, |
1762 | newPart.Scale, | 2571 | newPart.Scale, |
1763 | newPart.RotationOffset, | 2572 | newPart.GetWorldRotation(), |
1764 | originalPartPa.IsPhysical, | 2573 | isphys, |
2574 | isphan, | ||
1765 | newPart.LocalId); | 2575 | newPart.LocalId); |
1766 | 2576 | ||
1767 | newPart.DoPhysicsPropertyUpdate(originalPartPa.IsPhysical, true); | 2577 | newPart.DoPhysicsPropertyUpdate(isphys, true); |
1768 | } | 2578 | */ |
2579 | if (userExposed) | ||
2580 | newPart.ApplyPhysics((uint)newPart.Flags,newPart.VolumeDetectActive,true); | ||
2581 | // } | ||
2582 | // copy keyframemotion | ||
1769 | if (part.KeyframeMotion != null) | 2583 | if (part.KeyframeMotion != null) |
1770 | newPart.KeyframeMotion = part.KeyframeMotion.Copy(dupe); | 2584 | newPart.KeyframeMotion = part.KeyframeMotion.Copy(dupe); |
1771 | } | 2585 | } |
1772 | 2586 | ||
1773 | if (userExposed) | 2587 | if (userExposed) |
1774 | { | 2588 | { |
1775 | dupe.UpdateParentIDs(); | 2589 | // done above dupe.UpdateParentIDs(); |
2590 | |||
2591 | if (dupe.m_rootPart.PhysActor != null) | ||
2592 | dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building | ||
2593 | |||
1776 | dupe.HasGroupChanged = true; | 2594 | dupe.HasGroupChanged = true; |
1777 | dupe.AttachToBackup(); | 2595 | dupe.AttachToBackup(); |
1778 | 2596 | ||
1779 | ScheduleGroupForFullUpdate(); | 2597 | ScheduleGroupForFullUpdate(); |
1780 | } | 2598 | } |
1781 | 2599 | ||
2600 | m_dupeInProgress = false; | ||
1782 | return dupe; | 2601 | return dupe; |
1783 | } | 2602 | } |
1784 | 2603 | ||
@@ -1790,7 +2609,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
1790 | /// <param name="cGroupID"></param> | 2609 | /// <param name="cGroupID"></param> |
1791 | public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) | 2610 | public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) |
1792 | { | 2611 | { |
1793 | SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); | 2612 | SceneObjectPart newpart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed); |
2613 | // SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed); | ||
2614 | // newpart.LocalId = m_scene.AllocateLocalId(); | ||
2615 | |||
2616 | SetRootPart(newpart); | ||
2617 | if (userExposed) | ||
2618 | RootPart.Velocity = Vector3.Zero; // In case source is moving | ||
1794 | } | 2619 | } |
1795 | 2620 | ||
1796 | public void ScriptSetPhysicsStatus(bool usePhysics) | 2621 | public void ScriptSetPhysicsStatus(bool usePhysics) |
@@ -1848,13 +2673,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
1848 | 2673 | ||
1849 | if (pa != null) | 2674 | if (pa != null) |
1850 | { | 2675 | { |
1851 | pa.AddForce(impulse, true); | 2676 | // false to be applied as a impulse |
2677 | pa.AddForce(impulse, false); | ||
1852 | m_scene.PhysicsScene.AddPhysicsActorTaint(pa); | 2678 | m_scene.PhysicsScene.AddPhysicsActorTaint(pa); |
1853 | } | 2679 | } |
1854 | } | 2680 | } |
1855 | } | 2681 | } |
1856 | 2682 | ||
1857 | public void applyAngularImpulse(Vector3 impulse) | 2683 | public void ApplyAngularImpulse(Vector3 impulse) |
1858 | { | 2684 | { |
1859 | PhysicsActor pa = RootPart.PhysActor; | 2685 | PhysicsActor pa = RootPart.PhysActor; |
1860 | 2686 | ||
@@ -1862,21 +2688,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
1862 | { | 2688 | { |
1863 | if (!IsAttachment) | 2689 | if (!IsAttachment) |
1864 | { | 2690 | { |
1865 | pa.AddAngularForce(impulse, true); | 2691 | // false to be applied as a impulse |
1866 | m_scene.PhysicsScene.AddPhysicsActorTaint(pa); | 2692 | pa.AddAngularForce(impulse, false); |
1867 | } | ||
1868 | } | ||
1869 | } | ||
1870 | |||
1871 | public void setAngularImpulse(Vector3 impulse) | ||
1872 | { | ||
1873 | PhysicsActor pa = RootPart.PhysActor; | ||
1874 | |||
1875 | if (pa != null) | ||
1876 | { | ||
1877 | if (!IsAttachment) | ||
1878 | { | ||
1879 | pa.Torque = impulse; | ||
1880 | m_scene.PhysicsScene.AddPhysicsActorTaint(pa); | 2693 | m_scene.PhysicsScene.AddPhysicsActorTaint(pa); |
1881 | } | 2694 | } |
1882 | } | 2695 | } |
@@ -1884,21 +2697,15 @@ namespace OpenSim.Region.Framework.Scenes | |||
1884 | 2697 | ||
1885 | public Vector3 GetTorque() | 2698 | public Vector3 GetTorque() |
1886 | { | 2699 | { |
1887 | PhysicsActor pa = RootPart.PhysActor; | 2700 | return RootPart.Torque; |
1888 | |||
1889 | if (pa != null) | ||
1890 | { | ||
1891 | if (!IsAttachment) | ||
1892 | { | ||
1893 | Vector3 torque = pa.Torque; | ||
1894 | return torque; | ||
1895 | } | ||
1896 | } | ||
1897 | |||
1898 | return Vector3.Zero; | ||
1899 | } | 2701 | } |
1900 | 2702 | ||
2703 | <<<<<<< HEAD | ||
1901 | public void MoveToTarget(Vector3 target, float tau) | 2704 | public void MoveToTarget(Vector3 target, float tau) |
2705 | ======= | ||
2706 | // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object | ||
2707 | public void moveToTarget(Vector3 target, float tau) | ||
2708 | >>>>>>> avn/ubitvar | ||
1902 | { | 2709 | { |
1903 | if (IsAttachment) | 2710 | if (IsAttachment) |
1904 | { | 2711 | { |
@@ -1925,6 +2732,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1925 | if (IsAttachment) | 2732 | if (IsAttachment) |
1926 | { | 2733 | { |
1927 | ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); | 2734 | ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar); |
2735 | <<<<<<< HEAD | ||
1928 | 2736 | ||
1929 | if (avatar != null) | 2737 | if (avatar != null) |
1930 | avatar.ResetMoveToTarget(); | 2738 | avatar.ResetMoveToTarget(); |
@@ -1938,10 +2746,64 @@ namespace OpenSim.Region.Framework.Scenes | |||
1938 | pa.PIDActive = false; | 2746 | pa.PIDActive = false; |
1939 | 2747 | ||
1940 | ScheduleGroupForTerseUpdate(); | 2748 | ScheduleGroupForTerseUpdate(); |
2749 | ======= | ||
2750 | if (avatar != null) | ||
2751 | { | ||
2752 | avatar.ResetMoveToTarget(); | ||
2753 | } | ||
2754 | } | ||
2755 | else | ||
2756 | { | ||
2757 | PhysicsActor pa = RootPart.PhysActor; | ||
2758 | |||
2759 | if (pa != null) | ||
2760 | pa.PIDActive = false; | ||
2761 | |||
2762 | RootPart.ScheduleTerseUpdate(); // send a stop information | ||
2763 | } | ||
2764 | } | ||
2765 | |||
2766 | public void rotLookAt(Quaternion target, float strength, float damping) | ||
2767 | { | ||
2768 | SceneObjectPart rootpart = m_rootPart; | ||
2769 | if (rootpart != null) | ||
2770 | { | ||
2771 | if (IsAttachment) | ||
2772 | { | ||
2773 | /* | ||
2774 | ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar); | ||
2775 | if (avatar != null) | ||
2776 | { | ||
2777 | Rotate the Av? | ||
2778 | } */ | ||
2779 | } | ||
2780 | else | ||
2781 | { | ||
2782 | if (rootpart.PhysActor != null) | ||
2783 | { // APID must be implemented in your physics system for this to function. | ||
2784 | rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W); | ||
2785 | rootpart.PhysActor.APIDStrength = strength; | ||
2786 | rootpart.PhysActor.APIDDamping = damping; | ||
2787 | rootpart.PhysActor.APIDActive = true; | ||
2788 | } | ||
2789 | >>>>>>> avn/ubitvar | ||
1941 | } | 2790 | } |
1942 | } | 2791 | } |
1943 | } | 2792 | } |
2793 | |||
2794 | public void stopLookAt() | ||
2795 | { | ||
2796 | SceneObjectPart rootpart = m_rootPart; | ||
2797 | if (rootpart != null) | ||
2798 | { | ||
2799 | if (rootpart.PhysActor != null) | ||
2800 | { // APID must be implemented in your physics system for this to function. | ||
2801 | rootpart.PhysActor.APIDActive = false; | ||
2802 | } | ||
2803 | } | ||
1944 | 2804 | ||
2805 | } | ||
2806 | |||
1945 | /// <summary> | 2807 | /// <summary> |
1946 | /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. | 2808 | /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. |
1947 | /// </summary> | 2809 | /// </summary> |
@@ -1958,7 +2820,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
1958 | { | 2820 | { |
1959 | pa.PIDHoverHeight = height; | 2821 | pa.PIDHoverHeight = height; |
1960 | pa.PIDHoverType = hoverType; | 2822 | pa.PIDHoverType = hoverType; |
1961 | pa.PIDTau = tau; | 2823 | pa.PIDHoverTau = tau; |
1962 | pa.PIDHoverActive = true; | 2824 | pa.PIDHoverActive = true; |
1963 | } | 2825 | } |
1964 | else | 2826 | else |
@@ -1999,6 +2861,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
1999 | public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) | 2861 | public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) |
2000 | { | 2862 | { |
2001 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); | 2863 | SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); |
2864 | // SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed); | ||
2865 | // newPart.LocalId = m_scene.AllocateLocalId(); | ||
2866 | |||
2002 | AddPart(newPart); | 2867 | AddPart(newPart); |
2003 | 2868 | ||
2004 | SetPartAsNonRoot(newPart); | 2869 | SetPartAsNonRoot(newPart); |
@@ -2048,6 +2913,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2048 | 2913 | ||
2049 | #endregion | 2914 | #endregion |
2050 | 2915 | ||
2916 | |||
2051 | public override void Update() | 2917 | public override void Update() |
2052 | { | 2918 | { |
2053 | // Check that the group was not deleted before the scheduled update | 2919 | // Check that the group was not deleted before the scheduled update |
@@ -2055,7 +2921,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2055 | // an object has been deleted from a scene before update was processed. | 2921 | // an object has been deleted from a scene before update was processed. |
2056 | // A more fundamental overhaul of the update mechanism is required to eliminate all | 2922 | // A more fundamental overhaul of the update mechanism is required to eliminate all |
2057 | // the race conditions. | 2923 | // the race conditions. |
2058 | if (IsDeleted) | 2924 | if (IsDeleted || inTransit) |
2059 | return; | 2925 | return; |
2060 | 2926 | ||
2061 | // Even temporary objects take part in physics (e.g. temp-on-rez bullets) | 2927 | // Even temporary objects take part in physics (e.g. temp-on-rez bullets) |
@@ -2066,18 +2932,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2066 | // check to see if the physical position or rotation warrant an update. | 2932 | // check to see if the physical position or rotation warrant an update. |
2067 | if (m_rootPart.UpdateFlag == UpdateRequired.NONE) | 2933 | if (m_rootPart.UpdateFlag == UpdateRequired.NONE) |
2068 | { | 2934 | { |
2069 | bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0); | 2935 | // rootpart SendScheduledUpdates will check if a update is needed |
2070 | 2936 | m_rootPart.UpdateFlag = UpdateRequired.TERSE; | |
2071 | if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f)) | 2937 | } |
2072 | { | ||
2073 | m_rootPart.UpdateFlag = UpdateRequired.TERSE; | ||
2074 | lastPhysGroupPos = AbsolutePosition; | ||
2075 | } | ||
2076 | 2938 | ||
2077 | if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f)) | 2939 | if (IsAttachment) |
2940 | { | ||
2941 | ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar); | ||
2942 | if (sp != null) | ||
2078 | { | 2943 | { |
2079 | m_rootPart.UpdateFlag = UpdateRequired.TERSE; | 2944 | sp.SendAttachmentScheduleUpdate(this); |
2080 | lastPhysGroupRot = GroupRotation; | 2945 | return; |
2081 | } | 2946 | } |
2082 | } | 2947 | } |
2083 | 2948 | ||
@@ -2137,20 +3002,30 @@ namespace OpenSim.Region.Framework.Scenes | |||
2137 | /// Immediately send a full update for this scene object. | 3002 | /// Immediately send a full update for this scene object. |
2138 | /// </summary> | 3003 | /// </summary> |
2139 | public void SendGroupFullUpdate() | 3004 | public void SendGroupFullUpdate() |
2140 | { | 3005 | { |
2141 | if (IsDeleted) | 3006 | if (IsDeleted) |
2142 | return; | 3007 | return; |
2143 | 3008 | ||
2144 | // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); | 3009 | // m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); |
2145 | 3010 | ||
2146 | RootPart.SendFullUpdateToAllClients(); | 3011 | if (IsAttachment) |
3012 | { | ||
3013 | ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar); | ||
3014 | if (sp != null) | ||
3015 | { | ||
3016 | sp.SendAttachmentUpdate(this,UpdateRequired.FULL); | ||
3017 | return; | ||
3018 | } | ||
3019 | } | ||
3020 | |||
3021 | RootPart.SendFullUpdateToAllClientsInternal(); | ||
2147 | 3022 | ||
2148 | SceneObjectPart[] parts = m_parts.GetArray(); | 3023 | SceneObjectPart[] parts = m_parts.GetArray(); |
2149 | for (int i = 0; i < parts.Length; i++) | 3024 | for (int i = 0; i < parts.Length; i++) |
2150 | { | 3025 | { |
2151 | SceneObjectPart part = parts[i]; | 3026 | SceneObjectPart part = parts[i]; |
2152 | if (part != RootPart) | 3027 | if (part != RootPart) |
2153 | part.SendFullUpdateToAllClients(); | 3028 | part.SendFullUpdateToAllClientsInternal(); |
2154 | } | 3029 | } |
2155 | } | 3030 | } |
2156 | 3031 | ||
@@ -2162,7 +3037,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2162 | /// </summary> | 3037 | /// </summary> |
2163 | public void SendGroupRootTerseUpdate() | 3038 | public void SendGroupRootTerseUpdate() |
2164 | { | 3039 | { |
2165 | if (IsDeleted) | 3040 | if (IsDeleted || inTransit) |
2166 | return; | 3041 | return; |
2167 | 3042 | ||
2168 | RootPart.SendTerseUpdateToAllClients(); | 3043 | RootPart.SendTerseUpdateToAllClients(); |
@@ -2181,12 +3056,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
2181 | /// </summary> | 3056 | /// </summary> |
2182 | public void SendGroupTerseUpdate() | 3057 | public void SendGroupTerseUpdate() |
2183 | { | 3058 | { |
2184 | if (IsDeleted) | 3059 | if (IsDeleted || inTransit) |
2185 | return; | 3060 | return; |
2186 | 3061 | ||
3062 | if (IsAttachment) | ||
3063 | { | ||
3064 | ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar); | ||
3065 | if (sp != null) | ||
3066 | { | ||
3067 | sp.SendAttachmentUpdate(this, UpdateRequired.TERSE); | ||
3068 | return; | ||
3069 | } | ||
3070 | } | ||
3071 | |||
2187 | SceneObjectPart[] parts = m_parts.GetArray(); | 3072 | SceneObjectPart[] parts = m_parts.GetArray(); |
2188 | for (int i = 0; i < parts.Length; i++) | 3073 | for (int i = 0; i < parts.Length; i++) |
2189 | parts[i].SendTerseUpdateToAllClients(); | 3074 | parts[i].SendTerseUpdateToAllClientsInternal(); |
2190 | } | 3075 | } |
2191 | 3076 | ||
2192 | /// <summary> | 3077 | /// <summary> |
@@ -2294,9 +3179,41 @@ namespace OpenSim.Region.Framework.Scenes | |||
2294 | return; | 3179 | return; |
2295 | } | 3180 | } |
2296 | 3181 | ||
3182 | // physical prims count limit | ||
3183 | // not very eficient :( | ||
3184 | |||
3185 | if (UsesPhysics && m_scene.m_linksetPhysCapacity > 0 && (PrimCount + objectGroup.PrimCount) > | ||
3186 | m_scene.m_linksetPhysCapacity) | ||
3187 | { | ||
3188 | int cntr = 0; | ||
3189 | foreach (SceneObjectPart part in Parts) | ||
3190 | { | ||
3191 | if (part.PhysicsShapeType != (byte)PhysicsShapeType.None) | ||
3192 | cntr++; | ||
3193 | } | ||
3194 | foreach (SceneObjectPart part in objectGroup.Parts) | ||
3195 | { | ||
3196 | if (part.PhysicsShapeType != (byte)PhysicsShapeType.None) | ||
3197 | cntr++; | ||
3198 | } | ||
3199 | |||
3200 | if (cntr > m_scene.m_linksetPhysCapacity) | ||
3201 | { | ||
3202 | // cancel physics | ||
3203 | RootPart.Flags &= ~PrimFlags.Physics; | ||
3204 | ApplyPhysics(); | ||
3205 | } | ||
3206 | } | ||
3207 | |||
3208 | |||
2297 | // 'linkPart' == the root of the group being linked into this group | 3209 | // 'linkPart' == the root of the group being linked into this group |
2298 | SceneObjectPart linkPart = objectGroup.m_rootPart; | 3210 | SceneObjectPart linkPart = objectGroup.m_rootPart; |
2299 | 3211 | ||
3212 | if (m_rootPart.PhysActor != null) | ||
3213 | m_rootPart.PhysActor.Building = true; | ||
3214 | if (linkPart.PhysActor != null) | ||
3215 | linkPart.PhysActor.Building = true; | ||
3216 | |||
2300 | // physics flags from group to be applied to linked parts | 3217 | // physics flags from group to be applied to linked parts |
2301 | bool grpusephys = UsesPhysics; | 3218 | bool grpusephys = UsesPhysics; |
2302 | bool grptemporary = IsTemporary; | 3219 | bool grptemporary = IsTemporary; |
@@ -2313,22 +3230,24 @@ namespace OpenSim.Region.Framework.Scenes | |||
2313 | // First move the new group's root SOP's position to be relative to ours | 3230 | // First move the new group's root SOP's position to be relative to ours |
2314 | // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not, | 3231 | // (radams1: Not sure if the multiple setting of OffsetPosition is required. If not, |
2315 | // this code can be reordered to have a more logical flow.) | 3232 | // this code can be reordered to have a more logical flow.) |
2316 | linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; | 3233 | linkPart.setOffsetPosition(linkPart.GroupPosition - AbsolutePosition); |
2317 | // Assign the new parent to the root of the old group | 3234 | // Assign the new parent to the root of the old group |
2318 | linkPart.ParentID = m_rootPart.LocalId; | 3235 | linkPart.ParentID = m_rootPart.LocalId; |
2319 | // Now that it's a child, it's group position is our root position | 3236 | // Now that it's a child, it's group position is our root position |
2320 | linkPart.GroupPosition = AbsolutePosition; | 3237 | linkPart.setGroupPosition(AbsolutePosition); |
2321 | 3238 | ||
2322 | Vector3 axPos = linkPart.OffsetPosition; | ||
2323 | // Rotate the linking root SOP's position to be relative to the new root prim | 3239 | // Rotate the linking root SOP's position to be relative to the new root prim |
2324 | Quaternion parentRot = m_rootPart.RotationOffset; | 3240 | Quaternion parentRot = m_rootPart.RotationOffset; |
2325 | axPos *= Quaternion.Inverse(parentRot); | ||
2326 | linkPart.OffsetPosition = axPos; | ||
2327 | 3241 | ||
2328 | // Make the linking root SOP's rotation relative to the new root prim | 3242 | // Make the linking root SOP's rotation relative to the new root prim |
2329 | Quaternion oldRot = linkPart.RotationOffset; | 3243 | Quaternion oldRot = linkPart.RotationOffset; |
2330 | Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; | 3244 | Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot; |
2331 | linkPart.RotationOffset = newRot; | 3245 | linkPart.setRotationOffset(newRot); |
3246 | |||
3247 | Vector3 axPos = linkPart.OffsetPosition; | ||
3248 | axPos *= Quaternion.Conjugate(parentRot); | ||
3249 | linkPart.OffsetPosition = axPos; | ||
3250 | |||
2332 | 3251 | ||
2333 | // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. | 3252 | // If there is only one SOP in a SOG, the LinkNum is zero. I.e., not a linkset. |
2334 | // Now that we know this SOG has at least two SOPs in it, the new root | 3253 | // Now that we know this SOG has at least two SOPs in it, the new root |
@@ -2358,10 +3277,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2358 | m_parts.Add(linkPart.UUID, linkPart); | 3277 | m_parts.Add(linkPart.UUID, linkPart); |
2359 | 3278 | ||
2360 | linkPart.SetParent(this); | 3279 | linkPart.SetParent(this); |
3280 | m_scene.updateScenePartGroup(linkPart, this); | ||
3281 | |||
2361 | linkPart.CreateSelected = true; | 3282 | linkPart.CreateSelected = true; |
2362 | 3283 | ||
2363 | // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now | 3284 | // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now |
2364 | linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive); | 3285 | linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true); |
2365 | 3286 | ||
2366 | // If the added SOP is physical, also tell the physics engine about the link relationship. | 3287 | // If the added SOP is physical, also tell the physics engine about the link relationship. |
2367 | if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) | 3288 | if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) |
@@ -2371,6 +3292,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2371 | } | 3292 | } |
2372 | 3293 | ||
2373 | linkPart.LinkNum = linkNum++; | 3294 | linkPart.LinkNum = linkNum++; |
3295 | linkPart.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false); | ||
2374 | 3296 | ||
2375 | // Get a list of the SOP's in the old group in order of their linknum's. | 3297 | // Get a list of the SOP's in the old group in order of their linknum's. |
2376 | SceneObjectPart[] ogParts = objectGroup.Parts; | 3298 | SceneObjectPart[] ogParts = objectGroup.Parts; |
@@ -2389,7 +3311,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2389 | 3311 | ||
2390 | // Update the physics flags for the newly added SOP | 3312 | // Update the physics flags for the newly added SOP |
2391 | // (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??) | 3313 | // (Is this necessary? LinkNonRootPart() has already called UpdatePrimFlags but with different flags!??) |
2392 | part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive); | 3314 | part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true); |
2393 | 3315 | ||
2394 | // If the added SOP is physical, also tell the physics engine about the link relationship. | 3316 | // If the added SOP is physical, also tell the physics engine about the link relationship. |
2395 | if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) | 3317 | if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) |
@@ -2407,7 +3329,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
2407 | objectGroup.IsDeleted = true; | 3329 | objectGroup.IsDeleted = true; |
2408 | 3330 | ||
2409 | objectGroup.m_parts.Clear(); | 3331 | objectGroup.m_parts.Clear(); |
2410 | 3332 | ||
2411 | // Can't do this yet since backup still makes use of the root part without any synchronization | 3333 | // Can't do this yet since backup still makes use of the root part without any synchronization |
2412 | // objectGroup.m_rootPart = null; | 3334 | // objectGroup.m_rootPart = null; |
2413 | 3335 | ||
@@ -2423,6 +3345,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
2423 | // unmoved prims! | 3345 | // unmoved prims! |
2424 | ResetChildPrimPhysicsPositions(); | 3346 | ResetChildPrimPhysicsPositions(); |
2425 | 3347 | ||
3348 | if (m_rootPart.PhysActor != null) | ||
3349 | m_rootPart.PhysActor.Building = false; | ||
3350 | |||
2426 | //HasGroupChanged = true; | 3351 | //HasGroupChanged = true; |
2427 | //ScheduleGroupForFullUpdate(); | 3352 | //ScheduleGroupForFullUpdate(); |
2428 | } | 3353 | } |
@@ -2490,7 +3415,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
2490 | // m_log.DebugFormat( | 3415 | // m_log.DebugFormat( |
2491 | // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", | 3416 | // "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", |
2492 | // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); | 3417 | // linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); |
2493 | 3418 | ||
3419 | if (m_rootPart.PhysActor != null) | ||
3420 | m_rootPart.PhysActor.Building = true; | ||
3421 | |||
2494 | linkPart.ClearUndoState(); | 3422 | linkPart.ClearUndoState(); |
2495 | 3423 | ||
2496 | Vector3 worldPos = linkPart.GetWorldPosition(); | 3424 | Vector3 worldPos = linkPart.GetWorldPosition(); |
@@ -2545,20 +3473,18 @@ namespace OpenSim.Region.Framework.Scenes | |||
2545 | linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; | 3473 | linkPart.GroupPosition = AbsolutePosition + linkPart.OffsetPosition; |
2546 | linkPart.OffsetPosition = new Vector3(0, 0, 0); | 3474 | linkPart.OffsetPosition = new Vector3(0, 0, 0); |
2547 | */ | 3475 | */ |
2548 | linkPart.GroupPosition = worldPos; | 3476 | linkPart.setGroupPosition(worldPos); |
2549 | linkPart.OffsetPosition = Vector3.Zero; | 3477 | linkPart.setOffsetPosition(Vector3.Zero); |
2550 | linkPart.RotationOffset = worldRot; | 3478 | linkPart.setRotationOffset(worldRot); |
2551 | 3479 | ||
2552 | // Create a new SOG to go around this unlinked and unattached SOP | 3480 | // Create a new SOG to go around this unlinked and unattached SOP |
2553 | SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); | 3481 | SceneObjectGroup objectGroup = new SceneObjectGroup(linkPart); |
2554 | 3482 | ||
2555 | m_scene.AddNewSceneObject(objectGroup, true); | 3483 | m_scene.AddNewSceneObject(objectGroup, true); |
2556 | 3484 | ||
2557 | if (sendEvents) | ||
2558 | linkPart.TriggerScriptChangedEvent(Changed.LINK); | ||
2559 | |||
2560 | linkPart.Rezzed = RootPart.Rezzed; | 3485 | linkPart.Rezzed = RootPart.Rezzed; |
2561 | 3486 | ||
3487 | <<<<<<< HEAD | ||
2562 | // We must persist the delinked group to the database immediately, for safety. The problem | 3488 | // We must persist the delinked group to the database immediately, for safety. The problem |
2563 | // is that although in memory the new group has a new SceneGroupID, in the database it | 3489 | // is that although in memory the new group has a new SceneGroupID, in the database it |
2564 | // still has the parent group's SceneGroupID (until the next backup). This means that if the | 3490 | // still has the parent group's SceneGroupID (until the next backup). This means that if the |
@@ -2569,6 +3495,22 @@ namespace OpenSim.Region.Framework.Scenes | |||
2569 | // not happen. (We can't use a just-in-time trick like GroupContainsForeignPrims in this case | 3495 | // not happen. (We can't use a just-in-time trick like GroupContainsForeignPrims in this case |
2570 | // because the delinked group doesn't know when the source group is deleted.) | 3496 | // because the delinked group doesn't know when the source group is deleted.) |
2571 | m_scene.ForceSceneObjectBackup(objectGroup); | 3497 | m_scene.ForceSceneObjectBackup(objectGroup); |
3498 | ======= | ||
3499 | // When we delete a group, we currently have to force persist to the database if the object id has changed | ||
3500 | // (since delete works by deleting all rows which have a given object id) | ||
3501 | |||
3502 | // this is as it seems to be in sl now | ||
3503 | if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none) | ||
3504 | linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now | ||
3505 | |||
3506 | if (m_rootPart.PhysActor != null) | ||
3507 | m_rootPart.PhysActor.Building = false; | ||
3508 | |||
3509 | objectGroup.HasGroupChangedDueToDelink = true; | ||
3510 | >>>>>>> avn/ubitvar | ||
3511 | |||
3512 | if (sendEvents) | ||
3513 | linkPart.TriggerScriptChangedEvent(Changed.LINK); | ||
2572 | 3514 | ||
2573 | return objectGroup; | 3515 | return objectGroup; |
2574 | } | 3516 | } |
@@ -2579,7 +3521,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
2579 | /// <param name="objectGroup"></param> | 3521 | /// <param name="objectGroup"></param> |
2580 | public virtual void DetachFromBackup() | 3522 | public virtual void DetachFromBackup() |
2581 | { | 3523 | { |
3524 | <<<<<<< HEAD | ||
2582 | if (Backup && Scene != null) | 3525 | if (Backup && Scene != null) |
3526 | ======= | ||
3527 | if (m_scene != null) | ||
3528 | m_scene.SceneGraph.FireDetachFromBackup(this); | ||
3529 | if (m_isBackedUp && Scene != null) | ||
3530 | >>>>>>> avn/ubitvar | ||
2583 | m_scene.EventManager.OnBackup -= ProcessBackup; | 3531 | m_scene.EventManager.OnBackup -= ProcessBackup; |
2584 | 3532 | ||
2585 | Backup = false; | 3533 | Backup = false; |
@@ -2595,14 +3543,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
2595 | Quaternion parentRot = oldGroupRotation; | 3543 | Quaternion parentRot = oldGroupRotation; |
2596 | Quaternion oldRot = part.RotationOffset; | 3544 | Quaternion oldRot = part.RotationOffset; |
2597 | 3545 | ||
2598 | // Move our position to not be relative to the old parent | 3546 | // Move our position in world |
2599 | Vector3 axPos = part.OffsetPosition; | 3547 | Vector3 axPos = part.OffsetPosition; |
2600 | axPos *= parentRot; | 3548 | axPos *= parentRot; |
2601 | part.OffsetPosition = axPos; | 3549 | Vector3 newPos = oldGroupPosition + axPos; |
2602 | part.GroupPosition = oldGroupPosition + part.OffsetPosition; | 3550 | part.setGroupPosition(newPos); |
2603 | part.OffsetPosition = Vector3.Zero; | 3551 | part.setOffsetPosition(Vector3.Zero); |
2604 | 3552 | ||
2605 | // Compution our rotation to be not relative to the old parent | 3553 | // Compution our rotation in world |
2606 | Quaternion worldRot = parentRot * oldRot; | 3554 | Quaternion worldRot = parentRot * oldRot; |
2607 | part.RotationOffset = worldRot; | 3555 | part.RotationOffset = worldRot; |
2608 | 3556 | ||
@@ -2613,29 +3561,32 @@ namespace OpenSim.Region.Framework.Scenes | |||
2613 | 3561 | ||
2614 | part.LinkNum = linkNum; | 3562 | part.LinkNum = linkNum; |
2615 | 3563 | ||
3564 | m_scene.updateScenePartGroup(part, this); | ||
3565 | |||
2616 | // Compute the new position of this SOP relative to the group position | 3566 | // Compute the new position of this SOP relative to the group position |
2617 | part.OffsetPosition = part.GroupPosition - AbsolutePosition; | 3567 | part.setOffsetPosition(newPos - AbsolutePosition); |
2618 | 3568 | ||
2619 | // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times. | 3569 | // (radams1 20120711: I don't know why part.OffsetPosition is set multiple times. |
2620 | // It would have the affect of setting the physics engine position multiple | 3570 | // It would have the affect of setting the physics engine position multiple |
2621 | // times. In theory, that is not necessary but I don't have a good linkset | 3571 | // times. In theory, that is not necessary but I don't have a good linkset |
2622 | // test to know that cleaning up this code wouldn't break things.) | 3572 | // test to know that cleaning up this code wouldn't break things.) |
2623 | 3573 | ||
2624 | // Rotate the relative position by the rotation of the group | ||
2625 | Quaternion rootRotation = m_rootPart.RotationOffset; | ||
2626 | Vector3 pos = part.OffsetPosition; | ||
2627 | pos *= Quaternion.Inverse(rootRotation); | ||
2628 | part.OffsetPosition = pos; | ||
2629 | |||
2630 | // Compute the SOP's rotation relative to the rotation of the group. | 3574 | // Compute the SOP's rotation relative to the rotation of the group. |
2631 | parentRot = m_rootPart.RotationOffset; | 3575 | parentRot = m_rootPart.RotationOffset; |
3576 | |||
2632 | oldRot = part.RotationOffset; | 3577 | oldRot = part.RotationOffset; |
2633 | Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; | 3578 | Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot; |
2634 | part.RotationOffset = newRot; | 3579 | part.setRotationOffset(newRot); |
3580 | |||
3581 | Vector3 pos = part.OffsetPosition; | ||
3582 | pos *= Quaternion.Conjugate(parentRot); | ||
3583 | |||
3584 | part.OffsetPosition = pos; // update position and orientation on physics also | ||
2635 | 3585 | ||
2636 | // Since this SOP's state has changed, push those changes into the physics engine | 3586 | // Since this SOP's state has changed, push those changes into the physics engine |
2637 | // and the simulator. | 3587 | // and the simulator. |
2638 | part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect); | 3588 | // done on caller |
3589 | // part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false); | ||
2639 | } | 3590 | } |
2640 | 3591 | ||
2641 | /// <summary> | 3592 | /// <summary> |
@@ -2663,10 +3614,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
2663 | { | 3614 | { |
2664 | if (!BlockGrabOverride && !part.BlockGrab) | 3615 | if (!BlockGrabOverride && !part.BlockGrab) |
2665 | { | 3616 | { |
2666 | Vector3 llmoveforce = pos - AbsolutePosition; | 3617 | /* Vector3 llmoveforce = pos - AbsolutePosition; |
2667 | Vector3 grabforce = llmoveforce; | 3618 | Vector3 grabforce = llmoveforce; |
2668 | grabforce = (grabforce / 10) * pa.Mass; | 3619 | grabforce = (grabforce / 10) * pa.Mass; |
2669 | pa.AddForce(grabforce, true); | 3620 | */ |
3621 | // empirically convert distance diference to a impulse | ||
3622 | Vector3 grabforce = pos - AbsolutePosition; | ||
3623 | grabforce = grabforce * (pa.Mass/ 10.0f); | ||
3624 | pa.AddForce(grabforce, false); | ||
2670 | m_scene.PhysicsScene.AddPhysicsActorTaint(pa); | 3625 | m_scene.PhysicsScene.AddPhysicsActorTaint(pa); |
2671 | } | 3626 | } |
2672 | } | 3627 | } |
@@ -2880,6 +3835,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
2880 | /// <param name="SetVolumeDetect"></param> | 3835 | /// <param name="SetVolumeDetect"></param> |
2881 | public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect) | 3836 | public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect) |
2882 | { | 3837 | { |
3838 | HasGroupChanged = true; | ||
3839 | |||
2883 | SceneObjectPart selectionPart = GetPart(localID); | 3840 | SceneObjectPart selectionPart = GetPart(localID); |
2884 | 3841 | ||
2885 | if (Scene != null) | 3842 | if (Scene != null) |
@@ -2905,8 +3862,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
2905 | { | 3862 | { |
2906 | SceneObjectPart[] parts = m_parts.GetArray(); | 3863 | SceneObjectPart[] parts = m_parts.GetArray(); |
2907 | 3864 | ||
2908 | if (Scene != null) | 3865 | if (Scene != null && UsePhysics) |
2909 | { | 3866 | { |
3867 | int maxprims = m_scene.m_linksetPhysCapacity; | ||
3868 | bool checkShape = (maxprims > 0 && | ||
3869 | parts.Length > maxprims); | ||
3870 | |||
2910 | for (int i = 0; i < parts.Length; i++) | 3871 | for (int i = 0; i < parts.Length; i++) |
2911 | { | 3872 | { |
2912 | SceneObjectPart part = parts[i]; | 3873 | SceneObjectPart part = parts[i]; |
@@ -2917,11 +3878,34 @@ namespace OpenSim.Region.Framework.Scenes | |||
2917 | UsePhysics = false; // Reset physics | 3878 | UsePhysics = false; // Reset physics |
2918 | break; | 3879 | break; |
2919 | } | 3880 | } |
3881 | |||
3882 | if (checkShape && part.PhysicsShapeType != (byte)PhysicsShapeType.None) | ||
3883 | { | ||
3884 | if (--maxprims < 0) | ||
3885 | { | ||
3886 | UsePhysics = false; | ||
3887 | break; | ||
3888 | } | ||
3889 | } | ||
2920 | } | 3890 | } |
2921 | } | 3891 | } |
2922 | 3892 | ||
2923 | for (int i = 0; i < parts.Length; i++) | 3893 | if (parts.Length > 1) |
2924 | parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); | 3894 | { |
3895 | m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true); | ||
3896 | |||
3897 | for (int i = 0; i < parts.Length; i++) | ||
3898 | { | ||
3899 | |||
3900 | if (parts[i].UUID != m_rootPart.UUID) | ||
3901 | parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true); | ||
3902 | } | ||
3903 | |||
3904 | if (m_rootPart.PhysActor != null) | ||
3905 | m_rootPart.PhysActor.Building = false; | ||
3906 | } | ||
3907 | else | ||
3908 | m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false); | ||
2925 | } | 3909 | } |
2926 | } | 3910 | } |
2927 | 3911 | ||
@@ -2934,6 +3918,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
2934 | } | 3918 | } |
2935 | } | 3919 | } |
2936 | 3920 | ||
3921 | |||
3922 | |||
3923 | /// <summary> | ||
3924 | /// Gets the number of parts | ||
3925 | /// </summary> | ||
3926 | /// <returns></returns> | ||
3927 | public int GetPartCount() | ||
3928 | { | ||
3929 | return Parts.Count(); | ||
3930 | } | ||
3931 | |||
2937 | /// <summary> | 3932 | /// <summary> |
2938 | /// Update the texture entry for this part | 3933 | /// Update the texture entry for this part |
2939 | /// </summary> | 3934 | /// </summary> |
@@ -2978,7 +3973,27 @@ namespace OpenSim.Region.Framework.Scenes | |||
2978 | { | 3973 | { |
2979 | RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF); | 3974 | RootPart.UpdatePermissions(AgentID, field, localID, mask, addRemTF); |
2980 | 3975 | ||
3976 | <<<<<<< HEAD | ||
2981 | AdjustChildPrimPermissions(Scene.Permissions.IsGod(AgentID)); | 3977 | AdjustChildPrimPermissions(Scene.Permissions.IsGod(AgentID)); |
3978 | ======= | ||
3979 | bool god = Scene.Permissions.IsGod(AgentID); | ||
3980 | |||
3981 | if (field == 1 && god) | ||
3982 | { | ||
3983 | ForEachPart(part => | ||
3984 | { | ||
3985 | part.BaseMask = RootPart.BaseMask; | ||
3986 | }); | ||
3987 | } | ||
3988 | |||
3989 | AdjustChildPrimPermissions(); | ||
3990 | >>>>>>> avn/ubitvar | ||
3991 | |||
3992 | if (field == 1 && god) // Base mask was set. Update all child part inventories | ||
3993 | { | ||
3994 | foreach (SceneObjectPart part in Parts) | ||
3995 | part.Inventory.ApplyGodPermissions(RootPart.BaseMask); | ||
3996 | } | ||
2982 | 3997 | ||
2983 | HasGroupChanged = true; | 3998 | HasGroupChanged = true; |
2984 | 3999 | ||
@@ -3025,8 +4040,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3025 | 4040 | ||
3026 | PhysicsActor pa = m_rootPart.PhysActor; | 4041 | PhysicsActor pa = m_rootPart.PhysActor; |
3027 | 4042 | ||
3028 | RootPart.StoreUndoState(true); | ||
3029 | |||
3030 | if (Scene != null) | 4043 | if (Scene != null) |
3031 | { | 4044 | { |
3032 | scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); | 4045 | scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); |
@@ -3054,7 +4067,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3054 | SceneObjectPart obPart = parts[i]; | 4067 | SceneObjectPart obPart = parts[i]; |
3055 | if (obPart.UUID != m_rootPart.UUID) | 4068 | if (obPart.UUID != m_rootPart.UUID) |
3056 | { | 4069 | { |
3057 | // obPart.IgnoreUndoUpdate = true; | ||
3058 | Vector3 oldSize = new Vector3(obPart.Scale); | 4070 | Vector3 oldSize = new Vector3(obPart.Scale); |
3059 | 4071 | ||
3060 | float f = 1.0f; | 4072 | float f = 1.0f; |
@@ -3166,8 +4178,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3166 | z *= a; | 4178 | z *= a; |
3167 | } | 4179 | } |
3168 | } | 4180 | } |
3169 | |||
3170 | // obPart.IgnoreUndoUpdate = false; | ||
3171 | } | 4181 | } |
3172 | } | 4182 | } |
3173 | } | 4183 | } |
@@ -3177,9 +4187,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3177 | prevScale.Y *= y; | 4187 | prevScale.Y *= y; |
3178 | prevScale.Z *= z; | 4188 | prevScale.Z *= z; |
3179 | 4189 | ||
3180 | // RootPart.IgnoreUndoUpdate = true; | ||
3181 | RootPart.Resize(prevScale); | 4190 | RootPart.Resize(prevScale); |
3182 | // RootPart.IgnoreUndoUpdate = false; | ||
3183 | 4191 | ||
3184 | for (int i = 0; i < parts.Length; i++) | 4192 | for (int i = 0; i < parts.Length; i++) |
3185 | { | 4193 | { |
@@ -3187,8 +4195,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3187 | 4195 | ||
3188 | if (obPart.UUID != m_rootPart.UUID) | 4196 | if (obPart.UUID != m_rootPart.UUID) |
3189 | { | 4197 | { |
3190 | obPart.IgnoreUndoUpdate = true; | ||
3191 | |||
3192 | Vector3 currentpos = new Vector3(obPart.OffsetPosition); | 4198 | Vector3 currentpos = new Vector3(obPart.OffsetPosition); |
3193 | currentpos.X *= x; | 4199 | currentpos.X *= x; |
3194 | currentpos.Y *= y; | 4200 | currentpos.Y *= y; |
@@ -3201,16 +4207,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3201 | 4207 | ||
3202 | obPart.Resize(newSize); | 4208 | obPart.Resize(newSize); |
3203 | obPart.UpdateOffSet(currentpos); | 4209 | obPart.UpdateOffSet(currentpos); |
3204 | |||
3205 | obPart.IgnoreUndoUpdate = false; | ||
3206 | } | 4210 | } |
3207 | 4211 | ||
3208 | // obPart.IgnoreUndoUpdate = false; | 4212 | HasGroupChanged = true; |
3209 | // obPart.StoreUndoState(); | 4213 | m_rootPart.TriggerScriptChangedEvent(Changed.SCALE); |
4214 | ScheduleGroupForTerseUpdate(); | ||
3210 | } | 4215 | } |
3211 | |||
3212 | // m_log.DebugFormat( | ||
3213 | // "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale); | ||
3214 | } | 4216 | } |
3215 | 4217 | ||
3216 | #endregion | 4218 | #endregion |
@@ -3223,14 +4225,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3223 | /// <param name="pos"></param> | 4225 | /// <param name="pos"></param> |
3224 | public void UpdateGroupPosition(Vector3 pos) | 4226 | public void UpdateGroupPosition(Vector3 pos) |
3225 | { | 4227 | { |
3226 | // m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos); | ||
3227 | |||
3228 | RootPart.StoreUndoState(true); | ||
3229 | |||
3230 | // SceneObjectPart[] parts = m_parts.GetArray(); | ||
3231 | // for (int i = 0; i < parts.Length; i++) | ||
3232 | // parts[i].StoreUndoState(); | ||
3233 | |||
3234 | if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) | 4228 | if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) |
3235 | { | 4229 | { |
3236 | if (IsAttachment) | 4230 | if (IsAttachment) |
@@ -3263,21 +4257,17 @@ namespace OpenSim.Region.Framework.Scenes | |||
3263 | /// </summary> | 4257 | /// </summary> |
3264 | /// <param name="pos"></param> | 4258 | /// <param name="pos"></param> |
3265 | /// <param name="localID"></param> | 4259 | /// <param name="localID"></param> |
4260 | /// | ||
4261 | |||
3266 | public void UpdateSinglePosition(Vector3 pos, uint localID) | 4262 | public void UpdateSinglePosition(Vector3 pos, uint localID) |
3267 | { | 4263 | { |
3268 | SceneObjectPart part = GetPart(localID); | 4264 | SceneObjectPart part = GetPart(localID); |
3269 | 4265 | ||
3270 | // SceneObjectPart[] parts = m_parts.GetArray(); | ||
3271 | // for (int i = 0; i < parts.Length; i++) | ||
3272 | // parts[i].StoreUndoState(); | ||
3273 | |||
3274 | if (part != null) | 4266 | if (part != null) |
3275 | { | 4267 | { |
3276 | // m_log.DebugFormat( | 4268 | // unlock parts position change |
3277 | // "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); | 4269 | if (m_rootPart.PhysActor != null) |
3278 | 4270 | m_rootPart.PhysActor.Building = true; | |
3279 | part.StoreUndoState(false); | ||
3280 | part.IgnoreUndoUpdate = true; | ||
3281 | 4271 | ||
3282 | if (part.UUID == m_rootPart.UUID) | 4272 | if (part.UUID == m_rootPart.UUID) |
3283 | { | 4273 | { |
@@ -3288,8 +4278,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
3288 | part.UpdateOffSet(pos); | 4278 | part.UpdateOffSet(pos); |
3289 | } | 4279 | } |
3290 | 4280 | ||
4281 | if (m_rootPart.PhysActor != null) | ||
4282 | m_rootPart.PhysActor.Building = false; | ||
4283 | |||
3291 | HasGroupChanged = true; | 4284 | HasGroupChanged = true; |
3292 | part.IgnoreUndoUpdate = false; | ||
3293 | } | 4285 | } |
3294 | } | 4286 | } |
3295 | 4287 | ||
@@ -3299,13 +4291,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
3299 | /// <param name="newPos"></param> | 4291 | /// <param name="newPos"></param> |
3300 | public void UpdateRootPosition(Vector3 newPos) | 4292 | public void UpdateRootPosition(Vector3 newPos) |
3301 | { | 4293 | { |
3302 | // m_log.DebugFormat( | 4294 | // needs to be called with phys building true |
3303 | // "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos); | ||
3304 | |||
3305 | // SceneObjectPart[] parts = m_parts.GetArray(); | ||
3306 | // for (int i = 0; i < parts.Length; i++) | ||
3307 | // parts[i].StoreUndoState(); | ||
3308 | |||
3309 | Vector3 oldPos; | 4295 | Vector3 oldPos; |
3310 | 4296 | ||
3311 | if (IsAttachment) | 4297 | if (IsAttachment) |
@@ -3326,12 +4312,19 @@ namespace OpenSim.Region.Framework.Scenes | |||
3326 | } | 4312 | } |
3327 | 4313 | ||
3328 | AbsolutePosition = newPos; | 4314 | AbsolutePosition = newPos; |
3329 | 4315 | ||
3330 | if (IsAttachment) | 4316 | if (IsAttachment) |
3331 | m_rootPart.AttachedPos = newPos; | 4317 | m_rootPart.AttachedPos = newPos; |
3332 | 4318 | ||
3333 | HasGroupChanged = true; | 4319 | HasGroupChanged = true; |
3334 | ScheduleGroupForTerseUpdate(); | 4320 | if (m_rootPart.Undoing) |
4321 | { | ||
4322 | ScheduleGroupForFullUpdate(); | ||
4323 | } | ||
4324 | else | ||
4325 | { | ||
4326 | ScheduleGroupForTerseUpdate(); | ||
4327 | } | ||
3335 | } | 4328 | } |
3336 | 4329 | ||
3337 | #endregion | 4330 | #endregion |
@@ -3344,24 +4337,16 @@ namespace OpenSim.Region.Framework.Scenes | |||
3344 | /// <param name="rot"></param> | 4337 | /// <param name="rot"></param> |
3345 | public void UpdateGroupRotationR(Quaternion rot) | 4338 | public void UpdateGroupRotationR(Quaternion rot) |
3346 | { | 4339 | { |
3347 | // m_log.DebugFormat( | ||
3348 | // "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot); | ||
3349 | |||
3350 | // SceneObjectPart[] parts = m_parts.GetArray(); | ||
3351 | // for (int i = 0; i < parts.Length; i++) | ||
3352 | // parts[i].StoreUndoState(); | ||
3353 | |||
3354 | m_rootPart.StoreUndoState(true); | ||
3355 | |||
3356 | m_rootPart.UpdateRotation(rot); | 4340 | m_rootPart.UpdateRotation(rot); |
3357 | 4341 | ||
4342 | /* this is done by rootpart RotationOffset set called by UpdateRotation | ||
3358 | PhysicsActor actor = m_rootPart.PhysActor; | 4343 | PhysicsActor actor = m_rootPart.PhysActor; |
3359 | if (actor != null) | 4344 | if (actor != null) |
3360 | { | 4345 | { |
3361 | actor.Orientation = m_rootPart.RotationOffset; | 4346 | actor.Orientation = m_rootPart.RotationOffset; |
3362 | m_scene.PhysicsScene.AddPhysicsActorTaint(actor); | 4347 | m_scene.PhysicsScene.AddPhysicsActorTaint(actor); |
3363 | } | 4348 | } |
3364 | 4349 | */ | |
3365 | HasGroupChanged = true; | 4350 | HasGroupChanged = true; |
3366 | ScheduleGroupForTerseUpdate(); | 4351 | ScheduleGroupForTerseUpdate(); |
3367 | } | 4352 | } |
@@ -3373,16 +4358,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3373 | /// <param name="rot"></param> | 4358 | /// <param name="rot"></param> |
3374 | public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) | 4359 | public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) |
3375 | { | 4360 | { |
3376 | // m_log.DebugFormat( | ||
3377 | // "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot); | ||
3378 | |||
3379 | // SceneObjectPart[] parts = m_parts.GetArray(); | ||
3380 | // for (int i = 0; i < parts.Length; i++) | ||
3381 | // parts[i].StoreUndoState(); | ||
3382 | |||
3383 | RootPart.StoreUndoState(true); | ||
3384 | RootPart.IgnoreUndoUpdate = true; | ||
3385 | |||
3386 | m_rootPart.UpdateRotation(rot); | 4361 | m_rootPart.UpdateRotation(rot); |
3387 | 4362 | ||
3388 | PhysicsActor actor = m_rootPart.PhysActor; | 4363 | PhysicsActor actor = m_rootPart.PhysActor; |
@@ -3401,8 +4376,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
3401 | 4376 | ||
3402 | HasGroupChanged = true; | 4377 | HasGroupChanged = true; |
3403 | ScheduleGroupForTerseUpdate(); | 4378 | ScheduleGroupForTerseUpdate(); |
3404 | |||
3405 | RootPart.IgnoreUndoUpdate = false; | ||
3406 | } | 4379 | } |
3407 | 4380 | ||
3408 | /// <summary> | 4381 | /// <summary> |
@@ -3415,13 +4388,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
3415 | SceneObjectPart part = GetPart(localID); | 4388 | SceneObjectPart part = GetPart(localID); |
3416 | 4389 | ||
3417 | SceneObjectPart[] parts = m_parts.GetArray(); | 4390 | SceneObjectPart[] parts = m_parts.GetArray(); |
3418 | for (int i = 0; i < parts.Length; i++) | ||
3419 | parts[i].StoreUndoState(); | ||
3420 | 4391 | ||
3421 | if (part != null) | 4392 | if (part != null) |
3422 | { | 4393 | { |
3423 | // m_log.DebugFormat( | 4394 | if (m_rootPart.PhysActor != null) |
3424 | // "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); | 4395 | m_rootPart.PhysActor.Building = true; |
3425 | 4396 | ||
3426 | if (part.UUID == m_rootPart.UUID) | 4397 | if (part.UUID == m_rootPart.UUID) |
3427 | { | 4398 | { |
@@ -3431,6 +4402,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3431 | { | 4402 | { |
3432 | part.UpdateRotation(rot); | 4403 | part.UpdateRotation(rot); |
3433 | } | 4404 | } |
4405 | |||
4406 | if (m_rootPart.PhysActor != null) | ||
4407 | m_rootPart.PhysActor.Building = false; | ||
3434 | } | 4408 | } |
3435 | } | 4409 | } |
3436 | 4410 | ||
@@ -3444,12 +4418,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3444 | SceneObjectPart part = GetPart(localID); | 4418 | SceneObjectPart part = GetPart(localID); |
3445 | if (part != null) | 4419 | if (part != null) |
3446 | { | 4420 | { |
3447 | // m_log.DebugFormat( | 4421 | if (m_rootPart.PhysActor != null) |
3448 | // "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", | 4422 | m_rootPart.PhysActor.Building = true; |
3449 | // part.Name, part.LocalId, rot); | ||
3450 | |||
3451 | part.StoreUndoState(); | ||
3452 | part.IgnoreUndoUpdate = true; | ||
3453 | 4423 | ||
3454 | if (part.UUID == m_rootPart.UUID) | 4424 | if (part.UUID == m_rootPart.UUID) |
3455 | { | 4425 | { |
@@ -3462,7 +4432,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3462 | part.OffsetPosition = pos; | 4432 | part.OffsetPosition = pos; |
3463 | } | 4433 | } |
3464 | 4434 | ||
3465 | part.IgnoreUndoUpdate = false; | 4435 | if (m_rootPart.PhysActor != null) |
4436 | m_rootPart.PhysActor.Building = false; | ||
3466 | } | 4437 | } |
3467 | } | 4438 | } |
3468 | 4439 | ||
@@ -3472,15 +4443,12 @@ namespace OpenSim.Region.Framework.Scenes | |||
3472 | /// <param name="rot"></param> | 4443 | /// <param name="rot"></param> |
3473 | public void UpdateRootRotation(Quaternion rot) | 4444 | public void UpdateRootRotation(Quaternion rot) |
3474 | { | 4445 | { |
3475 | // m_log.DebugFormat( | 4446 | // needs to be called with phys building true |
3476 | // "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}", | ||
3477 | // Name, LocalId, rot); | ||
3478 | |||
3479 | Quaternion axRot = rot; | 4447 | Quaternion axRot = rot; |
3480 | Quaternion oldParentRot = m_rootPart.RotationOffset; | 4448 | Quaternion oldParentRot = m_rootPart.RotationOffset; |
3481 | 4449 | ||
3482 | m_rootPart.StoreUndoState(); | 4450 | //Don't use UpdateRotation because it schedules an update prematurely |
3483 | m_rootPart.UpdateRotation(rot); | 4451 | m_rootPart.RotationOffset = rot; |
3484 | 4452 | ||
3485 | PhysicsActor pa = m_rootPart.PhysActor; | 4453 | PhysicsActor pa = m_rootPart.PhysActor; |
3486 | 4454 | ||
@@ -3496,35 +4464,145 @@ namespace OpenSim.Region.Framework.Scenes | |||
3496 | SceneObjectPart prim = parts[i]; | 4464 | SceneObjectPart prim = parts[i]; |
3497 | if (prim.UUID != m_rootPart.UUID) | 4465 | if (prim.UUID != m_rootPart.UUID) |
3498 | { | 4466 | { |
3499 | prim.IgnoreUndoUpdate = true; | 4467 | Quaternion NewRot = oldParentRot * prim.RotationOffset; |
4468 | NewRot = Quaternion.Inverse(axRot) * NewRot; | ||
4469 | prim.RotationOffset = NewRot; | ||
4470 | |||
3500 | Vector3 axPos = prim.OffsetPosition; | 4471 | Vector3 axPos = prim.OffsetPosition; |
4472 | |||
3501 | axPos *= oldParentRot; | 4473 | axPos *= oldParentRot; |
3502 | axPos *= Quaternion.Inverse(axRot); | 4474 | axPos *= Quaternion.Inverse(axRot); |
3503 | prim.OffsetPosition = axPos; | 4475 | prim.OffsetPosition = axPos; |
3504 | Quaternion primsRot = prim.RotationOffset; | ||
3505 | Quaternion newRot = oldParentRot * primsRot; | ||
3506 | newRot = Quaternion.Inverse(axRot) * newRot; | ||
3507 | prim.RotationOffset = newRot; | ||
3508 | prim.ScheduleTerseUpdate(); | ||
3509 | prim.IgnoreUndoUpdate = false; | ||
3510 | } | 4476 | } |
3511 | } | 4477 | } |
3512 | 4478 | ||
3513 | // for (int i = 0; i < parts.Length; i++) | 4479 | HasGroupChanged = true; |
3514 | // { | 4480 | ScheduleGroupForFullUpdate(); |
3515 | // SceneObjectPart childpart = parts[i]; | 4481 | } |
3516 | // if (childpart != m_rootPart) | ||
3517 | // { | ||
3518 | //// childpart.IgnoreUndoUpdate = false; | ||
3519 | //// childpart.StoreUndoState(); | ||
3520 | // } | ||
3521 | // } | ||
3522 | 4482 | ||
3523 | m_rootPart.ScheduleTerseUpdate(); | 4483 | private enum updatetype :int |
4484 | { | ||
4485 | none = 0, | ||
4486 | partterse = 1, | ||
4487 | partfull = 2, | ||
4488 | groupterse = 3, | ||
4489 | groupfull = 4 | ||
4490 | } | ||
3524 | 4491 | ||
3525 | // m_log.DebugFormat( | 4492 | public void doChangeObject(SceneObjectPart part, ObjectChangeData data) |
3526 | // "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", | 4493 | { |
3527 | // Name, LocalId, rot); | 4494 | // TODO this still as excessive *.Schedule*Update()s |
4495 | |||
4496 | if (part != null && part.ParentGroup != null) | ||
4497 | { | ||
4498 | ObjectChangeType change = data.change; | ||
4499 | bool togroup = ((change & ObjectChangeType.Group) != 0); | ||
4500 | // bool uniform = ((what & ObjectChangeType.UniformScale) != 0); not in use | ||
4501 | |||
4502 | SceneObjectGroup group = part.ParentGroup; | ||
4503 | PhysicsActor pha = group.RootPart.PhysActor; | ||
4504 | |||
4505 | updatetype updateType = updatetype.none; | ||
4506 | |||
4507 | if (togroup) | ||
4508 | { | ||
4509 | // related to group | ||
4510 | if ((change & (ObjectChangeType.Rotation | ObjectChangeType.Position)) != 0) | ||
4511 | { | ||
4512 | if ((change & ObjectChangeType.Rotation) != 0) | ||
4513 | { | ||
4514 | group.RootPart.UpdateRotation(data.rotation); | ||
4515 | updateType = updatetype.none; | ||
4516 | } | ||
4517 | if ((change & ObjectChangeType.Position) != 0) | ||
4518 | { | ||
4519 | if (IsAttachment || m_scene.Permissions.CanObjectEntry(group.UUID, false, data.position)) | ||
4520 | UpdateGroupPosition(data.position); | ||
4521 | updateType = updatetype.groupterse; | ||
4522 | } | ||
4523 | else | ||
4524 | // ugly rotation update of all parts | ||
4525 | { | ||
4526 | group.ResetChildPrimPhysicsPositions(); | ||
4527 | } | ||
4528 | |||
4529 | } | ||
4530 | if ((change & ObjectChangeType.Scale) != 0) | ||
4531 | { | ||
4532 | if (pha != null) | ||
4533 | pha.Building = true; | ||
4534 | |||
4535 | group.GroupResize(data.scale); | ||
4536 | updateType = updatetype.none; | ||
4537 | |||
4538 | if (pha != null) | ||
4539 | pha.Building = false; | ||
4540 | } | ||
4541 | } | ||
4542 | else | ||
4543 | { | ||
4544 | // related to single prim in a link-set ( ie group) | ||
4545 | if (pha != null) | ||
4546 | pha.Building = true; | ||
4547 | |||
4548 | // root part is special | ||
4549 | // parts offset positions or rotations need to change also | ||
4550 | |||
4551 | if (part == group.RootPart) | ||
4552 | { | ||
4553 | if ((change & ObjectChangeType.Rotation) != 0) | ||
4554 | group.UpdateRootRotation(data.rotation); | ||
4555 | if ((change & ObjectChangeType.Position) != 0) | ||
4556 | group.UpdateRootPosition(data.position); | ||
4557 | if ((change & ObjectChangeType.Scale) != 0) | ||
4558 | part.Resize(data.scale); | ||
4559 | } | ||
4560 | else | ||
4561 | { | ||
4562 | if ((change & ObjectChangeType.Position) != 0) | ||
4563 | { | ||
4564 | part.OffsetPosition = data.position; | ||
4565 | updateType = updatetype.partterse; | ||
4566 | } | ||
4567 | if ((change & ObjectChangeType.Rotation) != 0) | ||
4568 | { | ||
4569 | part.UpdateRotation(data.rotation); | ||
4570 | updateType = updatetype.none; | ||
4571 | } | ||
4572 | if ((change & ObjectChangeType.Scale) != 0) | ||
4573 | { | ||
4574 | part.Resize(data.scale); | ||
4575 | updateType = updatetype.none; | ||
4576 | } | ||
4577 | } | ||
4578 | |||
4579 | if (pha != null) | ||
4580 | pha.Building = false; | ||
4581 | } | ||
4582 | |||
4583 | if (updateType != updatetype.none) | ||
4584 | { | ||
4585 | group.HasGroupChanged = true; | ||
4586 | |||
4587 | switch (updateType) | ||
4588 | { | ||
4589 | case updatetype.partterse: | ||
4590 | part.ScheduleTerseUpdate(); | ||
4591 | break; | ||
4592 | case updatetype.partfull: | ||
4593 | part.ScheduleFullUpdate(); | ||
4594 | break; | ||
4595 | case updatetype.groupterse: | ||
4596 | group.ScheduleGroupForTerseUpdate(); | ||
4597 | break; | ||
4598 | case updatetype.groupfull: | ||
4599 | group.ScheduleGroupForFullUpdate(); | ||
4600 | break; | ||
4601 | default: | ||
4602 | break; | ||
4603 | } | ||
4604 | } | ||
4605 | } | ||
3528 | } | 4606 | } |
3529 | 4607 | ||
3530 | #endregion | 4608 | #endregion |
@@ -3565,6 +4643,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3565 | waypoint.handle = handle; | 4643 | waypoint.handle = handle; |
3566 | lock (m_rotTargets) | 4644 | lock (m_rotTargets) |
3567 | { | 4645 | { |
4646 | if (m_rotTargets.Count >= 8) | ||
4647 | m_rotTargets.Remove(m_rotTargets.ElementAt(0).Key); | ||
3568 | m_rotTargets.Add(handle, waypoint); | 4648 | m_rotTargets.Add(handle, waypoint); |
3569 | } | 4649 | } |
3570 | m_scene.AddGroupTarget(this); | 4650 | m_scene.AddGroupTarget(this); |
@@ -3590,6 +4670,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3590 | waypoint.handle = handle; | 4670 | waypoint.handle = handle; |
3591 | lock (m_targets) | 4671 | lock (m_targets) |
3592 | { | 4672 | { |
4673 | if (m_targets.Count >= 8) | ||
4674 | m_targets.Remove(m_targets.ElementAt(0).Key); | ||
3593 | m_targets.Add(handle, waypoint); | 4675 | m_targets.Add(handle, waypoint); |
3594 | } | 4676 | } |
3595 | m_scene.AddGroupTarget(this); | 4677 | m_scene.AddGroupTarget(this); |
@@ -3623,10 +4705,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
3623 | scriptPosTarget target = m_targets[idx]; | 4705 | scriptPosTarget target = m_targets[idx]; |
3624 | if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance) | 4706 | if (Util.GetDistanceTo(target.targetPos, m_rootPart.GroupPosition) <= target.tolerance) |
3625 | { | 4707 | { |
4708 | at_target = true; | ||
4709 | |||
3626 | // trigger at_target | 4710 | // trigger at_target |
3627 | if (m_scriptListens_atTarget) | 4711 | if (m_scriptListens_atTarget) |
3628 | { | 4712 | { |
3629 | at_target = true; | ||
3630 | scriptPosTarget att = new scriptPosTarget(); | 4713 | scriptPosTarget att = new scriptPosTarget(); |
3631 | att.targetPos = target.targetPos; | 4714 | att.targetPos = target.targetPos; |
3632 | att.tolerance = target.tolerance; | 4715 | att.tolerance = target.tolerance; |
@@ -3744,11 +4827,50 @@ namespace OpenSim.Region.Framework.Scenes | |||
3744 | } | 4827 | } |
3745 | } | 4828 | } |
3746 | } | 4829 | } |
3747 | 4830 | ||
4831 | public Vector3 GetGeometricCenter() | ||
4832 | { | ||
4833 | // this is not real geometric center but a average of positions relative to root prim acording to | ||
4834 | // http://wiki.secondlife.com/wiki/llGetGeometricCenter | ||
4835 | // ignoring tortured prims details since sl also seems to ignore | ||
4836 | // so no real use in doing it on physics | ||
4837 | |||
4838 | Vector3 gc = Vector3.Zero; | ||
4839 | |||
4840 | int nparts = m_parts.Count; | ||
4841 | if (nparts <= 1) | ||
4842 | return gc; | ||
4843 | |||
4844 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
4845 | nparts = parts.Length; // just in case it changed | ||
4846 | if (nparts <= 1) | ||
4847 | return gc; | ||
4848 | |||
4849 | Quaternion parentRot = RootPart.RotationOffset; | ||
4850 | Vector3 pPos; | ||
4851 | |||
4852 | // average all parts positions | ||
4853 | for (int i = 0; i < nparts; i++) | ||
4854 | { | ||
4855 | // do it directly | ||
4856 | // gc += parts[i].GetWorldPosition(); | ||
4857 | if (parts[i] != RootPart) | ||
4858 | { | ||
4859 | pPos = parts[i].OffsetPosition; | ||
4860 | gc += pPos; | ||
4861 | } | ||
4862 | |||
4863 | } | ||
4864 | gc /= nparts; | ||
4865 | |||
4866 | // relative to root: | ||
4867 | // gc -= AbsolutePosition; | ||
4868 | return gc; | ||
4869 | } | ||
4870 | |||
3748 | public float GetMass() | 4871 | public float GetMass() |
3749 | { | 4872 | { |
3750 | float retmass = 0f; | 4873 | float retmass = 0f; |
3751 | |||
3752 | SceneObjectPart[] parts = m_parts.GetArray(); | 4874 | SceneObjectPart[] parts = m_parts.GetArray(); |
3753 | for (int i = 0; i < parts.Length; i++) | 4875 | for (int i = 0; i < parts.Length; i++) |
3754 | retmass += parts[i].GetMass(); | 4876 | retmass += parts[i].GetMass(); |
@@ -3756,6 +4878,39 @@ namespace OpenSim.Region.Framework.Scenes | |||
3756 | return retmass; | 4878 | return retmass; |
3757 | } | 4879 | } |
3758 | 4880 | ||
4881 | // center of mass of full object | ||
4882 | public Vector3 GetCenterOfMass() | ||
4883 | { | ||
4884 | PhysicsActor pa = RootPart.PhysActor; | ||
4885 | |||
4886 | if(((RootPart.Flags & PrimFlags.Physics) !=0) && pa !=null) | ||
4887 | { | ||
4888 | // physics knows better about center of mass of physical prims | ||
4889 | Vector3 tmp = pa.CenterOfMass; | ||
4890 | return tmp; | ||
4891 | } | ||
4892 | |||
4893 | Vector3 Ptot = Vector3.Zero; | ||
4894 | float totmass = 0f; | ||
4895 | float m; | ||
4896 | |||
4897 | SceneObjectPart[] parts = m_parts.GetArray(); | ||
4898 | for (int i = 0; i < parts.Length; i++) | ||
4899 | { | ||
4900 | m = parts[i].GetMass(); | ||
4901 | Ptot += parts[i].GetPartCenterOfMass() * m; | ||
4902 | totmass += m; | ||
4903 | } | ||
4904 | |||
4905 | if (totmass == 0) | ||
4906 | totmass = 0; | ||
4907 | else | ||
4908 | totmass = 1 / totmass; | ||
4909 | Ptot *= totmass; | ||
4910 | |||
4911 | return Ptot; | ||
4912 | } | ||
4913 | |||
3759 | /// <summary> | 4914 | /// <summary> |
3760 | /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that | 4915 | /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that |
3761 | /// the physics engine can use it. | 4916 | /// the physics engine can use it. |
@@ -3935,6 +5090,14 @@ namespace OpenSim.Region.Framework.Scenes | |||
3935 | FromItemID = uuid; | 5090 | FromItemID = uuid; |
3936 | } | 5091 | } |
3937 | 5092 | ||
5093 | public void ResetOwnerChangeFlag() | ||
5094 | { | ||
5095 | ForEachPart(delegate(SceneObjectPart part) | ||
5096 | { | ||
5097 | part.ResetOwnerChangeFlag(); | ||
5098 | }); | ||
5099 | } | ||
5100 | |||
3938 | #endregion | 5101 | #endregion |
3939 | } | 5102 | } |
3940 | } | 5103 | } |