aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs21
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs28
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs479
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs301
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs104
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs219
7 files changed, 723 insertions, 433 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 8195a0d..6e66632 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1751,8 +1751,9 @@ namespace OpenSim.Region.Framework.Scenes
1751 SceneObjectPart rootPart = group.GetChildPart(group.UUID); 1751 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
1752 rootPart.Flags &= ~PrimFlags.Scripted; 1752 rootPart.Flags &= ~PrimFlags.Scripted;
1753 rootPart.TrimPermissions(); 1753 rootPart.TrimPermissions();
1754 group.CheckSculptAndLoad(); 1754
1755 //rootPart.DoPhysicsPropertyUpdate(UsePhysics, true); 1755 // Don't do this here - it will get done later on when sculpt data is loaded.
1756// group.CheckSculptAndLoad();
1756 } 1757 }
1757 1758
1758 m_log.Info("[SCENE]: Loaded " + PrimsFromDB.Count.ToString() + " SceneObject(s)"); 1759 m_log.Info("[SCENE]: Loaded " + PrimsFromDB.Count.ToString() + " SceneObject(s)");
@@ -2715,12 +2716,14 @@ namespace OpenSim.Region.Framework.Scenes
2715 2716
2716 public virtual void SubscribeToClientPrimEvents(IClientAPI client) 2717 public virtual void SubscribeToClientPrimEvents(IClientAPI client)
2717 { 2718 {
2718 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimPosition; 2719 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition;
2719 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; 2720 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
2720 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimRotation; 2721
2721 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimRotation; 2722 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation;
2723 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation;
2722 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; 2724 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
2723 client.OnUpdatePrimSingleRotationPosition += m_sceneGraph.UpdatePrimSingleRotationPosition; 2725 client.OnUpdatePrimSingleRotationPosition += m_sceneGraph.UpdatePrimSingleRotationPosition;
2726
2724 client.OnUpdatePrimScale += m_sceneGraph.UpdatePrimScale; 2727 client.OnUpdatePrimScale += m_sceneGraph.UpdatePrimScale;
2725 client.OnUpdatePrimGroupScale += m_sceneGraph.UpdatePrimGroupScale; 2728 client.OnUpdatePrimGroupScale += m_sceneGraph.UpdatePrimGroupScale;
2726 client.OnUpdateExtraParams += m_sceneGraph.UpdateExtraParam; 2729 client.OnUpdateExtraParams += m_sceneGraph.UpdateExtraParam;
@@ -2842,12 +2845,14 @@ namespace OpenSim.Region.Framework.Scenes
2842 2845
2843 public virtual void UnSubscribeToClientPrimEvents(IClientAPI client) 2846 public virtual void UnSubscribeToClientPrimEvents(IClientAPI client)
2844 { 2847 {
2845 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimPosition; 2848 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition;
2846 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; 2849 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition;
2847 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimRotation; 2850
2848 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimRotation; 2851 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation;
2852 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation;
2849 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; 2853 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation;
2850 client.OnUpdatePrimSingleRotationPosition -= m_sceneGraph.UpdatePrimSingleRotationPosition; 2854 client.OnUpdatePrimSingleRotationPosition -= m_sceneGraph.UpdatePrimSingleRotationPosition;
2855
2851 client.OnUpdatePrimScale -= m_sceneGraph.UpdatePrimScale; 2856 client.OnUpdatePrimScale -= m_sceneGraph.UpdatePrimScale;
2852 client.OnUpdatePrimGroupScale -= m_sceneGraph.UpdatePrimGroupScale; 2857 client.OnUpdatePrimGroupScale -= m_sceneGraph.UpdatePrimGroupScale;
2853 client.OnUpdateExtraParams -= m_sceneGraph.UpdateExtraParam; 2858 client.OnUpdateExtraParams -= m_sceneGraph.UpdateExtraParam;
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 7ec7ea3..65dc2c9 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -564,11 +564,13 @@ namespace OpenSim.Region.Framework.Scenes
564 part.Undo(); 564 part.Undo();
565 } 565 }
566 } 566 }
567
567 protected internal void HandleRedo(IClientAPI remoteClient, UUID primId) 568 protected internal void HandleRedo(IClientAPI remoteClient, UUID primId)
568 { 569 {
569 if (primId != UUID.Zero) 570 if (primId != UUID.Zero)
570 { 571 {
571 SceneObjectPart part = m_parentScene.GetSceneObjectPart(primId); 572 SceneObjectPart part = m_parentScene.GetSceneObjectPart(primId);
573
572 if (part != null) 574 if (part != null)
573 part.Redo(); 575 part.Redo();
574 } 576 }
@@ -1210,19 +1212,20 @@ namespace OpenSim.Region.Framework.Scenes
1210 #region Client Event handlers 1212 #region Client Event handlers
1211 1213
1212 /// <summary> 1214 /// <summary>
1213 /// 1215 /// Update the scale of an individual prim.
1214 /// </summary> 1216 /// </summary>
1215 /// <param name="localID"></param> 1217 /// <param name="localID"></param>
1216 /// <param name="scale"></param> 1218 /// <param name="scale"></param>
1217 /// <param name="remoteClient"></param> 1219 /// <param name="remoteClient"></param>
1218 protected internal void UpdatePrimScale(uint localID, Vector3 scale, IClientAPI remoteClient) 1220 protected internal void UpdatePrimScale(uint localID, Vector3 scale, IClientAPI remoteClient)
1219 { 1221 {
1220 SceneObjectGroup group = GetGroupByPrim(localID); 1222 SceneObjectPart part = GetSceneObjectPart(localID);
1221 if (group != null) 1223
1224 if (part != null)
1222 { 1225 {
1223 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1226 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId))
1224 { 1227 {
1225 group.Resize(scale, localID); 1228 part.Resize(scale);
1226 } 1229 }
1227 } 1230 }
1228 } 1231 }
@@ -1234,7 +1237,7 @@ namespace OpenSim.Region.Framework.Scenes
1234 { 1237 {
1235 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1238 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1236 { 1239 {
1237 group.GroupResize(scale, localID); 1240 group.GroupResize(scale);
1238 } 1241 }
1239 } 1242 }
1240 } 1243 }
@@ -1288,19 +1291,18 @@ namespace OpenSim.Region.Framework.Scenes
1288 { 1291 {
1289 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) 1292 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))
1290 { 1293 {
1291 group.UpdateSingleRotation(rot,pos, localID); 1294 group.UpdateSingleRotation(rot, pos, localID);
1292 } 1295 }
1293 } 1296 }
1294 } 1297 }
1295 1298
1296
1297 /// <summary> 1299 /// <summary>
1298 /// 1300 /// Update the rotation of a whole group.
1299 /// </summary> 1301 /// </summary>
1300 /// <param name="localID"></param> 1302 /// <param name="localID"></param>
1301 /// <param name="rot"></param> 1303 /// <param name="rot"></param>
1302 /// <param name="remoteClient"></param> 1304 /// <param name="remoteClient"></param>
1303 protected internal void UpdatePrimRotation(uint localID, Quaternion rot, IClientAPI remoteClient) 1305 protected internal void UpdatePrimGroupRotation(uint localID, Quaternion rot, IClientAPI remoteClient)
1304 { 1306 {
1305 SceneObjectGroup group = GetGroupByPrim(localID); 1307 SceneObjectGroup group = GetGroupByPrim(localID);
1306 if (group != null) 1308 if (group != null)
@@ -1319,7 +1321,7 @@ namespace OpenSim.Region.Framework.Scenes
1319 /// <param name="pos"></param> 1321 /// <param name="pos"></param>
1320 /// <param name="rot"></param> 1322 /// <param name="rot"></param>
1321 /// <param name="remoteClient"></param> 1323 /// <param name="remoteClient"></param>
1322 protected internal void UpdatePrimRotation(uint localID, Vector3 pos, Quaternion rot, IClientAPI remoteClient) 1324 protected internal void UpdatePrimGroupRotation(uint localID, Vector3 pos, Quaternion rot, IClientAPI remoteClient)
1323 { 1325 {
1324 SceneObjectGroup group = GetGroupByPrim(localID); 1326 SceneObjectGroup group = GetGroupByPrim(localID);
1325 if (group != null) 1327 if (group != null)
@@ -1350,12 +1352,12 @@ namespace OpenSim.Region.Framework.Scenes
1350 } 1352 }
1351 1353
1352 /// <summary> 1354 /// <summary>
1353 /// Update the position of the given part 1355 /// Update the position of the given group.
1354 /// </summary> 1356 /// </summary>
1355 /// <param name="localID"></param> 1357 /// <param name="localID"></param>
1356 /// <param name="pos"></param> 1358 /// <param name="pos"></param>
1357 /// <param name="remoteClient"></param> 1359 /// <param name="remoteClient"></param>
1358 public void UpdatePrimPosition(uint localID, Vector3 pos, IClientAPI remoteClient) 1360 public void UpdatePrimGroupPosition(uint localID, Vector3 pos, IClientAPI remoteClient)
1359 { 1361 {
1360 SceneObjectGroup group = GetGroupByPrim(localID); 1362 SceneObjectGroup group = GetGroupByPrim(localID);
1361 1363
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index fa23fcd..b6fb5a4 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -236,6 +236,38 @@ namespace OpenSim.Region.Framework.Scenes
236 get { return m_rootPart.RotationOffset; } 236 get { return m_rootPart.RotationOffset; }
237 } 237 }
238 238
239 public Vector3 GroupScale
240 {
241 get
242 {
243 Vector3 minScale = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionSize);
244 Vector3 maxScale = Vector3.Zero;
245 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
246
247 SceneObjectPart[] parts = m_parts.GetArray();
248 for (int i = 0; i < parts.Length; i++)
249 {
250 SceneObjectPart part = parts[i];
251 Vector3 partscale = part.Scale;
252 Vector3 partoffset = part.OffsetPosition;
253
254 minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X;
255 minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.Y + partoffset.Y : minScale.Y;
256 minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.Z + partoffset.Z : minScale.Z;
257
258 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
259 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
260 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
261 }
262
263 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
264 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
265 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
266
267 return finalScale;
268 }
269 }
270
239 public UUID GroupID 271 public UUID GroupID
240 { 272 {
241 get { return m_rootPart.GroupID; } 273 get { return m_rootPart.GroupID; }
@@ -584,7 +616,7 @@ namespace OpenSim.Region.Framework.Scenes
584 part.ParentID = m_rootPart.LocalId; 616 part.ParentID = m_rootPart.LocalId;
585 //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID); 617 //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID);
586 } 618 }
587 619
588 ApplyPhysics(m_scene.m_physicalPrim); 620 ApplyPhysics(m_scene.m_physicalPrim);
589 621
590 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 622 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
@@ -592,34 +624,6 @@ namespace OpenSim.Region.Framework.Scenes
592 //ScheduleGroupForFullUpdate(); 624 //ScheduleGroupForFullUpdate();
593 } 625 }
594 626
595 public Vector3 GroupScale()
596 {
597 Vector3 minScale = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionSize);
598 Vector3 maxScale = Vector3.Zero;
599 Vector3 finalScale = new Vector3(0.5f, 0.5f, 0.5f);
600
601 SceneObjectPart[] parts = m_parts.GetArray();
602 for (int i = 0; i < parts.Length; i++)
603 {
604 SceneObjectPart part = parts[i];
605 Vector3 partscale = part.Scale;
606 Vector3 partoffset = part.OffsetPosition;
607
608 minScale.X = (partscale.X + partoffset.X < minScale.X) ? partscale.X + partoffset.X : minScale.X;
609 minScale.Y = (partscale.Y + partoffset.Y < minScale.Y) ? partscale.Y + partoffset.Y : minScale.Y;
610 minScale.Z = (partscale.Z + partoffset.Z < minScale.Z) ? partscale.Z + partoffset.Z : minScale.Z;
611
612 maxScale.X = (partscale.X + partoffset.X > maxScale.X) ? partscale.X + partoffset.X : maxScale.X;
613 maxScale.Y = (partscale.Y + partoffset.Y > maxScale.Y) ? partscale.Y + partoffset.Y : maxScale.Y;
614 maxScale.Z = (partscale.Z + partoffset.Z > maxScale.Z) ? partscale.Z + partoffset.Z : maxScale.Z;
615 }
616
617 finalScale.X = (minScale.X > maxScale.X) ? minScale.X : maxScale.X;
618 finalScale.Y = (minScale.Y > maxScale.Y) ? minScale.Y : maxScale.Y;
619 finalScale.Z = (minScale.Z > maxScale.Z) ? minScale.Z : maxScale.Z;
620 return finalScale;
621
622 }
623 public EntityIntersection TestIntersection(Ray hRay, bool frontFacesOnly, bool faceCenters) 627 public EntityIntersection TestIntersection(Ray hRay, bool frontFacesOnly, bool faceCenters)
624 { 628 {
625 // We got a request from the inner_scene to raytrace along the Ray hRay 629 // We got a request from the inner_scene to raytrace along the Ray hRay
@@ -1141,6 +1145,10 @@ namespace OpenSim.Region.Framework.Scenes
1141 1145
1142 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1146 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1143 { 1147 {
1148// m_log.DebugFormat(
1149// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1150// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1151
1144 part.StoreUndoState(); 1152 part.StoreUndoState();
1145 part.OnGrab(offsetPos, remoteClient); 1153 part.OnGrab(offsetPos, remoteClient);
1146 } 1154 }
@@ -1463,17 +1471,17 @@ namespace OpenSim.Region.Framework.Scenes
1463 // Need to duplicate the physics actor as well 1471 // Need to duplicate the physics actor as well
1464 if (part.PhysActor != null && userExposed) 1472 if (part.PhysActor != null && userExposed)
1465 { 1473 {
1466 PrimitiveBaseShape pbs = part.Shape; 1474 PrimitiveBaseShape pbs = newPart.Shape;
1467 1475
1468 newPart.PhysActor 1476 newPart.PhysActor
1469 = m_scene.PhysicsScene.AddPrimShape( 1477 = m_scene.PhysicsScene.AddPrimShape(
1470 part.LocalId, 1478 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1471 string.Format("{0}/{1}", part.Name, part.UUID),
1472 pbs, 1479 pbs,
1473 part.AbsolutePosition, 1480 newPart.AbsolutePosition,
1474 part.Scale, 1481 newPart.Scale,
1475 part.RotationOffset, 1482 newPart.RotationOffset,
1476 part.PhysActor.IsPhysical); 1483 part.PhysActor.IsPhysical,
1484 newPart.LocalId);
1477 1485
1478 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 1486 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1479 } 1487 }
@@ -2608,195 +2616,150 @@ namespace OpenSim.Region.Framework.Scenes
2608 #region Resize 2616 #region Resize
2609 2617
2610 /// <summary> 2618 /// <summary>
2611 /// Resize the given part 2619 /// Resize the entire group of prims.
2612 /// </summary> 2620 /// </summary>
2613 /// <param name="scale"></param> 2621 /// <param name="scale"></param>
2614 /// <param name="localID"></param> 2622 public void GroupResize(Vector3 scale)
2615 public void Resize(Vector3 scale, uint localID)
2616 { 2623 {
2617 if (scale.X > m_scene.m_maxNonphys) 2624// m_log.DebugFormat(
2618 scale.X = m_scene.m_maxNonphys; 2625// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2619 if (scale.Y > m_scene.m_maxNonphys)
2620 scale.Y = m_scene.m_maxNonphys;
2621 if (scale.Z > m_scene.m_maxNonphys)
2622 scale.Z = m_scene.m_maxNonphys;
2623 2626
2624 SceneObjectPart part = GetChildPart(localID); 2627 RootPart.StoreUndoState(true);
2625 if (part != null)
2626 {
2627 part.Resize(scale);
2628 if (part.PhysActor != null)
2629 {
2630 if (part.PhysActor.IsPhysical)
2631 {
2632 if (scale.X > m_scene.m_maxPhys)
2633 scale.X = m_scene.m_maxPhys;
2634 if (scale.Y > m_scene.m_maxPhys)
2635 scale.Y = m_scene.m_maxPhys;
2636 if (scale.Z > m_scene.m_maxPhys)
2637 scale.Z = m_scene.m_maxPhys;
2638 }
2639 part.PhysActor.Size = scale;
2640 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2641 }
2642 //if (part.UUID != m_rootPart.UUID)
2643 2628
2644 HasGroupChanged = true; 2629 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
2645 part.TriggerScriptChangedEvent(Changed.SCALE); 2630 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
2646 ScheduleGroupForFullUpdate(); 2631 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
2647 2632
2648 //if (part.UUID == m_rootPart.UUID) 2633 if (RootPart.PhysActor != null && RootPart.PhysActor.IsPhysical)
2649 //{ 2634 {
2650 //if (m_rootPart.PhysActor != null) 2635 scale.X = Math.Min(scale.X, Scene.m_maxPhys);
2651 //{ 2636 scale.Y = Math.Min(scale.Y, Scene.m_maxPhys);
2652 //m_rootPart.PhysActor.Size = 2637 scale.Z = Math.Min(scale.Z, Scene.m_maxPhys);
2653 //new PhysicsVector(m_rootPart.Scale.X, m_rootPart.Scale.Y, m_rootPart.Scale.Z);
2654 //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
2655 //}
2656 //}
2657 } 2638 }
2658 }
2659 2639
2660 public void GroupResize(Vector3 scale, uint localID) 2640 float x = (scale.X / RootPart.Scale.X);
2661 { 2641 float y = (scale.Y / RootPart.Scale.Y);
2662 SceneObjectPart part = GetChildPart(localID); 2642 float z = (scale.Z / RootPart.Scale.Z);
2663 if (part != null)
2664 {
2665 part.IgnoreUndoUpdate = true;
2666 if (scale.X > m_scene.m_maxNonphys)
2667 scale.X = m_scene.m_maxNonphys;
2668 if (scale.Y > m_scene.m_maxNonphys)
2669 scale.Y = m_scene.m_maxNonphys;
2670 if (scale.Z > m_scene.m_maxNonphys)
2671 scale.Z = m_scene.m_maxNonphys;
2672 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2673 {
2674 if (scale.X > m_scene.m_maxPhys)
2675 scale.X = m_scene.m_maxPhys;
2676 if (scale.Y > m_scene.m_maxPhys)
2677 scale.Y = m_scene.m_maxPhys;
2678 if (scale.Z > m_scene.m_maxPhys)
2679 scale.Z = m_scene.m_maxPhys;
2680 }
2681 float x = (scale.X / part.Scale.X);
2682 float y = (scale.Y / part.Scale.Y);
2683 float z = (scale.Z / part.Scale.Z);
2684 2643
2685 SceneObjectPart[] parts; 2644 SceneObjectPart[] parts;
2686 if (x > 1.0f || y > 1.0f || z > 1.0f) 2645 if (x > 1.0f || y > 1.0f || z > 1.0f)
2646 {
2647 parts = m_parts.GetArray();
2648 for (int i = 0; i < parts.Length; i++)
2687 { 2649 {
2688 parts = m_parts.GetArray(); 2650 SceneObjectPart obPart = parts[i];
2689 for (int i = 0; i < parts.Length; i++) 2651 if (obPart.UUID != m_rootPart.UUID)
2690 { 2652 {
2691 SceneObjectPart obPart = parts[i]; 2653// obPart.IgnoreUndoUpdate = true;
2692 if (obPart.UUID != m_rootPart.UUID) 2654 Vector3 oldSize = new Vector3(obPart.Scale);
2655
2656 float f = 1.0f;
2657 float a = 1.0f;
2658
2659 if (RootPart.PhysActor != null && RootPart.PhysActor.IsPhysical)
2693 { 2660 {
2694 obPart.IgnoreUndoUpdate = true; 2661 if (oldSize.X * x > m_scene.m_maxPhys)
2695 Vector3 oldSize = new Vector3(obPart.Scale); 2662 {
2663 f = m_scene.m_maxPhys / oldSize.X;
2664 a = f / x;
2665 x *= a;
2666 y *= a;
2667 z *= a;
2668 }
2696 2669
2697 float f = 1.0f; 2670 if (oldSize.Y * y > m_scene.m_maxPhys)
2698 float a = 1.0f; 2671 {
2672 f = m_scene.m_maxPhys / oldSize.Y;
2673 a = f / y;
2674 x *= a;
2675 y *= a;
2676 z *= a;
2677 }
2699 2678
2700 if (part.PhysActor != null && part.PhysActor.IsPhysical) 2679 if (oldSize.Z * z > m_scene.m_maxPhys)
2701 { 2680 {
2702 if (oldSize.X * x > m_scene.m_maxPhys) 2681 f = m_scene.m_maxPhys / oldSize.Z;
2703 { 2682 a = f / z;
2704 f = m_scene.m_maxPhys / oldSize.X; 2683 x *= a;
2705 a = f / x; 2684 y *= a;
2706 x *= a; 2685 z *= a;
2707 y *= a; 2686 }
2708 z *= a; 2687 }
2709 } 2688 else
2710 if (oldSize.Y * y > m_scene.m_maxPhys) 2689 {
2711 { 2690 if (oldSize.X * x > m_scene.m_maxNonphys)
2712 f = m_scene.m_maxPhys / oldSize.Y; 2691 {
2713 a = f / y; 2692 f = m_scene.m_maxNonphys / oldSize.X;
2714 x *= a; 2693 a = f / x;
2715 y *= a; 2694 x *= a;
2716 z *= a; 2695 y *= a;
2717 } 2696 z *= a;
2718 if (oldSize.Z * z > m_scene.m_maxPhys)
2719 {
2720 f = m_scene.m_maxPhys / oldSize.Z;
2721 a = f / z;
2722 x *= a;
2723 y *= a;
2724 z *= a;
2725 }
2726 } 2697 }
2727 else 2698
2699 if (oldSize.Y * y > m_scene.m_maxNonphys)
2728 { 2700 {
2729 if (oldSize.X * x > m_scene.m_maxNonphys) 2701 f = m_scene.m_maxNonphys / oldSize.Y;
2730 { 2702 a = f / y;
2731 f = m_scene.m_maxNonphys / oldSize.X; 2703 x *= a;
2732 a = f / x; 2704 y *= a;
2733 x *= a; 2705 z *= a;
2734 y *= a; 2706 }
2735 z *= a; 2707
2736 } 2708 if (oldSize.Z * z > m_scene.m_maxNonphys)
2737 if (oldSize.Y * y > m_scene.m_maxNonphys) 2709 {
2738 { 2710 f = m_scene.m_maxNonphys / oldSize.Z;
2739 f = m_scene.m_maxNonphys / oldSize.Y; 2711 a = f / z;
2740 a = f / y; 2712 x *= a;
2741 x *= a; 2713 y *= a;
2742 y *= a; 2714 z *= a;
2743 z *= a;
2744 }
2745 if (oldSize.Z * z > m_scene.m_maxNonphys)
2746 {
2747 f = m_scene.m_maxNonphys / oldSize.Z;
2748 a = f / z;
2749 x *= a;
2750 y *= a;
2751 z *= a;
2752 }
2753 } 2715 }
2754 obPart.IgnoreUndoUpdate = false;
2755 obPart.StoreUndoState();
2756 } 2716 }
2717
2718// obPart.IgnoreUndoUpdate = false;
2757 } 2719 }
2758 } 2720 }
2721 }
2759 2722
2760 Vector3 prevScale = part.Scale; 2723 Vector3 prevScale = RootPart.Scale;
2761 prevScale.X *= x; 2724 prevScale.X *= x;
2762 prevScale.Y *= y; 2725 prevScale.Y *= y;
2763 prevScale.Z *= z; 2726 prevScale.Z *= z;
2764 part.Resize(prevScale);
2765 2727
2766 parts = m_parts.GetArray(); 2728// RootPart.IgnoreUndoUpdate = true;
2767 for (int i = 0; i < parts.Length; i++) 2729 RootPart.Resize(prevScale);
2730// RootPart.IgnoreUndoUpdate = false;
2731
2732 parts = m_parts.GetArray();
2733 for (int i = 0; i < parts.Length; i++)
2734 {
2735 SceneObjectPart obPart = parts[i];
2736
2737 if (obPart.UUID != m_rootPart.UUID)
2768 { 2738 {
2769 SceneObjectPart obPart = parts[i];
2770 obPart.IgnoreUndoUpdate = true; 2739 obPart.IgnoreUndoUpdate = true;
2771 if (obPart.UUID != m_rootPart.UUID)
2772 {
2773 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2774 currentpos.X *= x;
2775 currentpos.Y *= y;
2776 currentpos.Z *= z;
2777 Vector3 newSize = new Vector3(obPart.Scale);
2778 newSize.X *= x;
2779 newSize.Y *= y;
2780 newSize.Z *= z;
2781 obPart.Resize(newSize);
2782 obPart.UpdateOffSet(currentpos);
2783 }
2784 obPart.IgnoreUndoUpdate = false;
2785 obPart.StoreUndoState();
2786 }
2787 2740
2788 if (part.PhysActor != null) 2741 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2789 { 2742 currentpos.X *= x;
2790 part.PhysActor.Size = prevScale; 2743 currentpos.Y *= y;
2791 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2744 currentpos.Z *= z;
2745
2746 Vector3 newSize = new Vector3(obPart.Scale);
2747 newSize.X *= x;
2748 newSize.Y *= y;
2749 newSize.Z *= z;
2750
2751 obPart.Resize(newSize);
2752 obPart.UpdateOffSet(currentpos);
2753
2754 obPart.IgnoreUndoUpdate = false;
2792 } 2755 }
2793 2756
2794 part.IgnoreUndoUpdate = false; 2757// obPart.IgnoreUndoUpdate = false;
2795 part.StoreUndoState(); 2758// obPart.StoreUndoState();
2796 HasGroupChanged = true;
2797 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
2798 ScheduleGroupForTerseUpdate();
2799 } 2759 }
2760
2761// m_log.DebugFormat(
2762// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale);
2800 } 2763 }
2801 2764
2802 #endregion 2765 #endregion
@@ -2809,9 +2772,13 @@ namespace OpenSim.Region.Framework.Scenes
2809 /// <param name="pos"></param> 2772 /// <param name="pos"></param>
2810 public void UpdateGroupPosition(Vector3 pos) 2773 public void UpdateGroupPosition(Vector3 pos)
2811 { 2774 {
2812 SceneObjectPart[] parts = m_parts.GetArray(); 2775// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
2813 for (int i = 0; i < parts.Length; i++) 2776
2814 parts[i].StoreUndoState(); 2777 RootPart.StoreUndoState(true);
2778
2779// SceneObjectPart[] parts = m_parts.GetArray();
2780// for (int i = 0; i < parts.Length; i++)
2781// parts[i].StoreUndoState();
2815 2782
2816 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 2783 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2817 { 2784 {
@@ -2848,12 +2815,18 @@ namespace OpenSim.Region.Framework.Scenes
2848 { 2815 {
2849 SceneObjectPart part = GetChildPart(localID); 2816 SceneObjectPart part = GetChildPart(localID);
2850 2817
2851 SceneObjectPart[] parts = m_parts.GetArray(); 2818// SceneObjectPart[] parts = m_parts.GetArray();
2852 for (int i = 0; i < parts.Length; i++) 2819// for (int i = 0; i < parts.Length; i++)
2853 parts[i].StoreUndoState(); 2820// parts[i].StoreUndoState();
2854 2821
2855 if (part != null) 2822 if (part != null)
2856 { 2823 {
2824// m_log.DebugFormat(
2825// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos);
2826
2827 part.StoreUndoState(false);
2828 part.IgnoreUndoUpdate = true;
2829
2857 if (part.UUID == m_rootPart.UUID) 2830 if (part.UUID == m_rootPart.UUID)
2858 { 2831 {
2859 UpdateRootPosition(pos); 2832 UpdateRootPosition(pos);
@@ -2864,18 +2837,22 @@ namespace OpenSim.Region.Framework.Scenes
2864 } 2837 }
2865 2838
2866 HasGroupChanged = true; 2839 HasGroupChanged = true;
2840 part.IgnoreUndoUpdate = false;
2867 } 2841 }
2868 } 2842 }
2869 2843
2870 /// <summary> 2844 /// <summary>
2871 /// 2845 /// Update just the root prim position in a linkset
2872 /// </summary> 2846 /// </summary>
2873 /// <param name="pos"></param> 2847 /// <param name="pos"></param>
2874 private void UpdateRootPosition(Vector3 pos) 2848 public void UpdateRootPosition(Vector3 pos)
2875 { 2849 {
2876 SceneObjectPart[] parts = m_parts.GetArray(); 2850// m_log.DebugFormat(
2877 for (int i = 0; i < parts.Length; i++) 2851// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
2878 parts[i].StoreUndoState(); 2852
2853// SceneObjectPart[] parts = m_parts.GetArray();
2854// for (int i = 0; i < parts.Length; i++)
2855// parts[i].StoreUndoState();
2879 2856
2880 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 2857 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2881 Vector3 oldPos = 2858 Vector3 oldPos =
@@ -2888,7 +2865,7 @@ namespace OpenSim.Region.Framework.Scenes
2888 axDiff *= Quaternion.Inverse(partRotation); 2865 axDiff *= Quaternion.Inverse(partRotation);
2889 diff = axDiff; 2866 diff = axDiff;
2890 2867
2891 parts = m_parts.GetArray(); 2868 SceneObjectPart[] parts = m_parts.GetArray();
2892 for (int i = 0; i < parts.Length; i++) 2869 for (int i = 0; i < parts.Length; i++)
2893 { 2870 {
2894 SceneObjectPart obPart = parts[i]; 2871 SceneObjectPart obPart = parts[i];
@@ -2917,9 +2894,14 @@ namespace OpenSim.Region.Framework.Scenes
2917 /// <param name="rot"></param> 2894 /// <param name="rot"></param>
2918 public void UpdateGroupRotationR(Quaternion rot) 2895 public void UpdateGroupRotationR(Quaternion rot)
2919 { 2896 {
2920 SceneObjectPart[] parts = m_parts.GetArray(); 2897// m_log.DebugFormat(
2921 for (int i = 0; i < parts.Length; i++) 2898// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
2922 parts[i].StoreUndoState(); 2899
2900// SceneObjectPart[] parts = m_parts.GetArray();
2901// for (int i = 0; i < parts.Length; i++)
2902// parts[i].StoreUndoState();
2903
2904 m_rootPart.StoreUndoState(true);
2923 2905
2924 m_rootPart.UpdateRotation(rot); 2906 m_rootPart.UpdateRotation(rot);
2925 2907
@@ -2941,9 +2923,15 @@ namespace OpenSim.Region.Framework.Scenes
2941 /// <param name="rot"></param> 2923 /// <param name="rot"></param>
2942 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 2924 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
2943 { 2925 {
2944 SceneObjectPart[] parts = m_parts.GetArray(); 2926// m_log.DebugFormat(
2945 for (int i = 0; i < parts.Length; i++) 2927// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
2946 parts[i].StoreUndoState(); 2928
2929// SceneObjectPart[] parts = m_parts.GetArray();
2930// for (int i = 0; i < parts.Length; i++)
2931// parts[i].StoreUndoState();
2932
2933 RootPart.StoreUndoState(true);
2934 RootPart.IgnoreUndoUpdate = true;
2947 2935
2948 m_rootPart.UpdateRotation(rot); 2936 m_rootPart.UpdateRotation(rot);
2949 2937
@@ -2958,6 +2946,8 @@ namespace OpenSim.Region.Framework.Scenes
2958 2946
2959 HasGroupChanged = true; 2947 HasGroupChanged = true;
2960 ScheduleGroupForTerseUpdate(); 2948 ScheduleGroupForTerseUpdate();
2949
2950 RootPart.IgnoreUndoUpdate = false;
2961 } 2951 }
2962 2952
2963 /// <summary> 2953 /// <summary>
@@ -2975,6 +2965,9 @@ namespace OpenSim.Region.Framework.Scenes
2975 2965
2976 if (part != null) 2966 if (part != null)
2977 { 2967 {
2968// m_log.DebugFormat(
2969// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot);
2970
2978 if (part.UUID == m_rootPart.UUID) 2971 if (part.UUID == m_rootPart.UUID)
2979 { 2972 {
2980 UpdateRootRotation(rot); 2973 UpdateRootRotation(rot);
@@ -2996,6 +2989,13 @@ namespace OpenSim.Region.Framework.Scenes
2996 SceneObjectPart part = GetChildPart(localID); 2989 SceneObjectPart part = GetChildPart(localID);
2997 if (part != null) 2990 if (part != null)
2998 { 2991 {
2992// m_log.DebugFormat(
2993// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}",
2994// part.Name, part.LocalId, rot);
2995
2996 part.StoreUndoState();
2997 part.IgnoreUndoUpdate = true;
2998
2999 if (part.UUID == m_rootPart.UUID) 2999 if (part.UUID == m_rootPart.UUID)
3000 { 3000 {
3001 UpdateRootRotation(rot); 3001 UpdateRootRotation(rot);
@@ -3003,12 +3003,11 @@ namespace OpenSim.Region.Framework.Scenes
3003 } 3003 }
3004 else 3004 else
3005 { 3005 {
3006 part.IgnoreUndoUpdate = true;
3007 part.UpdateRotation(rot); 3006 part.UpdateRotation(rot);
3008 part.OffsetPosition = pos; 3007 part.OffsetPosition = pos;
3009 part.IgnoreUndoUpdate = false;
3010 part.StoreUndoState();
3011 } 3008 }
3009
3010 part.IgnoreUndoUpdate = false;
3012 } 3011 }
3013 } 3012 }
3014 3013
@@ -3016,8 +3015,12 @@ namespace OpenSim.Region.Framework.Scenes
3016 /// 3015 ///
3017 /// </summary> 3016 /// </summary>
3018 /// <param name="rot"></param> 3017 /// <param name="rot"></param>
3019 private void UpdateRootRotation(Quaternion rot) 3018 public void UpdateRootRotation(Quaternion rot)
3020 { 3019 {
3020// m_log.DebugFormat(
3021// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
3022// Name, LocalId, rot);
3023
3021 Quaternion axRot = rot; 3024 Quaternion axRot = rot;
3022 Quaternion oldParentRot = m_rootPart.RotationOffset; 3025 Quaternion oldParentRot = m_rootPart.RotationOffset;
3023 3026
@@ -3045,20 +3048,25 @@ namespace OpenSim.Region.Framework.Scenes
3045 newRot *= Quaternion.Inverse(axRot); 3048 newRot *= Quaternion.Inverse(axRot);
3046 prim.RotationOffset = newRot; 3049 prim.RotationOffset = newRot;
3047 prim.ScheduleTerseUpdate(); 3050 prim.ScheduleTerseUpdate();
3051 prim.IgnoreUndoUpdate = false;
3048 } 3052 }
3049 } 3053 }
3050 3054
3051 for (int i = 0; i < parts.Length; i++) 3055// for (int i = 0; i < parts.Length; i++)
3052 { 3056// {
3053 SceneObjectPart childpart = parts[i]; 3057// SceneObjectPart childpart = parts[i];
3054 if (childpart != m_rootPart) 3058// if (childpart != m_rootPart)
3055 { 3059// {
3056 childpart.IgnoreUndoUpdate = false; 3060//// childpart.IgnoreUndoUpdate = false;
3057 childpart.StoreUndoState(); 3061//// childpart.StoreUndoState();
3058 } 3062// }
3059 } 3063// }
3060 3064
3061 m_rootPart.ScheduleTerseUpdate(); 3065 m_rootPart.ScheduleTerseUpdate();
3066
3067// m_log.DebugFormat(
3068// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
3069// Name, LocalId, rot);
3062 } 3070 }
3063 3071
3064 #endregion 3072 #endregion
@@ -3313,23 +3321,6 @@ namespace OpenSim.Region.Framework.Scenes
3313 } 3321 }
3314 3322
3315 /// <summary> 3323 /// <summary>
3316 /// Handle an asset received asynchronously from the asset service.
3317 /// </summary>
3318 /// <param name="id"></param>
3319 /// <param name="sender"></param>
3320 /// <param name="asset"></param>
3321 protected void AssetReceived(string id, Object sender, AssetBase asset)
3322 {
3323 SceneObjectPart sop = (SceneObjectPart)sender;
3324
3325 if (sop != null)
3326 {
3327 if (asset != null)
3328 sop.SculptTextureCallback(asset.FullID, asset);
3329 }
3330 }
3331
3332 /// <summary>
3333 /// Set the user group to which this scene object belongs. 3324 /// Set the user group to which this scene object belongs.
3334 /// </summary> 3325 /// </summary>
3335 /// <param name="GroupID"></param> 3326 /// <param name="GroupID"></param>
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 2026c53..4629757 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -287,8 +287,8 @@ namespace OpenSim.Region.Framework.Scenes
287 private string m_sitAnimation = "SIT"; 287 private string m_sitAnimation = "SIT";
288 private string m_text = String.Empty; 288 private string m_text = String.Empty;
289 private string m_touchName = String.Empty; 289 private string m_touchName = String.Empty;
290 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 290 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5);
291 private readonly UndoStack<UndoState> m_redo = new UndoStack<UndoState>(5); 291 private readonly Stack<UndoState> m_redo = new Stack<UndoState>(5);
292 private UUID _creatorID; 292 private UUID _creatorID;
293 293
294 private bool m_passTouches; 294 private bool m_passTouches;
@@ -414,7 +414,6 @@ namespace OpenSim.Region.Framework.Scenes
414 CreateSelected = true; 414 CreateSelected = true;
415 415
416 TrimPermissions(); 416 TrimPermissions();
417 //m_undo = new UndoStack<UndoState>(ParentGroup.GetSceneMaxUndo());
418 417
419 m_inventory = new SceneObjectPartInventory(this); 418 m_inventory = new SceneObjectPartInventory(this);
420 } 419 }
@@ -789,7 +788,7 @@ namespace OpenSim.Region.Framework.Scenes
789 get { return m_offsetPosition; } 788 get { return m_offsetPosition; }
790 set 789 set
791 { 790 {
792 StoreUndoState(); 791// StoreUndoState();
793 m_offsetPosition = value; 792 m_offsetPosition = value;
794 793
795 if (ParentGroup != null && !ParentGroup.IsDeleted) 794 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -1015,15 +1014,19 @@ namespace OpenSim.Region.Framework.Scenes
1015 get { return m_shape; } 1014 get { return m_shape; }
1016 set { m_shape = value; } 1015 set { m_shape = value; }
1017 } 1016 }
1018 1017
1018 /// <summary>
1019 /// Change the scale of this part.
1020 /// </summary>
1019 public Vector3 Scale 1021 public Vector3 Scale
1020 { 1022 {
1021 get { return m_shape.Scale; } 1023 get { return m_shape.Scale; }
1022 set 1024 set
1023 { 1025 {
1024 StoreUndoState();
1025 if (m_shape != null) 1026 if (m_shape != null)
1026 { 1027 {
1028 StoreUndoState();
1029
1027 m_shape.Scale = value; 1030 m_shape.Scale = value;
1028 1031
1029 PhysicsActor actor = PhysActor; 1032 PhysicsActor actor = PhysActor;
@@ -1034,11 +1037,16 @@ namespace OpenSim.Region.Framework.Scenes
1034 if (m_parentGroup.Scene.PhysicsScene != null) 1037 if (m_parentGroup.Scene.PhysicsScene != null)
1035 { 1038 {
1036 actor.Size = m_shape.Scale; 1039 actor.Size = m_shape.Scale;
1037 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 1040
1041 if (((OpenMetaverse.SculptType)Shape.SculptType) == SculptType.Mesh)
1042 CheckSculptAndLoad();
1043 else
1044 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
1038 } 1045 }
1039 } 1046 }
1040 } 1047 }
1041 } 1048 }
1049
1042 TriggerScriptChangedEvent(Changed.SCALE); 1050 TriggerScriptChangedEvent(Changed.SCALE);
1043 } 1051 }
1044 } 1052 }
@@ -1588,17 +1596,23 @@ namespace OpenSim.Region.Framework.Scenes
1588 // or flexible 1596 // or flexible
1589 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible)) 1597 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible))
1590 { 1598 {
1591// m_log.DebugFormat("[SCENE OBJECT PART]: Creating PhysActor for {0} {1} {2}", Name, LocalId, UUID); 1599 try
1592 1600 {
1593 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( 1601 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
1594 LocalId, 1602 string.Format("{0}/{1}", Name, UUID),
1595 string.Format("{0}/{1}", Name, UUID), 1603 Shape,
1596 Shape, 1604 AbsolutePosition,
1597 AbsolutePosition, 1605 Scale,
1598 Scale, 1606 RotationOffset,
1599 RotationOffset, 1607 RigidBody,
1600 RigidBody); 1608 m_localId);
1601 1609 PhysActor.SetMaterial(Material);
1610 }
1611 catch
1612 {
1613 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid);
1614 PhysActor = null;
1615 }
1602 // Basic Physics returns null.. joy joy joy. 1616 // Basic Physics returns null.. joy joy joy.
1603 if (PhysActor != null) 1617 if (PhysActor != null)
1604 { 1618 {
@@ -1615,19 +1629,6 @@ namespace OpenSim.Region.Framework.Scenes
1615 } 1629 }
1616 } 1630 }
1617 1631
1618 public void ClearUndoState()
1619 {
1620 lock (m_undo)
1621 {
1622 m_undo.Clear();
1623 }
1624 lock (m_redo)
1625 {
1626 m_redo.Clear();
1627 }
1628 StoreUndoState();
1629 }
1630
1631 public byte ConvertScriptUintToByte(uint indata) 1632 public byte ConvertScriptUintToByte(uint indata)
1632 { 1633 {
1633 byte outdata = (byte)TextureAnimFlags.NONE; 1634 byte outdata = (byte)TextureAnimFlags.NONE;
@@ -1705,7 +1706,8 @@ namespace OpenSim.Region.Framework.Scenes
1705 { 1706 {
1706 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero) 1707 if (dupe.m_shape.SculptEntry && dupe.m_shape.SculptTexture != UUID.Zero)
1707 { 1708 {
1708 m_parentGroup.Scene.AssetService.Get(dupe.m_shape.SculptTexture.ToString(), dupe, AssetReceived); 1709 ParentGroup.Scene.AssetService.Get(
1710 dupe.m_shape.SculptTexture.ToString(), dupe, dupe.AssetReceived);
1709 } 1711 }
1710 1712
1711 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 1713 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
@@ -1719,14 +1721,20 @@ namespace OpenSim.Region.Framework.Scenes
1719 return dupe; 1721 return dupe;
1720 } 1722 }
1721 1723
1724 /// <summary>
1725 /// Called back by asynchronous asset fetch.
1726 /// </summary>
1727 /// <param name="id">ID of asset received</param>
1728 /// <param name="sender">Register</param>
1729 /// <param name="asset"></param>
1722 protected void AssetReceived(string id, Object sender, AssetBase asset) 1730 protected void AssetReceived(string id, Object sender, AssetBase asset)
1723 { 1731 {
1724 if (asset != null) 1732 if (asset != null)
1725 { 1733 SculptTextureCallback(asset);
1726 SceneObjectPart sop = (SceneObjectPart)sender; 1734 else
1727 if (sop != null) 1735 m_log.WarnFormat(
1728 sop.SculptTextureCallback(asset.FullID, asset); 1736 "[SCENE OBJECT PART]: Part {0} {1} requested mesh/sculpt data for asset id {2} from asset service but received no data",
1729 } 1737 Name, LocalId, id);
1730 } 1738 }
1731 1739
1732 public static SceneObjectPart Create() 1740 public static SceneObjectPart Create()
@@ -1896,7 +1904,12 @@ namespace OpenSim.Region.Framework.Scenes
1896 } 1904 }
1897 } 1905 }
1898 1906
1899 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); 1907 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
1908 // mesh data.
1909 if (((OpenMetaverse.SculptType)Shape.SculptType) == SculptType.Mesh)
1910 CheckSculptAndLoad();
1911 else
1912 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor);
1900 } 1913 }
1901 } 1914 }
1902 } 1915 }
@@ -2823,19 +2836,29 @@ namespace OpenSim.Region.Framework.Scenes
2823 } 2836 }
2824 2837
2825 /// <summary> 2838 /// <summary>
2826 /// Resize this part. 2839 /// Set the scale of this part.
2827 /// </summary> 2840 /// </summary>
2841 /// <remarks>
2842 /// Unlike the scale property, this checks the new size against scene limits and schedules a full property
2843 /// update to viewers.
2844 /// </remarks>
2828 /// <param name="scale"></param> 2845 /// <param name="scale"></param>
2829 public void Resize(Vector3 scale) 2846 public void Resize(Vector3 scale)
2830 { 2847 {
2831 StoreUndoState(); 2848 scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys);
2832 m_shape.Scale = scale; 2849 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys);
2850 scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys);
2833 2851
2834 // If we're a mesh/sculpt, then we need to tell the physics engine about our new size. To do this, we 2852 if (PhysActor != null && PhysActor.IsPhysical)
2835 // need to reinsert the sculpt data into the shape, since the physics engine deletes it when done to 2853 {
2836 // save memory 2854 scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys);
2837 if (PhysActor != null) 2855 scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys);
2838 CheckSculptAndLoad(); 2856 scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys);
2857 }
2858
2859// m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale);
2860
2861 Scale = scale;
2839 2862
2840 ParentGroup.HasGroupChanged = true; 2863 ParentGroup.HasGroupChanged = true;
2841 ScheduleFullUpdate(); 2864 ScheduleFullUpdate();
@@ -2965,7 +2988,11 @@ namespace OpenSim.Region.Framework.Scenes
2965 } 2988 }
2966 } 2989 }
2967 2990
2968 public void SculptTextureCallback(UUID textureID, AssetBase texture) 2991 /// <summary>
2992 /// Set sculpt and mesh data, and tell the physics engine to process the change.
2993 /// </summary>
2994 /// <param name="texture">The mesh itself.</param>
2995 public void SculptTextureCallback(AssetBase texture)
2969 { 2996 {
2970 if (m_shape.SculptEntry) 2997 if (m_shape.SculptEntry)
2971 { 2998 {
@@ -2991,16 +3018,6 @@ namespace OpenSim.Region.Framework.Scenes
2991 } 3018 }
2992 } 3019 }
2993 3020
2994// /// <summary>
2995// ///
2996// /// </summary>
2997// /// <param name="remoteClient"></param>
2998// public void SendFullUpdate(IClientAPI remoteClient, uint clientFlags)
2999// {
3000// m_parentGroup.SendPartFullUpdate(remoteClient, this, clientFlags);
3001// }
3002
3003
3004 /// <summary> 3021 /// <summary>
3005 /// Send a full update to the client for the given part 3022 /// Send a full update to the client for the given part
3006 /// </summary> 3023 /// </summary>
@@ -3648,6 +3665,11 @@ namespace OpenSim.Region.Framework.Scenes
3648 3665
3649 public void StoreUndoState() 3666 public void StoreUndoState()
3650 { 3667 {
3668 StoreUndoState(false);
3669 }
3670
3671 public void StoreUndoState(bool forGroup)
3672 {
3651 if (!Undoing) 3673 if (!Undoing)
3652 { 3674 {
3653 if (!IgnoreUndoUpdate) 3675 if (!IgnoreUndoUpdate)
@@ -3661,24 +3683,138 @@ namespace OpenSim.Region.Framework.Scenes
3661 UndoState last = m_undo.Peek(); 3683 UndoState last = m_undo.Peek();
3662 if (last != null) 3684 if (last != null)
3663 { 3685 {
3686 // TODO: May need to fix for group comparison
3664 if (last.Compare(this)) 3687 if (last.Compare(this))
3688 {
3689// m_log.DebugFormat(
3690// "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3691// Name, LocalId, m_undo.Count);
3692
3665 return; 3693 return;
3694 }
3666 } 3695 }
3667 } 3696 }
3668 3697
3698// m_log.DebugFormat(
3699// "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3700// Name, LocalId, forGroup, m_undo.Count);
3701
3669 if (m_parentGroup.GetSceneMaxUndo() > 0) 3702 if (m_parentGroup.GetSceneMaxUndo() > 0)
3670 { 3703 {
3671 UndoState nUndo = new UndoState(this); 3704 UndoState nUndo = new UndoState(this, forGroup);
3672 3705
3673 m_undo.Push(nUndo); 3706 m_undo.Push(nUndo);
3707
3708 if (m_redo.Count > 0)
3709 m_redo.Clear();
3710
3711// m_log.DebugFormat(
3712// "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3713// Name, LocalId, forGroup, m_undo.Count);
3674 } 3714 }
3715 }
3716 }
3717 }
3718// else
3719// {
3720// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3721// }
3722 }
3723// else
3724// {
3725// m_log.DebugFormat(
3726// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3727// }
3728 }
3729
3730 /// <summary>
3731 /// Return number of undos on the stack. Here temporarily pending a refactor.
3732 /// </summary>
3733 public int UndoCount
3734 {
3735 get
3736 {
3737 lock (m_undo)
3738 return m_undo.Count;
3739 }
3740 }
3675 3741
3742 public void Undo()
3743 {
3744 lock (m_undo)
3745 {
3746// m_log.DebugFormat(
3747// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3748// Name, LocalId, m_undo.Count);
3749
3750 if (m_undo.Count > 0)
3751 {
3752 UndoState goback = m_undo.Pop();
3753
3754 if (goback != null)
3755 {
3756 UndoState nUndo = null;
3757
3758 if (m_parentGroup.GetSceneMaxUndo() > 0)
3759 {
3760 nUndo = new UndoState(this, goback.ForGroup);
3761 }
3762
3763 goback.PlaybackState(this);
3764
3765 if (nUndo != null)
3766 m_redo.Push(nUndo);
3767 }
3768 }
3769
3770// m_log.DebugFormat(
3771// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}",
3772// Name, LocalId, m_undo.Count);
3773 }
3774 }
3775
3776 public void Redo()
3777 {
3778 lock (m_undo)
3779 {
3780// m_log.DebugFormat(
3781// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3782// Name, LocalId, m_redo.Count);
3783
3784 if (m_redo.Count > 0)
3785 {
3786 UndoState gofwd = m_redo.Pop();
3787
3788 if (gofwd != null)
3789 {
3790 if (m_parentGroup.GetSceneMaxUndo() > 0)
3791 {
3792 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3793
3794 m_undo.Push(nUndo);
3676 } 3795 }
3796
3797 gofwd.PlayfwdState(this);
3677 } 3798 }
3799
3800// m_log.DebugFormat(
3801// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}",
3802// Name, LocalId, m_redo.Count);
3678 } 3803 }
3679 } 3804 }
3680 } 3805 }
3681 3806
3807 public void ClearUndoState()
3808 {
3809// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId);
3810
3811 lock (m_undo)
3812 {
3813 m_undo.Clear();
3814 m_redo.Clear();
3815 }
3816 }
3817
3682 public EntityIntersection TestIntersection(Ray iray, Quaternion parentrot) 3818 public EntityIntersection TestIntersection(Ray iray, Quaternion parentrot)
3683 { 3819 {
3684 // In this case we're using a sphere with a radius of the largest dimension of the prim 3820 // In this case we're using a sphere with a radius of the largest dimension of the prim
@@ -4139,44 +4275,6 @@ namespace OpenSim.Region.Framework.Scenes
4139 _nextOwnerMask &= (uint)PermissionMask.All; 4275 _nextOwnerMask &= (uint)PermissionMask.All;
4140 } 4276 }
4141 4277
4142 public void Undo()
4143 {
4144 lock (m_undo)
4145 {
4146 if (m_undo.Count > 0)
4147 {
4148 UndoState nUndo = null;
4149 if (m_parentGroup.GetSceneMaxUndo() > 0)
4150 {
4151 nUndo = new UndoState(this);
4152 }
4153 UndoState goback = m_undo.Pop();
4154 if (goback != null)
4155 {
4156 goback.PlaybackState(this);
4157 if (nUndo != null)
4158 m_redo.Push(nUndo);
4159 }
4160 }
4161 }
4162 }
4163
4164 public void Redo()
4165 {
4166 lock (m_redo)
4167 {
4168 if (m_parentGroup.GetSceneMaxUndo() > 0)
4169 {
4170 UndoState nUndo = new UndoState(this);
4171
4172 m_undo.Push(nUndo);
4173 }
4174 UndoState gofwd = m_redo.Pop();
4175 if (gofwd != null)
4176 gofwd.PlayfwdState(this);
4177 }
4178 }
4179
4180 public void UpdateExtraParam(ushort type, bool inUse, byte[] data) 4278 public void UpdateExtraParam(ushort type, bool inUse, byte[] data)
4181 { 4279 {
4182 m_shape.ReadInUpdateExtraParam(type, inUse, data); 4280 m_shape.ReadInUpdateExtraParam(type, inUse, data);
@@ -4435,13 +4533,14 @@ namespace OpenSim.Region.Framework.Scenes
4435 { 4533 {
4436 // It's not phantom anymore. So make sure the physics engine get's knowledge of it 4534 // It's not phantom anymore. So make sure the physics engine get's knowledge of it
4437 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( 4535 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
4438 LocalId,
4439 string.Format("{0}/{1}", Name, UUID), 4536 string.Format("{0}/{1}", Name, UUID),
4440 Shape, 4537 Shape,
4441 AbsolutePosition, 4538 AbsolutePosition,
4442 Scale, 4539 Scale,
4443 RotationOffset, 4540 RotationOffset,
4444 UsePhysics); 4541 UsePhysics,
4542 m_localId);
4543 PhysActor.SetMaterial(Material);
4445 4544
4446 pa = PhysActor; 4545 pa = PhysActor;
4447 if (pa != null) 4546 if (pa != null)
@@ -4600,7 +4699,7 @@ namespace OpenSim.Region.Framework.Scenes
4600 /// </remarks> 4699 /// </remarks>
4601 public void CheckSculptAndLoad() 4700 public void CheckSculptAndLoad()
4602 { 4701 {
4603// m_log.Debug("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId); 4702// m_log.DebugFormat("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
4604 4703
4605 if (ParentGroup.IsDeleted) 4704 if (ParentGroup.IsDeleted)
4606 return; 4705 return;
@@ -4611,9 +4710,11 @@ namespace OpenSim.Region.Framework.Scenes
4611 if (Shape.SculptEntry && Shape.SculptTexture != UUID.Zero) 4710 if (Shape.SculptEntry && Shape.SculptTexture != UUID.Zero)
4612 { 4711 {
4613 // check if a previously decoded sculpt map has been cached 4712 // check if a previously decoded sculpt map has been cached
4713 // We don't read the file here - the meshmerizer will do that later.
4714 // TODO: Could we simplify the meshmerizer code by reading and setting the data here?
4614 if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + Shape.SculptTexture.ToString()))) 4715 if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + Shape.SculptTexture.ToString())))
4615 { 4716 {
4616 SculptTextureCallback(Shape.SculptTexture, null); 4717 SculptTextureCallback(null);
4617 } 4718 }
4618 else 4719 else
4619 { 4720 {
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index c18c93a..8fb9fad 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -102,7 +102,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
102 sceneObject.AddPart(part); 102 sceneObject.AddPart(part);
103 part.LinkNum = linkNum; 103 part.LinkNum = linkNum;
104 part.TrimPermissions(); 104 part.TrimPermissions();
105 part.StoreUndoState();
106 reader.Close(); 105 reader.Close();
107 sr.Close(); 106 sr.Close();
108 } 107 }
@@ -236,15 +235,14 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
236 if (originalLinkNum != 0) 235 if (originalLinkNum != 0)
237 part.LinkNum = originalLinkNum; 236 part.LinkNum = originalLinkNum;
238 237
239 part.StoreUndoState();
240 reader.Close(); 238 reader.Close();
241 sr.Close(); 239 sr.Close();
242 } 240 }
243 241
244 // Script state may, or may not, exist. Not having any, is NOT 242 // Script state may, or may not, exist. Not having any, is NOT
245 // ever a problem. 243 // ever a problem.
246
247 sceneObject.LoadScriptState(doc); 244 sceneObject.LoadScriptState(doc);
245
248 return sceneObject; 246 return sceneObject;
249 } 247 }
250 catch (Exception e) 248 catch (Exception e)
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
new file mode 100644
index 0000000..c4047ee
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectResizeTests.cs
@@ -0,0 +1,104 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
26 */
27
28using System;
29using System.Reflection;
30using NUnit.Framework;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Framework.Communications;
34using OpenSim.Region.Framework.Scenes;
35using OpenSim.Tests.Common;
36using OpenSim.Tests.Common.Mock;
37
38namespace OpenSim.Region.Framework.Scenes.Tests
39{
40 /// <summary>
41 /// Basic scene object resize tests
42 /// </summary>
43 [TestFixture]
44 public class SceneObjectResizeTests
45 {
46 /// <summary>
47 /// Test resizing an object
48 /// </summary>
49 [Test]
50 public void TestResizeSceneObject()
51 {
52 TestHelper.InMethod();
53// log4net.Config.XmlConfigurator.Configure();
54
55 Scene scene = SceneSetupHelpers.SetupScene();
56 SceneObjectGroup g1 = SceneSetupHelpers.AddSceneObject(scene).ParentGroup;
57
58 g1.GroupResize(new Vector3(2, 3, 4));
59
60 SceneObjectGroup g1Post = scene.GetSceneObjectGroup(g1.UUID);
61
62 Assert.That(g1Post.RootPart.Scale.X, Is.EqualTo(2));
63 Assert.That(g1Post.RootPart.Scale.Y, Is.EqualTo(3));
64 Assert.That(g1Post.RootPart.Scale.Z, Is.EqualTo(4));
65
66 Assert.That(g1Post.RootPart.UndoCount, Is.EqualTo(1));
67 }
68
69 /// <summary>
70 /// Test resizing an individual part in a scene object.
71 /// </summary>
72 [Test]
73 public void TestResizeSceneObjectPart()
74 {
75 TestHelper.InMethod();
76 //log4net.Config.XmlConfigurator.Configure();
77
78 Scene scene = SceneSetupHelpers.SetupScene();
79
80 SceneObjectGroup g1 = SceneSetupHelpers.CreateSceneObject(2, UUID.Zero);
81 g1.RootPart.Scale = new Vector3(2, 3, 4);
82 g1.Parts[1].Scale = new Vector3(5, 6, 7);
83
84 scene.AddSceneObject(g1);
85
86 SceneObjectGroup g1Post = scene.GetSceneObjectGroup(g1.UUID);
87
88 g1Post.Parts[1].Resize(new Vector3(8, 9, 10));
89
90 SceneObjectGroup g1PostPost = scene.GetSceneObjectGroup(g1.UUID);
91
92 SceneObjectPart g1RootPart = g1PostPost.RootPart;
93 SceneObjectPart g1ChildPart = g1PostPost.Parts[1];
94
95 Assert.That(g1RootPart.Scale.X, Is.EqualTo(2));
96 Assert.That(g1RootPart.Scale.Y, Is.EqualTo(3));
97 Assert.That(g1RootPart.Scale.Z, Is.EqualTo(4));
98
99 Assert.That(g1ChildPart.Scale.X, Is.EqualTo(8));
100 Assert.That(g1ChildPart.Scale.Y, Is.EqualTo(9));
101 Assert.That(g1ChildPart.Scale.Z, Is.EqualTo(10));
102 }
103 }
104} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 55e407e..393f42d 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -25,6 +25,9 @@
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System;
29using System.Reflection;
30using log4net;
28using OpenMetaverse; 31using OpenMetaverse;
29using OpenSim.Region.Framework.Interfaces; 32using OpenSim.Region.Framework.Interfaces;
30 33
@@ -32,110 +35,199 @@ namespace OpenSim.Region.Framework.Scenes
32{ 35{
33 public class UndoState 36 public class UndoState
34 { 37 {
38 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39
35 public Vector3 Position = Vector3.Zero; 40 public Vector3 Position = Vector3.Zero;
36 public Vector3 Scale = Vector3.Zero; 41 public Vector3 Scale = Vector3.Zero;
37 public Quaternion Rotation = Quaternion.Identity; 42 public Quaternion Rotation = Quaternion.Identity;
38 43
39 public UndoState(SceneObjectPart part) 44 /// <summary>
45 /// Is this undo state for an entire group?
46 /// </summary>
47 public bool ForGroup;
48
49 /// <summary>
50 /// Constructor.
51 /// </summary>
52 /// <param name="part"></param>
53 /// <param name="forGroup">True if the undo is for an entire group</param>
54 public UndoState(SceneObjectPart part, bool forGroup)
40 { 55 {
41 if (part != null) 56 if (part.ParentID == 0)
42 { 57 {
43 if (part.ParentID == 0) 58 ForGroup = forGroup;
44 { 59
60// if (ForGroup)
45 Position = part.ParentGroup.AbsolutePosition; 61 Position = part.ParentGroup.AbsolutePosition;
46 Rotation = part.RotationOffset; 62// else
47 Scale = part.Shape.Scale; 63// Position = part.OffsetPosition;
48 } 64
49 else 65// m_log.DebugFormat(
50 { 66// "[UNDO STATE]: Storing undo position {0} for root part", Position);
51 Position = part.OffsetPosition; 67
52 Rotation = part.RotationOffset; 68 Rotation = part.RotationOffset;
53 Scale = part.Shape.Scale; 69
54 } 70// m_log.DebugFormat(
71// "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation);
72
73 Scale = part.Shape.Scale;
74
75// m_log.DebugFormat(
76// "[UNDO STATE]: Storing undo scale {0} for root part", Scale);
77 }
78 else
79 {
80 Position = part.OffsetPosition;
81// m_log.DebugFormat(
82// "[UNDO STATE]: Storing undo position {0} for child part", Position);
83
84 Rotation = part.RotationOffset;
85// m_log.DebugFormat(
86// "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation);
87
88 Scale = part.Shape.Scale;
89// m_log.DebugFormat(
90// "[UNDO STATE]: Storing undo scale {0} for child part", Scale);
55 } 91 }
56 } 92 }
57 93
94 /// <summary>
95 /// Compare the relevant state in the given part to this state.
96 /// </summary>
97 /// <param name="part"></param>
98 /// <returns>true if both the part's position, rotation and scale match those in this undo state. False otherwise.</returns>
58 public bool Compare(SceneObjectPart part) 99 public bool Compare(SceneObjectPart part)
59 { 100 {
60 if (part != null) 101 if (part != null)
61 { 102 {
62 if (part.ParentID == 0) 103 if (part.ParentID == 0)
63 { 104 return
64 if (Position == part.ParentGroup.AbsolutePosition && Rotation == part.ParentGroup.Rotation) 105 Position == part.ParentGroup.AbsolutePosition
65 return true; 106 && Rotation == part.RotationOffset
66 else 107 && Scale == part.Shape.Scale;
67 return false;
68 }
69 else 108 else
70 { 109 return
71 if (Position == part.OffsetPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale) 110 Position == part.OffsetPosition
72 return true; 111 && Rotation == part.RotationOffset
73 else 112 && Scale == part.Shape.Scale;
74 return false;
75
76 }
77 } 113 }
114
78 return false; 115 return false;
79 } 116 }
80 117
81 public void PlaybackState(SceneObjectPart part) 118 public void PlaybackState(SceneObjectPart part)
82 { 119 {
83 if (part != null) 120 part.Undoing = true;
121
122 if (part.ParentID == 0)
84 { 123 {
85 part.Undoing = true; 124// m_log.DebugFormat(
125// "[UNDO STATE]: Undoing position to {0} for root part {1} {2}",
126// Position, part.Name, part.LocalId);
86 127
87 if (part.ParentID == 0) 128 if (Position != Vector3.Zero)
88 { 129 {
89 if (Position != Vector3.Zero) 130 if (ForGroup)
90 part.ParentGroup.AbsolutePosition = Position; 131 part.ParentGroup.AbsolutePosition = Position;
91 part.RotationOffset = Rotation; 132 else
92 if (Scale != Vector3.Zero) 133 part.ParentGroup.UpdateRootPosition(Position);
93 part.Resize(Scale);
94 part.ParentGroup.ScheduleGroupForTerseUpdate();
95 } 134 }
135
136// m_log.DebugFormat(
137// "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}",
138// part.RotationOffset, Rotation, part.Name, part.LocalId);
139
140 if (ForGroup)
141 part.UpdateRotation(Rotation);
96 else 142 else
143 part.ParentGroup.UpdateRootRotation(Rotation);
144
145 if (Scale != Vector3.Zero)
97 { 146 {
98 if (Position != Vector3.Zero) 147// m_log.DebugFormat(
99 part.OffsetPosition = Position; 148// "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}",
100 part.UpdateRotation(Rotation); 149// part.Shape.Scale, Scale, part.Name, part.LocalId);
101 if (Scale != Vector3.Zero) 150
102 part.Resize(Scale); part.ScheduleTerseUpdate(); 151 if (ForGroup)
152 part.ParentGroup.GroupResize(Scale);
153 else
154 part.Resize(Scale);
103 } 155 }
104 part.Undoing = false;
105 156
157 part.ParentGroup.ScheduleGroupForTerseUpdate();
106 } 158 }
159 else
160 {
161 if (Position != Vector3.Zero)
162 {
163// m_log.DebugFormat(
164// "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}",
165// part.OffsetPosition, Position, part.Name, part.LocalId);
166
167 part.OffsetPosition = Position;
168 }
169
170// m_log.DebugFormat(
171// "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}",
172// part.RotationOffset, Rotation, part.Name, part.LocalId);
173
174 part.UpdateRotation(Rotation);
175
176 if (Scale != Vector3.Zero)
177 {
178// m_log.DebugFormat(
179// "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}",
180// part.Shape.Scale, Scale, part.Name, part.LocalId);
181
182 part.Resize(Scale);
183 }
184
185 part.ScheduleTerseUpdate();
186 }
187
188 part.Undoing = false;
107 } 189 }
190
108 public void PlayfwdState(SceneObjectPart part) 191 public void PlayfwdState(SceneObjectPart part)
109 { 192 {
110 if (part != null) 193 part.Undoing = true;
194
195 if (part.ParentID == 0)
111 { 196 {
112 part.Undoing = true; 197 if (Position != Vector3.Zero)
198 part.ParentGroup.AbsolutePosition = Position;
113 199
114 if (part.ParentID == 0) 200 if (Rotation != Quaternion.Identity)
115 { 201 part.UpdateRotation(Rotation);
116 if (Position != Vector3.Zero) 202
117 part.ParentGroup.AbsolutePosition = Position; 203 if (Scale != Vector3.Zero)
118 if (Rotation != Quaternion.Identity)
119 part.UpdateRotation(Rotation);
120 if (Scale != Vector3.Zero)
121 part.Resize(Scale);
122 part.ParentGroup.ScheduleGroupForTerseUpdate();
123 }
124 else
125 { 204 {
126 if (Position != Vector3.Zero) 205 if (ForGroup)
127 part.OffsetPosition = Position; 206 part.ParentGroup.GroupResize(Scale);
128 if (Rotation != Quaternion.Identity) 207 else
129 part.UpdateRotation(Rotation);
130 if (Scale != Vector3.Zero)
131 part.Resize(Scale); 208 part.Resize(Scale);
132 part.ScheduleTerseUpdate();
133 } 209 }
134 part.Undoing = false;
135 210
211 part.ParentGroup.ScheduleGroupForTerseUpdate();
136 } 212 }
213 else
214 {
215 if (Position != Vector3.Zero)
216 part.OffsetPosition = Position;
217
218 if (Rotation != Quaternion.Identity)
219 part.UpdateRotation(Rotation);
220
221 if (Scale != Vector3.Zero)
222 part.Resize(Scale);
223
224 part.ScheduleTerseUpdate();
225 }
226
227 part.Undoing = false;
137 } 228 }
138 } 229 }
230
139 public class LandUndoState 231 public class LandUndoState
140 { 232 {
141 public ITerrainModule m_terrainModule; 233 public ITerrainModule m_terrainModule;
@@ -149,10 +241,7 @@ namespace OpenSim.Region.Framework.Scenes
149 241
150 public bool Compare(ITerrainChannel terrainChannel) 242 public bool Compare(ITerrainChannel terrainChannel)
151 { 243 {
152 if (m_terrainChannel != terrainChannel) 244 return m_terrainChannel == terrainChannel;
153 return false;
154 else
155 return false;
156 } 245 }
157 246
158 public void PlaybackState() 247 public void PlaybackState()
@@ -160,4 +249,4 @@ namespace OpenSim.Region.Framework.Scenes
160 m_terrainModule.UndoTerrain(m_terrainChannel); 249 m_terrainModule.UndoTerrain(m_terrainChannel);
161 } 250 }
162 } 251 }
163} 252} \ No newline at end of file