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