-// \r
-// Radegast Metaverse Client\r
-// Copyright (c) 2009, Radegast Development Team\r
-// All rights reserved.\r
-// \r
-// Redistribution and use in source and binary forms, with or without\r
-// modification, are permitted provided that the following conditions are met:\r
-// \r
-// * Redistributions of source code must retain the above copyright notice,\r
-// this list of conditions and the following disclaimer.\r
-// * Redistributions in binary form must reproduce the above copyright\r
-// notice, this list of conditions and the following disclaimer in the\r
-// documentation and/or other materials provided with the distribution.\r
-// * Neither the name of the application "Radegast", nor the names of its\r
-// contributors may be used to endorse or promote products derived from\r
-// this software without specific prior written permission.\r
-// \r
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
-// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\r
-// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\r
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\r
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\r
-// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
-// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\r
-// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\r
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
-//\r
-// $Id$\r
-//\r
-using System;\r
-using System.Collections.Generic;\r
-using System.Drawing;\r
-using System.Text;\r
-using System.Text.RegularExpressions;\r
-using System.Timers;\r
-using System.Threading;\r
-using System.Windows.Forms;\r
-using System.Resources;\r
-using System.IO;\r
-using System.Web;\r
-using Radegast.Netcom;\r
-using OpenMetaverse;\r
-using OpenMetaverse.StructuredData;\r
-using OpenMetaverse.Assets;\r
-\r
-namespace Radegast\r
-{\r
- public partial class frmMain : RadegastForm\r
- {\r
- #region Public members\r
- public static ImageList ResourceImages = new ImageList();\r
- public static List<string> ImageNames = new List<string>();\r
-\r
- public TabsConsole TabConsole\r
- {\r
- get { return tabsConsole; }\r
- }\r
-\r
- public MapConsole WorldMap\r
- {\r
- get\r
- {\r
- if (MapTab != null)\r
- {\r
- return (MapConsole)MapTab.Control;\r
- }\r
- return null;\r
- }\r
- }\r
-\r
- public RadegastTab MapTab\r
- {\r
- get\r
- {\r
- if (tabsConsole.TabExists("map"))\r
- {\r
- return tabsConsole.Tabs["map"];\r
- }\r
- else\r
- {\r
- return null;\r
- }\r
- }\r
- }\r
-\r
- public MediaConsole MediaConsole { get { return mediaConsole; } }\r
-\r
- /// <summary>\r
- /// Drop down that contains the tools menu\r
- /// </summary>\r
- public ToolStripDropDownButton ToolsMenu\r
- {\r
- get { return tbnTools; }\r
- }\r
-\r
- /// <summary>\r
- /// Dropdown that contains the heelp menu\r
- /// </summary>\r
- public ToolStripDropDownButton HelpMenu\r
- {\r
- get { return tbtnHelp; }\r
- }\r
-\r
- /// <summary>\r
- /// Drop down that contants the plugins menu. Make sure to set it Visible if\r
- /// you add items to this menu, it's hidden by default\r
- /// </summary>\r
- public ToolStripDropDownButton PluginsMenu\r
- {\r
- get { return tbnPlugins; }\r
- }\r
-\r
- #endregion\r
-\r
- #region Private members\r
- private RadegastInstance instance;\r
- private GridClient client { get { return instance.Client; } }\r
- private RadegastNetcom netcom { get { return instance.Netcom; } }\r
- private TabsConsole tabsConsole;\r
- private System.Timers.Timer statusTimer;\r
- private AutoPilot ap;\r
- private bool AutoPilotActive = false;\r
- private TransparentButton btnDialogNextControl;\r
- private MediaConsole mediaConsole;\r
- #endregion\r
-\r
- #region Constructor and disposal\r
- public frmMain(RadegastInstance instance)\r
- : base(instance)\r
- {\r
- GetSLTimeZone();\r
- InitializeComponent();\r
- Disposed += new EventHandler(frmMain_Disposed);\r
-\r
- this.instance = instance;\r
- this.instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);\r
- netcom.NetcomSync = this;\r
-\r
- pnlDialog.Visible = false;\r
- btnDialogNextControl = new TransparentButton();\r
- pnlDialog.Controls.Add(btnDialogNextControl);\r
- pnlDialog.Top = 0;\r
-\r
- btnDialogNextControl.Size = new Size(35, 20);\r
- btnDialogNextControl.BackColor = Color.Transparent;\r
- btnDialogNextControl.ForeColor = Color.Gold;\r
- btnDialogNextControl.FlatAppearance.BorderSize = 0;\r
- btnDialogNextControl.FlatStyle = FlatStyle.Flat;\r
- btnDialogNextControl.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;\r
- btnDialogNextControl.Text = ">>";\r
- btnDialogNextControl.Font = new Font(btnDialogNextControl.Font, FontStyle.Bold);\r
- btnDialogNextControl.Margin = new Padding(0);\r
- btnDialogNextControl.Padding = new Padding(0);\r
- btnDialogNextControl.UseVisualStyleBackColor = false;\r
- btnDialogNextControl.Top = btnDialogNextControl.Parent.ClientSize.Height - btnDialogNextControl.Size.Height;\r
- btnDialogNextControl.Left = btnDialogNextControl.Parent.ClientSize.Width - btnDialogNextControl.Size.Width;\r
- btnDialogNextControl.Click += new EventHandler(btnDialogNextControl_Click);\r
-\r
- if (instance.MonoRuntime)\r
- {\r
- statusStrip1.LayoutStyle = ToolStripLayoutStyle.Table;\r
- }\r
-\r
- // Config options\r
- if (instance.GlobalSettings["transaction_notification_chat"].Type == OSDType.Unknown)\r
- instance.GlobalSettings["transaction_notification_chat"] = OSD.FromBoolean(true);\r
-\r
- if (instance.GlobalSettings["transaction_notification_dialog"].Type == OSDType.Unknown)\r
- instance.GlobalSettings["transaction_notification_dialog"] = OSD.FromBoolean(true);\r
-\r
- // Callbacks\r
- netcom.ClientLoginStatus += new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);\r
- netcom.ClientLoggedOut += new EventHandler(netcom_ClientLoggedOut);\r
- netcom.ClientDisconnected += new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);\r
- RegisterClientEvents(client);\r
-\r
- InitializeStatusTimer();\r
- RefreshWindowTitle();\r
- }\r
-\r
- private void RegisterClientEvents(GridClient client)\r
- {\r
- client.Parcels.ParcelProperties += new EventHandler<ParcelPropertiesEventArgs>(Parcels_ParcelProperties);\r
- client.Self.MoneyBalanceReply += new EventHandler<MoneyBalanceReplyEventArgs>(Self_MoneyBalanceReply);\r
- }\r
-\r
- private void UnregisterClientEvents(GridClient client)\r
- {\r
- client.Parcels.ParcelProperties -= new EventHandler<ParcelPropertiesEventArgs>(Parcels_ParcelProperties);\r
- client.Self.MoneyBalanceReply -= new EventHandler<MoneyBalanceReplyEventArgs>(Self_MoneyBalanceReply);\r
- }\r
-\r
- void instance_ClientChanged(object sender, ClientChangedEventArgs e)\r
- {\r
- UnregisterClientEvents(e.OldClient);\r
- RegisterClientEvents(client);\r
- }\r
-\r
- void frmMain_Disposed(object sender, EventArgs e)\r
- {\r
- netcom.NetcomSync = null;\r
- netcom.ClientLoginStatus -= new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);\r
- netcom.ClientLoggedOut -= new EventHandler(netcom_ClientLoggedOut);\r
- netcom.ClientDisconnected -= new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);\r
- UnregisterClientEvents(client);\r
- this.instance.CleanUp();\r
- }\r
- #endregion\r
-\r
- #region Event handlers\r
- void Self_MoneyBalanceReply(object sender, MoneyBalanceReplyEventArgs e)\r
- {\r
- if (!String.IsNullOrEmpty(e.Description))\r
- {\r
- if (instance.GlobalSettings["transaction_notification_dialog"].AsBoolean())\r
- AddNotification(new ntfGeneric(instance, e.Description));\r
- if (instance.GlobalSettings["transaction_notification_chat"].AsBoolean())\r
- TabConsole.DisplayNotificationInChat(e.Description);\r
- }\r
- }\r
-\r
- public void InitializeControls()\r
- {\r
- InitializeTabsConsole();\r
-\r
- if (instance.MediaManager.SoundSystemAvailable)\r
- {\r
- mediaConsole = new MediaConsole(instance);\r
- tbtnMedia.Visible = true;\r
- }\r
- }\r
-\r
- public bool InAutoReconnect { get; set; }\r
-\r
- private void DisplayAutoReconnectForm()\r
- {\r
- if (IsDisposed) return;\r
-\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(DisplayAutoReconnectForm));\r
- return;\r
- }\r
-\r
- InAutoReconnect = true;\r
- frmReconnect dialog = new frmReconnect(instance, 120);\r
- dialog.ShowDialog(this);\r
- dialog.Dispose();\r
- dialog = null;\r
- }\r
-\r
- public void BeginAutoReconnect()\r
- {\r
- // Sleep for 3 seconds on a separate thread while things unwind on\r
- // disconnect, since ShowDialog() blocks GUI thread\r
- (new Thread(new ThreadStart(() =>\r
- {\r
- System.Threading.Thread.Sleep(3000);\r
- DisplayAutoReconnectForm();\r
- }\r
- ))\r
- {\r
- Name = "Reconnect Delay Thread",\r
- IsBackground = true\r
- }\r
- ).Start();\r
- }\r
-\r
- private void netcom_ClientLoginStatus(object sender, LoginProgressEventArgs e)\r
- {\r
- if (e.Status == LoginStatus.Failed)\r
- {\r
- if (InAutoReconnect)\r
- {\r
- if (instance.GlobalSettings["auto_reconnect"].AsBoolean())\r
- BeginAutoReconnect();\r
- else\r
- InAutoReconnect = false;\r
- }\r
- }\r
- else if (e.Status == LoginStatus.Success)\r
- {\r
- InAutoReconnect = false;\r
- tbtnVoice.Enabled = disconnectToolStripMenuItem.Enabled =\r
- tbtnGroups.Enabled = tbnObjects.Enabled = tbtnWorld.Enabled = tbnTools.Enabled = tmnuImport.Enabled =\r
- tbtnFriends.Enabled = tbtnInventory.Enabled = tbtnSearch.Enabled = tbtnMap.Enabled = true;\r
-\r
- statusTimer.Start();\r
- RefreshWindowTitle();\r
- }\r
- }\r
-\r
- private void netcom_ClientLoggedOut(object sender, EventArgs e)\r
- {\r
- tbtnVoice.Enabled = disconnectToolStripMenuItem.Enabled =\r
- tbtnGroups.Enabled = tbnObjects.Enabled = tbtnWorld.Enabled = tbnTools.Enabled = tmnuImport.Enabled =\r
- tbtnFriends.Enabled = tbtnInventory.Enabled = tbtnSearch.Enabled = tbtnMap.Enabled = false;\r
-\r
- reconnectToolStripMenuItem.Enabled = true;\r
- InAutoReconnect = false;\r
-\r
- if (statusTimer != null)\r
- statusTimer.Stop();\r
-\r
- RefreshStatusBar();\r
- RefreshWindowTitle();\r
- }\r
-\r
- private void netcom_ClientDisconnected(object sender, DisconnectedEventArgs e)\r
- {\r
- if (e.Reason == NetworkManager.DisconnectType.ClientInitiated) return;\r
- netcom_ClientLoggedOut(sender, EventArgs.Empty);\r
-\r
- if (instance.GlobalSettings["auto_reconnect"].AsBoolean())\r
- {\r
- BeginAutoReconnect();\r
- }\r
- }\r
-\r
- private void frmMain_FormClosing(object sender, FormClosingEventArgs e)\r
- {\r
- if (statusTimer != null)\r
- {\r
- statusTimer.Stop();\r
- statusTimer.Dispose();\r
- statusTimer = null;\r
- }\r
-\r
- if (mediaConsole != null)\r
- {\r
- if (tabsConsole.TabExists("media"))\r
- {\r
- tabsConsole.Tabs["media"].AllowClose = true;\r
- tabsConsole.Tabs["media"].Close();\r
- }\r
- else\r
- {\r
- mediaConsole.Dispose();\r
- }\r
- mediaConsole = null;\r
- }\r
-\r
- if (netcom.IsLoggedIn)\r
- {\r
- Thread saveInvToDisk = new Thread(new ThreadStart(\r
- delegate()\r
- {\r
- client.Inventory.Store.SaveToDisk(instance.InventoryCacheFileName);\r
- }));\r
- saveInvToDisk.Name = "Save inventory to disk";\r
- saveInvToDisk.Start();\r
-\r
- netcom.Logout();\r
- }\r
- }\r
- #endregion\r
-\r
- # region Update status\r
-\r
- void Parcels_ParcelProperties(object sender, ParcelPropertiesEventArgs e)\r
- {\r
- if (e.Result != ParcelResult.Single) return;\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(() => Parcels_ParcelProperties(sender, e)));\r
- return;\r
- }\r
-\r
- Parcel parcel = e.Parcel;\r
-\r
- tlblParcel.Text = parcel.Name;\r
- tlblParcel.ToolTipText = parcel.Desc;\r
-\r
- if ((parcel.Flags & ParcelFlags.AllowFly) != ParcelFlags.AllowFly)\r
- icoNoFly.Visible = true;\r
- else\r
- icoNoFly.Visible = false;\r
-\r
- if ((parcel.Flags & ParcelFlags.CreateObjects) != ParcelFlags.CreateObjects)\r
- icoNoBuild.Visible = true;\r
- else\r
- icoNoBuild.Visible = false;\r
-\r
- if ((parcel.Flags & ParcelFlags.AllowOtherScripts) != ParcelFlags.AllowOtherScripts)\r
- icoNoScript.Visible = true;\r
- else\r
- icoNoScript.Visible = false;\r
-\r
- if ((parcel.Flags & ParcelFlags.RestrictPushObject) == ParcelFlags.RestrictPushObject)\r
- icoNoPush.Visible = true;\r
- else\r
- icoNoPush.Visible = false;\r
-\r
- if ((parcel.Flags & ParcelFlags.AllowDamage) == ParcelFlags.AllowDamage)\r
- icoHealth.Visible = true;\r
- else\r
- icoHealth.Visible = false;\r
-\r
- if ((parcel.Flags & ParcelFlags.AllowVoiceChat) != ParcelFlags.AllowVoiceChat)\r
- icoNoVoice.Visible = true;\r
- else\r
- icoNoVoice.Visible = false;\r
- }\r
-\r
- private void RefreshStatusBar()\r
- {\r
- if (netcom.IsLoggedIn)\r
- {\r
- tlblLoginName.Text = netcom.LoginOptions.FullName;\r
- tlblMoneyBalance.Text = client.Self.Balance.ToString();\r
- icoHealth.Text = client.Self.Health.ToString() + "%";\r
-\r
- tlblRegionInfo.Text =\r
- client.Network.CurrentSim.Name +\r
- " (" + Math.Floor(client.Self.SimPosition.X).ToString() + ", " +\r
- Math.Floor(client.Self.SimPosition.Y).ToString() + ", " +\r
- Math.Floor(client.Self.SimPosition.Z).ToString() + ")";\r
- }\r
- else\r
- {\r
- tlblLoginName.Text = "Offline";\r
- tlblMoneyBalance.Text = "0";\r
- icoHealth.Text = "0%";\r
- tlblRegionInfo.Text = "No Region";\r
- tlblParcel.Text = "No Parcel";\r
-\r
- icoHealth.Visible = false;\r
- icoNoBuild.Visible = false;\r
- icoNoFly.Visible = false;\r
- icoNoPush.Visible = false;\r
- icoNoScript.Visible = false;\r
- icoNoVoice.Visible = false;\r
- }\r
- }\r
-\r
- private void RefreshWindowTitle()\r
- {\r
- StringBuilder sb = new StringBuilder();\r
- sb.Append("Radegast - ");\r
-\r
- if (netcom.IsLoggedIn)\r
- {\r
- sb.Append("[" + netcom.LoginOptions.FullName + "]");\r
-\r
- if (instance.State.IsAway)\r
- {\r
- sb.Append(" - Away");\r
- if (instance.State.IsBusy) sb.Append(", Busy");\r
- }\r
- else if (instance.State.IsBusy)\r
- {\r
- sb.Append(" - Busy");\r
- }\r
-\r
- if (instance.State.IsFollowing)\r
- {\r
- sb.Append(" - Following ");\r
- sb.Append(instance.State.FollowName);\r
- }\r
- }\r
- else\r
- {\r
- sb.Append("Logged Out");\r
- }\r
-\r
- this.Text = sb.ToString();\r
- sb = null;\r
- }\r
-\r
- private void InitializeStatusTimer()\r
- {\r
- statusTimer = new System.Timers.Timer(250);\r
- statusTimer.SynchronizingObject = this;\r
- statusTimer.Elapsed += new ElapsedEventHandler(statusTimer_Elapsed);\r
- }\r
-\r
- private void statusTimer_Elapsed(object sender, ElapsedEventArgs e)\r
- {\r
- // Mono sometimes fires timer after is's disposed\r
- try\r
- {\r
- RefreshWindowTitle();\r
- RefreshStatusBar();\r
- }\r
- catch { }\r
- }\r
- #endregion\r
-\r
- #region Initialization, configuration, and key shortcuts\r
- private void InitializeTabsConsole()\r
- {\r
- tabsConsole = new TabsConsole(instance);\r
- tabsConsole.Dock = DockStyle.Fill;\r
- toolStripContainer1.ContentPanel.Controls.Add(tabsConsole);\r
- }\r
-\r
- private void frmMain_KeyDown(object sender, KeyEventArgs e)\r
- {\r
- // Ctl-Shift-H: Teleport Home\r
- if (e.Modifiers == (Keys.Control | Keys.Shift) && e.KeyCode == Keys.H)\r
- {\r
- e.Handled = e.SuppressKeyPress = true;\r
- tmnuTeleportHome.PerformClick();\r
- return;\r
- }\r
-\r
- // Alt 1-8: Toggle various tabs\r
- if (e.Modifiers == Keys.Alt)\r
- {\r
- switch (e.KeyCode)\r
- {\r
- case Keys.D1:\r
- e.Handled = e.SuppressKeyPress = true;\r
- tabsConsole.Tabs["chat"].Select();\r
- break;\r
-\r
- case Keys.D2:\r
- e.Handled = e.SuppressKeyPress = true;\r
- tbtnFriends.PerformClick();\r
- break;\r
-\r
- case Keys.D3:\r
- e.Handled = e.SuppressKeyPress = true;\r
- tbtnGroups.PerformClick();\r
- break;\r
-\r
- case Keys.D4:\r
- e.Handled = e.SuppressKeyPress = true;\r
- tbtnInventory.PerformClick();\r
- break;\r
-\r
- case Keys.D5:\r
- e.Handled = e.SuppressKeyPress = true;\r
- tbtnSearch.PerformClick();\r
- break;\r
-\r
- case Keys.D6:\r
- e.Handled = e.SuppressKeyPress = true;\r
- tbtnMap.PerformClick();\r
- break;\r
-\r
- case Keys.D7:\r
- e.Handled = e.SuppressKeyPress = true;\r
- tbnObjects.PerformClick();\r
- break;\r
-\r
- case Keys.D8:\r
- e.Handled = e.SuppressKeyPress = true;\r
- tbtnMedia.PerformClick();\r
- break;\r
-\r
- case Keys.D9:\r
- e.Handled = e.SuppressKeyPress = true;\r
- tbtnVoice.PerformClick();\r
- break;\r
- }\r
- }\r
-\r
- // ctrl-g, goto slurl\r
- if (e.Control && e.KeyCode == Keys.G)\r
- {\r
- if (!ProcessLink(Clipboard.GetText(), true))\r
- MapToCurrentLocation();\r
-\r
- e.Handled = e.SuppressKeyPress = true;\r
- return;\r
- }\r
-\r
- // ctrl-(shift)-tab for next/previous tab\r
- if (e.Control && e.KeyCode == Keys.Tab)\r
- {\r
- if (e.Shift)\r
- {\r
- TabConsole.SelectPreviousTab();\r
- }\r
- else\r
- {\r
- TabConsole.SelectNextTab();\r
- }\r
- e.Handled = e.SuppressKeyPress = true;\r
- return;\r
- }\r
- }\r
-\r
- private void frmMain_KeyUp(object sender, KeyEventArgs e)\r
- {\r
- }\r
-\r
- private void frmMain_Load(object sender, EventArgs e)\r
- {\r
- tabsConsole.SelectTab("login");\r
- ResourceManager rm = Properties.Resources.ResourceManager;\r
- ResourceSet set = rm.GetResourceSet(System.Globalization.CultureInfo.CurrentCulture, true, true);\r
- System.Collections.IDictionaryEnumerator de = set.GetEnumerator();\r
- while (de.MoveNext() == true)\r
- {\r
- if (de.Entry.Value is Image)\r
- {\r
- Bitmap bitMap = de.Entry.Value as Bitmap;\r
- ResourceImages.Images.Add(bitMap);\r
- ImageNames.Add(de.Entry.Key.ToString());\r
- }\r
- }\r
- StartUpdateCheck(false);\r
- }\r
- #endregion\r
-\r
- #region Public methods\r
-\r
- private Dictionary<UUID, frmProfile> shownProfiles = new Dictionary<UUID, frmProfile>();\r
-\r
- public void ShowAgentProfile(string name, UUID agentID)\r
- {\r
- lock (shownProfiles)\r
- {\r
- frmProfile profile = null;\r
- if (shownProfiles.TryGetValue(agentID, out profile))\r
- {\r
- profile.WindowState = FormWindowState.Normal;\r
- profile.Focus();\r
- }\r
- else\r
- {\r
- profile = new frmProfile(instance, name, agentID);\r
-\r
- profile.Disposed += (object sender, EventArgs e) =>\r
- {\r
- lock (shownProfiles)\r
- {\r
- frmProfile agentProfile = (frmProfile)sender;\r
- if (shownProfiles.ContainsKey(agentProfile.AgentID))\r
- shownProfiles.Remove(agentProfile.AgentID);\r
- }\r
- };\r
-\r
- profile.Show();\r
- profile.Focus();\r
- shownProfiles.Add(agentID, profile);\r
- }\r
- }\r
- }\r
-\r
- private Dictionary<UUID, frmGroupInfo> shownGroupProfiles = new Dictionary<UUID, frmGroupInfo>();\r
-\r
- public void ShowGroupProfile(OpenMetaverse.Group group)\r
- {\r
- lock (shownGroupProfiles)\r
- {\r
- frmGroupInfo profile = null;\r
- if (shownGroupProfiles.TryGetValue(group.ID, out profile))\r
- {\r
- profile.WindowState = FormWindowState.Normal;\r
- profile.Focus();\r
- }\r
- else\r
- {\r
- profile = new frmGroupInfo(instance, group);\r
-\r
- profile.Disposed += (object sender, EventArgs e) =>\r
- {\r
- lock (shownGroupProfiles)\r
- {\r
- frmGroupInfo groupProfile = (frmGroupInfo)sender;\r
- if (shownGroupProfiles.ContainsKey(groupProfile.Group.ID))\r
- shownGroupProfiles.Remove(groupProfile.Group.ID);\r
- }\r
- };\r
-\r
- profile.Show();\r
- profile.Focus();\r
- shownGroupProfiles.Add(group.ID, profile);\r
- }\r
- }\r
- }\r
-\r
- public void ProcessLink(string link)\r
- {\r
- ProcessLink(link, false);\r
- }\r
-\r
- public bool ProcessLink(string link, bool onlyMap)\r
- {\r
- if (!link.Contains("://"))\r
- {\r
- link = "http://" + link;\r
- }\r
-\r
- Regex r = new Regex(@"^(http://slurl.com/secondlife/|secondlife://)([^/]+)/(\d+)/(\d+)(/(\d+))?");\r
- Match m = r.Match(link);\r
-\r
- if (m.Success)\r
- {\r
- string region = HttpUtility.UrlDecode(m.Groups[2].Value);\r
- int x = int.Parse(m.Groups[3].Value);\r
- int y = int.Parse(m.Groups[4].Value);\r
- int z = 0;\r
-\r
- if (m.Groups.Count > 5 && m.Groups[6].Value != String.Empty)\r
- {\r
- z = int.Parse(m.Groups[6].Value);\r
- }\r
-\r
- MapTab.Select();\r
- WorldMap.DisplayLocation(region, x, y, z);\r
- return true;\r
- }\r
- else if (!onlyMap)\r
- {\r
- System.Diagnostics.Process.Start(link);\r
- }\r
- return false;\r
- }\r
- #endregion\r
-\r
- #region Notifications\r
- CircularList<Control> notifications = new CircularList<Control>();\r
-\r
- public Color NotificationBackground\r
- {\r
- get { return pnlDialog.BackColor; }\r
- }\r
-\r
- void ResizeNotificationByControl(Control active)\r
- {\r
- int Width = active.Size.Width + 6;\r
- int Height = notifications.Count > 1 ? active.Size.Height + 3 + btnDialogNextControl.Size.Height : active.Size.Height + 3;\r
- pnlDialog.Size = new Size(Width, Height);\r
- pnlDialog.Top = 0;\r
- pnlDialog.Left = pnlDialog.Parent.ClientSize.Width - Width;\r
-\r
- btnDialogNextControl.Top = btnDialogNextControl.Parent.ClientSize.Height - btnDialogNextControl.Size.Height;\r
- btnDialogNextControl.Left = btnDialogNextControl.Parent.ClientSize.Width - btnDialogNextControl.Size.Width;\r
-\r
- btnDialogNextControl.BringToFront();\r
- }\r
-\r
- public void AddNotification(Control control)\r
- {\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(delegate()\r
- {\r
- AddNotification(control);\r
- }\r
- ));\r
- return;\r
- }\r
-\r
- FormFlash.StartFlash(this);\r
- pnlDialog.Visible = true;\r
- pnlDialog.BringToFront();\r
-\r
- foreach (Control existing in notifications)\r
- {\r
- existing.Visible = false;\r
- }\r
-\r
- notifications.Add(control);\r
- control.Visible = true;\r
- control.Anchor = AnchorStyles.Top | AnchorStyles.Left;\r
- control.Top = 3;\r
- control.Left = 3;\r
- pnlDialog.Controls.Add(control);\r
- ResizeNotificationByControl(control);\r
-\r
- btnDialogNextControl.Visible = notifications.Count > 1;\r
- }\r
-\r
- public void RemoveNotification(Control control)\r
- {\r
- pnlDialog.Controls.Remove(control);\r
- notifications.Remove(control);\r
- control.Dispose();\r
-\r
- if (notifications.HasNext)\r
- {\r
- pnlDialog.Visible = true;\r
- Control active = notifications.Next;\r
- active.Visible = true;\r
- ResizeNotificationByControl(active);\r
- }\r
- else\r
- {\r
- pnlDialog.Visible = false;\r
- }\r
-\r
- btnDialogNextControl.Visible = notifications.Count > 1;\r
- }\r
-\r
- private void btnDialogNextControl_Click(object sender, EventArgs e)\r
- {\r
- foreach (Control existing in notifications)\r
- {\r
- existing.Visible = false;\r
- }\r
-\r
- if (notifications.HasNext)\r
- {\r
- pnlDialog.Visible = true;\r
- Control active = notifications.Next;\r
- active.Visible = true;\r
- ResizeNotificationByControl(active);\r
- }\r
- else\r
- {\r
- pnlDialog.Visible = false;\r
- }\r
-\r
- }\r
- #endregion Notifications\r
-\r
- #region Menu click handlers\r
-\r
- private void tbtnTeleport_Click(object sender, EventArgs e)\r
- {\r
- (new frmTeleport(instance)).ShowDialog();\r
- }\r
-\r
- private void tmnuStatusAway_Click(object sender, EventArgs e)\r
- {\r
- instance.State.SetAway(tmnuStatusAway.Checked);\r
- }\r
-\r
- private void tmnuHelpReadme_Click(object sender, EventArgs e)\r
- {\r
- System.Diagnostics.Process.Start(Application.StartupPath + @"\Readme.txt");\r
- }\r
-\r
- private void tmnuStatusBusy_Click(object sender, EventArgs e)\r
- {\r
- instance.State.SetBusy(tmnuStatusBusy.Checked);\r
- }\r
-\r
- private void tmnuControlFly_Click(object sender, EventArgs e)\r
- {\r
- instance.State.SetFlying(tmnuControlFly.Checked);\r
- }\r
-\r
- private void tmnuControlAlwaysRun_Click(object sender, EventArgs e)\r
- {\r
- instance.State.SetAlwaysRun(tmnuControlAlwaysRun.Checked);\r
- }\r
-\r
- private void tmnuPrefs_Click(object sender, EventArgs e)\r
- {\r
- (new frmSettings(instance)).ShowDialog();\r
- }\r
-\r
- private void tbtnAppearance_Click(object sender, EventArgs e)\r
- {\r
- client.Appearance.RequestSetAppearance(false);\r
- }\r
-\r
- private void importObjectToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- PrimDeserializer.ImportFromFile(client);\r
- }\r
-\r
- private void autopilotToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- if (ap == null)\r
- {\r
- ap = new AutoPilot(client);\r
- /*\r
- ap.InsertWaypoint(new Vector3(66, 163, 21));\r
- ap.InsertWaypoint(new Vector3(66, 98, 21));\r
-\r
- ap.InsertWaypoint(new Vector3(101, 98, 21));\r
- ap.InsertWaypoint(new Vector3(101, 45, 21));\r
- ap.InsertWaypoint(new Vector3(93, 27, 21));\r
- ap.InsertWaypoint(new Vector3(106, 12, 21));\r
- ap.InsertWaypoint(new Vector3(123, 24, 21));\r
- ap.InsertWaypoint(new Vector3(114, 45, 21));\r
- ap.InsertWaypoint(new Vector3(114, 98, 21));\r
-\r
- ap.InsertWaypoint(new Vector3(130, 98, 21));\r
- ap.InsertWaypoint(new Vector3(130, 163, 21));\r
- **/\r
- ap.InsertWaypoint(new Vector3(64, 68, 21));\r
- ap.InsertWaypoint(new Vector3(65, 20, 21));\r
- ap.InsertWaypoint(new Vector3(33, 23, 21));\r
- ap.InsertWaypoint(new Vector3(17, 39, 21));\r
- ap.InsertWaypoint(new Vector3(17, 62, 21));\r
-\r
-\r
- }\r
- if (AutoPilotActive)\r
- {\r
- AutoPilotActive = false;\r
- ap.Stop();\r
- }\r
- else\r
- {\r
- AutoPilotActive = true;\r
- ap.Start();\r
- }\r
-\r
- }\r
-\r
- private void cleanCacheToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- client.Assets.Cache.Clear();\r
- }\r
-\r
- private void rebakeTexturesToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- client.Appearance.RequestSetAppearance(true);\r
- }\r
-\r
- public void MapToCurrentLocation()\r
- {\r
- if (MapTab != null && client.Network.Connected)\r
- {\r
- MapTab.Select();\r
- WorldMap.DisplayLocation(client.Network.CurrentSim.Name,\r
- (int)client.Self.SimPosition.X,\r
- (int)client.Self.SimPosition.Y,\r
- (int)client.Self.SimPosition.Z);\r
- }\r
- }\r
-\r
- private void standToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- client.Self.Stand();\r
- }\r
-\r
- private void groundSitToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- client.Self.SitOnGround();\r
- }\r
-\r
- private void newWindowToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- try { System.Diagnostics.Process.Start(Application.ExecutablePath); }\r
- catch (Exception) { }\r
- }\r
-\r
- private void tmnuExit_Click(object sender, EventArgs e)\r
- {\r
- Close();\r
- }\r
-\r
- private void tlblRegionInfo_Click(object sender, EventArgs e)\r
- {\r
- if (WorldMap != null && client.Network.Connected)\r
- {\r
- MapTab.Select();\r
- }\r
- }\r
-\r
- private void scriptEditorToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- ScriptEditor se = new ScriptEditor(instance);\r
- se.Dock = DockStyle.Fill;\r
- se.ShowDetached();\r
- }\r
-\r
- private void tmnuSetHome_Click(object sender, EventArgs e)\r
- {\r
- client.Self.SetHome();\r
- }\r
-\r
- private void tmnuCreateLandmark_Click(object sender, EventArgs e)\r
- {\r
- string location = string.Format(", {0} ({1}, {2}, {3})",\r
- client.Network.CurrentSim.Name,\r
- (int)client.Self.SimPosition.X,\r
- (int)client.Self.SimPosition.Y,\r
- (int)client.Self.SimPosition.Z\r
- );\r
-\r
- string name = tlblParcel.Text;\r
- int maxLen = 63 - location.Length;\r
-\r
- if (name.Length > maxLen)\r
- name = name.Substring(0, maxLen);\r
-\r
- name += location;\r
-\r
- client.Inventory.RequestCreateItem(\r
- client.Inventory.FindFolderForType(AssetType.Landmark),\r
- name,\r
- tlblParcel.ToolTipText,\r
- AssetType.Landmark,\r
- UUID.Random(),\r
- InventoryType.Landmark,\r
- PermissionMask.All,\r
- (bool success, InventoryItem item) =>\r
- {\r
- if (success)\r
- {\r
- BeginInvoke(new MethodInvoker(() =>\r
- {\r
- Landmark ln = new Landmark(instance, (InventoryLandmark)item);\r
- ln.Dock = DockStyle.Fill;\r
- ln.Detached = true;\r
- }));\r
- }\r
- }\r
- );\r
- }\r
-\r
- private void tmnuTeleportHome_Click(object sender, EventArgs e)\r
- {\r
- if (WorldMap != null)\r
- {\r
- WorldMap.GoHome();\r
- }\r
- }\r
-\r
- private TimeZoneInfo SLTime;\r
-\r
- private void GetSLTimeZone()\r
- {\r
- try\r
- {\r
- foreach (TimeZoneInfo tz in TimeZoneInfo.GetSystemTimeZones())\r
- {\r
- if (tz.Id == "Pacific Standard Time" || tz.Id == "America/Los_Angeles")\r
- {\r
- SLTime = tz;\r
- break;\r
- }\r
- }\r
- }\r
- catch (Exception) { }\r
- }\r
-\r
- private void timerWorldClock_Tick(object sender, EventArgs e)\r
- {\r
- DateTime now;\r
- try\r
- {\r
- if (SLTime != null)\r
- now = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, SLTime);\r
- else\r
- now = DateTime.UtcNow.AddHours(-7);\r
- }\r
- catch (Exception)\r
- {\r
- now = DateTime.UtcNow.AddHours(-7);\r
- }\r
- lblTime.Text = now.ToString("h:mm tt", System.Globalization.CultureInfo.InvariantCulture);\r
- }\r
-\r
- private void reportBugsToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- ProcessLink("http://jira.openmetaverse.org/browse/RAD");\r
- }\r
-\r
- private void aboutRadegastToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- (new frmAbout(instance)).ShowDialog();\r
- }\r
-\r
- #region Update Checking\r
- private UpdateChecker updateChecker = null;\r
- private bool ManualUpdateCheck = false;\r
-\r
- public void StartUpdateCheck(bool userInitiated)\r
- {\r
- ManualUpdateCheck = userInitiated;\r
-\r
- if (updateChecker != null)\r
- {\r
- if (ManualUpdateCheck)\r
- tabsConsole.DisplayNotificationInChat("Update check already in progress.");\r
- return;\r
- }\r
-\r
- if (ManualUpdateCheck)\r
- tabsConsole.DisplayNotificationInChat("Checking for updates...", ChatBufferTextStyle.StatusBlue);\r
- updateChecker = new UpdateChecker();\r
- updateChecker.OnUpdateInfoReceived += new UpdateChecker.UpdateInfoCallback(OnUpdateInfoReceived);\r
- updateChecker.StartCheck();\r
- }\r
-\r
- private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- tabsConsole.SelectTab("chat");\r
- StartUpdateCheck(true);\r
- }\r
-\r
- void OnUpdateInfoReceived(object sender, UpdateCheckerArgs e)\r
- {\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(() => OnUpdateInfoReceived(sender, e)));\r
- return;\r
- }\r
-\r
- if (!e.Success)\r
- {\r
- if (ManualUpdateCheck)\r
- tabsConsole.DisplayNotificationInChat("Error: Failed connecting to the update site.", ChatBufferTextStyle.StatusBlue);\r
- }\r
- else\r
- {\r
- if (!ManualUpdateCheck && e.Info.DisplayMOTD)\r
- {\r
- tabsConsole.DisplayNotificationInChat(e.Info.MOTD, ChatBufferTextStyle.StatusBlue);\r
- }\r
-\r
- if (e.Info.UpdateAvailable)\r
- {\r
- tabsConsole.DisplayNotificationInChat("New version available at " + e.Info.DownloadSite, ChatBufferTextStyle.Alert);\r
- }\r
- else\r
- {\r
- if (ManualUpdateCheck)\r
- tabsConsole.DisplayNotificationInChat("Your version is up to date.", ChatBufferTextStyle.StatusBlue);\r
- }\r
- }\r
-\r
- updateChecker.Dispose();\r
- updateChecker = null;\r
- }\r
- #endregion\r
-\r
- private void ToggleHidden(string tabName)\r
- {\r
- if (!tabsConsole.TabExists(tabName)) return;\r
-\r
- RadegastTab tab = tabsConsole.Tabs[tabName];\r
-\r
- if (tab.Hidden)\r
- {\r
- tab.Show();\r
- }\r
- else\r
- {\r
- if (!tab.Selected)\r
- {\r
- tab.Select();\r
- }\r
- else\r
- {\r
- tab.Hide();\r
- }\r
- }\r
- }\r
-\r
- private void tbtnFriends_Click(object sender, EventArgs e)\r
- {\r
- ToggleHidden("friends");\r
- }\r
-\r
- private void tbtnInventory_Click(object sender, EventArgs e)\r
- {\r
- ToggleHidden("inventory");\r
- }\r
-\r
- private void tbtnSearch_Click(object sender, EventArgs e)\r
- {\r
- ToggleHidden("search");\r
- }\r
-\r
- private void tbtnGroups_Click(object sender, EventArgs e)\r
- {\r
- ToggleHidden("groups");\r
- }\r
-\r
- private void tbtnVoice_Click(object sender, EventArgs e)\r
- {\r
- ToggleHidden("voice");\r
- }\r
-\r
- private void tbtnMedia_Click(object sender, EventArgs e)\r
- {\r
- if (tabsConsole.TabExists("media"))\r
- {\r
- ToggleHidden("media");\r
- }\r
- else\r
- {\r
- RadegastTab tab = tabsConsole.AddTab("media", "Media", mediaConsole);\r
- tab.AllowClose = false;\r
- tab.AllowHide = true;\r
- tab.Select();\r
- }\r
- }\r
-\r
- private void tbnObjects_Click(object sender, EventArgs e)\r
- {\r
- if (tabsConsole.TabExists("objects"))\r
- {\r
- RadegastTab tab = tabsConsole.Tabs["objects"];\r
- if (!tab.Selected)\r
- {\r
- tab.Select();\r
- ((ObjectsConsole)tab.Control).RefreshObjectList();\r
- }\r
- else\r
- {\r
- tab.Close();\r
- }\r
- }\r
- else\r
- {\r
- RadegastTab tab = tabsConsole.AddTab("objects", "Objects", new ObjectsConsole(instance));\r
- tab.AllowClose = true;\r
- tab.AllowDetach = true;\r
- tab.Visible = true;\r
- tab.AllowHide = false;\r
- tab.Select();\r
- ((ObjectsConsole)tab.Control).RefreshObjectList();\r
- }\r
- }\r
-\r
- private void tbtnMap_Click(object sender, EventArgs e)\r
- {\r
- ToggleHidden("map");\r
- if (!MapTab.Hidden)\r
- MapToCurrentLocation();\r
- }\r
-\r
- private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- if (client.Network.Connected)\r
- client.Network.RequestLogout();\r
- }\r
-\r
- private void reconnectToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- instance.Reconnect();\r
- }\r
-\r
- private frmKeyboardShortcuts keyboardShortcutsForm = null;\r
- private void keyboardShortcutsToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- if (keyboardShortcutsForm != null)\r
- {\r
- keyboardShortcutsForm.Focus();\r
- }\r
- else\r
- {\r
- keyboardShortcutsForm = new frmKeyboardShortcuts(instance);\r
-\r
- keyboardShortcutsForm.Disposed += (object senderx, EventArgs ex) =>\r
- {\r
- if (components != null)\r
- {\r
- components.Remove(keyboardShortcutsForm);\r
- }\r
- keyboardShortcutsForm = null;\r
- };\r
-\r
- keyboardShortcutsForm.Show(this);\r
- keyboardShortcutsForm.Top = Top + 100;\r
- keyboardShortcutsForm.Left = Left + 100;\r
-\r
- if (components != null)\r
- {\r
- components.Add(keyboardShortcutsForm);\r
- }\r
- }\r
- }\r
-\r
- // Menu item for testing out stuff\r
- private void testToolStripMenuItem_Click(object sender, EventArgs e)\r
- {\r
- foreach (KeyValuePair<UUID, string> kvp in Sounds.ToDictionary())\r
- {\r
- client.Assets.RequestAsset(kvp.Key, AssetType.Sound, true, (AssetDownload transfer, Asset asset) =>\r
- {\r
- System.Console.WriteLine("Sound '{0}' download success: {1}", transfer.AssetID, transfer.Success);\r
- }\r
- );\r
- }\r
- }\r
-\r
- #endregion\r
- }\r
+//
+// Radegast Metaverse Client
+// Copyright (c) 2009-2014, Radegast Development Team
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of the application "Radegast", nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// $Id$
+//
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Timers;
+#if (COGBOT_LIBOMV || USE_STHREADS)
+using ThreadPoolUtil;
+using Thread = ThreadPoolUtil.Thread;
+using ThreadPool = ThreadPoolUtil.ThreadPool;
+using Monitor = ThreadPoolUtil.Monitor;
+#endif
+using System.Threading;
+
+using System.Windows.Forms;
+using System.Resources;
+using System.IO;
+using System.Web;
+using Radegast.Netcom;
+using OpenMetaverse;
+using OpenMetaverse.StructuredData;
+using OpenMetaverse.Assets;
+
+namespace Radegast
+{
+ public partial class frmMain : RadegastForm
+ {
+ #region Public members
+ public static ImageList ResourceImages = new ImageList();
+ public static List<string> ImageNames = new List<string>();
+ public bool PreventParcelUpdate = false;
+ public delegate void ProfileHandlerDelegate(string agentName, UUID agentID);
+ public ProfileHandlerDelegate ShowAgentProfile;
+
+ public TabsConsole TabConsole
+ {
+ get { return tabsConsole; }
+ }
+
+ public MapConsole WorldMap
+ {
+ get
+ {
+ if (MapTab != null)
+ {
+ return (MapConsole)MapTab.Control;
+ }
+ return null;
+ }
+ }
+
+ public RadegastTab MapTab
+ {
+ get
+ {
+ if (tabsConsole.TabExists("map"))
+ {
+ return tabsConsole.Tabs["map"];
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+
+ public MediaConsole MediaConsole { get { return mediaConsole; } }
+
+ /// <summary>
+ /// Drop down that contains the tools menu
+ /// </summary>
+ public ToolStripDropDownButton ToolsMenu
+ {
+ get { return tbnTools; }
+ }
+
+ /// <summary>
+ /// Dropdown that contains the heelp menu
+ /// </summary>
+ public ToolStripDropDownButton HelpMenu
+ {
+ get { return tbtnHelp; }
+ }
+
+ /// <summary>
+ /// Drop down that contants the plugins menu. Make sure to set it Visible if
+ /// you add items to this menu, it's hidden by default
+ /// </summary>
+ public ToolStripDropDownButton PluginsMenu
+ {
+ get { return tbnPlugins; }
+ }
+
+ #endregion
+
+ #region Private members
+ private RadegastInstance instance;
+ private GridClient client { get { return instance.Client; } }
+ private RadegastNetcom netcom { get { return instance.Netcom; } }
+ private TabsConsole tabsConsole;
+ private System.Timers.Timer statusTimer;
+ private AutoPilot ap;
+ private bool AutoPilotActive = false;
+ private TransparentButton btnDialogNextControl;
+ private MediaConsole mediaConsole;
+ private SlUriParser uriParser;
+ #endregion
+
+ #region Constructor and disposal
+ public frmMain(RadegastInstance instance)
+ : base(instance)
+ {
+ InitializeComponent();
+ Disposed += new EventHandler(frmMain_Disposed);
+
+ this.instance = instance;
+ this.instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);
+ netcom.NetcomSync = this;
+ ShowAgentProfile = ShowAgentProfileInternal;
+
+ pnlDialog.Visible = false;
+ btnDialogNextControl = new TransparentButton();
+ pnlDialog.Controls.Add(btnDialogNextControl);
+ pnlDialog.Top = 0;
+
+ btnDialogNextControl.Size = new Size(35, 20);
+ btnDialogNextControl.BackColor = Color.Transparent;
+ btnDialogNextControl.ForeColor = Color.Gold;
+ btnDialogNextControl.FlatAppearance.BorderSize = 0;
+ btnDialogNextControl.FlatStyle = FlatStyle.Flat;
+ btnDialogNextControl.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
+ btnDialogNextControl.Text = ">>";
+ btnDialogNextControl.Font = new Font(btnDialogNextControl.Font, FontStyle.Bold);
+ btnDialogNextControl.Margin = new Padding(0);
+ btnDialogNextControl.Padding = new Padding(0);
+ btnDialogNextControl.UseVisualStyleBackColor = false;
+ btnDialogNextControl.Top = btnDialogNextControl.Parent.ClientSize.Height - btnDialogNextControl.Size.Height;
+ btnDialogNextControl.Left = btnDialogNextControl.Parent.ClientSize.Width - btnDialogNextControl.Size.Width;
+ btnDialogNextControl.Click += new EventHandler(btnDialogNextControl_Click);
+
+ if (instance.MonoRuntime)
+ {
+ statusStrip1.LayoutStyle = ToolStripLayoutStyle.Table;
+ }
+
+ // Callbacks
+ netcom.ClientLoginStatus += new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);
+ netcom.ClientLoggedOut += new EventHandler(netcom_ClientLoggedOut);
+ netcom.ClientDisconnected += new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);
+ instance.Names.NameUpdated += new EventHandler<UUIDNameReplyEventArgs>(Names_NameUpdated);
+ RegisterClientEvents(client);
+
+ InitializeStatusTimer();
+ RefreshWindowTitle();
+ }
+
+ private void RegisterClientEvents(GridClient client)
+ {
+ client.Parcels.ParcelProperties += new EventHandler<ParcelPropertiesEventArgs>(Parcels_ParcelProperties);
+ client.Self.MoneyBalanceReply += new EventHandler<MoneyBalanceReplyEventArgs>(Self_MoneyBalanceReply);
+ client.Self.MoneyBalance += new EventHandler<BalanceEventArgs>(Self_MoneyBalance);
+ }
+
+ private void UnregisterClientEvents(GridClient client)
+ {
+ client.Parcels.ParcelProperties -= new EventHandler<ParcelPropertiesEventArgs>(Parcels_ParcelProperties);
+ client.Self.MoneyBalanceReply -= new EventHandler<MoneyBalanceReplyEventArgs>(Self_MoneyBalanceReply);
+ client.Self.MoneyBalance -= new EventHandler<BalanceEventArgs>(Self_MoneyBalance);
+ }
+
+ void instance_ClientChanged(object sender, ClientChangedEventArgs e)
+ {
+ UnregisterClientEvents(e.OldClient);
+ RegisterClientEvents(client);
+ }
+
+ void frmMain_Disposed(object sender, EventArgs e)
+ {
+ if (netcom != null)
+ {
+ netcom.NetcomSync = null;
+ netcom.ClientLoginStatus -= new EventHandler<LoginProgressEventArgs>(netcom_ClientLoginStatus);
+ netcom.ClientLoggedOut -= new EventHandler(netcom_ClientLoggedOut);
+ netcom.ClientDisconnected -= new EventHandler<DisconnectedEventArgs>(netcom_ClientDisconnected);
+ }
+
+ if (client != null)
+ {
+ UnregisterClientEvents(client);
+ }
+
+ if (instance != null && instance.Names != null)
+ {
+ instance.Names.NameUpdated -= new EventHandler<UUIDNameReplyEventArgs>(Names_NameUpdated);
+ }
+
+ this.instance.CleanUp();
+ }
+ #endregion
+
+ #region Event handlers
+ bool firstMoneyNotification = true;
+ void Self_MoneyBalance(object sender, BalanceEventArgs e)
+ {
+ int oldBalance = 0;
+ int.TryParse(tlblMoneyBalance.Text, out oldBalance);
+ int delta = Math.Abs(oldBalance - e.Balance);
+
+ if (firstMoneyNotification)
+ {
+ firstMoneyNotification = false;
+ }
+ else
+ {
+ if (delta > 50)
+ {
+ if (oldBalance > e.Balance)
+ {
+ instance.MediaManager.PlayUISound(UISounds.MoneyIn);
+ }
+ else
+ {
+ instance.MediaManager.PlayUISound(UISounds.MoneyOut);
+ }
+ }
+ }
+ }
+
+ void Names_NameUpdated(object sender, UUIDNameReplyEventArgs e)
+ {
+ if (!e.Names.ContainsKey(client.Self.AgentID)) return;
+
+ if (InvokeRequired)
+ {
+ if (IsHandleCreated || !instance.MonoRuntime)
+ {
+ BeginInvoke(new MethodInvoker(() => Names_NameUpdated(sender, e)));
+ }
+ return;
+ }
+
+ RefreshWindowTitle();
+ RefreshStatusBar();
+ }
+
+ void Self_MoneyBalanceReply(object sender, MoneyBalanceReplyEventArgs e)
+ {
+ if (!String.IsNullOrEmpty(e.Description))
+ {
+ if (instance.GlobalSettings["transaction_notification_dialog"].AsBoolean())
+ AddNotification(new ntfGeneric(instance, e.Description));
+ if (instance.GlobalSettings["transaction_notification_chat"].AsBoolean())
+ TabConsole.DisplayNotificationInChat(e.Description);
+ }
+ }
+
+ public void InitializeControls()
+ {
+ InitializeTabsConsole();
+ uriParser = new SlUriParser();
+
+ if (instance.MediaManager.SoundSystemAvailable)
+ {
+ mediaConsole = new MediaConsole(instance);
+ tbtnMedia.Visible = true;
+ }
+ }
+
+ public bool InAutoReconnect { get; set; }
+
+ private void DisplayAutoReconnectForm()
+ {
+ if (IsDisposed) return;
+
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(DisplayAutoReconnectForm));
+ return;
+ }
+
+ InAutoReconnect = true;
+ frmReconnect dialog = new frmReconnect(instance, instance.GlobalSettings["reconnect_time"]);
+ dialog.ShowDialog(this);
+ dialog.Dispose();
+ dialog = null;
+ }
+
+ public void BeginAutoReconnect()
+ {
+ // Sleep for 3 seconds on a separate thread while things unwind on
+ // disconnect, since ShowDialog() blocks GUI thread
+ (new Thread(new ThreadStart(() =>
+ {
+ System.Threading.Thread.Sleep(3000);
+ DisplayAutoReconnectForm();
+ }
+ ))
+ {
+ Name = "Reconnect Delay Thread",
+ IsBackground = true
+ }
+ ).Start();
+ }
+
+ private void netcom_ClientLoginStatus(object sender, LoginProgressEventArgs e)
+ {
+ if (e.Status == LoginStatus.Failed)
+ {
+ if (InAutoReconnect)
+ {
+ if (instance.GlobalSettings["auto_reconnect"].AsBoolean() && e.FailReason != "tos")
+ BeginAutoReconnect();
+ else
+ InAutoReconnect = false;
+ }
+ }
+ else if (e.Status == LoginStatus.Success)
+ {
+ InAutoReconnect = false;
+ reconnectToolStripMenuItem.Enabled = false;
+ loginToolStripMenuItem.Enabled = false;
+ tsb3D.Enabled = tbtnVoice.Enabled = disconnectToolStripMenuItem.Enabled =
+ tbtnGroups.Enabled = tbnObjects.Enabled = tbtnWorld.Enabled = tbnTools.Enabled = tmnuImport.Enabled =
+ tbtnFriends.Enabled = tbtnInventory.Enabled = tbtnSearch.Enabled = tbtnMap.Enabled = true;
+
+ statusTimer.Start();
+ RefreshWindowTitle();
+ }
+ }
+
+ private void netcom_ClientLoggedOut(object sender, EventArgs e)
+ {
+ tsb3D.Enabled = tbtnVoice.Enabled = disconnectToolStripMenuItem.Enabled =
+ tbtnGroups.Enabled = tbnObjects.Enabled = tbtnWorld.Enabled = tbnTools.Enabled = tmnuImport.Enabled =
+ tbtnFriends.Enabled = tbtnInventory.Enabled = tbtnSearch.Enabled = tbtnMap.Enabled = false;
+
+ reconnectToolStripMenuItem.Enabled = true;
+ loginToolStripMenuItem.Enabled = true;
+ InAutoReconnect = false;
+
+ if (statusTimer != null)
+ statusTimer.Stop();
+
+ RefreshStatusBar();
+ RefreshWindowTitle();
+ }
+
+ private void netcom_ClientDisconnected(object sender, DisconnectedEventArgs e)
+ {
+ firstMoneyNotification = true;
+
+ if (e.Reason == NetworkManager.DisconnectType.ClientInitiated) return;
+ netcom_ClientLoggedOut(sender, EventArgs.Empty);
+
+ if (instance.GlobalSettings["auto_reconnect"].AsBoolean())
+ {
+ BeginAutoReconnect();
+ }
+ }
+
+ private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ if (statusTimer != null)
+ {
+ statusTimer.Stop();
+ statusTimer.Dispose();
+ statusTimer = null;
+ }
+
+ if (mediaConsole != null)
+ {
+ if (tabsConsole.TabExists("media"))
+ {
+ tabsConsole.Tabs["media"].AllowClose = true;
+ tabsConsole.Tabs["media"].Close();
+ }
+ else
+ {
+ mediaConsole.Dispose();
+ }
+ mediaConsole = null;
+ }
+
+ if (netcom.IsLoggedIn)
+ {
+ Thread saveInvToDisk = new Thread(new ThreadStart(
+ delegate()
+ {
+ client.Inventory.Store.SaveToDisk(instance.InventoryCacheFileName);
+ }));
+ saveInvToDisk.Name = "Save inventory to disk";
+ saveInvToDisk.Start();
+
+ netcom.Logout();
+ }
+ }
+ #endregion
+
+ # region Update status
+
+ void Parcels_ParcelProperties(object sender, ParcelPropertiesEventArgs e)
+ {
+ if (PreventParcelUpdate || e.Result != ParcelResult.Single) return;
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(() => Parcels_ParcelProperties(sender, e)));
+ return;
+ }
+
+ Parcel parcel = instance.State.Parcel = e.Parcel;
+
+ tlblParcel.Text = parcel.Name;
+ tlblParcel.ToolTipText = parcel.Desc;
+
+ if ((parcel.Flags & ParcelFlags.AllowFly) != ParcelFlags.AllowFly)
+ icoNoFly.Visible = true;
+ else
+ icoNoFly.Visible = false;
+
+ if ((parcel.Flags & ParcelFlags.CreateObjects) != ParcelFlags.CreateObjects)
+ icoNoBuild.Visible = true;
+ else
+ icoNoBuild.Visible = false;
+
+ if ((parcel.Flags & ParcelFlags.AllowOtherScripts) != ParcelFlags.AllowOtherScripts)
+ icoNoScript.Visible = true;
+ else
+ icoNoScript.Visible = false;
+
+ if ((parcel.Flags & ParcelFlags.RestrictPushObject) == ParcelFlags.RestrictPushObject)
+ icoNoPush.Visible = true;
+ else
+ icoNoPush.Visible = false;
+
+ if ((parcel.Flags & ParcelFlags.AllowDamage) == ParcelFlags.AllowDamage)
+ icoHealth.Visible = true;
+ else
+ icoHealth.Visible = false;
+
+ if ((parcel.Flags & ParcelFlags.AllowVoiceChat) != ParcelFlags.AllowVoiceChat)
+ icoNoVoice.Visible = true;
+ else
+ icoNoVoice.Visible = false;
+ }
+
+ private void RefreshStatusBar()
+ {
+ if (netcom.IsLoggedIn)
+ {
+ tlblLoginName.Text = instance.Names.Get(client.Self.AgentID, client.Self.Name);
+ tlblMoneyBalance.Text = client.Self.Balance.ToString();
+ icoHealth.Text = client.Self.Health.ToString() + "%";
+
+ var cs = client.Network.CurrentSim;
+ tlblRegionInfo.Text =
+ (cs == null ? "No region" : cs.Name) +
+ " (" + Math.Floor(client.Self.SimPosition.X).ToString() + ", " +
+ Math.Floor(client.Self.SimPosition.Y).ToString() + ", " +
+ Math.Floor(client.Self.SimPosition.Z).ToString() + ")";
+ }
+ else
+ {
+ tlblLoginName.Text = "Offline";
+ tlblMoneyBalance.Text = "0";
+ icoHealth.Text = "0%";
+ tlblRegionInfo.Text = "No Region";
+ tlblParcel.Text = "No Parcel";
+
+ icoHealth.Visible = false;
+ icoNoBuild.Visible = false;
+ icoNoFly.Visible = false;
+ icoNoPush.Visible = false;
+ icoNoScript.Visible = false;
+ icoNoVoice.Visible = false;
+ }
+ }
+
+ private void RefreshWindowTitle()
+ {
+ string name = instance.Names.Get(client.Self.AgentID, client.Self.Name);
+ StringBuilder sb = new StringBuilder();
+ sb.Append("Radegast - ");
+
+ if (netcom.IsLoggedIn)
+ {
+ sb.Append("[" + name + "]");
+
+ if (instance.State.IsAway)
+ {
+ sb.Append(" - Away");
+ if (instance.State.IsBusy) sb.Append(", Busy");
+ }
+ else if (instance.State.IsBusy)
+ {
+ sb.Append(" - Busy");
+ }
+
+ if (instance.State.IsFollowing)
+ {
+ sb.Append(" - Following ");
+ sb.Append(instance.State.FollowName);
+ }
+ }
+ else
+ {
+ sb.Append("Logged Out");
+ }
+
+ this.Text = sb.ToString();
+
+ // When minimized to tray, update tray tool tip also
+ if (WindowState == FormWindowState.Minimized && instance.GlobalSettings["minimize_to_tray"])
+ {
+ trayIcon.Text = sb.ToString();
+ ctxTrayMenuLabel.Text = sb.ToString();
+ }
+
+ sb = null;
+ }
+
+ private void InitializeStatusTimer()
+ {
+ statusTimer = new System.Timers.Timer(250);
+ statusTimer.SynchronizingObject = this;
+ statusTimer.Elapsed += new ElapsedEventHandler(statusTimer_Elapsed);
+ }
+
+ private void statusTimer_Elapsed(object sender, ElapsedEventArgs e)
+ {
+ // Mono sometimes fires timer after is's disposed
+ try
+ {
+ RefreshWindowTitle();
+ RefreshStatusBar();
+ }
+ catch { }
+ }
+ #endregion
+
+ #region Initialization, configuration, and key shortcuts
+ private void InitializeTabsConsole()
+ {
+ tabsConsole = new TabsConsole(instance);
+ tabsConsole.Dock = DockStyle.Fill;
+ toolStripContainer1.ContentPanel.Controls.Add(tabsConsole);
+ }
+
+ private void frmMain_KeyDown(object sender, KeyEventArgs e)
+ {
+ // Ctrl-Alt-Shift-H Say "Hippos!" in chat
+ if (e.Modifiers == (Keys.Control | Keys.Shift | Keys.Alt) && e.KeyCode == Keys.H)
+ {
+ e.Handled = e.SuppressKeyPress = true;
+ netcom.ChatOut("Hippos!", ChatType.Normal, 0);
+ return;
+ }
+
+ // Ctrl-Shift-1 (sim/parcel info)
+ if (e.Modifiers == (Keys.Control | Keys.Shift) && e.KeyCode == Keys.D1)
+ {
+ e.Handled = e.SuppressKeyPress = true;
+ DisplayRegionParcelConsole();
+ return;
+ }
+
+ // Ctrl-W: Close tab
+ if (e.Modifiers == Keys.Control && e.KeyCode == Keys.W)
+ {
+ e.Handled = e.SuppressKeyPress = true;
+ RadegastTab tab = tabsConsole.SelectedTab;
+
+ if (tab.AllowClose)
+ {
+ tab.Close();
+ }
+ else if (tab.AllowHide)
+ {
+ tab.Hide();
+ }
+
+ return;
+ }
+
+ // Ctl-Shift-H: Teleport Home
+ if (e.Modifiers == (Keys.Control | Keys.Shift) && e.KeyCode == Keys.H)
+ {
+ e.Handled = e.SuppressKeyPress = true;
+ tmnuTeleportHome.PerformClick();
+ return;
+ }
+
+ // Alt-Ctrl-D Open debug console
+ if (e.Modifiers == (Keys.Control | Keys.Alt) && e.KeyCode == Keys.D)
+ {
+ e.Handled = e.SuppressKeyPress = true;
+ debugConsoleToolStripMenuItem.PerformClick();
+ return;
+ }
+
+ // Alt 1-8: Toggle various tabs
+ if (e.Modifiers == Keys.Alt)
+ {
+ switch (e.KeyCode)
+ {
+ case Keys.D1:
+ e.Handled = e.SuppressKeyPress = true;
+ tabsConsole.Tabs["chat"].Select();
+ return;
+
+ case Keys.D2:
+ e.Handled = e.SuppressKeyPress = true;
+ tbtnFriends.PerformClick();
+ return;
+
+ case Keys.D3:
+ e.Handled = e.SuppressKeyPress = true;
+ tbtnGroups.PerformClick();
+ return;
+
+ case Keys.D4:
+ e.Handled = e.SuppressKeyPress = true;
+ tbtnInventory.PerformClick();
+ return;
+
+ case Keys.D5:
+ e.Handled = e.SuppressKeyPress = true;
+ tbtnSearch.PerformClick();
+ return;
+
+ case Keys.D6:
+ e.Handled = e.SuppressKeyPress = true;
+ tbtnMap.PerformClick();
+ return;
+
+ case Keys.D7:
+ e.Handled = e.SuppressKeyPress = true;
+ tbnObjects.PerformClick();
+ return;
+
+ case Keys.D8:
+ e.Handled = e.SuppressKeyPress = true;
+ tbtnMedia.PerformClick();
+ return;
+
+ case Keys.D9:
+ e.Handled = e.SuppressKeyPress = true;
+ tbtnVoice.PerformClick();
+ return;
+ }
+ }
+
+ // ctrl-g, goto slurl
+ if (e.Control && e.KeyCode == Keys.G)
+ {
+ if (!ProcessLink(Clipboard.GetText(), true))
+ MapToCurrentLocation();
+
+ e.Handled = e.SuppressKeyPress = true;
+ return;
+ }
+
+ // ctrl-(shift)-tab for next/previous tab
+ if (e.Control && e.KeyCode == Keys.Tab)
+ {
+ if (e.Shift)
+ {
+ TabConsole.SelectPreviousTab();
+ }
+ else
+ {
+ TabConsole.SelectNextTab();
+ }
+ e.Handled = e.SuppressKeyPress = true;
+ return;
+ }
+ }
+
+ bool firstLoad = true;
+
+ private void frmMain_Load(object sender, EventArgs e)
+ {
+ if (firstLoad)
+ {
+ firstLoad = false;
+ tabsConsole.SelectTab("login");
+ ResourceManager rm = Properties.Resources.ResourceManager;
+ ResourceSet set = rm.GetResourceSet(System.Globalization.CultureInfo.CurrentCulture, true, true);
+ System.Collections.IDictionaryEnumerator de = set.GetEnumerator();
+ while (de.MoveNext() == true)
+ {
+ if (de.Entry.Value is Image)
+ {
+ Bitmap bitMap = de.Entry.Value as Bitmap;
+ ResourceImages.Images.Add(bitMap);
+ ImageNames.Add(de.Entry.Key.ToString());
+ }
+ }
+ StartUpdateCheck(false);
+
+ if (instance.PlainColors)
+ {
+ pnlDialog.BackColor = System.Drawing.Color.FromArgb(120, 220, 255);
+ }
+
+ }
+ }
+ #endregion
+
+ #region Public methods
+
+ private Dictionary<UUID, frmProfile> shownProfiles = new Dictionary<UUID, frmProfile>();
+
+ void ShowAgentProfileInternal(string name, UUID agentID)
+ {
+ lock (shownProfiles)
+ {
+ frmProfile profile = null;
+ if (shownProfiles.TryGetValue(agentID, out profile))
+ {
+ profile.WindowState = FormWindowState.Normal;
+ profile.Focus();
+ }
+ else
+ {
+ profile = new frmProfile(instance, name, agentID);
+
+ profile.Disposed += (object sender, EventArgs e) =>
+ {
+ lock (shownProfiles)
+ {
+ frmProfile agentProfile = (frmProfile)sender;
+ if (shownProfiles.ContainsKey(agentProfile.AgentID))
+ shownProfiles.Remove(agentProfile.AgentID);
+ }
+ };
+
+ profile.Show();
+ profile.Focus();
+ shownProfiles.Add(agentID, profile);
+ }
+ }
+ }
+
+ private Dictionary<UUID, frmGroupInfo> shownGroupProfiles = new Dictionary<UUID, frmGroupInfo>();
+
+ public void ShowGroupProfile(UUID id)
+ {
+ ShowGroupProfile(new OpenMetaverse.Group()
+ {
+ ID = id,
+ });
+ }
+
+ public void ShowGroupProfile(AvatarGroup group)
+ {
+ ShowGroupProfile(new OpenMetaverse.Group()
+ {
+ ID = group.GroupID,
+ InsigniaID = group.GroupInsigniaID,
+ Name = group.GroupName
+ }
+ );
+ }
+
+ public void ShowGroupProfile(OpenMetaverse.Group group)
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(() => ShowGroupProfile(group)));
+ return;
+ }
+
+ lock (shownGroupProfiles)
+ {
+ frmGroupInfo profile = null;
+ if (shownGroupProfiles.TryGetValue(group.ID, out profile))
+ {
+ profile.WindowState = FormWindowState.Normal;
+ profile.Focus();
+ }
+ else
+ {
+ profile = new frmGroupInfo(instance, group);
+
+ profile.Disposed += (object sender, EventArgs e) =>
+ {
+ lock (shownGroupProfiles)
+ {
+ frmGroupInfo groupProfile = (frmGroupInfo)sender;
+ if (shownGroupProfiles.ContainsKey(groupProfile.Group.ID))
+ shownGroupProfiles.Remove(groupProfile.Group.ID);
+ }
+ };
+
+ profile.Show();
+ profile.Focus();
+ shownGroupProfiles.Add(group.ID, profile);
+ }
+ }
+ }
+
+ public bool ProcessSecondlifeURI(string link)
+ {
+ uriParser.ExecuteLink(link);
+ return true;
+ }
+
+ public void ProcessLink(string link)
+ {
+ ProcessLink(link, false);
+ }
+
+ public bool ProcessLink(string link, bool onlyMap)
+ {
+ var pos = link.IndexOf(RRichTextBox.LinkSeparator);
+ if (pos > 0)
+ {
+ link = link.Substring(pos + 1);
+ }
+
+ if (link.StartsWith("secondlife://") || link.StartsWith("[secondlife://"))
+ {
+ return ProcessSecondlifeURI(link);
+ }
+
+ if (!link.Contains("://"))
+ {
+ link = "http://" + link;
+ }
+
+ Regex r = new Regex(@"^(http://(slurl\.com|maps\.secondlife\.com)/secondlife/|secondlife://)(?<region>[^/]+)/(?<x>\d+)/(?<y>\d+)(/(?<z>\d+))?",
+ RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase
+ );
+ Match m = r.Match(link);
+
+ if (m.Success)
+ {
+ string region = HttpUtility.UrlDecode(m.Groups["region"].Value);
+ int x = int.Parse(m.Groups["x"].Value);
+ int y = int.Parse(m.Groups["y"].Value);
+ int z = 0;
+
+ if (!string.IsNullOrEmpty(m.Groups["z"].Value))
+ {
+ z = int.Parse(m.Groups["z"].Value);
+ }
+
+ MapTab.Select();
+ WorldMap.DisplayLocation(region, x, y, z);
+ return true;
+ }
+ else if (!onlyMap)
+ {
+ System.Diagnostics.Process.Start(link);
+ }
+ return false;
+ }
+ #endregion
+
+ #region Notifications
+ CircularList<Control> notifications = new CircularList<Control>();
+
+ public Color NotificationBackground
+ {
+ get { return pnlDialog.BackColor; }
+ }
+
+ void ResizeNotificationByControl(Control active)
+ {
+ int Width = active.Size.Width + 6;
+ int Height = notifications.Count > 1 ? active.Size.Height + 3 + btnDialogNextControl.Size.Height : active.Size.Height + 3;
+ pnlDialog.Size = new Size(Width, Height);
+ pnlDialog.Top = 0;
+ pnlDialog.Left = pnlDialog.Parent.ClientSize.Width - Width;
+
+ btnDialogNextControl.Top = btnDialogNextControl.Parent.ClientSize.Height - btnDialogNextControl.Size.Height;
+ btnDialogNextControl.Left = btnDialogNextControl.Parent.ClientSize.Width - btnDialogNextControl.Size.Width;
+
+ btnDialogNextControl.BringToFront();
+ }
+
+ public void AddNotification(Control control)
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(delegate()
+ {
+ AddNotification(control);
+ }
+ ));
+ return;
+ }
+
+ Control active = TabsConsole.FindFocusedControl(this);
+
+ FormFlash.StartFlash(this);
+ pnlDialog.Visible = true;
+ pnlDialog.BringToFront();
+
+ foreach (Control existing in notifications)
+ {
+ existing.Visible = false;
+ }
+
+ notifications.Add(control);
+ control.Visible = true;
+ control.Anchor = AnchorStyles.Top | AnchorStyles.Left;
+ control.Top = 3;
+ control.Left = 3;
+ pnlDialog.Controls.Add(control);
+ ResizeNotificationByControl(control);
+
+ btnDialogNextControl.Visible = notifications.Count > 1;
+
+ if (active != null)
+ {
+ active.Focus();
+ }
+ }
+
+ public void RemoveNotification(Control control)
+ {
+ pnlDialog.Controls.Remove(control);
+ notifications.Remove(control);
+ control.Dispose();
+
+ if (notifications.HasNext)
+ {
+ pnlDialog.Visible = true;
+ Control active = notifications.Next;
+ active.Visible = true;
+ ResizeNotificationByControl(active);
+ }
+ else
+ {
+ pnlDialog.Visible = false;
+ }
+
+ btnDialogNextControl.Visible = notifications.Count > 1;
+ }
+
+ private void btnDialogNextControl_Click(object sender, EventArgs e)
+ {
+ foreach (Control existing in notifications)
+ {
+ existing.Visible = false;
+ }
+
+ if (notifications.HasNext)
+ {
+ pnlDialog.Visible = true;
+ Control active = notifications.Next;
+ active.Visible = true;
+ ResizeNotificationByControl(active);
+ }
+ else
+ {
+ pnlDialog.Visible = false;
+ }
+
+ }
+ #endregion Notifications
+
+ #region Menu click handlers
+
+ private void tmnuStatusAway_Click(object sender, EventArgs e)
+ {
+ instance.State.SetAway(tmnuStatusAway.Checked);
+ }
+
+ private void tmnuHelpReadme_Click(object sender, EventArgs e)
+ {
+ System.Diagnostics.Process.Start(Application.StartupPath + @"\Readme.txt");
+ }
+
+ private void tmnuStatusBusy_Click(object sender, EventArgs e)
+ {
+ instance.State.SetBusy(tmnuStatusBusy.Checked);
+ }
+
+ private void tmnuControlFly_Click(object sender, EventArgs e)
+ {
+ instance.State.SetFlying(tmnuControlFly.Checked);
+ }
+
+ private void tmnuControlAlwaysRun_Click(object sender, EventArgs e)
+ {
+ instance.State.SetAlwaysRun(tmnuControlAlwaysRun.Checked);
+ }
+
+ private void tmnuPrefs_Click(object sender, EventArgs e)
+ {
+ (new frmSettings(instance)).ShowDialog();
+ }
+
+ private void tbtnAppearance_Click(object sender, EventArgs e)
+ {
+ client.Appearance.RequestSetAppearance(false);
+ }
+
+ private void importObjectToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ //PrimDeserializer.ImportFromFile(client);
+ DisplayImportConsole();
+ }
+
+ private void autopilotToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (ap == null)
+ {
+ ap = new AutoPilot(client);
+ /*
+ ap.InsertWaypoint(new Vector3(66, 163, 21));
+ ap.InsertWaypoint(new Vector3(66, 98, 21));
+
+ ap.InsertWaypoint(new Vector3(101, 98, 21));
+ ap.InsertWaypoint(new Vector3(101, 45, 21));
+ ap.InsertWaypoint(new Vector3(93, 27, 21));
+ ap.InsertWaypoint(new Vector3(106, 12, 21));
+ ap.InsertWaypoint(new Vector3(123, 24, 21));
+ ap.InsertWaypoint(new Vector3(114, 45, 21));
+ ap.InsertWaypoint(new Vector3(114, 98, 21));
+
+ ap.InsertWaypoint(new Vector3(130, 98, 21));
+ ap.InsertWaypoint(new Vector3(130, 163, 21));
+ **/
+ ap.InsertWaypoint(new Vector3(64, 68, 21));
+ ap.InsertWaypoint(new Vector3(65, 20, 21));
+ ap.InsertWaypoint(new Vector3(33, 23, 21));
+ ap.InsertWaypoint(new Vector3(17, 39, 21));
+ ap.InsertWaypoint(new Vector3(17, 62, 21));
+
+
+ }
+ if (AutoPilotActive)
+ {
+ AutoPilotActive = false;
+ ap.Stop();
+ }
+ else
+ {
+ AutoPilotActive = true;
+ ap.Start();
+ }
+
+ }
+
+ int filesDeleted;
+
+ private void deleteFolder(DirectoryInfo dir)
+ {
+ foreach (var file in dir.GetFiles())
+ {
+ try
+ {
+ file.Delete();
+ filesDeleted++;
+ }
+ catch { }
+ }
+
+ foreach (var subDir in dir.GetDirectories())
+ {
+ deleteFolder(subDir);
+ }
+
+ try { dir.Delete(); }
+ catch { }
+ }
+
+ private void cleanCacheToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ WorkPool.QueueUserWorkItem(sync =>
+ {
+ filesDeleted = 0;
+ try { deleteFolder(new DirectoryInfo(client.Settings.ASSET_CACHE_DIR)); }
+ catch { }
+ Logger.DebugLog("Wiped out " + filesDeleted + " files from the cache directory.");
+ });
+ instance.Names.CleanCache();
+ }
+
+ private void rebakeTexturesToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ instance.COF.RebakeTextures();
+ }
+
+ public void MapToCurrentLocation()
+ {
+ if (MapTab != null && client.Network.Connected)
+ {
+ MapTab.Select();
+ WorldMap.DisplayLocation(client.Network.CurrentSim.Name,
+ (int)client.Self.SimPosition.X,
+ (int)client.Self.SimPosition.Y,
+ (int)client.Self.SimPosition.Z);
+ }
+ }
+
+ private void standToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ instance.State.SetSitting(false, UUID.Zero);
+ }
+
+ private void groundSitToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ client.Self.SitOnGround();
+ }
+
+ private void newWindowToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ try { System.Diagnostics.Process.Start(Application.ExecutablePath); }
+ catch (Exception) { }
+ }
+
+ private void tmnuExit_Click(object sender, EventArgs e)
+ {
+ Close();
+ }
+
+ private void tlblRegionInfo_Click(object sender, EventArgs e)
+ {
+ if (WorldMap != null && client.Network.Connected)
+ {
+ MapTab.Select();
+ }
+ }
+
+ private void scriptEditorToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ ScriptEditor se = new ScriptEditor(instance);
+ se.Dock = DockStyle.Fill;
+ se.ShowDetached();
+ }
+
+ private void tmnuSetHome_Click(object sender, EventArgs e)
+ {
+ client.Self.SetHome();
+ }
+
+ private void tmnuCreateLandmark_Click(object sender, EventArgs e)
+ {
+ string location = string.Format(", {0} ({1}, {2}, {3})",
+ client.Network.CurrentSim.Name,
+ (int)client.Self.SimPosition.X,
+ (int)client.Self.SimPosition.Y,
+ (int)client.Self.SimPosition.Z
+ );
+
+ string name = tlblParcel.Text;
+ int maxLen = 63 - location.Length;
+
+ if (name.Length > maxLen)
+ name = name.Substring(0, maxLen);
+
+ name += location;
+
+ client.Inventory.RequestCreateItem(
+ client.Inventory.FindFolderForType(AssetType.Landmark),
+ name,
+ tlblParcel.ToolTipText,
+ AssetType.Landmark,
+ UUID.Random(),
+ InventoryType.Landmark,
+ PermissionMask.All,
+ (bool success, InventoryItem item) =>
+ {
+ if (success)
+ {
+ BeginInvoke(new MethodInvoker(() =>
+ {
+ Landmark ln = new Landmark(instance, (InventoryLandmark)item);
+ ln.Dock = DockStyle.Fill;
+ ln.Detached = true;
+ }));
+ }
+ }
+ );
+ }
+
+
+ private void timerWorldClock_Tick(object sender, EventArgs e)
+ {
+ lblTime.Text = instance.GetWorldTime().ToString("h:mm tt", System.Globalization.CultureInfo.InvariantCulture);
+ }
+
+ private void reportBugsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ ProcessLink("http://jira.openmetaverse.org/browse/RAD");
+ }
+
+ private void accessibilityGuideToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ ProcessLink("http://radegast.org/wiki/Accessibility_Guide");
+ }
+
+ private void aboutRadegastToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ (new frmAbout(instance)).ShowDialog();
+ }
+
+ #region Update Checking
+ private UpdateChecker updateChecker = null;
+ private bool ManualUpdateCheck = false;
+
+ public void StartUpdateCheck(bool userInitiated)
+ {
+ ManualUpdateCheck = userInitiated;
+
+ if (updateChecker != null)
+ {
+ if (ManualUpdateCheck)
+ tabsConsole.DisplayNotificationInChat("Update check already in progress.");
+ return;
+ }
+
+ if (ManualUpdateCheck)
+ tabsConsole.DisplayNotificationInChat("Checking for updates...", ChatBufferTextStyle.StatusBlue);
+ updateChecker = new UpdateChecker();
+ updateChecker.OnUpdateInfoReceived += new UpdateChecker.UpdateInfoCallback(OnUpdateInfoReceived);
+ updateChecker.StartCheck();
+ }
+
+ private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ tabsConsole.SelectTab("chat");
+ StartUpdateCheck(true);
+ }
+
+ void OnUpdateInfoReceived(object sender, UpdateCheckerArgs e)
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(() => OnUpdateInfoReceived(sender, e)));
+ return;
+ }
+
+ if (!e.Success)
+ {
+ if (ManualUpdateCheck)
+ tabsConsole.DisplayNotificationInChat("Error: Failed connecting to the update site.", ChatBufferTextStyle.StatusBlue);
+ }
+ else
+ {
+ if (!ManualUpdateCheck && e.Info.DisplayMOTD)
+ {
+ tabsConsole.DisplayNotificationInChat(e.Info.MOTD, ChatBufferTextStyle.StatusBlue);
+ }
+
+ if (e.Info.UpdateAvailable)
+ {
+ tabsConsole.DisplayNotificationInChat("New version available at " + e.Info.DownloadSite, ChatBufferTextStyle.Alert);
+ }
+ else
+ {
+ if (ManualUpdateCheck)
+ tabsConsole.DisplayNotificationInChat("Your version is up to date.", ChatBufferTextStyle.StatusBlue);
+ }
+ }
+
+ updateChecker.Dispose();
+ updateChecker = null;
+ }
+ #endregion
+
+ private void ToggleHidden(string tabName)
+ {
+ if (!tabsConsole.TabExists(tabName)) return;
+
+ RadegastTab tab = tabsConsole.Tabs[tabName];
+
+ if (tab.Hidden)
+ {
+ tab.Show();
+ }
+ else
+ {
+ if (!tab.Selected)
+ {
+ tab.Select();
+ }
+ else
+ {
+ tab.Hide();
+ }
+ }
+ }
+
+ private void tbtnFriends_Click(object sender, EventArgs e)
+ {
+ ToggleHidden("friends");
+ }
+
+ private void tbtnInventory_Click(object sender, EventArgs e)
+ {
+ ToggleHidden("inventory");
+ }
+
+ private void tbtnSearch_Click(object sender, EventArgs e)
+ {
+ ToggleHidden("search");
+ }
+
+ private void tbtnGroups_Click(object sender, EventArgs e)
+ {
+ ToggleHidden("groups");
+ }
+
+ private void tbtnVoice_Click(object sender, EventArgs e)
+ {
+ ToggleHidden("voice");
+ }
+
+ private void tbtnMedia_Click(object sender, EventArgs e)
+ {
+ if (tabsConsole.TabExists("media"))
+ {
+ ToggleHidden("media");
+ }
+ else
+ {
+ RadegastTab tab = tabsConsole.AddTab("media", "Media", mediaConsole);
+ tab.AllowClose = false;
+ tab.AllowHide = true;
+ tab.Select();
+ }
+ }
+
+ private void debugConsoleToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (tabsConsole.TabExists("debug"))
+ {
+ ToggleHidden("debug");
+ }
+ else
+ {
+ RadegastTab tab = tabsConsole.AddTab("debug", "Debug", new DebugConsole(instance));
+ tab.AllowClose = false;
+ tab.AllowHide = true;
+ tab.Select();
+ }
+ }
+
+ private void tbnObjects_Click(object sender, EventArgs e)
+ {
+ if (tabsConsole.TabExists("objects"))
+ {
+ RadegastTab tab = tabsConsole.Tabs["objects"];
+ if (!tab.Selected)
+ {
+ tab.Select();
+ ((ObjectsConsole)tab.Control).RefreshObjectList();
+ }
+ else
+ {
+ tab.Close();
+ }
+ }
+ else
+ {
+ RadegastTab tab = tabsConsole.AddTab("objects", "Objects", new ObjectsConsole(instance));
+ tab.AllowClose = true;
+ tab.AllowDetach = true;
+ tab.Visible = true;
+ tab.AllowHide = false;
+ tab.Select();
+ ((ObjectsConsole)tab.Control).RefreshObjectList();
+ }
+ }
+
+ private void tbtnMap_Click(object sender, EventArgs e)
+ {
+ if (MapTab == null) return; // too soon!
+
+ ToggleHidden("map");
+ if (!MapTab.Hidden)
+ MapToCurrentLocation();
+ }
+
+ private void disconnectToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (client.Network.Connected)
+ client.Network.RequestLogout();
+ }
+
+ private void reconnectToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (!client.Network.Connected)
+ {
+ instance.Reconnect();
+ }
+ }
+
+ private frmKeyboardShortcuts keyboardShortcutsForm = null;
+ private void keyboardShortcutsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (keyboardShortcutsForm != null)
+ {
+ keyboardShortcutsForm.Focus();
+ }
+ else
+ {
+ keyboardShortcutsForm = new frmKeyboardShortcuts(instance);
+
+ keyboardShortcutsForm.Disposed += (object senderx, EventArgs ex) =>
+ {
+ if (components != null)
+ {
+ components.Remove(keyboardShortcutsForm);
+ }
+ keyboardShortcutsForm = null;
+ };
+
+ keyboardShortcutsForm.Show(this);
+ keyboardShortcutsForm.Top = Top + 100;
+ keyboardShortcutsForm.Left = Left + 100;
+
+ if (components != null)
+ {
+ components.Add(keyboardShortcutsForm);
+ }
+ }
+ }
+
+ // Menu item for testing out stuff
+ private void testToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ }
+
+ private void reloadInventoryToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (tabsConsole.TabExists("inventory"))
+ {
+ ((InventoryConsole)tabsConsole.Tabs["inventory"].Control).ReloadInventory();
+ tabsConsole.Tabs["inventory"].Select();
+ }
+ }
+
+ private void btnLoadScript_Click(object sender, EventArgs e)
+ {
+ if (!TabConsole.TabExists("plugin_manager"))
+ {
+ TabConsole.AddTab("plugin_manager", "Plugins", new PluginsTab(instance));
+ }
+ TabConsole.Tabs["plugin_manager"].Select();
+ }
+
+ private void frmMain_Resize(object sender, EventArgs e)
+ {
+ if (WindowState == FormWindowState.Minimized && instance.GlobalSettings["minimize_to_tray"].AsBoolean())
+ {
+ if (TabConsole.TabExists("scene_window") && !TabConsole.Tabs["scene_window"].Detached)
+ {
+ TabConsole.Tabs["scene_window"].Close();
+ }
+ ShowInTaskbar = false;
+ trayIcon.Visible = true;
+ trayIcon.BalloonTipText = "Radegast is runnig in the background";
+ trayIcon.ShowBalloonTip(2000);
+ }
+ }
+
+ private void treyIcon_MouseDoubleClick(object sender, MouseEventArgs e)
+ {
+ WindowState = FormWindowState.Normal;
+ ShowInTaskbar = true;
+ trayIcon.Visible = false;
+ }
+
+ private void ctxTreyRestore_Click(object sender, EventArgs e)
+ {
+ treyIcon_MouseDoubleClick(this, null);
+ }
+
+ private void ctxTreyExit_Click(object sender, EventArgs e)
+ {
+ tmnuExit_Click(this, EventArgs.Empty);
+ }
+
+ private void tmnuTeleportHome_Click(object sender, EventArgs e)
+ {
+ TabConsole.DisplayNotificationInChat("Teleporting home...");
+ client.Self.RequestTeleport(UUID.Zero);
+ }
+
+ private void stopAllAnimationsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ instance.State.StopAllAnimations();
+ }
+
+ public void DisplayRegionParcelConsole()
+ {
+ if (tabsConsole.TabExists("current region info"))
+ {
+ tabsConsole.Tabs["current region info"].Select();
+ (tabsConsole.Tabs["current region info"].Control as RegionInfo).UpdateDisplay();
+ }
+ else
+ {
+ tabsConsole.AddTab("current region info", "Region info", new RegionInfo(instance));
+ tabsConsole.Tabs["current region info"].Select();
+ }
+ }
+
+ public void DisplayExportConsole(uint localID)
+ {
+ if (InvokeRequired)
+ {
+ if (IsHandleCreated || !instance.MonoRuntime)
+ BeginInvoke(new MethodInvoker(() => DisplayExportConsole(localID)));
+ return;
+ }
+
+ if (tabsConsole.TabExists("export console"))
+ {
+ tabsConsole.Tabs["export console"].Close();
+ }
+ RadegastTab tab = tabsConsole.AddTab("export console", "Export Object", new ExportConsole(client, localID));
+ tab.Select();
+ }
+
+ public void DisplayImportConsole()
+ {
+ if (TabConsole.TabExists("import console"))
+ {
+ TabConsole.Tabs["import console"].Select();
+ }
+ else
+ {
+ RadegastTab tab = tabsConsole.AddTab("import console", "Import Object", new ImportConsole(client));
+ tab.AllowClose = false;
+ tab.AllowHide = true;
+ tab.Select();
+ }
+ }
+
+ public void DisplayColladaConsole(Primitive prim)
+ {
+ if (InvokeRequired)
+ {
+ if (IsHandleCreated || !instance.MonoRuntime)
+ BeginInvoke(new MethodInvoker(() => DisplayColladaConsole(prim)));
+ return;
+ }
+
+ if (tabsConsole.TabExists("collada console"))
+ {
+ tabsConsole.Tabs["collada console"].Close();
+ }
+ RadegastTab tab = tabsConsole.AddTab("collada console", "Export Collada", new ExportCollada(instance, prim));
+ tab.Select();
+ }
+
+ private void regionParcelToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ DisplayRegionParcelConsole();
+ }
+
+ private void tlblParcel_Click(object sender, EventArgs e)
+ {
+ if (!client.Network.Connected) return;
+ DisplayRegionParcelConsole();
+ }
+
+ private void changeMyDisplayNameToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (!client.Avatars.DisplayNamesAvailable())
+ {
+ tabsConsole.DisplayNotificationInChat("This grid does not support display names.", ChatBufferTextStyle.Error);
+ return;
+ }
+
+ var dlg = new DisplayNameChange(instance);
+ dlg.ShowDialog();
+ }
+
+ private void muteListToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (!tabsConsole.TabExists("mute list console"))
+ {
+ tabsConsole.AddTab("mute list console", "Mute list", new MuteList(instance));
+ }
+ tabsConsole.Tabs["mute list console"].Select();
+ }
+
+ private void uploadImageToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (!tabsConsole.TabExists("image upload console"))
+ {
+ tabsConsole.AddTab("image upload console", "Upload image", new ImageUploadConsole(instance));
+ }
+ tabsConsole.Tabs["image upload console"].Select();
+ }
+ #endregion
+
+ private void myAttachmentsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ Avatar av = client.Network.CurrentSim.ObjectsAvatars.Find((Avatar a) => { return a.ID == client.Self.AgentID; });
+
+ if (av == null)
+ {
+ tabsConsole.DisplayNotificationInChat("Unable to find my avatar!", ChatBufferTextStyle.Error);
+ return;
+ }
+
+ if (!instance.TabConsole.TabExists("AT: " + av.ID.ToString()))
+ {
+ instance.TabConsole.AddTab("AT: " + av.ID.ToString(), "My Attachments", new AttachmentTab(instance, av));
+ }
+ instance.TabConsole.SelectTab("AT: " + av.ID.ToString());
+
+ }
+
+ private void tsb3D_Click(object sender, EventArgs e)
+ {
+ if (instance.TabConsole.TabExists("scene_window"))
+ {
+ instance.TabConsole.Tabs["scene_window"].Select();
+ }
+ else
+ {
+ var control = new Rendering.SceneWindow(instance);
+ control.Dock = DockStyle.Fill;
+ instance.TabConsole.AddTab("scene_window", "Scene Viewer", control);
+ instance.TabConsole.Tabs["scene_window"].Floater = false;
+ instance.TabConsole.Tabs["scene_window"].CloseOnDetachedClose = true;
+ control.RegisterTabEvents();
+
+ if (instance.GlobalSettings["scene_window_docked"])
+ {
+ instance.TabConsole.Tabs["scene_window"].Select();
+ }
+ else
+ {
+ instance.TabConsole.Tabs["scene_window"].Detach(instance);
+ }
+ }
+ }
+
+ private void loginToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ // We are logging in without exiting the client
+ // Mark last run as successful
+ instance.MarkEndExecution();
+ TabConsole.InitializeMainTab();
+ TabConsole.Tabs["login"].Select();
+ }
+
+ private void setMaturityLevel(string level)
+ {
+ client.Self.SetAgentAccess(level, res =>
+ {
+ if (res.Success)
+ {
+ tabsConsole.DisplayNotificationInChat("Successfully changed maturity access level to " + res.NewLevel);
+ }
+ else
+ {
+ tabsConsole.DisplayNotificationInChat("Failed to change maturity access level.", ChatBufferTextStyle.Error);
+ }
+ });
+ }
+
+ private void pGToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ setMaturityLevel("PG");
+ }
+
+ private void matureToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ setMaturityLevel("M");
+ }
+
+ private void adultToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ setMaturityLevel("A");
+ }
+
+ private void uploadmeshToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ if (!tabsConsole.TabExists("mesh upload console"))
+ {
+ tabsConsole.AddTab("mesh upload console", "Upload mesh", new MeshUploadConsole(instance));
+ }
+ tabsConsole.Tabs["mesh upload console"].Select();
+ }
+
+ }
}
\ No newline at end of file