diff --git a/OpenMetaverse.GUI/AvatarList.cs b/OpenMetaverse.GUI/AvatarList.cs index bbe56958..2957270f 100644 --- a/OpenMetaverse.GUI/AvatarList.cs +++ b/OpenMetaverse.GUI/AvatarList.cs @@ -28,20 +28,46 @@ using OpenMetaverse; using System; using System.Collections; using System.Collections.Generic; +using System.Drawing; using System.Windows.Forms; namespace OpenMetaverse.GUI { + + /// + /// Contains any available information for an avatar in the simulator. + /// A null value for .Avatar indicates coarse data for an avatar outside of visible range. + /// + public class TrackedAvatar + { + /// Assigned if the avatar is within visible range + public Avatar Avatar = null; + + /// Last known coarse location of avatar + public Vector3 CoarseLocation; + + /// Avatar ID + public UUID ID; + + /// ListViewItem associated with this avatar + public ListViewItem ListViewItem; + + /// Populated by RequestAvatarName if avatar is not visible + public string Name = "(Loading...)"; + } + /// /// ListView GUI component for viewing a client's nearby avatars list /// public class AvatarList : ListView { private GridClient _Client; - private List _Avatars = new List(); private ColumnSorter _ColumnSorter = new ColumnSorter(); - public delegate void AvatarDoubleClickCallback(Avatar avatar); + private DoubleDictionary _TrackedAvatars = new DoubleDictionary(); + private Dictionary _UntrackedAvatars = new Dictionary(); + + public delegate void AvatarDoubleClickCallback(TrackedAvatar trackedAvatar); /// /// Triggered when the user double clicks on an avatar in the list @@ -68,7 +94,9 @@ namespace OpenMetaverse.GUI ColumnHeader header2 = this.Columns.Add(" "); header2.Width = 40; - _ColumnSorter.SortColumn = 0; + _ColumnSorter.SortColumn = 1; + this.Sorting = SortOrder.Ascending; + this.ListViewItemSorter = _ColumnSorter; this.DoubleBuffered = true; this.ListViewItemSorter = _ColumnSorter; @@ -89,34 +117,85 @@ namespace OpenMetaverse.GUI /// /// Thread-safe method for clearing the TreeView control /// - public void ClearNodes() + public void ClearItems() { - if (this.InvokeRequired) this.BeginInvoke((MethodInvoker)delegate { ClearNodes(); }); - else this.Items.Clear(); + if (this.InvokeRequired) this.BeginInvoke((MethodInvoker)delegate { ClearItems(); }); + else + { + if (this.Handle != IntPtr.Zero) + this.Items.Clear(); + } } private void InitializeClient(GridClient client) { _Client = client; + _Client.Avatars.OnAvatarAppearance += new AvatarManager.AvatarAppearanceCallback(Avatars_OnAvatarAppearance); + _Client.Avatars.OnAvatarNames += new AvatarManager.AvatarNamesCallback(Avatars_OnAvatarNames); + _Client.Grid.OnCoarseLocationUpdate += new GridManager.CoarseLocationUpdateCallback(Grid_OnCoarseLocationUpdate); _Client.Network.OnCurrentSimChanged += new NetworkManager.CurrentSimChangedCallback(Network_OnCurrentSimChanged); _Client.Objects.OnNewAvatar += new ObjectManager.NewAvatarCallback(Objects_OnNewAvatar); _Client.Objects.OnObjectKilled += new ObjectManager.KillObjectCallback(Objects_OnObjectKilled); _Client.Objects.OnObjectUpdated += new ObjectManager.ObjectUpdatedCallback(Objects_OnObjectUpdated); } + private void AddAvatar(uint localID, UUID avatarID, Vector3 coarsePosition, Avatar avatar) + { + if (this.InvokeRequired) this.BeginInvoke((MethodInvoker)delegate { AddAvatar(localID, avatarID, coarsePosition, avatar); }); + else + { + if (!this.IsHandleCreated) return; + + TrackedAvatar trackedAvatar = new TrackedAvatar(); + trackedAvatar.CoarseLocation = coarsePosition; + trackedAvatar.ID = avatarID; + trackedAvatar.ListViewItem = this.Items.Add(avatarID.ToString(), trackedAvatar.Name, null); + + string strDist = avatarID == _Client.Self.AgentID ? "--" : (int)Vector3.Distance(_Client.Self.SimPosition, coarsePosition) + "m"; + trackedAvatar.ListViewItem.SubItems.Add(strDist); + + if (avatar != null) + { + trackedAvatar.Name = avatar.Name; + trackedAvatar.ListViewItem.Text = avatar.Name; + + lock (_TrackedAvatars) + _TrackedAvatars.Add(localID, avatarID, trackedAvatar); + } + else + { + lock (_UntrackedAvatars) + { + _UntrackedAvatars.Add(avatarID, trackedAvatar); + + trackedAvatar.ListViewItem.ForeColor = Color.FromKnownColor(KnownColor.GrayText); + + if (avatarID == _Client.Self.AgentID) + { + trackedAvatar.Name = _Client.Self.Name; + trackedAvatar.ListViewItem.Text = _Client.Self.Name; + } + + else Client.Avatars.RequestAvatarName(avatarID); + } + } + } + } + private void RemoveAvatar(uint localID) { if (this.InvokeRequired) this.BeginInvoke((MethodInvoker)delegate { RemoveAvatar(localID); }); else { - lock (_Avatars) + if (!this.IsHandleCreated) return; + + lock (_TrackedAvatars) { - if (_Avatars.Contains(localID)) + TrackedAvatar trackedAvatar; + if (_TrackedAvatars.TryGetValue(localID, out trackedAvatar)) { - _Avatars.Remove(localID); - string key = localID.ToString(); - int index = this.Items.IndexOfKey(key); - if (index > -1) this.Items.RemoveAt(index); + this.Items.Remove(trackedAvatar.ListViewItem); + _TrackedAvatars.Remove(localID); } } } @@ -127,37 +206,72 @@ namespace OpenMetaverse.GUI if (this.InvokeRequired) this.BeginInvoke((MethodInvoker)delegate { UpdateAvatar(avatar); }); else { - lock (_Avatars) - { - ListViewItem item; - if (_Avatars.Contains(avatar.LocalID)) - { - item = this.Items[avatar.LocalID.ToString()]; - item.SubItems[1].Text = (int)Vector3.Distance(_Client.Self.SimPosition, avatar.Position) + "m"; - item.Tag = avatar; - } + if (!this.IsHandleCreated) return; + lock (_TrackedAvatars) + { + TrackedAvatar trackedAvatar; + + lock (_UntrackedAvatars) + { + if (_UntrackedAvatars.TryGetValue(avatar.ID, out trackedAvatar)) + { + trackedAvatar.Name = avatar.Name; + trackedAvatar.ListViewItem.Text = avatar.Name; + trackedAvatar.ListViewItem.ForeColor = Color.FromKnownColor(KnownColor.ControlText); + + _TrackedAvatars.Add(avatar.LocalID, avatar.ID, trackedAvatar); + _UntrackedAvatars.Remove(avatar.ID); + } + } + + if (_TrackedAvatars.TryGetValue(avatar.ID, out trackedAvatar)) + { + trackedAvatar.Avatar = avatar; + trackedAvatar.Name = avatar.Name; + trackedAvatar.ID = avatar.ID; + + string strDist = avatar.ID == _Client.Self.AgentID ? "--" : (int)Vector3.Distance(_Client.Self.SimPosition, avatar.Position) + "m"; + trackedAvatar.ListViewItem.SubItems[1].Text = strDist; + } else { - bool replace = false; - for (int i = 0; i < this.Items.Count; i++) + AddAvatar(avatar.LocalID, avatar.ID, Vector3.Zero, avatar); + } + } + + this.Sort(); + } + } + + private void UpdateCoarseInfo(Simulator sim, List newEntries, List removedEntries) + { + if (this.InvokeRequired) this.BeginInvoke((MethodInvoker)delegate { UpdateCoarseInfo(sim, newEntries, removedEntries); }); + else + { + lock (_UntrackedAvatars) + { + for (int i = 0; i < removedEntries.Count; i++) + { + TrackedAvatar trackedAvatar; + if (_UntrackedAvatars.TryGetValue(removedEntries[i], out trackedAvatar)) { - if (this.Items[i].Text == avatar.Name) - { - this.Items[i].Name = avatar.LocalID.ToString(); - this.Items[i].Tag = avatar; - replace = true; - } + this.Items.Remove(trackedAvatar.ListViewItem); + _UntrackedAvatars.Remove(trackedAvatar.ID); } - if (!replace) + } + for (int i = 0; i < newEntries.Count; i++) + { + int index = this.Items.IndexOfKey(newEntries[i].ToString()); + if (index == -1) { - _Avatars.Add(avatar.LocalID); - string key = avatar.LocalID.ToString(); - item = this.Items.Add(key, avatar.Name, null); - item.SubItems.Add((int)Vector3.Distance(_Client.Self.SimPosition, avatar.Position) + "m"); - item.Tag = avatar; + Vector3 coarsePos; + if (!sim.AvatarPositions.TryGetValue(newEntries[i], out coarsePos)) + continue; + + AddAvatar(0, newEntries[i], coarsePos, null); } - } + } } } } @@ -175,19 +289,77 @@ namespace OpenMetaverse.GUI if (OnAvatarDoubleClick != null) { ListView list = (ListView)sender; - if (list.SelectedItems.Count > 0 && list.SelectedItems[0].Tag is Avatar) + if (list.SelectedItems.Count > 0) { - Avatar av = (Avatar)list.SelectedItems[0].Tag; - try { OnAvatarDoubleClick(av); } + TrackedAvatar trackedAvatar; + if (!_TrackedAvatars.TryGetValue(new UUID(list.SelectedItems[0].Name), out trackedAvatar) + && !_UntrackedAvatars.TryGetValue(new UUID(list.SelectedItems[0].Name), out trackedAvatar)) + return; + + try { OnAvatarDoubleClick(trackedAvatar); } catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Error, Client, ex); } } } } + private void Avatars_OnAvatarAppearance(UUID avatarID, bool isTrial, Primitive.TextureEntryFace defaultTexture, Primitive.TextureEntryFace[] faceTextures, List visualParams) + { + if (visualParams.Count > 105) + { + lock (_TrackedAvatars) + { + TrackedAvatar trackedAvatar; + if (_TrackedAvatars.TryGetValue(avatarID, out trackedAvatar)) + { + + this.BeginInvoke((MethodInvoker)delegate + { + byte param = visualParams[80]; + if (param > 117) + trackedAvatar.ListViewItem.ForeColor = Color.Blue; + else + trackedAvatar.ListViewItem.ForeColor = Color.Magenta; + }); + + } + } + } + } + + private void Avatars_OnAvatarNames(Dictionary names) + { + lock (_UntrackedAvatars) + { + foreach (KeyValuePair name in names) + { + TrackedAvatar trackedAvatar; + if (_UntrackedAvatars.TryGetValue(name.Key, out trackedAvatar)) + { + trackedAvatar.Name = name.Value; + + this.BeginInvoke((MethodInvoker)delegate + { + trackedAvatar.ListViewItem.Text = name.Value; + }); + } + } + } + } + + private void Grid_OnCoarseLocationUpdate(Simulator sim, List newEntries, List removedEntries) + { + UpdateCoarseInfo(sim, newEntries, removedEntries); + } + private void Network_OnCurrentSimChanged(Simulator PreviousSimulator) { - lock (_Avatars) _Avatars.Clear(); - ClearNodes(); + lock (_TrackedAvatars) + _TrackedAvatars.Clear(); + + lock (_UntrackedAvatars) + _UntrackedAvatars.Clear(); + + ClearItems(); } private void Objects_OnNewAvatar(Simulator simulator, Avatar avatar, ulong regionHandle, ushort timeDilation) @@ -197,17 +369,17 @@ namespace OpenMetaverse.GUI private void Objects_OnObjectKilled(Simulator simulator, uint objectID) { - lock (_Avatars) + lock (_TrackedAvatars) { - if (_Avatars.Contains(objectID)) RemoveAvatar(objectID); + if (_TrackedAvatars.ContainsKey(objectID)) RemoveAvatar(objectID); } } private void Objects_OnObjectUpdated(Simulator simulator, ObjectUpdate update, ulong regionHandle, ushort timeDilation) { - lock (_Avatars) + lock (_TrackedAvatars) { - if (_Avatars.Contains(update.LocalID)) + if (_TrackedAvatars.ContainsKey(update.LocalID)) { Avatar av; if (simulator.ObjectsAvatars.TryGetValue(update.LocalID, out av)) @@ -228,8 +400,8 @@ namespace OpenMetaverse.GUI if (SortColumn == 1) { - int valueA = itemB.SubItems.Count > 1 ? int.Parse(itemA.SubItems[1].Text.Replace("m", "")) : 0; - int valueB = itemB.SubItems.Count > 1 ? int.Parse(itemB.SubItems[1].Text.Replace("m", "")) : 0; + int valueA = itemB.SubItems.Count > 1 ? int.Parse(itemA.SubItems[1].Text.Replace("m", "").Replace("--", "0")) : 0; + int valueB = itemB.SubItems.Count > 1 ? int.Parse(itemB.SubItems[1].Text.Replace("m", "").Replace("--", "0")) : 0; if (Ascending) { if (valueA == valueB) return 0; diff --git a/OpenMetaverse.GUI/MiniMap.cs b/OpenMetaverse.GUI/MiniMap.cs index 18c9f292..122ab576 100644 --- a/OpenMetaverse.GUI/MiniMap.cs +++ b/OpenMetaverse.GUI/MiniMap.cs @@ -25,16 +25,23 @@ */ using OpenMetaverse.Imaging; +using System; +using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; namespace OpenMetaverse.GUI { + /// + /// PictureBox GUI component for displaying a client's mini-map + /// public class MiniMap : PictureBox { private UUID _MapImageID; private GridClient _Client; private Image _MapLayer; + private Point _MousePosition; + ToolTip _ToolTip; /// /// Gets or sets the GridClient associated with this control @@ -60,6 +67,26 @@ namespace OpenMetaverse.GUI public MiniMap(GridClient client) : this () { InitializeClient(client); + + _ToolTip = new ToolTip(); + _ToolTip.Active = true; + _ToolTip.AutomaticDelay = 1; + + this.MouseHover += new System.EventHandler(MiniMap_MouseHover); + this.MouseMove += new MouseEventHandler(MiniMap_MouseMove); + } + + void MiniMap_MouseHover(object sender, System.EventArgs e) + { + _ToolTip.SetToolTip(this, "test"); + _ToolTip.Show("test", this); + //TODO: tooltip popup with closest avatar's name, if within range + } + + void MiniMap_MouseMove(object sender, MouseEventArgs e) + { + _ToolTip.Hide(this); + _MousePosition = e.Location; } private void InitializeClient(GridClient client) @@ -94,61 +121,80 @@ namespace OpenMetaverse.GUI if (this.InvokeRequired) this.BeginInvoke((MethodInvoker)delegate { UpdateMiniMap(sim); }); else { + if (!this.IsHandleCreated) return; + Bitmap bmp = _MapLayer == null ? new Bitmap(256, 256) : (Bitmap)_MapLayer.Clone(); Graphics g = Graphics.FromImage(bmp); if (_MapLayer == null) { g.Clear(this.BackColor); - g.FillRectangle(Brushes.White, 0f, 0f, 256f, 256f); + g.FillRectangle(Brushes.Navy, 0f, 0f, 256f, 256f); } - if (!sim.AvatarPositions.ContainsKey(Client.Self.AgentID)) return; + Vector3 myCoarsePos; + + if (!sim.AvatarPositions.TryGetValue(Client.Self.AgentID, out myCoarsePos)) return; int i = 0; - Vector3 myPos = sim.AvatarPositions[_Client.Self.AgentID]; - - foreach (Vector3 pos in _Client.Network.CurrentSim.AvatarPositions.Values) + lock (_Client.Network.CurrentSim.AvatarPositions.Dictionary) { - int x = (int)pos.X; - int y = 255 - (int)pos.Y; - if (i == _Client.Network.CurrentSim.PositionIndexYou) + foreach (KeyValuePair coarse in _Client.Network.CurrentSim.AvatarPositions.Dictionary) { - g.FillEllipse(Brushes.PaleGreen, x - 5, y - 5, 10, 10); - g.DrawEllipse(Pens.Green, x - 5, y - 5, 10, 10); - } - else - { - if (myPos.Z - (pos.Z * 4) > 5) + int x = (int)coarse.Value.X; + int y = 255 - (int)coarse.Value.Y; + if (coarse.Key == Client.Self.AgentID) { - Point[] points = new Point[3] { new Point(x - 6, y - 6), new Point(x + 6, y - 6), new Point(x, y + 6) }; - g.FillPolygon(Brushes.Red, points); - g.DrawPolygon(Pens.DarkRed, points); + g.FillEllipse(Brushes.Yellow, x - 5, y - 5, 10, 10); + g.DrawEllipse(Pens.Khaki, x - 5, y - 5, 10, 10); } - - else if (myPos.Z - (pos.Z * 4) < -5) - { - Point[] points = new Point[3] { new Point(x - 6, y + 6), new Point(x + 6, y + 6), new Point(x, y - 6) }; - g.FillPolygon(Brushes.Red, points); - g.DrawPolygon(Pens.DarkRed, points); - } - else { - g.FillEllipse(Brushes.Red, x - 5, y - 5, 10, 10); - g.DrawEllipse(Pens.DarkRed, x - 5, y - 5, 10, 10); + Pen penColor; + Brush brushColor; + + if (Client.Network.CurrentSim.ObjectsAvatars.Find(delegate(Avatar av) { return av.ID == coarse.Key; }) != null) + { + brushColor = Brushes.PaleGreen; + penColor = Pens.Green; + } + else + { + brushColor = Brushes.LightGray; + penColor = Pens.Gray; + } + + if (myCoarsePos.Z - coarse.Value.Z > 1) + { + Point[] points = new Point[3] { new Point(x - 6, y - 6), new Point(x + 6, y - 6), new Point(x, y + 6) }; + g.FillPolygon(brushColor, points); + g.DrawPolygon(penColor, points); + } + + else if (myCoarsePos.Z - coarse.Value.Z < -1) + { + Point[] points = new Point[3] { new Point(x - 6, y + 6), new Point(x + 6, y + 6), new Point(x, y - 6) }; + g.FillPolygon(brushColor, points); + g.DrawPolygon(penColor, points); + } + + else + { + g.FillEllipse(brushColor, x - 5, y - 5, 10, 10); + g.DrawEllipse(penColor, x - 5, y - 5, 10, 10); + } } - } - i++; - }; + i++; + }; + } g.DrawImage(bmp, 0, 0); this.Image = bmp; } } - private void Grid_OnCoarseLocationUpdate(Simulator sim) + private void Grid_OnCoarseLocationUpdate(Simulator sim, List newEntries, List removedEntries) { UpdateMiniMap(sim); } diff --git a/OpenMetaverse.GUI/StatusOutput.cs b/OpenMetaverse.GUI/StatusOutput.cs index dc600f17..b59b33cc 100644 --- a/OpenMetaverse.GUI/StatusOutput.cs +++ b/OpenMetaverse.GUI/StatusOutput.cs @@ -30,6 +30,9 @@ using System.Windows.Forms; namespace OpenMetaverse.GUI { + /// + /// RichTextBox GUI component for displaying a client's status output + /// public class StatusOutput : RichTextBox { private GridClient _Client; @@ -57,6 +60,8 @@ namespace OpenMetaverse.GUI } else { + if (!this.IsHandleCreated) return; + this.SelectionStart = this.Text.Length; this.SelectionColor = color; DateTime now = DateTime.Now; diff --git a/OpenMetaverse/GridManager.cs b/OpenMetaverse/GridManager.cs index 02546c10..8124aff5 100644 --- a/OpenMetaverse/GridManager.cs +++ b/OpenMetaverse/GridManager.cs @@ -193,7 +193,7 @@ namespace OpenMetaverse /// /// /// - public delegate void CoarseLocationUpdateCallback(Simulator sim); + public delegate void CoarseLocationUpdateCallback(Simulator sim, List newEntries, List removedEntries); /// /// /// @@ -240,6 +240,8 @@ namespace OpenMetaverse public Vector3 SunDirection { get { return sunDirection; } } /// Current angular velocity of the sun public Vector3 SunAngVelocity { get { return sunAngVelocity; } } + /// Current world time + public DateTime WorldTime { get { return WorldTime; } } /// A dictionary of all the regions, indexed by region name internal Dictionary Regions = new Dictionary(); @@ -250,6 +252,7 @@ namespace OpenMetaverse private float sunPhase; private Vector3 sunDirection; private Vector3 sunAngVelocity; + private DateTime worldTime; /// /// Constructor @@ -608,38 +611,54 @@ namespace OpenMetaverse sunAngVelocity = time.TimeInfo.SunAngVelocity; // TODO: Does anyone have a use for the time stuff? - } + } private void CoarseLocationHandler(Packet packet, Simulator simulator) { CoarseLocationUpdatePacket coarse = (CoarseLocationUpdatePacket)packet; + // populate a dictionary from the packet, for local use + Dictionary coarseEntries = new Dictionary(); + for (int i = 0; i < coarse.AgentData.Length; i++) + { + coarseEntries[coarse.AgentData[i].AgentID] = new Vector3((int)coarse.Location[i].X, (int)coarse.Location[i].Y, (int)coarse.Location[i].Z * 4); + + // the friend we are tracking on radar + if (i == coarse.Index.Prey) + simulator.preyID = coarse.AgentData[i].AgentID; + } + + // find stale entries (people who left the sim) + List removedEntries = simulator.avatarPositions.FindAll(delegate(UUID findID) { return !coarseEntries.ContainsKey(findID); }); + + // anyone who was not listed in the previous update + List newEntries = new List(); + lock (simulator.avatarPositions) { - simulator.avatarPositions.Clear(); - - for (int i = 0; i < coarse.Location.Length; i++) + // remove stale entries + foreach(UUID trackedID in simulator.avatarPositions.Dictionary.Keys) { - if (i == coarse.Index.You) - { - simulator.positionIndexYou = i; - } - else if (i == coarse.Index.Prey) - { - simulator.positionIndexPrey = i; - } - simulator.avatarPositions.Add( - coarse.AgentData[i].AgentID, - new Vector3(coarse.Location[i].X, coarse.Location[i].Y, - coarse.Location[i].Z * 4)); + if (removedEntries.Contains(trackedID)) + simulator.avatarPositions.Dictionary.Remove(trackedID); } - if (OnCoarseLocationUpdate != null) + // add or update tracked info, and record who is new + foreach (KeyValuePair entry in coarseEntries) { - try { OnCoarseLocationUpdate(simulator); } - catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + if (!simulator.avatarPositions.Dictionary.ContainsKey(entry.Key)) + newEntries.Add(entry.Key); + + simulator.avatarPositions.Dictionary[entry.Key] = entry.Value; } } + + if (OnCoarseLocationUpdate != null) + { + try { OnCoarseLocationUpdate(simulator, newEntries, removedEntries); } + catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); } + } + } private void RegionHandleReplyHandler(Packet packet, Simulator simulator) diff --git a/OpenMetaverse/InternalDictionary.cs b/OpenMetaverse/InternalDictionary.cs index 77e2cdcb..cd8b7035 100644 --- a/OpenMetaverse/InternalDictionary.cs +++ b/OpenMetaverse/InternalDictionary.cs @@ -124,7 +124,10 @@ namespace OpenMetaverse /// public bool TryGetValue(TKey key, out TValue value) { - return Dictionary.TryGetValue(key, out value); + lock (Dictionary) + { + return Dictionary.TryGetValue(key, out value); + } } /// @@ -183,6 +186,33 @@ namespace OpenMetaverse return found; } + /// Find All items in an + /// return matching keys. + /// a containing found keys. + /// + /// Find All keys which also exist in another dictionary + /// + /// List<UUID> matches = myDict.FindAll( + /// delegate(UUID id) { + /// return myOtherDict.ContainsKey(id); + /// } + /// ); + /// + /// + public List FindAll(Predicate match) + { + List found = new List(); + lock (Dictionary) + { + foreach (KeyValuePair kvp in Dictionary) + { + if (match(kvp.Key)) + found.Add(kvp.Key); + } + } + return found; + } + /// Perform an on each entry in an /// to perform /// diff --git a/OpenMetaverse/Simulator.cs b/OpenMetaverse/Simulator.cs index 9451daea..76e28e21 100644 --- a/OpenMetaverse/Simulator.cs +++ b/OpenMetaverse/Simulator.cs @@ -363,11 +363,9 @@ namespace OpenMetaverse /// not public bool Connected { get { return connected; } } /// Coarse locations of avatars in this simulator - public Dictionary AvatarPositions { get { return avatarPositions; } } - /// AvatarPositions index representing your avatar - public int PositionIndexYou { get { return positionIndexYou; } } - /// AvatarPositions index representing TrackAgent target - public int PositionIndexPrey { get { return positionIndexPrey; } } + public InternalDictionary AvatarPositions { get { return avatarPositions; } } + /// AvatarPositions key representing TrackAgent target + public UUID PreyID { get { return preyID; } } #endregion Properties @@ -381,11 +379,9 @@ namespace OpenMetaverse /// to the property Connected internal bool connected; /// Coarse locations of avatars in this simulator - internal Dictionary avatarPositions = new Dictionary(); - /// AvatarPositions index representing your avatar - internal int positionIndexYou = -1; - /// AvatarPositions index representing TrackAgent target - internal int positionIndexPrey = -1; + internal InternalDictionary avatarPositions = new InternalDictionary(); + /// AvatarPositions key representing TrackAgent target + internal UUID preyID = UUID.Zero; /// Sequence numbers of packets we've received /// (for duplicate checking) internal Queue PacketArchive; diff --git a/Programs/examples/Dashboard/Dashboard.Designer.cs b/Programs/examples/Dashboard/Dashboard.Designer.cs index 031067f3..b909fc9c 100644 --- a/Programs/examples/Dashboard/Dashboard.Designer.cs +++ b/Programs/examples/Dashboard/Dashboard.Designer.cs @@ -36,13 +36,13 @@ namespace Dashboard this.tabPage2 = new System.Windows.Forms.TabPage(); this.tabPage3 = new System.Windows.Forms.TabPage(); this.tabPage4 = new System.Windows.Forms.TabPage(); + this.localChat1 = new OpenMetaverse.GUI.LocalChat(); + this.statusOutput1 = new OpenMetaverse.GUI.StatusOutput(); this.avatarList1 = new OpenMetaverse.GUI.AvatarList(); this.friendsList1 = new OpenMetaverse.GUI.FriendList(); this.groupList1 = new OpenMetaverse.GUI.GroupList(); this.inventoryTree1 = new OpenMetaverse.GUI.InventoryTree(); this.miniMap1 = new OpenMetaverse.GUI.MiniMap(); - this.localChat1 = new OpenMetaverse.GUI.LocalChat(); - this.statusOutput1 = new OpenMetaverse.GUI.StatusOutput(); this.splitContainer1.Panel1.SuspendLayout(); this.splitContainer1.Panel2.SuspendLayout(); this.splitContainer1.SuspendLayout(); @@ -143,7 +143,7 @@ namespace Dashboard this.tabPage2.Location = new System.Drawing.Point(4, 22); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(3); - this.tabPage2.Size = new System.Drawing.Size(202, 194); + this.tabPage2.Size = new System.Drawing.Size(202, 199); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "Friends"; this.tabPage2.UseVisualStyleBackColor = true; @@ -153,7 +153,7 @@ namespace Dashboard this.tabPage3.Controls.Add(this.groupList1); this.tabPage3.Location = new System.Drawing.Point(4, 22); this.tabPage3.Name = "tabPage3"; - this.tabPage3.Size = new System.Drawing.Size(202, 194); + this.tabPage3.Size = new System.Drawing.Size(202, 199); this.tabPage3.TabIndex = 2; this.tabPage3.Text = "Groups"; this.tabPage3.UseVisualStyleBackColor = true; @@ -163,66 +163,11 @@ namespace Dashboard this.tabPage4.Controls.Add(this.inventoryTree1); this.tabPage4.Location = new System.Drawing.Point(4, 22); this.tabPage4.Name = "tabPage4"; - this.tabPage4.Size = new System.Drawing.Size(202, 194); + this.tabPage4.Size = new System.Drawing.Size(202, 199); this.tabPage4.TabIndex = 3; this.tabPage4.Text = "Inventory"; this.tabPage4.UseVisualStyleBackColor = true; // - // avatarList1 - // - this.avatarList1.Client = null; - this.avatarList1.Dock = System.Windows.Forms.DockStyle.Fill; - this.avatarList1.Location = new System.Drawing.Point(3, 3); - this.avatarList1.Name = "avatarList1"; - this.avatarList1.Size = new System.Drawing.Size(196, 193); - this.avatarList1.TabIndex = 2; - this.avatarList1.UseCompatibleStateImageBehavior = false; - this.avatarList1.View = System.Windows.Forms.View.Details; - // - // friendsList1 - // - this.friendsList1.Client = null; - this.friendsList1.Dock = System.Windows.Forms.DockStyle.Fill; - this.friendsList1.Location = new System.Drawing.Point(3, 3); - this.friendsList1.Name = "friendsList1"; - this.friendsList1.Size = new System.Drawing.Size(196, 188); - this.friendsList1.TabIndex = 5; - this.friendsList1.UseCompatibleStateImageBehavior = false; - this.friendsList1.View = System.Windows.Forms.View.Details; - // - // groupList1 - // - this.groupList1.Client = null; - this.groupList1.Dock = System.Windows.Forms.DockStyle.Fill; - this.groupList1.Location = new System.Drawing.Point(0, 0); - this.groupList1.Name = "groupList1"; - this.groupList1.Size = new System.Drawing.Size(202, 194); - this.groupList1.TabIndex = 7; - this.groupList1.UseCompatibleStateImageBehavior = false; - this.groupList1.View = System.Windows.Forms.View.Details; - // - // inventoryTree1 - // - this.inventoryTree1.Client = null; - this.inventoryTree1.Dock = System.Windows.Forms.DockStyle.Fill; - this.inventoryTree1.Location = new System.Drawing.Point(0, 0); - this.inventoryTree1.Name = "inventoryTree1"; - this.inventoryTree1.Size = new System.Drawing.Size(202, 194); - this.inventoryTree1.TabIndex = 1; - // - // miniMap1 - // - this.miniMap1.BackColor = System.Drawing.SystemColors.Control; - this.miniMap1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.miniMap1.Client = null; - this.miniMap1.Dock = System.Windows.Forms.DockStyle.Fill; - this.miniMap1.Location = new System.Drawing.Point(0, 0); - this.miniMap1.Name = "miniMap1"; - this.miniMap1.Size = new System.Drawing.Size(210, 214); - this.miniMap1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; - this.miniMap1.TabIndex = 11; - this.miniMap1.TabStop = false; - // // localChat1 // this.localChat1.Client = null; @@ -244,6 +189,61 @@ namespace Dashboard this.statusOutput1.TabIndex = 0; this.statusOutput1.Text = ""; // + // avatarList1 + // + this.avatarList1.Client = null; + this.avatarList1.Dock = System.Windows.Forms.DockStyle.Fill; + this.avatarList1.Location = new System.Drawing.Point(3, 3); + this.avatarList1.Name = "avatarList1"; + this.avatarList1.Size = new System.Drawing.Size(196, 193); + this.avatarList1.TabIndex = 2; + this.avatarList1.UseCompatibleStateImageBehavior = false; + this.avatarList1.View = System.Windows.Forms.View.Details; + // + // friendsList1 + // + this.friendsList1.Client = null; + this.friendsList1.Dock = System.Windows.Forms.DockStyle.Fill; + this.friendsList1.Location = new System.Drawing.Point(3, 3); + this.friendsList1.Name = "friendsList1"; + this.friendsList1.Size = new System.Drawing.Size(196, 193); + this.friendsList1.TabIndex = 5; + this.friendsList1.UseCompatibleStateImageBehavior = false; + this.friendsList1.View = System.Windows.Forms.View.Details; + // + // groupList1 + // + this.groupList1.Client = null; + this.groupList1.Dock = System.Windows.Forms.DockStyle.Fill; + this.groupList1.Location = new System.Drawing.Point(0, 0); + this.groupList1.Name = "groupList1"; + this.groupList1.Size = new System.Drawing.Size(202, 199); + this.groupList1.TabIndex = 7; + this.groupList1.UseCompatibleStateImageBehavior = false; + this.groupList1.View = System.Windows.Forms.View.Details; + // + // inventoryTree1 + // + this.inventoryTree1.Client = null; + this.inventoryTree1.Dock = System.Windows.Forms.DockStyle.Fill; + this.inventoryTree1.Location = new System.Drawing.Point(0, 0); + this.inventoryTree1.Name = "inventoryTree1"; + this.inventoryTree1.Size = new System.Drawing.Size(202, 199); + this.inventoryTree1.TabIndex = 1; + // + // miniMap1 + // + this.miniMap1.BackColor = System.Drawing.SystemColors.Control; + this.miniMap1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.miniMap1.Client = null; + this.miniMap1.Dock = System.Windows.Forms.DockStyle.Fill; + this.miniMap1.Location = new System.Drawing.Point(0, 0); + this.miniMap1.Name = "miniMap1"; + this.miniMap1.Size = new System.Drawing.Size(210, 214); + this.miniMap1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.miniMap1.TabIndex = 11; + this.miniMap1.TabStop = false; + // // Dashboard // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); diff --git a/Programs/examples/Dashboard/Dashboard.cs b/Programs/examples/Dashboard/Dashboard.cs index 5f72d1fa..c07da906 100644 --- a/Programs/examples/Dashboard/Dashboard.cs +++ b/Programs/examples/Dashboard/Dashboard.cs @@ -12,6 +12,7 @@ namespace Dashboard { GridClient Client; + LoginParams ClientLogin; /// /// Provides a full representation of OpenMetaverse.GUI @@ -26,11 +27,36 @@ namespace Dashboard //force logout and exit when form is closed this.FormClosing += new FormClosingEventHandler(Dashboard_FormClosing); + //initialize the client object and related controls + InitializeClient(true); + + //double-click events + avatarList1.OnAvatarDoubleClick += new AvatarList.AvatarDoubleClickCallback(avatarList1_OnAvatarDoubleClick); + friendsList1.OnFriendDoubleClick += new FriendList.FriendDoubleClickCallback(friendsList1_OnFriendDoubleClick); + groupList1.OnGroupDoubleClick += new GroupList.GroupDoubleClickCallback(groupList1_OnGroupDoubleClick); + + //login + ClientLogin = Client.Network.DefaultLoginParams(firstName, lastName, password, "OpenMetaverse Dashboard", Assembly.GetExecutingAssembly().GetName().Version.ToString()); + ClientLogin.Start = "last"; + Client.Network.BeginLogin(ClientLogin); + } + + private void InitializeClient(bool initialize) + { + if (Client != null) + { + if (Client.Network.Connected) + Client.Network.Logout(); + + Client = null; + } + + if (!initialize) return; + //initialize client object Client = new GridClient(); + Client.Network.OnLogin += new NetworkManager.LoginCallback(Network_OnLogin); Client.Settings.USE_TEXTURE_CACHE = true; - LoginParams ClientLogin = Client.Network.DefaultLoginParams(firstName, lastName, password, "OpenMetaverse Dashboard", Assembly.GetExecutingAssembly().GetName().Version.ToString()); - ClientLogin.Start = "last"; //define the client object for each GUI element avatarList1.Client = Client; @@ -40,26 +66,17 @@ namespace Dashboard localChat1.Client = Client; miniMap1.Client = Client; statusOutput1.Client = Client; - - //double-click events - avatarList1.OnAvatarDoubleClick += new AvatarList.AvatarDoubleClickCallback(avatarList1_OnAvatarDoubleClick); - friendsList1.OnFriendDoubleClick += new FriendList.FriendDoubleClickCallback(friendsList1_OnFriendDoubleClick); - groupList1.OnGroupDoubleClick += new GroupList.GroupDoubleClickCallback(groupList1_OnGroupDoubleClick); - - //login - Client.Network.BeginLogin(ClientLogin); } private void Dashboard_FormClosing(object sender, FormClosingEventArgs e) { - e.Cancel = true; - if (Client != null && Client.Network.Connected) Client.Network.Logout(); + InitializeClient(false); Environment.Exit(0); } - private void avatarList1_OnAvatarDoubleClick(Avatar avatar) + private void avatarList1_OnAvatarDoubleClick(TrackedAvatar trackedAvatar) { - MessageBox.Show(avatar.Name + " = " + avatar.ID); + MessageBox.Show(trackedAvatar.Name + " = " + trackedAvatar.ID); } private void friendsList1_OnFriendDoubleClick(FriendInfo friend) @@ -72,5 +89,20 @@ namespace Dashboard MessageBox.Show(group.Name + " = " + group.ID); } + private void Network_OnLogin(LoginStatus login, string message) + { + if (login == LoginStatus.Failed) + { + this.BeginInvoke((MethodInvoker)delegate + { + if (MessageBox.Show(this, "Login failed. Try again?", this.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes) + { + InitializeClient(true); + Client.Network.BeginLogin(ClientLogin); + } + }); + } + } + } } \ No newline at end of file