diff options
author | UbitUmarov | 2012-02-15 03:51:30 +0000 |
---|---|---|
committer | UbitUmarov | 2012-02-15 03:51:30 +0000 |
commit | 04279e36d1bc01f966940eb8cc0457064356fced (patch) | |
tree | bff74b33a2cf072877e8f1d876944905399d4be6 /OpenSim/Region/Framework/Scenes | |
parent | remove drawstuff from ubitode (diff) | |
parent | Merge branch 'master' of ssh://melanie@3dhosting.de/var/git/careminster into ... (diff) | |
download | opensim-SC-04279e36d1bc01f966940eb8cc0457064356fced.zip opensim-SC-04279e36d1bc01f966940eb8cc0457064356fced.tar.gz opensim-SC-04279e36d1bc01f966940eb8cc0457064356fced.tar.bz2 opensim-SC-04279e36d1bc01f966940eb8cc0457064356fced.tar.xz |
Merge branch 'master' of ssh://3dhosting.de/var/git/careminster into ubitwork
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
5 files changed, 194 insertions, 68 deletions
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs index 5dfd3e0..f678d07 100644 --- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs +++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs | |||
@@ -148,7 +148,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
148 | x = m_inventoryDeletes.Dequeue(); | 148 | x = m_inventoryDeletes.Dequeue(); |
149 | 149 | ||
150 | m_log.DebugFormat( | 150 | m_log.DebugFormat( |
151 | "[ASYNC DELETER]: Sending object to user's inventory, action {1}, count {2}, {0} item(s) remaining.", left, x.action, x.objectGroups.Count); | 151 | "[ASYNC DELETER]: Sending object to user's inventory, action {1}, count {2}, {0} item(s) remaining.", |
152 | left, x.action, x.objectGroups.Count); | ||
152 | 153 | ||
153 | try | 154 | try |
154 | { | 155 | { |
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 456e86b..8552d4c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs | |||
@@ -3408,9 +3408,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3408 | 3408 | ||
3409 | // Don't disable this log message - it's too helpful | 3409 | // Don't disable this log message - it's too helpful |
3410 | m_log.DebugFormat( | 3410 | m_log.DebugFormat( |
3411 | "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, teleportflags {6}, position {7})", | 3411 | "[SCENE]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, IP {6}, viewer {7}, teleportflags {8}, position {9})", |
3412 | RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, | 3412 | RegionInfo.RegionName, (agent.child ? "child" : "root"),agent.firstname, agent.lastname, |
3413 | agent.AgentID, agent.circuitcode, teleportFlags, agent.startpos); | 3413 | agent.AgentID, agent.circuitcode, agent.IPAddress, agent.Viewer, teleportFlags, agent.startpos); |
3414 | 3414 | ||
3415 | if (LoginsDisabled) | 3415 | if (LoginsDisabled) |
3416 | { | 3416 | { |
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 9961438..644b78a 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | |||
@@ -465,7 +465,77 @@ namespace OpenSim.Region.Framework.Scenes | |||
465 | || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) | 465 | || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) |
466 | && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) | 466 | && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) |
467 | { | 467 | { |
468 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); | 468 | IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>(); |
469 | uint x = 0; | ||
470 | uint y = 0; | ||
471 | string version = String.Empty; | ||
472 | Vector3 newpos = Vector3.Zero; | ||
473 | OpenSim.Services.Interfaces.GridRegion destination = null; | ||
474 | |||
475 | bool canCross = true; | ||
476 | foreach (ScenePresence av in m_linkedAvatars) | ||
477 | { | ||
478 | // We need to cross these agents. First, let's find | ||
479 | // out if any of them can't cross for some reason. | ||
480 | // We have to deny the crossing entirely if any | ||
481 | // of them are banned. Alternatively, we could | ||
482 | // unsit banned agents.... | ||
483 | |||
484 | |||
485 | // We set the avatar position as being the object | ||
486 | // position to get the region to send to | ||
487 | if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null) | ||
488 | { | ||
489 | canCross = false; | ||
490 | break; | ||
491 | } | ||
492 | |||
493 | m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); | ||
494 | } | ||
495 | |||
496 | if (canCross) | ||
497 | { | ||
498 | // We unparent the SP quietly so that it won't | ||
499 | // be made to stand up | ||
500 | foreach (ScenePresence av in m_linkedAvatars) | ||
501 | { | ||
502 | SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID); | ||
503 | if (parentPart != null) | ||
504 | av.ParentUUID = parentPart.UUID; | ||
505 | |||
506 | av.ParentID = 0; | ||
507 | } | ||
508 | |||
509 | m_scene.CrossPrimGroupIntoNewRegion(val, this, true); | ||
510 | |||
511 | // Normalize | ||
512 | if (val.X >= Constants.RegionSize) | ||
513 | val.X -= Constants.RegionSize; | ||
514 | if (val.Y >= Constants.RegionSize) | ||
515 | val.Y -= Constants.RegionSize; | ||
516 | if (val.X < 0) | ||
517 | val.X += Constants.RegionSize; | ||
518 | if (val.Y < 0) | ||
519 | val.Y += Constants.RegionSize; | ||
520 | |||
521 | // If it's deleted, crossing was successful | ||
522 | if (IsDeleted) | ||
523 | { | ||
524 | foreach (ScenePresence av in m_linkedAvatars) | ||
525 | { | ||
526 | m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val); | ||
527 | |||
528 | av.IsInTransit = true; | ||
529 | |||
530 | CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync; | ||
531 | d.BeginInvoke(av, val, x, y, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d); | ||
532 | } | ||
533 | |||
534 | return; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | val = AbsolutePosition; | ||
469 | } | 539 | } |
470 | } | 540 | } |
471 | 541 | ||
@@ -524,6 +594,23 @@ namespace OpenSim.Region.Framework.Scenes | |||
524 | } | 594 | } |
525 | } | 595 | } |
526 | 596 | ||
597 | private void CrossAgentToNewRegionCompleted(IAsyncResult iar) | ||
598 | { | ||
599 | CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState; | ||
600 | ScenePresence agent = icon.EndInvoke(iar); | ||
601 | |||
602 | //// If the cross was successful, this agent is a child agent | ||
603 | //if (agent.IsChildAgent) | ||
604 | // agent.Reset(); | ||
605 | //else // Not successful | ||
606 | // agent.RestoreInCurrentScene(); | ||
607 | |||
608 | // In any case | ||
609 | agent.IsInTransit = false; | ||
610 | |||
611 | m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); | ||
612 | } | ||
613 | |||
527 | public override uint LocalId | 614 | public override uint LocalId |
528 | { | 615 | { |
529 | get { return m_rootPart.LocalId; } | 616 | get { return m_rootPart.LocalId; } |
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 9100c29..8a42616 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs | |||
@@ -233,6 +233,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
233 | private bool m_collisionEventFlag = false; | 233 | private bool m_collisionEventFlag = false; |
234 | private object m_collisionEventLock = new Object(); | 234 | private object m_collisionEventLock = new Object(); |
235 | 235 | ||
236 | private Vector3 m_prevSitOffset; | ||
237 | |||
236 | protected AvatarAppearance m_appearance; | 238 | protected AvatarAppearance m_appearance; |
237 | 239 | ||
238 | public AvatarAppearance Appearance | 240 | public AvatarAppearance Appearance |
@@ -295,13 +297,10 @@ namespace OpenSim.Region.Framework.Scenes | |||
295 | /// </summary> | 297 | /// </summary> |
296 | public PhysicsActor PhysicsActor { get; private set; } | 298 | public PhysicsActor PhysicsActor { get; private set; } |
297 | 299 | ||
298 | private byte m_movementflag; | 300 | /// <summary> |
299 | 301 | /// Record user movement inputs. | |
300 | public byte MovementFlag | 302 | /// </summary> |
301 | { | 303 | public byte MovementFlag { get; private set; } |
302 | set { m_movementflag = value; } | ||
303 | get { return m_movementflag; } | ||
304 | } | ||
305 | 304 | ||
306 | private bool m_updateflag; | 305 | private bool m_updateflag; |
307 | 306 | ||
@@ -647,6 +646,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
647 | } | 646 | } |
648 | private uint m_parentID; | 647 | private uint m_parentID; |
649 | 648 | ||
649 | public UUID ParentUUID | ||
650 | { | ||
651 | get { return m_parentUUID; } | ||
652 | set { m_parentUUID = value; } | ||
653 | } | ||
654 | private UUID m_parentUUID = UUID.Zero; | ||
655 | |||
650 | public float Health | 656 | public float Health |
651 | { | 657 | { |
652 | get { return m_health; } | 658 | get { return m_health; } |
@@ -868,7 +874,26 @@ namespace OpenSim.Region.Framework.Scenes | |||
868 | "[SCENE]: Upgrading child to root agent for {0} in {1}", | 874 | "[SCENE]: Upgrading child to root agent for {0} in {1}", |
869 | Name, m_scene.RegionInfo.RegionName); | 875 | Name, m_scene.RegionInfo.RegionName); |
870 | 876 | ||
871 | //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); | 877 | if (ParentUUID != UUID.Zero) |
878 | { | ||
879 | m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); | ||
880 | SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); | ||
881 | if (part == null) | ||
882 | { | ||
883 | m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); | ||
884 | } | ||
885 | else | ||
886 | { | ||
887 | part.ParentGroup.AddAvatar(UUID); | ||
888 | if (part.SitTargetPosition != Vector3.Zero) | ||
889 | part.SitTargetAvatar = UUID; | ||
890 | ParentPosition = part.GetWorldPosition(); | ||
891 | ParentID = part.LocalId; | ||
892 | m_pos = m_prevSitOffset; | ||
893 | pos = ParentPosition; | ||
894 | } | ||
895 | ParentUUID = UUID.Zero; | ||
896 | } | ||
872 | 897 | ||
873 | bool wasChild = IsChildAgent; | 898 | bool wasChild = IsChildAgent; |
874 | IsChildAgent = false; | 899 | IsChildAgent = false; |
@@ -881,62 +906,64 @@ namespace OpenSim.Region.Framework.Scenes | |||
881 | 906 | ||
882 | m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); | 907 | m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); |
883 | 908 | ||
884 | // Moved this from SendInitialData to ensure that Appearance is initialized | 909 | if (ParentID == 0) |
885 | // before the inventory is processed in MakeRootAgent. This fixes a race condition | ||
886 | // related to the handling of attachments | ||
887 | //m_scene.GetAvatarAppearance(ControllingClient, out Appearance); | ||
888 | if (m_scene.TestBorderCross(pos, Cardinals.E)) | ||
889 | { | 910 | { |
890 | Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); | 911 | // Moved this from SendInitialData to ensure that Appearance is initialized |
891 | pos.X = crossedBorder.BorderLine.Z - 1; | 912 | // before the inventory is processed in MakeRootAgent. This fixes a race condition |
892 | } | 913 | // related to the handling of attachments |
914 | //m_scene.GetAvatarAppearance(ControllingClient, out Appearance); | ||
915 | if (m_scene.TestBorderCross(pos, Cardinals.E)) | ||
916 | { | ||
917 | Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); | ||
918 | pos.X = crossedBorder.BorderLine.Z - 1; | ||
919 | } | ||
893 | 920 | ||
894 | if (m_scene.TestBorderCross(pos, Cardinals.N)) | 921 | if (m_scene.TestBorderCross(pos, Cardinals.N)) |
895 | { | 922 | { |
896 | Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); | 923 | Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); |
897 | pos.Y = crossedBorder.BorderLine.Z - 1; | 924 | pos.Y = crossedBorder.BorderLine.Z - 1; |
898 | } | 925 | } |
899 | 926 | ||
900 | CheckAndAdjustLandingPoint(ref pos); | 927 | CheckAndAdjustLandingPoint(ref pos); |
901 | 928 | ||
902 | if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) | 929 | if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) |
903 | { | 930 | { |
904 | m_log.WarnFormat( | 931 | m_log.WarnFormat( |
905 | "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", | 932 | "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", |
906 | pos, Name, UUID); | 933 | pos, Name, UUID); |
907 | 934 | ||
908 | if (pos.X < 0f) pos.X = 0f; | 935 | if (pos.X < 0f) pos.X = 0f; |
909 | if (pos.Y < 0f) pos.Y = 0f; | 936 | if (pos.Y < 0f) pos.Y = 0f; |
910 | if (pos.Z < 0f) pos.Z = 0f; | 937 | if (pos.Z < 0f) pos.Z = 0f; |
911 | } | 938 | } |
912 | 939 | ||
913 | float localAVHeight = 1.56f; | 940 | float localAVHeight = 1.56f; |
914 | if (Appearance.AvatarHeight > 0) | 941 | if (Appearance.AvatarHeight > 0) |
915 | localAVHeight = Appearance.AvatarHeight; | 942 | localAVHeight = Appearance.AvatarHeight; |
916 | 943 | ||
917 | float posZLimit = 0; | 944 | float posZLimit = 0; |
918 | 945 | ||
919 | if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) | 946 | if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) |
920 | posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; | 947 | posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; |
921 | 948 | ||
922 | float newPosZ = posZLimit + localAVHeight / 2; | 949 | float newPosZ = posZLimit + localAVHeight / 2; |
923 | if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) | 950 | if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) |
924 | { | 951 | { |
925 | pos.Z = newPosZ; | 952 | pos.Z = newPosZ; |
926 | } | 953 | } |
927 | AbsolutePosition = pos; | 954 | AbsolutePosition = pos; |
928 | 955 | ||
929 | AddToPhysicalScene(isFlying); | 956 | AddToPhysicalScene(isFlying); |
930 | 957 | ||
931 | if (ForceFly) | 958 | if (ForceFly) |
932 | { | 959 | { |
933 | Flying = true; | 960 | Flying = true; |
934 | } | 961 | } |
935 | else if (FlyDisabled) | 962 | else if (FlyDisabled) |
936 | { | 963 | { |
937 | Flying = false; | 964 | Flying = false; |
965 | } | ||
938 | } | 966 | } |
939 | |||
940 | // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying | 967 | // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying |
941 | // avatar to return to the standing position in mid-air. On login it looks like this is being sent | 968 | // avatar to return to the standing position in mid-air. On login it looks like this is being sent |
942 | // elsewhere anyway | 969 | // elsewhere anyway |
@@ -954,11 +981,13 @@ namespace OpenSim.Region.Framework.Scenes | |||
954 | { | 981 | { |
955 | m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); | 982 | m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); |
956 | // Resume scripts | 983 | // Resume scripts |
957 | foreach (SceneObjectGroup sog in m_attachments) | 984 | Util.FireAndForget(delegate(object x) { |
958 | { | 985 | foreach (SceneObjectGroup sog in m_attachments) |
959 | sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); | 986 | { |
960 | sog.ResumeScripts(); | 987 | sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); |
961 | } | 988 | sog.ResumeScripts(); |
989 | } | ||
990 | }); | ||
962 | } | 991 | } |
963 | } | 992 | } |
964 | 993 | ||
@@ -3122,6 +3151,9 @@ namespace OpenSim.Region.Framework.Scenes | |||
3122 | cAgent.AlwaysRun = SetAlwaysRun; | 3151 | cAgent.AlwaysRun = SetAlwaysRun; |
3123 | 3152 | ||
3124 | cAgent.Appearance = new AvatarAppearance(Appearance); | 3153 | cAgent.Appearance = new AvatarAppearance(Appearance); |
3154 | |||
3155 | cAgent.ParentPart = ParentUUID; | ||
3156 | cAgent.SitOffset = m_pos; | ||
3125 | 3157 | ||
3126 | lock (scriptedcontrols) | 3158 | lock (scriptedcontrols) |
3127 | { | 3159 | { |
@@ -3181,6 +3213,8 @@ namespace OpenSim.Region.Framework.Scenes | |||
3181 | CameraAtAxis = cAgent.AtAxis; | 3213 | CameraAtAxis = cAgent.AtAxis; |
3182 | CameraLeftAxis = cAgent.LeftAxis; | 3214 | CameraLeftAxis = cAgent.LeftAxis; |
3183 | m_CameraUpAxis = cAgent.UpAxis; | 3215 | m_CameraUpAxis = cAgent.UpAxis; |
3216 | ParentUUID = cAgent.ParentPart; | ||
3217 | m_prevSitOffset = cAgent.SitOffset; | ||
3184 | 3218 | ||
3185 | // When we get to the point of re-computing neighbors everytime this | 3219 | // When we get to the point of re-computing neighbors everytime this |
3186 | // changes, then start using the agent's drawdistance rather than the | 3220 | // changes, then start using the agent's drawdistance rather than the |
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index ba33122..4b80e37 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs | |||
@@ -1486,7 +1486,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1486 | m_SOPXmlProcessors, | 1486 | m_SOPXmlProcessors, |
1487 | reader, | 1487 | reader, |
1488 | (o, nodeName, e) | 1488 | (o, nodeName, e) |
1489 | => m_log.ErrorFormat( | 1489 | => m_log.DebugFormat( |
1490 | "[SceneObjectSerializer]: Exception while parsing {0} in object {1} {2}: {3}{4}", | 1490 | "[SceneObjectSerializer]: Exception while parsing {0} in object {1} {2}: {3}{4}", |
1491 | ((SceneObjectPart)o).Name, ((SceneObjectPart)o).UUID, nodeName, e.Message, e.StackTrace)); | 1491 | ((SceneObjectPart)o).Name, ((SceneObjectPart)o).UUID, nodeName, e.Message, e.StackTrace)); |
1492 | 1492 | ||
@@ -1539,14 +1539,18 @@ namespace OpenSim.Region.Framework.Scenes.Serialization | |||
1539 | 1539 | ||
1540 | reader.ReadStartElement(name, String.Empty); // Shape | 1540 | reader.ReadStartElement(name, String.Empty); // Shape |
1541 | 1541 | ||
1542 | ExternalRepresentationUtils.ExecuteReadProcessors( | 1542 | errors = ExternalRepresentationUtils.ExecuteReadProcessors( |
1543 | shape, | 1543 | shape, |
1544 | m_ShapeXmlProcessors, | 1544 | m_ShapeXmlProcessors, |
1545 | reader, | 1545 | reader, |
1546 | (o, nodeName, e) | 1546 | (o, nodeName, e) |
1547 | => m_log.ErrorFormat( | 1547 | => |
1548 | "[SceneObjectSerializer]: Exception while parsing Shape property {0}: {1}{2}", | 1548 | { |
1549 | nodeName, e.Message, e.StackTrace)); | 1549 | m_log.DebugFormat( |
1550 | "[SceneObjectSerializer]: Exception while parsing Shape property {0}: {1}{2}", | ||
1551 | nodeName, e.Message, e.StackTrace); | ||
1552 | } | ||
1553 | ); | ||
1550 | 1554 | ||
1551 | reader.ReadEndElement(); // Shape | 1555 | reader.ReadEndElement(); // Shape |
1552 | 1556 | ||