-// \r
-// Radegast Metaverse Client\r
-// Copyright (c) 2009-2013, 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;\r
-using System.Collections.Generic;\r
-using System.Text;\r
-using System.Timers;\r
-using System.Windows.Forms;\r
-#if (COGBOT_LIBOMV || USE_STHREADS)\r
-using ThreadPoolUtil;\r
-using Thread = ThreadPoolUtil.Thread;\r
-using ThreadPool = ThreadPoolUtil.ThreadPool;\r
-using Monitor = ThreadPoolUtil.Monitor;\r
-#endif\r
-using System.Threading;\r
-using System.Drawing;\r
-using OpenMetaverse;\r
-using OpenMetaverse.Assets;\r
-\r
-namespace Radegast\r
-{\r
- public partial class ObjectsConsole : UserControl, IContextMenuProvider\r
- {\r
- public List<Primitive> Prims = new List<Primitive>();\r
-\r
- private RadegastInstance instance;\r
- private GridClient client { get { return instance.Client; } }\r
- private Primitive currentPrim = new Primitive();\r
- private float searchRadius = 40.0f;\r
- //public List<InventoryBase> subitems;\r
- PropertiesQueue propRequester;\r
- private Thread ContentsThread;\r
- private ObjectConsoleFilter filter;\r
- private ObjectSorter PrimSorter;\r
-\r
- public Primitive CurrentPrim { get { return currentPrim; } }\r
-\r
- public ObjectsConsole(RadegastInstance instance)\r
- {\r
- InitializeComponent();\r
- Disposed += new EventHandler(frmObjects_Disposed);\r
-\r
- this.instance = instance;\r
-\r
- propRequester = new PropertiesQueue(instance);\r
- propRequester.OnTick += new PropertiesQueue.TickCallback(propRequester_OnTick);\r
-\r
- btnPointAt.Text = (this.instance.State.IsPointing ? "Unpoint" : "Point At");\r
- State_SitStateChanged(this, new SitEventArgs(instance.State.IsSitting));\r
-\r
- nudRadius.Value = (decimal)searchRadius;\r
- nudRadius.ValueChanged += nudRadius_ValueChanged;\r
-\r
- PrimSorter = new ObjectSorter(client.Self);\r
-\r
- lstContents.LargeImageList = frmMain.ResourceImages;\r
- lstContents.SmallImageList = frmMain.ResourceImages;\r
-\r
- filter = (ObjectConsoleFilter)instance.GlobalSettings["object_console_filter"].AsInteger();\r
- comboFilter.SelectedIndex = 0;\r
- try\r
- {\r
- comboFilter.SelectedIndex = (int)filter;\r
- }\r
- catch { }\r
- comboFilter.SelectedIndexChanged += (ssender, se) =>\r
- {\r
- instance.GlobalSettings["object_console_filter"] = comboFilter.SelectedIndex;\r
- filter = (ObjectConsoleFilter)comboFilter.SelectedIndex;\r
- btnRefresh_Click(null, null);\r
- };\r
-\r
- //if (instance.MonoRuntime)\r
- //{\r
- // btnView.Visible = false;\r
- //}\r
-\r
- // Callbacks\r
- instance.Netcom.ClientDisconnected += new EventHandler<DisconnectedEventArgs>(Netcom_ClientDisconnected);\r
- instance.State.SitStateChanged += new EventHandler<SitEventArgs>(State_SitStateChanged);\r
- client.Objects.ObjectUpdate += new EventHandler<PrimEventArgs>(Objects_ObjectUpdate);\r
- client.Objects.KillObjects += new EventHandler<KillObjectsEventArgs>(Objects_KillObjects);\r
- client.Objects.ObjectProperties += new EventHandler<ObjectPropertiesEventArgs>(Objects_ObjectProperties);\r
- client.Objects.ObjectPropertiesFamily += new EventHandler<ObjectPropertiesFamilyEventArgs>(Objects_ObjectPropertiesFamily);\r
- client.Network.SimChanged += new EventHandler<SimChangedEventArgs>(Network_SimChanged);\r
- client.Self.MuteListUpdated += new EventHandler<EventArgs>(Self_MuteListUpdated);\r
- instance.Names.NameUpdated += new EventHandler<UUIDNameReplyEventArgs>(Avatars_UUIDNameReply);\r
- instance.State.OnWalkStateCanged += new StateManager.WalkStateCanged(State_OnWalkStateCanged);\r
- }\r
-\r
- void frmObjects_Disposed(object sender, EventArgs e)\r
- {\r
- if (ContentsThread != null)\r
- {\r
- if (ContentsThread.IsAlive) ContentsThread.Abort();\r
- ContentsThread = null;\r
- }\r
-\r
- propRequester.Dispose();\r
- instance.Netcom.ClientDisconnected -= new EventHandler<DisconnectedEventArgs>(Netcom_ClientDisconnected);\r
- instance.State.SitStateChanged -= new EventHandler<SitEventArgs>(State_SitStateChanged);\r
- client.Objects.ObjectUpdate -= new EventHandler<PrimEventArgs>(Objects_ObjectUpdate);\r
- client.Objects.KillObjects -= new EventHandler<KillObjectsEventArgs>(Objects_KillObjects);\r
- client.Objects.ObjectProperties -= new EventHandler<ObjectPropertiesEventArgs>(Objects_ObjectProperties);\r
- client.Objects.ObjectPropertiesFamily -= new EventHandler<ObjectPropertiesFamilyEventArgs>(Objects_ObjectPropertiesFamily);\r
- client.Network.SimChanged -= new EventHandler<SimChangedEventArgs>(Network_SimChanged);\r
- client.Self.MuteListUpdated -= new EventHandler<EventArgs>(Self_MuteListUpdated);\r
- instance.Names.NameUpdated -= new EventHandler<UUIDNameReplyEventArgs>(Avatars_UUIDNameReply);\r
- instance.State.OnWalkStateCanged -= new StateManager.WalkStateCanged(State_OnWalkStateCanged);\r
- }\r
-\r
- void State_SitStateChanged(object sender, SitEventArgs e)\r
- {\r
- if (InvokeRequired)\r
- {\r
- if (!instance.MonoRuntime || IsHandleCreated)\r
- {\r
- BeginInvoke(new MethodInvoker(() => State_SitStateChanged(sender, e)));\r
- }\r
- return;\r
- }\r
-\r
- btnSitOn.Text = (this.instance.State.IsSitting ? "Stand Up" : "Sit On");\r
- }\r
-\r
- public void RefreshObjectList()\r
- {\r
- btnRefresh_Click(this, EventArgs.Empty);\r
- }\r
-\r
- public List<Primitive> GetObjectList()\r
- {\r
- return new List<Primitive>(Prims);\r
- }\r
-\r
- void propRequester_OnTick(int remaining)\r
- {\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(delegate()\r
- {\r
- propRequester_OnTick(remaining);\r
- }\r
- ));\r
- return;\r
- }\r
-\r
- StringBuilder sb = new StringBuilder();\r
- sb.AppendFormat("Tracking {0} objects", Prims.Count);\r
-\r
- if (remaining > 10)\r
- {\r
- sb.AppendFormat(", fetching {0} object names.", remaining);\r
- }\r
- else\r
- {\r
- sb.Append(".");\r
- }\r
-\r
- lock (Prims)\r
- {\r
- Prims.Sort(PrimSorter);\r
- lstPrims.VirtualListSize = Prims.Count;\r
- }\r
- lstPrims.Invalidate();\r
- lblStatus.Text = sb.ToString();\r
- }\r
-\r
- void Network_SimChanged(object sender, SimChangedEventArgs e)\r
- {\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(() => Network_SimChanged(sender, e)));\r
- return;\r
- }\r
-\r
- btnRefresh_Click(null, null);\r
- }\r
-\r
- void Avatars_UUIDNameReply(object sender, UUIDNameReplyEventArgs e)\r
- {\r
- int minIndex = -1;\r
- int maxIndex = -1;\r
- bool updated = false;\r
-\r
- lock (Prims)\r
- {\r
- for (int i = 0; i < Prims.Count; i++)\r
- {\r
- Primitive prim = Prims[i];\r
- if (prim.Properties != null && e.Names.ContainsKey(prim.Properties.OwnerID))\r
- {\r
- if (minIndex == -1 || i < minIndex) minIndex = i;\r
- if (i > maxIndex) maxIndex = i;\r
- updated = true;\r
- }\r
- }\r
- }\r
-\r
- if (updated)\r
- {\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(() =>\r
- {\r
- try\r
- {\r
- lstPrims.RedrawItems(minIndex, maxIndex, true);\r
- }\r
- catch { }\r
- }));\r
- }\r
- else\r
- {\r
- lstPrims.RedrawItems(minIndex, maxIndex, true);\r
- }\r
- }\r
- }\r
-\r
- void UpdateProperties(Primitive.ObjectProperties props)\r
- {\r
- lock (Prims)\r
- {\r
- for (int i = 0; i < Prims.Count; i++)\r
- {\r
- if (Prims[i].ID == props.ObjectID)\r
- {\r
- Prims[i].Properties = props;\r
- try\r
- {\r
- lstPrims.RedrawItems(i, i, true);\r
- }\r
- catch { }\r
- break;\r
- }\r
- }\r
- }\r
-\r
- lock (lstChildren.Items)\r
- {\r
- if (lstChildren.Items.ContainsKey(props.ObjectID.ToString()))\r
- {\r
- Primitive prim = lstChildren.Items[props.ObjectID.ToString()].Tag as Primitive;\r
- prim.Properties = props;\r
- lstChildren.Items[props.ObjectID.ToString()].Text = prim.Properties.Name;\r
- }\r
- }\r
-\r
- if (props.ObjectID == currentPrim.ID)\r
- {\r
- UpdateCurrentObject(false);\r
- }\r
- }\r
-\r
- void Objects_ObjectProperties(object sender, ObjectPropertiesEventArgs e)\r
- {\r
- if (e.Simulator.Handle != client.Network.CurrentSim.Handle)\r
- {\r
- return;\r
- }\r
-\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(delegate() { Objects_ObjectProperties(sender, e); }));\r
- return;\r
- }\r
-\r
- UpdateProperties(e.Properties);\r
- }\r
-\r
- void Objects_ObjectPropertiesFamily(object sender, ObjectPropertiesFamilyEventArgs e)\r
- {\r
- if (e.Simulator.Handle != client.Network.CurrentSim.Handle)\r
- {\r
- return;\r
- }\r
-\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(delegate() { Objects_ObjectPropertiesFamily(sender, e); }));\r
- return;\r
- }\r
-\r
- UpdateProperties(e.Properties);\r
- }\r
-\r
-\r
- void UpdateObjectContents()\r
- {\r
- if (ContentsThread != null)\r
- {\r
- if (ContentsThread.IsAlive) ContentsThread.Abort();\r
- ContentsThread = null;\r
- }\r
-\r
- lstContents.Items.Clear();\r
- ListViewItem entry = new ListViewItem();\r
- entry.SubItems.Add("Loading...");\r
- lstContents.Items.Add(entry);\r
-\r
- ContentsThread = new Thread(new ThreadStart(() =>\r
- {\r
- lstContents.Tag = currentPrim;\r
- List<InventoryBase> items = client.Inventory.GetTaskInventory(currentPrim.ID, currentPrim.LocalID, 1000 * 30);\r
- lstContents.Invoke(new MethodInvoker(() => UpdateContentsList(items)));\r
- }));\r
-\r
- ContentsThread.IsBackground = true;\r
- ContentsThread.Start();\r
-\r
- }\r
-\r
- void UpdateContentsList(List<InventoryBase> items)\r
- {\r
- //object inventory in liste reinlesen\r
- lstContents.Items.Clear();\r
- btnOpen.Enabled = false;\r
- Primitive prim = (Primitive)lstContents.Tag;\r
-\r
- //subitems = items;\r
- if (items == null)\r
- {\r
- ListViewItem entry = new ListViewItem();\r
- entry.SubItems.Add("(failied to fetch contents)");\r
- entry.SubItems[0].Font = new System.Drawing.Font(entry.SubItems[0].Font, System.Drawing.FontStyle.Italic);\r
- lstContents.Items.Add(entry);\r
- }\r
- else\r
- {\r
- if (items.Count == 0)\r
- {\r
- ListViewItem entry = new ListViewItem();\r
- entry.SubItems.Add("(empty object)");\r
- entry.SubItems[0].Font = new System.Drawing.Font(entry.SubItems[0].Font, System.Drawing.FontStyle.Italic);\r
- lstContents.Items.Add(entry);\r
- }\r
- else\r
- {\r
- btnOpen.Enabled = prim.Properties != null && prim.Properties.OwnerID == client.Self.AgentID;\r
-\r
- for (int i = 0; i < items.Count; i++)\r
- {\r
- if (items[i] is InventoryItem)\r
- {\r
- InventoryItem item = (InventoryItem)items[i];\r
- ListViewItem entry = new ListViewItem();\r
-\r
- entry.ImageIndex = InventoryConsole.GetItemImageIndex(item.AssetType.ToString().ToLower());\r
- entry.Tag = item;\r
-\r
- ListViewItem.ListViewSubItem sub;\r
-\r
- entry.SubItems.Add(sub = new ListViewItem.ListViewSubItem()\r
- {\r
- Name = item.UUID.ToString(),\r
- Text = item.Name\r
- });\r
-\r
- if ((item.Permissions.OwnerMask & PermissionMask.Modify) == 0)\r
- sub.Text += " (no modify)";\r
-\r
- if ((item.Permissions.OwnerMask & PermissionMask.Copy) == 0)\r
- sub.Text += " (no copy)";\r
-\r
- if ((item.Permissions.OwnerMask & PermissionMask.Transfer) == 0)\r
- sub.Text += " (no transfer)";\r
-\r
- sub.Text += " (" + item.InventoryType.ToString() + ")";\r
- entry.ToolTipText = sub.Text;\r
-\r
- lstContents.Items.Add(entry);\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- private void ctxContents_Opening(object sender, System.ComponentModel.CancelEventArgs e)\r
- {\r
- e.Cancel = false;\r
-\r
- if (!(lstContents.Tag is Primitive))\r
- {\r
- e.Cancel = true;\r
- return;\r
- }\r
-\r
- ctxContents.Items.Clear();\r
- Primitive prim = (Primitive)lstContents.Tag;\r
- bool canModify = (prim.Flags & PrimFlags.ObjectModify) == PrimFlags.ObjectModify;\r
-\r
- if (lstContents.SelectedItems.Count == 1)\r
- {\r
- ListViewItem entry = lstContents.SelectedItems[0];\r
-\r
- if (entry.Tag is InventoryItem)\r
- {\r
- InventoryItem item = (InventoryItem)entry.Tag;\r
-\r
- if (canModify)\r
- {\r
- switch (item.InventoryType)\r
- {\r
- case InventoryType.Notecard:\r
- ctxContents.Items.Add("Edit Notecard", null, (object sd, EventArgs ev) =>\r
- {\r
- InventoryNotecard inv = (InventoryNotecard)entry.Tag;\r
- new Notecard(instance, inv, prim) { Detached = true };\r
- }\r
- );\r
- break;\r
-\r
- case InventoryType.LSL:\r
- ctxContents.Items.Add("Edit Script", null, (object sd, EventArgs ev) =>\r
- {\r
- InventoryLSL inv = (InventoryLSL)entry.Tag;\r
- new ScriptEditor(instance, inv, prim) { Detached = true };\r
- }\r
- );\r
- break;\r
- }\r
-\r
- }\r
- }\r
- }\r
-\r
- if (lstContents.SelectedItems.Count > 0)\r
- {\r
- ctxContents.Items.Add("Delete", null, (object sd, EventArgs ev) =>\r
- {\r
- foreach (ListViewItem i in lstContents.SelectedItems)\r
- if (i.Tag is InventoryItem)\r
- client.Inventory.RemoveTaskInventory(prim.LocalID, ((InventoryItem)i.Tag).UUID, client.Network.CurrentSim);\r
- });\r
- }\r
-\r
- if (ctxContents.Items.Count != 0)\r
- {\r
- ctxContents.Items.Add(new ToolStripSeparator());\r
- }\r
-\r
- if ((canModify || (prim.Flags & PrimFlags.AllowInventoryDrop) == PrimFlags.AllowInventoryDrop) && instance.InventoryClipboard != null)\r
- {\r
- if (instance.InventoryClipboard.Item is InventoryItem)\r
- {\r
- ctxContents.Items.Add("Paste from Inventory", null, (object sd, EventArgs ev) =>\r
- {\r
- if (instance.InventoryClipboard.Item is InventoryLSL)\r
- {\r
- client.Inventory.CopyScriptToTask(prim.LocalID, (InventoryItem)instance.InventoryClipboard.Item, true);\r
- }\r
- else\r
- {\r
- client.Inventory.UpdateTaskInventory(prim.LocalID, (InventoryItem)instance.InventoryClipboard.Item);\r
- }\r
- });\r
- }\r
- else if (instance.InventoryClipboard.Item is InventoryFolder)\r
- {\r
- ctxContents.Items.Add("Paste Folder Contents", null, (object sd, EventArgs ev) =>\r
- {\r
- foreach (InventoryBase oldItem in client.Inventory.Store.GetContents((InventoryFolder)instance.InventoryClipboard.Item))\r
- {\r
- if (oldItem is InventoryItem)\r
- {\r
- if (oldItem is InventoryLSL)\r
- {\r
- client.Inventory.CopyScriptToTask(prim.LocalID, (InventoryItem)oldItem, true);\r
- }\r
- else\r
- {\r
- client.Inventory.UpdateTaskInventory(prim.LocalID, (InventoryItem)oldItem);\r
- }\r
- }\r
- }\r
- });\r
- }\r
- }\r
-\r
- if (canModify)\r
- {\r
- ctxContents.Items.Add("Open (copy all to inventory)", null, OpenObject);\r
- }\r
-\r
- ctxContents.Items.Add("Close", null, btnCloseContents_Click);\r
- }\r
-\r
- void OpenObject(object sender, EventArgs e)\r
- {\r
- if (!(lstContents.Tag is Primitive)) return;\r
-\r
- Primitive prim = (Primitive)lstContents.Tag;\r
- if (prim.Properties == null) return;\r
-\r
- List<InventoryItem> items = new List<InventoryItem>();\r
-\r
- foreach (ListViewItem item in lstContents.Items)\r
- {\r
- if (item.Tag is InventoryItem)\r
- items.Add(item.Tag as InventoryItem);\r
- }\r
-\r
- if (items.Count == 0) return;\r
-\r
- UUID folderID = client.Inventory.CreateFolder(client.Inventory.Store.RootFolder.UUID, prim.Properties.Name);\r
-\r
- for (int i = 0; i < items.Count; i++)\r
- {\r
- client.Inventory.MoveTaskInventory(prim.LocalID, items[i].UUID, folderID, client.Network.CurrentSim);\r
- }\r
-\r
- instance.TabConsole.DisplayNotificationInChat("Items from object contents copied to new inventory folder " + prim.Properties.Name);\r
-\r
- }\r
-\r
- void UpdateCurrentObject()\r
- {\r
- UpdateCurrentObject(true);\r
- }\r
-\r
- void UpdateCurrentObject(bool updateContents)\r
- {\r
- if (currentPrim.Properties == null) return;\r
-\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(delegate() { UpdateCurrentObject(updateContents); }));\r
- return;\r
- }\r
-\r
- // currentItem.Text = GetObjectName(currentPrim);\r
-\r
- txtObjectName.Text = currentPrim.Properties.Name;\r
- txtDescription.Text = currentPrim.Properties.Description;\r
- if ((currentPrim.Flags & PrimFlags.ObjectModify) == PrimFlags.ObjectModify)\r
- {\r
- txtObjectName.ReadOnly = txtDescription.ReadOnly = false;\r
- gbxObjectDetails.Text = "Object details (you can modify)";\r
- }\r
- else\r
- {\r
- txtObjectName.ReadOnly = txtDescription.ReadOnly = true;\r
- gbxObjectDetails.Text = "Object details";\r
- }\r
-\r
- txtHover.Text = currentPrim.Text;\r
- txtOwner.AgentID = currentPrim.Properties.OwnerID;\r
- txtCreator.AgentID = currentPrim.Properties.CreatorID;\r
-\r
- Permissions p = currentPrim.Properties.Permissions;\r
- cbOwnerModify.Checked = (p.OwnerMask & PermissionMask.Modify) != 0;\r
- cbOwnerCopy.Checked = (p.OwnerMask & PermissionMask.Copy) != 0;\r
- cbOwnerTransfer.Checked = (p.OwnerMask & PermissionMask.Transfer) != 0;\r
-\r
- cbNextOwnModify.CheckedChanged -= cbNextOwnerUpdate_CheckedChanged;\r
- cbNextOwnCopy.CheckedChanged -= cbNextOwnerUpdate_CheckedChanged;\r
- cbNextOwnTransfer.CheckedChanged -= cbNextOwnerUpdate_CheckedChanged;\r
-\r
- cbNextOwnModify.Checked = (p.NextOwnerMask & PermissionMask.Modify) != 0;\r
- cbNextOwnCopy.Checked = (p.NextOwnerMask & PermissionMask.Copy) != 0;\r
- cbNextOwnTransfer.Checked = (p.NextOwnerMask & PermissionMask.Transfer) != 0;\r
-\r
- cbNextOwnModify.CheckedChanged += cbNextOwnerUpdate_CheckedChanged;\r
- cbNextOwnCopy.CheckedChanged += cbNextOwnerUpdate_CheckedChanged;\r
- cbNextOwnTransfer.CheckedChanged += cbNextOwnerUpdate_CheckedChanged;\r
-\r
- if (currentPrim.Properties.OwnerID == client.Self.AgentID)\r
- {\r
- cbNextOwnModify.Enabled = cbNextOwnCopy.Enabled = cbNextOwnTransfer.Enabled = true;\r
- }\r
- else\r
- {\r
- cbNextOwnModify.Enabled = cbNextOwnCopy.Enabled = cbNextOwnTransfer.Enabled = false;\r
- }\r
-\r
- txtPrims.Text = (client.Network.CurrentSim.ObjectsPrimitives.FindAll(\r
- delegate(Primitive prim)\r
- {\r
- return prim.ParentID == currentPrim.LocalID || prim.LocalID == currentPrim.LocalID;\r
- })).Count.ToString();\r
-\r
- if ((currentPrim.Flags & PrimFlags.Money) != 0)\r
- {\r
- btnPay.Enabled = true;\r
- }\r
- else\r
- {\r
- btnPay.Enabled = false;\r
- }\r
-\r
- if (currentPrim.Properties.SaleType != SaleType.Not)\r
- {\r
- btnBuy.Text = string.Format("Buy $L{0}", currentPrim.Properties.SalePrice);\r
- btnBuy.Enabled = true;\r
- }\r
- else\r
- {\r
- btnBuy.Text = "Buy";\r
- btnBuy.Enabled = false;\r
- }\r
-\r
- if (gbxContents.Visible /*&& updateContents*/)\r
- {\r
- UpdateObjectContents();\r
- }\r
-\r
- UpdateMuteButton();\r
- }\r
-\r
- void Netcom_ClientDisconnected(object sender, DisconnectedEventArgs e)\r
- {\r
- if (InvokeRequired)\r
- {\r
- if (!instance.MonoRuntime || IsHandleCreated)\r
- {\r
- BeginInvoke(new MethodInvoker(() => Netcom_ClientDisconnected(sender, e)));\r
- }\r
- return;\r
- }\r
-\r
- if (instance.TabConsole.TabExists("objects"))\r
- {\r
- instance.TabConsole.Tabs["objects"].Close();\r
- }\r
- }\r
-\r
- private string GetObjectName(Primitive prim, int distance)\r
- {\r
- string name = "Loading...";\r
- string ownerName = "Loading...";\r
-\r
- if (prim.Properties != null)\r
- {\r
- name = prim.Properties.Name;\r
- // prim.Properties.GroupID is the actual group when group owned, not prim.GroupID\r
- if (UUID.Zero == prim.Properties.OwnerID &&\r
- PrimFlags.ObjectGroupOwned == (prim.Flags & PrimFlags.ObjectGroupOwned) &&\r
- UUID.Zero != prim.Properties.GroupID)\r
- {\r
- System.Threading.AutoResetEvent nameReceivedSignal = new System.Threading.AutoResetEvent(false);\r
- EventHandler<GroupNamesEventArgs> cbGroupName = new EventHandler<GroupNamesEventArgs>(\r
- delegate(object sender, GroupNamesEventArgs e)\r
- {\r
- if (e.GroupNames.ContainsKey(prim.Properties.GroupID))\r
- {\r
- e.GroupNames.TryGetValue(prim.Properties.GroupID, out ownerName);\r
- if (string.IsNullOrEmpty(ownerName))\r
- ownerName = "Loading...";\r
- if (null != nameReceivedSignal)\r
- nameReceivedSignal.Set();\r
- }\r
- });\r
- client.Groups.GroupNamesReply += cbGroupName;\r
- client.Groups.RequestGroupName(prim.Properties.GroupID);\r
- nameReceivedSignal.WaitOne(5000, false);\r
- nameReceivedSignal.Close();\r
- client.Groups.GroupNamesReply -= cbGroupName;\r
- }\r
- else\r
- ownerName = instance.Names.Get(prim.Properties.OwnerID);\r
- }\r
-\r
- if (prim.ParentID == client.Self.LocalID)\r
- {\r
- return string.Format("{0} attached to {1}", name, prim.PrimData.AttachmentPoint.ToString());\r
- }\r
- else if (ownerName != "Loading...")\r
- {\r
- return String.Format("{0} ({1}m) owned by {2}", name, distance, ownerName);\r
- }\r
- else\r
- {\r
- return String.Format("{0} ({1}m)", name, distance);\r
- }\r
-\r
- }\r
-\r
- private string GetObjectName(Primitive prim)\r
- {\r
- int distance = (int)Vector3.Distance(client.Self.SimPosition, prim.Position);\r
- if (prim.ParentID == client.Self.LocalID) distance = 0;\r
- return GetObjectName(prim, distance);\r
- }\r
-\r
- private void AddPrim(Primitive prim)\r
- {\r
- lock (Prims)\r
- {\r
- string name = GetObjectName(prim);\r
- if (!Prims.Contains(prim) && (txtSearch.Text.Length == 0 || name.ToLower().Contains(txtSearch.Text.ToLower())))\r
- {\r
- Prims.Add(prim);\r
- if (prim.Properties == null)\r
- {\r
- propRequester.RequestProps(prim);\r
- }\r
- }\r
- }\r
- }\r
-\r
- void Objects_ObjectUpdate(object sender, PrimEventArgs e)\r
- {\r
- if (e.Simulator.Handle != client.Network.CurrentSim.Handle || e.Prim.Position == Vector3.Zero || e.Prim is Avatar) return;\r
-\r
- if (IncludePrim(e.Prim))\r
- {\r
- if (e.Prim.ParentID == 0)\r
- {\r
- int distance = (int)Vector3.Distance(client.Self.SimPosition, e.Prim.Position);\r
- if (distance < searchRadius)\r
- {\r
- AddPrim(e.Prim);\r
- }\r
- }\r
- else if (e.Prim.ParentID == client.Self.LocalID)\r
- {\r
- AddPrim(e.Prim);\r
- }\r
- }\r
-\r
- if (e.Prim.ID == currentPrim.ID)\r
- {\r
- if (currentPrim.Properties != null)\r
- {\r
- UpdateCurrentObject(false);\r
- }\r
- }\r
- }\r
-\r
- void Objects_KillObjects(object sender, KillObjectsEventArgs e)\r
- {\r
- if (e.Simulator.Handle != client.Network.CurrentSim.Handle) return;\r
-\r
- lock (Prims)\r
- {\r
- List<Primitive> killed = Prims.FindAll((p) =>\r
- {\r
- for (int i = 0; i < e.ObjectLocalIDs.Length; i++)\r
- {\r
- if (p.LocalID == e.ObjectLocalIDs[i])\r
- {\r
- return true;\r
- }\r
- }\r
- return false;\r
- });\r
-\r
- foreach (Primitive prim in killed)\r
- {\r
- Prims.Remove(prim);\r
- }\r
- }\r
-\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(() =>\r
- {\r
- lstPrims.VirtualListSize = Prims.Count;\r
- lstPrims.Invalidate();\r
- }));\r
- }\r
- else\r
- {\r
- lstPrims.VirtualListSize = Prims.Count;\r
- lstPrims.Invalidate();\r
- }\r
-\r
- }\r
-\r
- private bool IncludePrim(Primitive prim)\r
- {\r
- if ((prim.ParentID == client.Self.LocalID) && (filter == ObjectConsoleFilter.Attached || filter == ObjectConsoleFilter.Both))\r
- {\r
- return true;\r
- }\r
- else if ((prim.ParentID == 0) && (filter == ObjectConsoleFilter.Rezzed || filter == ObjectConsoleFilter.Both))\r
- {\r
- return true;\r
- }\r
- else\r
- {\r
- return false;\r
- }\r
- }\r
-\r
- private void AddAllObjects()\r
- {\r
- Vector3 location = client.Self.SimPosition;\r
-\r
- lock (Prims)\r
- {\r
- /*\r
- var prims = client.Network.CurrentSim.ObjectsPrimitives.FindAll(prim =>\r
- {\r
- return ((prim.ParentID == client.Self.LocalID) && (filter == ObjectConsoleFilter.Attached || filter == ObjectConsoleFilter.Both)) ||\r
- ((prim.ParentID == 0) && (filter == ObjectConsoleFilter.Rezzed || filter == ObjectConsoleFilter.Both));\r
- });\r
- */\r
- client.Network.CurrentSim.ObjectsPrimitives.ForEach(prim =>\r
- {\r
- int distance = (int)Vector3.Distance(prim.Position, location);\r
- if (prim.ParentID == client.Self.LocalID)\r
- {\r
- distance = 0;\r
- }\r
- if (IncludePrim(prim) &&\r
- (prim.Position != Vector3.Zero) &&\r
- (distance < searchRadius) &&\r
- (txtSearch.Text.Length == 0 || (prim.Properties != null && prim.Properties.Name.ToLower().Contains(txtSearch.Text.ToLower()))) && //root prims and attachments only\r
- !Prims.Contains(prim))\r
- {\r
- Prims.Add(prim);\r
- if (prim.Properties == null)\r
- {\r
- propRequester.RequestProps(prim);\r
- }\r
- }\r
- });\r
- Prims.Sort(PrimSorter);\r
- lstPrims.VirtualListSize = Prims.Count;\r
- lstPrims.Invalidate();\r
- }\r
- }\r
-\r
- private void btnPointAt_Click(object sender, EventArgs e)\r
- {\r
- if (btnPointAt.Text == "Point At")\r
- {\r
- instance.State.SetPointing(currentPrim, 3);\r
- btnPointAt.Text = "Unpoint";\r
- }\r
- else if (btnPointAt.Text == "Unpoint")\r
- {\r
- instance.State.UnSetPointing();\r
- btnPointAt.Text = "Point At";\r
- }\r
- }\r
-\r
- private void btnSitOn_Click(object sender, EventArgs e)\r
- {\r
- if (!instance.State.IsSitting)\r
- {\r
- instance.State.SetSitting(true, currentPrim.ID);\r
- }\r
- else\r
- {\r
- instance.State.SetSitting(false, currentPrim.ID);\r
- }\r
- }\r
-\r
- private void btnTouch_Click(object sender, EventArgs e)\r
- {\r
- client.Self.Touch(currentPrim.LocalID);\r
- }\r
-\r
- private void txtSearch_TextChanged(object sender, EventArgs e)\r
- {\r
- btnRefresh_Click(null, null);\r
- }\r
-\r
- private void btnClear_Click(object sender, EventArgs e)\r
- {\r
- txtSearch.Clear();\r
- txtSearch.Select();\r
- btnRefresh_Click(null, null);\r
- }\r
-\r
- private void btnRefresh_Click(object sender, EventArgs e)\r
- {\r
- instance.State.SetDefaultCamera();\r
- Cursor.Current = Cursors.WaitCursor;\r
- Prims.Clear();\r
- AddAllObjects();\r
-\r
- Cursor.Current = Cursors.Default;\r
- }\r
-\r
- private void lstPrims_SelectedIndexChanged(object sender, EventArgs e)\r
- {\r
- if (lstPrims.SelectedIndices.Count == 1)\r
- {\r
- lock (Prims)\r
- {\r
- try\r
- {\r
- currentPrim = Prims[lstPrims.SelectedIndices[0]];\r
- }\r
- catch\r
- {\r
- gbxInworld.Enabled = false;\r
- return;\r
- }\r
- }\r
-\r
- gbxInworld.Enabled = true;\r
- btnBuy.Tag = currentPrim;\r
-\r
- if (currentPrim.Properties == null || currentPrim.OwnerID == UUID.Zero || (currentPrim.Properties != null && currentPrim.Properties.CreatorID == UUID.Zero))\r
- {\r
- client.Objects.SelectObject(client.Network.CurrentSim, currentPrim.LocalID);\r
- }\r
-\r
- UpdateCurrentObject();\r
- UpdateChildren();\r
- }\r
- else\r
- {\r
- lstChildren.Visible = false;\r
- gbxInworld.Enabled = false;\r
- }\r
- }\r
-\r
- private void lstChildren_SelectedIndexChanged(object sender, EventArgs e)\r
- {\r
- if (lstChildren.SelectedItems.Count == 1)\r
- {\r
- gbxInworld.Enabled = true;\r
- currentPrim = lstChildren.SelectedItems[0].Tag as Primitive;\r
- btnBuy.Tag = currentPrim;\r
-\r
- if (currentPrim.Properties == null || (currentPrim.Properties != null && currentPrim.Properties.CreatorID == UUID.Zero))\r
- {\r
- client.Objects.SelectObject(client.Network.CurrentSim, currentPrim.LocalID);\r
- }\r
-\r
- UpdateCurrentObject();\r
- }\r
- else\r
- {\r
- gbxInworld.Enabled = false;\r
- }\r
- }\r
-\r
- void UpdateChildren()\r
- {\r
- if (currentPrim == null) return;\r
- var prims = client.Network.CurrentSim.ObjectsPrimitives.FindAll((Primitive p) => p.ParentID == currentPrim.LocalID);\r
- if (prims == null || prims.Count == 0) return;\r
- List<uint> toGetNames = new List<uint>();\r
-\r
- lstChildren.BeginUpdate();\r
- lock (lstChildren.Items)\r
- {\r
- lstChildren.Items.Clear();\r
- foreach (var prim in prims)\r
- {\r
- var item = new ListViewItem();\r
-\r
- if (prim.Properties != null)\r
- {\r
- item.Text = prim.Properties.Name;\r
- }\r
- else\r
- {\r
- item.Text = "Loading...";\r
- toGetNames.Add(prim.LocalID);\r
- }\r
-\r
- item.Tag = prim;\r
- item.Name = prim.ID.ToString();\r
- lstChildren.Items.Add(item);\r
- }\r
- }\r
- lstChildren.EndUpdate();\r
- lstChildren.Visible = true;\r
- if (toGetNames.Count > 0)\r
- {\r
- client.Objects.SelectObjects(client.Network.CurrentSim, toGetNames.ToArray(), true);\r
- }\r
- }\r
-\r
- private void btnPay_Click(object sender, EventArgs e)\r
- {\r
- (new frmPay(instance, currentPrim.ID, currentPrim.Properties.Name, true)).ShowDialog();\r
- }\r
-\r
- private void btnDetach_Click(object sender, EventArgs e)\r
- {\r
- var toDetach = CurrentOutfitFolder.GetAttachmentItem(currentPrim);\r
- if (toDetach != UUID.Zero)\r
- {\r
- if (client.Inventory.Store.Contains(toDetach))\r
- {\r
- instance.COF.Detach(client.Inventory.Store[toDetach] as InventoryItem);\r
- }\r
- }\r
- }\r
-\r
- private void btnView_Click(object sender, EventArgs e)\r
- {\r
- if (currentPrim.PrimData.PCode != PCode.Prim)\r
- {\r
- instance.TabConsole.DisplayNotificationInChat("Cannot display objects of that type", ChatBufferTextStyle.Error);\r
- return;\r
- }\r
-\r
- Rendering.frmPrimWorkshop pw = new Rendering.frmPrimWorkshop(instance, currentPrim.LocalID);\r
- pw.Show();\r
- }\r
-\r
- private void nudRadius_ValueChanged(object sender, EventArgs e)\r
- {\r
- searchRadius = (float)nudRadius.Value;\r
- btnRefresh_Click(null, null);\r
- }\r
-\r
- private void btnBuy_Click(object sender, EventArgs e)\r
- {\r
- if (lstPrims.SelectedIndices.Count != 1) return;\r
- btnBuy.Enabled = false;\r
- client.Objects.BuyObject(client.Network.CurrentSim, currentPrim.LocalID, currentPrim.Properties.SaleType, currentPrim.Properties.SalePrice, client.Self.ActiveGroup, client.Inventory.FindFolderForType(AssetType.Object));\r
- }\r
-\r
- private void rbDistance_CheckedChanged(object sender, EventArgs e)\r
- {\r
- if (rbDistance.Checked)\r
- {\r
- PrimSorter.SortByName = false;\r
- lock (Prims) Prims.Sort(PrimSorter);\r
- lstPrims.Invalidate();\r
- }\r
- }\r
-\r
- private void rbName_CheckedChanged(object sender, EventArgs e)\r
- {\r
- if (rbName.Checked)\r
- {\r
- PrimSorter.SortByName = true;\r
- lock (Prims) Prims.Sort(PrimSorter);\r
- lstPrims.Invalidate();\r
- }\r
- }\r
-\r
- private void btnTurnTo_Click(object sender, EventArgs e)\r
- {\r
- if (lstPrims.SelectedIndices.Count != 1) return;\r
- client.Self.Movement.TurnToward(currentPrim.Position);\r
- }\r
-\r
- private void btnWalkTo_Click(object sender, EventArgs e)\r
- {\r
- if (lstPrims.SelectedIndices.Count != 1) return;\r
-\r
- if (instance.State.IsWalking)\r
- {\r
- instance.State.EndWalking();\r
- }\r
- else\r
- {\r
- instance.State.WalkTo(currentPrim);\r
- }\r
- }\r
-\r
- void State_OnWalkStateCanged(bool walking)\r
- {\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(delegate() { State_OnWalkStateCanged(walking); }));\r
- return;\r
- }\r
-\r
- if (walking)\r
- {\r
- btnWalkTo.Text = "Stop";\r
- }\r
- else\r
- {\r
- btnWalkTo.Text = "Walk to";\r
- btnRefresh_Click(null, null);\r
- }\r
- }\r
-\r
- private void nudRadius_KeyUp(object sender, KeyEventArgs e)\r
- {\r
- if (e.KeyCode == Keys.Enter)\r
- {\r
- e.SuppressKeyPress = true;\r
- }\r
- }\r
-\r
- private void nudRadius_KeyDown(object sender, KeyEventArgs e)\r
- {\r
- if (e.KeyCode == Keys.Enter)\r
- {\r
- e.SuppressKeyPress = true;\r
- }\r
- }\r
-\r
- private void ctxMenuObjects_Opening(object sender, System.ComponentModel.CancelEventArgs e)\r
- {\r
- e.Cancel = false;\r
-\r
- if (lstPrims.SelectedIndices.Count != 1)\r
- {\r
- e.Cancel = true;\r
- return;\r
- }\r
-\r
- ctxMenuObjects.Items.Clear();\r
- ctxMenuObjects.Items.Add("Click/Touch", null, btnTouch_Click);\r
-\r
- if (currentPrim.ParentID == client.Self.LocalID)\r
- ctxMenuObjects.Items.Add("Detach", null, btnDetach_Click);\r
-\r
- if ((currentPrim.Flags & PrimFlags.Money) != 0)\r
- ctxMenuObjects.Items.Add("Pay", null, btnPay_Click);\r
-\r
- if (currentPrim.Properties != null && currentPrim.Properties.SaleType != SaleType.Not)\r
- ctxMenuObjects.Items.Add(string.Format("Buy for ${0}", currentPrim.Properties.SalePrice), null, btnBuy_Click);\r
-\r
- if (gbxInworld.Visible)\r
- ctxMenuObjects.Items.Add("Show Contents", null, btnContents_Click);\r
- else\r
- ctxMenuObjects.Items.Add("Hide Contents", null, btnCloseContents_Click);\r
-\r
- ctxMenuObjects.Items.Add(this.instance.State.IsSitting ? "Stand Up" : "Sit On", null, btnSitOn_Click);\r
- ctxMenuObjects.Items.Add("Turn To", null, btnTurnTo_Click);\r
- ctxMenuObjects.Items.Add("Walk To", null, btnWalkTo_Click);\r
- ctxMenuObjects.Items.Add(this.instance.State.IsPointing ? "Unpoint" : "Point At", null, btnPointAt_Click);\r
- ctxMenuObjects.Items.Add("3D View", null, btnView_Click);\r
- ctxMenuObjects.Items.Add("Take", null, btnTake_Click);\r
- ctxMenuObjects.Items.Add("Delete", null, btnDelete_Click);\r
- ctxMenuObjects.Items.Add("Return", null, btnReturn_Click);\r
-\r
- if (currentPrim.Properties != null)\r
- {\r
- if (currentPrim.Properties.CreatorID == client.Self.AgentID &&\r
- currentPrim.Properties.OwnerID == client.Self.AgentID)\r
- {\r
- ctxMenuObjects.Items.Add("Export", null, btnExport_Click);\r
- }\r
- }\r
-\r
- if (currentPrim.Properties != null)\r
- {\r
- bool isMuted = null != client.Self.MuteList.Find(me => me.Type == MuteType.Object && me.ID == currentPrim.ID);\r
-\r
- if (isMuted)\r
- {\r
- ctxMenuObjects.Items.Add("Unmute", null, (a, b) =>\r
- {\r
- client.Self.RemoveMuteListEntry(currentPrim.ID, currentPrim.Properties.Name);\r
- });\r
- }\r
- else\r
- {\r
- ctxMenuObjects.Items.Add("Mute", null, (a, b) =>\r
- {\r
- client.Self.UpdateMuteListEntry(MuteType.Object, currentPrim.ID, currentPrim.Properties.Name);\r
- });\r
- }\r
- }\r
-\r
- //if (currentPrim.MediaURL != null && currentPrim.MediaURL.StartsWith("x-mv:"))\r
- //{\r
- // ctxMenuObjects.Items.Add("Test", null, (object menuSender, EventArgs menuE) =>\r
- // {\r
- // client.Objects.RequestObjectMedia(currentPrim.ID, client.Network.CurrentSim, (bool success, string version, MediaEntry[] faceMedia) =>\r
- // {\r
- // int foo = 1;\r
- // }\r
- // );\r
- // }\r
- // );\r
- //}\r
-\r
- instance.ContextActionManager.AddContributions(ctxMenuObjects, currentPrim);\r
- }\r
-\r
- public RadegastContextMenuStrip GetContextMenu()\r
- {\r
- return ctxMenuObjects;\r
- }\r
-\r
- private void btnTake_Click(object sender, EventArgs e)\r
- {\r
- instance.MediaManager.PlayUISound(UISounds.ObjectDelete);\r
- client.Inventory.RequestDeRezToInventory(currentPrim.LocalID);\r
- }\r
-\r
- private void btnDelete_Click(object sender, EventArgs e)\r
- {\r
- if (currentPrim.Properties != null && currentPrim.Properties.OwnerID != client.Self.AgentID)\r
- btnReturn_Click(sender, e);\r
- else\r
- {\r
- instance.MediaManager.PlayUISound(UISounds.ObjectDelete);\r
- client.Inventory.RequestDeRezToInventory(currentPrim.LocalID, DeRezDestination.AgentInventoryTake, client.Inventory.FindFolderForType(AssetType.TrashFolder), UUID.Random());\r
- }\r
- }\r
-\r
- private void btnReturn_Click(object sender, EventArgs e)\r
- {\r
- instance.MediaManager.PlayUISound(UISounds.ObjectDelete);\r
- client.Inventory.RequestDeRezToInventory(currentPrim.LocalID, DeRezDestination.ReturnToOwner, UUID.Zero, UUID.Random());\r
- }\r
-\r
- private void btnCloseContents_Click(object sender, EventArgs e)\r
- {\r
- gbxContents.Hide();\r
- gbxInworld.Show();\r
- lstPrims.Focus();\r
- }\r
-\r
- private void btnContents_Click(object sender, EventArgs e)\r
- {\r
- gbxInworld.Hide();\r
- gbxContents.Show();\r
- UpdateObjectContents();\r
- lstContents.Focus();\r
- }\r
-\r
- private void btnExport_Click(object sender, EventArgs e)\r
- {\r
- instance.MainForm.DisplayExportConsole(currentPrim.LocalID);\r
- }\r
-\r
- private void lstContents_MouseDoubleClick(object sender, MouseEventArgs e)\r
- {\r
- if (lstContents.SelectedItems.Count != 1) return;\r
-\r
- ListViewItem contentItem = lstContents.SelectedItems[0];\r
-\r
- if (contentItem.Tag is InventoryLSL)\r
- {\r
- InventoryLSL inv = (InventoryLSL)contentItem.Tag;\r
- Primitive prim = (Primitive)lstContents.Tag;\r
- new ScriptEditor(instance, inv, prim) { Detached = true };\r
- }\r
- else if (contentItem.Tag is InventoryNotecard)\r
- {\r
- InventoryNotecard inv = (InventoryNotecard)contentItem.Tag;\r
- Primitive prim = (Primitive)lstContents.Tag;\r
- new Notecard(instance, inv, prim) { Detached = true };\r
- }\r
-\r
- }\r
-\r
- private void lstContents_KeyDown(object sender, KeyEventArgs e)\r
- {\r
- if (e.KeyCode == Keys.Enter)\r
- {\r
- lstContents_MouseDoubleClick(null, null);\r
-\r
- e.SuppressKeyPress = e.Handled = true;\r
- return;\r
- }\r
- //else if (e.KeyCode == Keys.Apps)\r
- //{\r
- // Point pos = new Point(50, 30);\r
-\r
- // if (lstContents.SelectedItems.Count > 0)\r
- // {\r
- // pos = lstContents.SelectedItems[0].Position;\r
- // pos.Y += 10;\r
- // pos.X += 120;\r
- // }\r
-\r
- // ctxContents.Show(lstContents, pos);\r
-\r
- // e.SuppressKeyPress = e.Handled = true;\r
- // return;\r
- //}\r
- }\r
-\r
- void Self_MuteListUpdated(object sender, EventArgs e)\r
- {\r
- if (InvokeRequired)\r
- {\r
- if (!instance.MonoRuntime || IsHandleCreated)\r
- {\r
- BeginInvoke(new MethodInvoker(() => Self_MuteListUpdated(sender, e)));\r
- }\r
- return;\r
- }\r
-\r
- if (lstPrims.SelectedIndices.Count != 1) return;\r
-\r
- UpdateMuteButton();\r
- }\r
-\r
- void UpdateMuteButton()\r
- {\r
- bool isMuted = null != client.Self.MuteList.Find(me => me.Type == MuteType.Object && me.ID == currentPrim.ID);\r
-\r
- if (isMuted)\r
- {\r
- btnMute.Text = "Unmute";\r
- }\r
- else\r
- {\r
- btnMute.Text = "Mute";\r
- }\r
- }\r
-\r
- private void btnMute_Click(object sender, EventArgs e)\r
- {\r
- if (lstPrims.SelectedIndices.Count != 1) return;\r
-\r
- if (currentPrim.Properties == null) return;\r
-\r
- if (btnMute.Text == "Mute")\r
- {\r
- client.Self.UpdateMuteListEntry(MuteType.Object, currentPrim.ID, currentPrim.Properties.Name);\r
- }\r
- else\r
- {\r
- client.Self.RemoveMuteListEntry(currentPrim.ID, currentPrim.Properties.Name);\r
- }\r
- }\r
-\r
- private void txtObjectName_Leave(object sender, EventArgs e)\r
- {\r
- if (currentPrim == null) return;\r
- if (currentPrim.Properties == null || (currentPrim.Properties != null && currentPrim.Properties.Name != txtObjectName.Text))\r
- {\r
- client.Objects.SetName(client.Network.CurrentSim, currentPrim.LocalID, txtObjectName.Text);\r
- }\r
- }\r
-\r
- private void txtDescription_Leave(object sender, EventArgs e)\r
- {\r
- if (currentPrim == null) return;\r
- if (currentPrim.Properties == null || (currentPrim.Properties != null && currentPrim.Properties.Description != txtDescription.Text))\r
- {\r
- client.Objects.SetDescription(client.Network.CurrentSim, currentPrim.LocalID, txtDescription.Text);\r
- }\r
- }\r
-\r
- private void cbNextOwnerUpdate_CheckedChanged(object sender, EventArgs e)\r
- {\r
- CheckBox cb = (CheckBox)sender;\r
- PermissionMask pm = PermissionMask.None;\r
-\r
- if (cb == cbNextOwnCopy) pm = PermissionMask.Copy;\r
- if (cb == cbNextOwnModify) pm = PermissionMask.Modify;\r
- if (cb == cbNextOwnTransfer) pm = PermissionMask.Transfer;\r
-\r
- if (pm == PermissionMask.None) return;\r
-\r
- client.Objects.SetPermissions(client.Network.CurrentSim, new List<uint>() { currentPrim.LocalID }, PermissionWho.NextOwner, pm, cb.Checked);\r
- }\r
-\r
- private void lstPrims_Enter(object sender, EventArgs e)\r
- {\r
- lstPrims_SelectedIndexChanged(sender, EventArgs.Empty);\r
- }\r
-\r
- private void lstChildren_Enter(object sender, EventArgs e)\r
- {\r
- lstChildren_SelectedIndexChanged(sender, EventArgs.Empty);\r
- }\r
-\r
- private void lstPrims_DoubleClick(object sender, EventArgs e)\r
- {\r
- btnView.PerformClick();\r
- }\r
-\r
- private void lstPrims_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)\r
- {\r
- Primitive prim = null;\r
- try\r
- {\r
- lock (Prims)\r
- {\r
- prim = Prims[e.ItemIndex];\r
- }\r
- }\r
- catch\r
- {\r
- e.Item = new ListViewItem();\r
- return;\r
- }\r
-\r
- string name = GetObjectName(prim);\r
- var item = new ListViewItem(name);\r
- item.Tag = prim;\r
- item.Name = prim.ID.ToString();\r
- e.Item = item;\r
- }\r
-\r
- }\r
-\r
- public enum ObjectConsoleFilter : int\r
- {\r
- Rezzed = 0,\r
- Attached = 1,\r
- Both = 2\r
- }\r
-\r
- public class ObjectSorter : IComparer<Primitive>\r
- {\r
- private AgentManager me;\r
- private bool sortByName = false;\r
-\r
- public bool SortByName { get { return sortByName; } set { sortByName = value; } }\r
-\r
- public ObjectSorter(AgentManager me)\r
- {\r
- this.me = me;\r
- }\r
-\r
- private int NameCompare(Primitive prim1, Primitive prim2)\r
- {\r
- if (prim1.Properties == null && prim2.Properties == null)\r
- {\r
- return 0;\r
- }\r
- else if (prim1.Properties != null && prim2.Properties == null)\r
- {\r
- return -1;\r
- }\r
- else if (prim1.Properties == null && prim2.Properties != null)\r
- {\r
- return 1;\r
- }\r
-\r
- return string.Compare(prim1.Properties.Name, prim2.Properties.Name);\r
- }\r
- //this routine should return -1 if xy and 0 if x==y.\r
- // for our sample we'll just use string comparison\r
- public int Compare(Primitive prim1, Primitive prim2)\r
- {\r
- if (sortByName)\r
- {\r
- return NameCompare(prim1, prim2);\r
- }\r
-\r
- float dist1 = prim1.ParentID == me.LocalID ? 0 : Vector3.Distance(me.SimPosition, prim1.Position);\r
- float dist2 = prim2.ParentID == me.LocalID ? 0 : Vector3.Distance(me.SimPosition, prim2.Position);\r
-\r
- if (dist1 == dist2)\r
- {\r
- return NameCompare(prim1, prim2);\r
- }\r
- else\r
- {\r
- if (dist1 < dist2)\r
- {\r
- return -1;\r
- }\r
- return 1;\r
- }\r
- }\r
- }\r
-\r
- public class PropertiesQueue : IDisposable\r
- {\r
- Object sync = new Object();\r
- RadegastInstance instance;\r
- System.Timers.Timer qTimer;\r
- Queue<Primitive> props = new Queue<Primitive>();\r
-\r
- public delegate void TickCallback(int remaining);\r
- public event TickCallback OnTick;\r
-\r
- public PropertiesQueue(RadegastInstance instance)\r
- {\r
- this.instance = instance;\r
- qTimer = new System.Timers.Timer(2500);\r
- qTimer.Enabled = true;\r
- qTimer.Elapsed += new ElapsedEventHandler(qTimer_Elapsed);\r
- }\r
-\r
- public void RequestProps(Primitive prim)\r
- {\r
- lock (sync)\r
- {\r
- if (!props.Contains(prim))\r
- {\r
- props.Enqueue(prim);\r
- }\r
- }\r
- }\r
-\r
- void qTimer_Elapsed(object sender, ElapsedEventArgs e)\r
- {\r
- lock (sync)\r
- {\r
- for (int i = 0; i < 25 && props.Count > 0; i++)\r
- {\r
- Primitive prim = props.Dequeue();\r
- if (prim.ParentID == 0)\r
- {\r
- instance.Client.Objects.RequestObjectPropertiesFamily(\r
- instance.Client.Network.CurrentSim, prim.ID, true);\r
- }\r
- else\r
- {\r
- instance.Client.Objects.SelectObject(instance.Client.Network.CurrentSim,\r
- prim.LocalID, true);\r
- }\r
- }\r
-\r
- if (OnTick != null)\r
- {\r
- OnTick(props.Count);\r
- }\r
- }\r
- }\r
-\r
- public void Dispose()\r
- {\r
- if (qTimer != null)\r
- {\r
- qTimer.Elapsed -= new ElapsedEventHandler(qTimer_Elapsed);\r
- qTimer.Enabled = false;\r
- qTimer = null;\r
- }\r
- props = null;\r
- instance = null;\r
- }\r
- }\r
-\r
+//
+// Radegast Metaverse Client
+// Copyright (c) 2009-2013, 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;
+using System.Collections.Generic;
+using System.Text;
+using System.Timers;
+using System.Windows.Forms;
+#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.Drawing;
+using OpenMetaverse;
+using OpenMetaverse.Assets;
+
+namespace Radegast
+{
+ public partial class ObjectsConsole : UserControl, IContextMenuProvider
+ {
+ public List<Primitive> Prims = new List<Primitive>();
+
+ private RadegastInstance instance;
+ private GridClient client { get { return instance.Client; } }
+ private Primitive currentPrim = new Primitive();
+ private float searchRadius = 40.0f;
+ //public List<InventoryBase> subitems;
+ PropertiesQueue propRequester;
+ private Thread ContentsThread;
+ private ObjectConsoleFilter filter;
+ private ObjectSorter PrimSorter;
+
+ public Primitive CurrentPrim { get { return currentPrim; } }
+
+ public ObjectsConsole(RadegastInstance instance)
+ {
+ InitializeComponent();
+ Disposed += new EventHandler(frmObjects_Disposed);
+
+ this.instance = instance;
+
+ propRequester = new PropertiesQueue(instance);
+ propRequester.OnTick += new PropertiesQueue.TickCallback(propRequester_OnTick);
+
+ btnPointAt.Text = (this.instance.State.IsPointing ? "Unpoint" : "Point At");
+ State_SitStateChanged(this, new SitEventArgs(instance.State.IsSitting));
+
+ nudRadius.Value = (decimal)searchRadius;
+ nudRadius.ValueChanged += nudRadius_ValueChanged;
+
+ PrimSorter = new ObjectSorter(client.Self);
+
+ lstContents.LargeImageList = frmMain.ResourceImages;
+ lstContents.SmallImageList = frmMain.ResourceImages;
+
+ filter = (ObjectConsoleFilter)instance.GlobalSettings["object_console_filter"].AsInteger();
+ comboFilter.SelectedIndex = 0;
+ try
+ {
+ comboFilter.SelectedIndex = (int)filter;
+ }
+ catch { }
+ comboFilter.SelectedIndexChanged += (ssender, se) =>
+ {
+ instance.GlobalSettings["object_console_filter"] = comboFilter.SelectedIndex;
+ filter = (ObjectConsoleFilter)comboFilter.SelectedIndex;
+ btnRefresh_Click(null, null);
+ };
+
+ //if (instance.MonoRuntime)
+ //{
+ // btnView.Visible = false;
+ //}
+
+ // Callbacks
+ instance.Netcom.ClientDisconnected += new EventHandler<DisconnectedEventArgs>(Netcom_ClientDisconnected);
+ instance.State.SitStateChanged += new EventHandler<SitEventArgs>(State_SitStateChanged);
+ client.Objects.ObjectUpdate += new EventHandler<PrimEventArgs>(Objects_ObjectUpdate);
+ client.Objects.KillObjects += new EventHandler<KillObjectsEventArgs>(Objects_KillObjects);
+ client.Objects.ObjectProperties += new EventHandler<ObjectPropertiesEventArgs>(Objects_ObjectProperties);
+ client.Objects.ObjectPropertiesFamily += new EventHandler<ObjectPropertiesFamilyEventArgs>(Objects_ObjectPropertiesFamily);
+ client.Network.SimChanged += new EventHandler<SimChangedEventArgs>(Network_SimChanged);
+ client.Self.MuteListUpdated += new EventHandler<EventArgs>(Self_MuteListUpdated);
+ instance.Names.NameUpdated += new EventHandler<UUIDNameReplyEventArgs>(Avatars_UUIDNameReply);
+ instance.State.OnWalkStateCanged += new StateManager.WalkStateCanged(State_OnWalkStateCanged);
+ }
+
+ void frmObjects_Disposed(object sender, EventArgs e)
+ {
+ if (ContentsThread != null)
+ {
+ if (ContentsThread.IsAlive) ContentsThread.Abort();
+ ContentsThread = null;
+ }
+
+ propRequester.Dispose();
+ instance.Netcom.ClientDisconnected -= new EventHandler<DisconnectedEventArgs>(Netcom_ClientDisconnected);
+ instance.State.SitStateChanged -= new EventHandler<SitEventArgs>(State_SitStateChanged);
+ client.Objects.ObjectUpdate -= new EventHandler<PrimEventArgs>(Objects_ObjectUpdate);
+ client.Objects.KillObjects -= new EventHandler<KillObjectsEventArgs>(Objects_KillObjects);
+ client.Objects.ObjectProperties -= new EventHandler<ObjectPropertiesEventArgs>(Objects_ObjectProperties);
+ client.Objects.ObjectPropertiesFamily -= new EventHandler<ObjectPropertiesFamilyEventArgs>(Objects_ObjectPropertiesFamily);
+ client.Network.SimChanged -= new EventHandler<SimChangedEventArgs>(Network_SimChanged);
+ client.Self.MuteListUpdated -= new EventHandler<EventArgs>(Self_MuteListUpdated);
+ instance.Names.NameUpdated -= new EventHandler<UUIDNameReplyEventArgs>(Avatars_UUIDNameReply);
+ instance.State.OnWalkStateCanged -= new StateManager.WalkStateCanged(State_OnWalkStateCanged);
+ }
+
+ void State_SitStateChanged(object sender, SitEventArgs e)
+ {
+ if (InvokeRequired)
+ {
+ if (!instance.MonoRuntime || IsHandleCreated)
+ {
+ BeginInvoke(new MethodInvoker(() => State_SitStateChanged(sender, e)));
+ }
+ return;
+ }
+
+ btnSitOn.Text = (this.instance.State.IsSitting ? "Stand Up" : "Sit On");
+ }
+
+ public void RefreshObjectList()
+ {
+ btnRefresh_Click(this, EventArgs.Empty);
+ }
+
+ public List<Primitive> GetObjectList()
+ {
+ return new List<Primitive>(Prims);
+ }
+
+ void propRequester_OnTick(int remaining)
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(delegate()
+ {
+ propRequester_OnTick(remaining);
+ }
+ ));
+ return;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.AppendFormat("Tracking {0} objects", Prims.Count);
+
+ if (remaining > 10)
+ {
+ sb.AppendFormat(", fetching {0} object names.", remaining);
+ }
+ else
+ {
+ sb.Append(".");
+ }
+
+ lock (Prims)
+ {
+ Prims.Sort(PrimSorter);
+ lstPrims.VirtualListSize = Prims.Count;
+ }
+ lstPrims.Invalidate();
+ lblStatus.Text = sb.ToString();
+ }
+
+ void Network_SimChanged(object sender, SimChangedEventArgs e)
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(() => Network_SimChanged(sender, e)));
+ return;
+ }
+
+ btnRefresh_Click(null, null);
+ }
+
+ void Avatars_UUIDNameReply(object sender, UUIDNameReplyEventArgs e)
+ {
+ int minIndex = -1;
+ int maxIndex = -1;
+ bool updated = false;
+
+ lock (Prims)
+ {
+ for (int i = 0; i < Prims.Count; i++)
+ {
+ Primitive prim = Prims[i];
+ if (prim.Properties != null && e.Names.ContainsKey(prim.Properties.OwnerID))
+ {
+ if (minIndex == -1 || i < minIndex) minIndex = i;
+ if (i > maxIndex) maxIndex = i;
+ updated = true;
+ }
+ }
+ }
+
+ if (updated)
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(() =>
+ {
+ try
+ {
+ lstPrims.RedrawItems(minIndex, maxIndex, true);
+ }
+ catch { }
+ }));
+ }
+ else
+ {
+ lstPrims.RedrawItems(minIndex, maxIndex, true);
+ }
+ }
+ }
+
+ void UpdateProperties(Primitive.ObjectProperties props)
+ {
+ lock (Prims)
+ {
+ for (int i = 0; i < Prims.Count; i++)
+ {
+ if (Prims[i].ID == props.ObjectID)
+ {
+ Prims[i].Properties = props;
+ try
+ {
+ lstPrims.RedrawItems(i, i, true);
+ }
+ catch { }
+ break;
+ }
+ }
+ }
+
+ lock (lstChildren.Items)
+ {
+ if (lstChildren.Items.ContainsKey(props.ObjectID.ToString()))
+ {
+ Primitive prim = lstChildren.Items[props.ObjectID.ToString()].Tag as Primitive;
+ prim.Properties = props;
+ lstChildren.Items[props.ObjectID.ToString()].Text = prim.Properties.Name;
+ }
+ }
+
+ if (props.ObjectID == currentPrim.ID)
+ {
+ UpdateCurrentObject(false);
+ }
+ }
+
+ void Objects_ObjectProperties(object sender, ObjectPropertiesEventArgs e)
+ {
+ if (e.Simulator.Handle != client.Network.CurrentSim.Handle)
+ {
+ return;
+ }
+
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(delegate() { Objects_ObjectProperties(sender, e); }));
+ return;
+ }
+
+ UpdateProperties(e.Properties);
+ }
+
+ void Objects_ObjectPropertiesFamily(object sender, ObjectPropertiesFamilyEventArgs e)
+ {
+ if (e.Simulator.Handle != client.Network.CurrentSim.Handle)
+ {
+ return;
+ }
+
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(delegate() { Objects_ObjectPropertiesFamily(sender, e); }));
+ return;
+ }
+
+ UpdateProperties(e.Properties);
+ }
+
+
+ void UpdateObjectContents()
+ {
+ if (ContentsThread != null)
+ {
+ if (ContentsThread.IsAlive) ContentsThread.Abort();
+ ContentsThread = null;
+ }
+
+ lstContents.Items.Clear();
+ ListViewItem entry = new ListViewItem();
+ entry.SubItems.Add("Loading...");
+ lstContents.Items.Add(entry);
+
+ ContentsThread = new Thread(new ThreadStart(() =>
+ {
+ lstContents.Tag = currentPrim;
+ List<InventoryBase> items = client.Inventory.GetTaskInventory(currentPrim.ID, currentPrim.LocalID, 1000 * 30);
+ lstContents.Invoke(new MethodInvoker(() => UpdateContentsList(items)));
+ }));
+
+ ContentsThread.IsBackground = true;
+ ContentsThread.Start();
+
+ }
+
+ void UpdateContentsList(List<InventoryBase> items)
+ {
+ //object inventory in liste reinlesen
+ lstContents.Items.Clear();
+ btnOpen.Enabled = false;
+ Primitive prim = (Primitive)lstContents.Tag;
+
+ //subitems = items;
+ if (items == null)
+ {
+ ListViewItem entry = new ListViewItem();
+ entry.SubItems.Add("(failied to fetch contents)");
+ entry.SubItems[0].Font = new System.Drawing.Font(entry.SubItems[0].Font, System.Drawing.FontStyle.Italic);
+ lstContents.Items.Add(entry);
+ }
+ else
+ {
+ if (items.Count == 0)
+ {
+ ListViewItem entry = new ListViewItem();
+ entry.SubItems.Add("(empty object)");
+ entry.SubItems[0].Font = new System.Drawing.Font(entry.SubItems[0].Font, System.Drawing.FontStyle.Italic);
+ lstContents.Items.Add(entry);
+ }
+ else
+ {
+ btnOpen.Enabled = prim.Properties != null && prim.Properties.OwnerID == client.Self.AgentID;
+
+ for (int i = 0; i < items.Count; i++)
+ {
+ if (items[i] is InventoryItem)
+ {
+ InventoryItem item = (InventoryItem)items[i];
+ ListViewItem entry = new ListViewItem();
+
+ entry.ImageIndex = InventoryConsole.GetItemImageIndex(item.AssetType.ToString().ToLower());
+ entry.Tag = item;
+
+ ListViewItem.ListViewSubItem sub;
+
+ entry.SubItems.Add(sub = new ListViewItem.ListViewSubItem()
+ {
+ Name = item.UUID.ToString(),
+ Text = item.Name
+ });
+
+ if ((item.Permissions.OwnerMask & PermissionMask.Modify) == 0)
+ sub.Text += " (no modify)";
+
+ if ((item.Permissions.OwnerMask & PermissionMask.Copy) == 0)
+ sub.Text += " (no copy)";
+
+ if ((item.Permissions.OwnerMask & PermissionMask.Transfer) == 0)
+ sub.Text += " (no transfer)";
+
+ sub.Text += " (" + item.InventoryType.ToString() + ")";
+ entry.ToolTipText = sub.Text;
+
+ lstContents.Items.Add(entry);
+ }
+ }
+ }
+ }
+ }
+
+ private void ctxContents_Opening(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ e.Cancel = false;
+
+ if (!(lstContents.Tag is Primitive))
+ {
+ e.Cancel = true;
+ return;
+ }
+
+ ctxContents.Items.Clear();
+ Primitive prim = (Primitive)lstContents.Tag;
+ bool canModify = (prim.Flags & PrimFlags.ObjectModify) == PrimFlags.ObjectModify;
+
+ if (lstContents.SelectedItems.Count == 1)
+ {
+ ListViewItem entry = lstContents.SelectedItems[0];
+
+ if (entry.Tag is InventoryItem)
+ {
+ InventoryItem item = (InventoryItem)entry.Tag;
+
+ if (canModify)
+ {
+ switch (item.InventoryType)
+ {
+ case InventoryType.Notecard:
+ ctxContents.Items.Add("Edit Notecard", null, (object sd, EventArgs ev) =>
+ {
+ InventoryNotecard inv = (InventoryNotecard)entry.Tag;
+ new Notecard(instance, inv, prim) { Detached = true };
+ }
+ );
+ break;
+
+ case InventoryType.LSL:
+ ctxContents.Items.Add("Edit Script", null, (object sd, EventArgs ev) =>
+ {
+ InventoryLSL inv = (InventoryLSL)entry.Tag;
+ new ScriptEditor(instance, inv, prim) { Detached = true };
+ }
+ );
+ break;
+ }
+
+ }
+ }
+ }
+
+ if (lstContents.SelectedItems.Count > 0)
+ {
+ ctxContents.Items.Add("Delete", null, (object sd, EventArgs ev) =>
+ {
+ foreach (ListViewItem i in lstContents.SelectedItems)
+ if (i.Tag is InventoryItem)
+ client.Inventory.RemoveTaskInventory(prim.LocalID, ((InventoryItem)i.Tag).UUID, client.Network.CurrentSim);
+ });
+ }
+
+ if (ctxContents.Items.Count != 0)
+ {
+ ctxContents.Items.Add(new ToolStripSeparator());
+ }
+
+ if ((canModify || (prim.Flags & PrimFlags.AllowInventoryDrop) == PrimFlags.AllowInventoryDrop) && instance.InventoryClipboard != null)
+ {
+ if (instance.InventoryClipboard.Item is InventoryItem)
+ {
+ ctxContents.Items.Add("Paste from Inventory", null, (object sd, EventArgs ev) =>
+ {
+ if (instance.InventoryClipboard.Item is InventoryLSL)
+ {
+ client.Inventory.CopyScriptToTask(prim.LocalID, (InventoryItem)instance.InventoryClipboard.Item, true);
+ }
+ else
+ {
+ client.Inventory.UpdateTaskInventory(prim.LocalID, (InventoryItem)instance.InventoryClipboard.Item);
+ }
+ });
+ }
+ else if (instance.InventoryClipboard.Item is InventoryFolder)
+ {
+ ctxContents.Items.Add("Paste Folder Contents", null, (object sd, EventArgs ev) =>
+ {
+ foreach (InventoryBase oldItem in client.Inventory.Store.GetContents((InventoryFolder)instance.InventoryClipboard.Item))
+ {
+ if (oldItem is InventoryItem)
+ {
+ if (oldItem is InventoryLSL)
+ {
+ client.Inventory.CopyScriptToTask(prim.LocalID, (InventoryItem)oldItem, true);
+ }
+ else
+ {
+ client.Inventory.UpdateTaskInventory(prim.LocalID, (InventoryItem)oldItem);
+ }
+ }
+ }
+ });
+ }
+ }
+
+ if (canModify)
+ {
+ ctxContents.Items.Add("Open (copy all to inventory)", null, OpenObject);
+ }
+
+ ctxContents.Items.Add("Close", null, btnCloseContents_Click);
+ }
+
+ void OpenObject(object sender, EventArgs e)
+ {
+ if (!(lstContents.Tag is Primitive)) return;
+
+ Primitive prim = (Primitive)lstContents.Tag;
+ if (prim.Properties == null) return;
+
+ List<InventoryItem> items = new List<InventoryItem>();
+
+ foreach (ListViewItem item in lstContents.Items)
+ {
+ if (item.Tag is InventoryItem)
+ items.Add(item.Tag as InventoryItem);
+ }
+
+ if (items.Count == 0) return;
+
+ UUID folderID = client.Inventory.CreateFolder(client.Inventory.Store.RootFolder.UUID, prim.Properties.Name);
+
+ for (int i = 0; i < items.Count; i++)
+ {
+ client.Inventory.MoveTaskInventory(prim.LocalID, items[i].UUID, folderID, client.Network.CurrentSim);
+ }
+
+ instance.TabConsole.DisplayNotificationInChat("Items from object contents copied to new inventory folder " + prim.Properties.Name);
+
+ }
+
+ void UpdateCurrentObject()
+ {
+ UpdateCurrentObject(true);
+ }
+
+ void UpdateCurrentObject(bool updateContents)
+ {
+ if (currentPrim.Properties == null) return;
+
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(delegate() { UpdateCurrentObject(updateContents); }));
+ return;
+ }
+
+ // currentItem.Text = GetObjectName(currentPrim);
+
+ txtObjectName.Text = currentPrim.Properties.Name;
+ txtDescription.Text = currentPrim.Properties.Description;
+ if ((currentPrim.Flags & PrimFlags.ObjectModify) == PrimFlags.ObjectModify)
+ {
+ txtObjectName.ReadOnly = txtDescription.ReadOnly = false;
+ gbxObjectDetails.Text = "Object details (you can modify)";
+ }
+ else
+ {
+ txtObjectName.ReadOnly = txtDescription.ReadOnly = true;
+ gbxObjectDetails.Text = "Object details";
+ }
+
+ txtHover.Text = currentPrim.Text;
+ txtOwner.AgentID = currentPrim.Properties.OwnerID;
+ txtCreator.AgentID = currentPrim.Properties.CreatorID;
+
+ Permissions p = currentPrim.Properties.Permissions;
+ cbOwnerModify.Checked = (p.OwnerMask & PermissionMask.Modify) != 0;
+ cbOwnerCopy.Checked = (p.OwnerMask & PermissionMask.Copy) != 0;
+ cbOwnerTransfer.Checked = (p.OwnerMask & PermissionMask.Transfer) != 0;
+
+ cbNextOwnModify.CheckedChanged -= cbNextOwnerUpdate_CheckedChanged;
+ cbNextOwnCopy.CheckedChanged -= cbNextOwnerUpdate_CheckedChanged;
+ cbNextOwnTransfer.CheckedChanged -= cbNextOwnerUpdate_CheckedChanged;
+
+ cbNextOwnModify.Checked = (p.NextOwnerMask & PermissionMask.Modify) != 0;
+ cbNextOwnCopy.Checked = (p.NextOwnerMask & PermissionMask.Copy) != 0;
+ cbNextOwnTransfer.Checked = (p.NextOwnerMask & PermissionMask.Transfer) != 0;
+
+ cbNextOwnModify.CheckedChanged += cbNextOwnerUpdate_CheckedChanged;
+ cbNextOwnCopy.CheckedChanged += cbNextOwnerUpdate_CheckedChanged;
+ cbNextOwnTransfer.CheckedChanged += cbNextOwnerUpdate_CheckedChanged;
+
+ if (currentPrim.Properties.OwnerID == client.Self.AgentID)
+ {
+ cbNextOwnModify.Enabled = cbNextOwnCopy.Enabled = cbNextOwnTransfer.Enabled = true;
+ }
+ else
+ {
+ cbNextOwnModify.Enabled = cbNextOwnCopy.Enabled = cbNextOwnTransfer.Enabled = false;
+ }
+
+ txtPrims.Text = (client.Network.CurrentSim.ObjectsPrimitives.FindAll(
+ delegate(Primitive prim)
+ {
+ return prim.ParentID == currentPrim.LocalID || prim.LocalID == currentPrim.LocalID;
+ })).Count.ToString();
+
+ if ((currentPrim.Flags & PrimFlags.Money) != 0)
+ {
+ btnPay.Enabled = true;
+ }
+ else
+ {
+ btnPay.Enabled = false;
+ }
+
+ if (currentPrim.Properties.SaleType != SaleType.Not)
+ {
+ btnBuy.Text = string.Format("Buy $L{0}", currentPrim.Properties.SalePrice);
+ btnBuy.Enabled = true;
+ }
+ else
+ {
+ btnBuy.Text = "Buy";
+ btnBuy.Enabled = false;
+ }
+
+ if (gbxContents.Visible /*&& updateContents*/)
+ {
+ UpdateObjectContents();
+ }
+
+ UpdateMuteButton();
+ }
+
+ void Netcom_ClientDisconnected(object sender, DisconnectedEventArgs e)
+ {
+ if (InvokeRequired)
+ {
+ if (!instance.MonoRuntime || IsHandleCreated)
+ {
+ BeginInvoke(new MethodInvoker(() => Netcom_ClientDisconnected(sender, e)));
+ }
+ return;
+ }
+
+ if (instance.TabConsole.TabExists("objects"))
+ {
+ instance.TabConsole.Tabs["objects"].Close();
+ }
+ }
+
+ private string GetObjectName(Primitive prim, int distance)
+ {
+ string name = "Loading...";
+ string ownerName = "Loading...";
+
+ if (prim.Properties != null)
+ {
+ name = prim.Properties.Name;
+ // prim.Properties.GroupID is the actual group when group owned, not prim.GroupID
+ if (UUID.Zero == prim.Properties.OwnerID &&
+ PrimFlags.ObjectGroupOwned == (prim.Flags & PrimFlags.ObjectGroupOwned) &&
+ UUID.Zero != prim.Properties.GroupID)
+ {
+ System.Threading.AutoResetEvent nameReceivedSignal = new System.Threading.AutoResetEvent(false);
+ EventHandler<GroupNamesEventArgs> cbGroupName = new EventHandler<GroupNamesEventArgs>(
+ delegate(object sender, GroupNamesEventArgs e)
+ {
+ if (e.GroupNames.ContainsKey(prim.Properties.GroupID))
+ {
+ e.GroupNames.TryGetValue(prim.Properties.GroupID, out ownerName);
+ if (string.IsNullOrEmpty(ownerName))
+ ownerName = "Loading...";
+ if (null != nameReceivedSignal)
+ nameReceivedSignal.Set();
+ }
+ });
+ client.Groups.GroupNamesReply += cbGroupName;
+ client.Groups.RequestGroupName(prim.Properties.GroupID);
+ nameReceivedSignal.WaitOne(5000, false);
+ nameReceivedSignal.Close();
+ client.Groups.GroupNamesReply -= cbGroupName;
+ }
+ else
+ ownerName = instance.Names.Get(prim.Properties.OwnerID);
+ }
+
+ if (prim.ParentID == client.Self.LocalID)
+ {
+ return string.Format("{0} attached to {1}", name, prim.PrimData.AttachmentPoint.ToString());
+ }
+ else if (ownerName != "Loading...")
+ {
+ return String.Format("{0} ({1}m) owned by {2}", name, distance, ownerName);
+ }
+ else
+ {
+ return String.Format("{0} ({1}m)", name, distance);
+ }
+
+ }
+
+ private string GetObjectName(Primitive prim)
+ {
+ int distance = (int)Vector3.Distance(client.Self.SimPosition, prim.Position);
+ if (prim.ParentID == client.Self.LocalID) distance = 0;
+ return GetObjectName(prim, distance);
+ }
+
+ private void AddPrim(Primitive prim)
+ {
+ lock (Prims)
+ {
+ string name = GetObjectName(prim);
+ if (!Prims.Contains(prim) && (txtSearch.Text.Length == 0 || name.ToLower().Contains(txtSearch.Text.ToLower())))
+ {
+ Prims.Add(prim);
+ if (prim.Properties == null)
+ {
+ propRequester.RequestProps(prim);
+ }
+ }
+ }
+ }
+
+ void Objects_ObjectUpdate(object sender, PrimEventArgs e)
+ {
+ if (e.Simulator.Handle != client.Network.CurrentSim.Handle || e.Prim.Position == Vector3.Zero || e.Prim is Avatar) return;
+
+ if (IncludePrim(e.Prim))
+ {
+ if (e.Prim.ParentID == 0)
+ {
+ int distance = (int)Vector3.Distance(client.Self.SimPosition, e.Prim.Position);
+ if (distance < searchRadius)
+ {
+ AddPrim(e.Prim);
+ }
+ }
+ else if (e.Prim.ParentID == client.Self.LocalID)
+ {
+ AddPrim(e.Prim);
+ }
+ }
+
+ if (e.Prim.ID == currentPrim.ID)
+ {
+ if (currentPrim.Properties != null)
+ {
+ UpdateCurrentObject(false);
+ }
+ }
+ }
+
+ void Objects_KillObjects(object sender, KillObjectsEventArgs e)
+ {
+ if (e.Simulator.Handle != client.Network.CurrentSim.Handle) return;
+
+ lock (Prims)
+ {
+ List<Primitive> killed = Prims.FindAll((p) =>
+ {
+ for (int i = 0; i < e.ObjectLocalIDs.Length; i++)
+ {
+ if (p.LocalID == e.ObjectLocalIDs[i])
+ {
+ return true;
+ }
+ }
+ return false;
+ });
+
+ foreach (Primitive prim in killed)
+ {
+ Prims.Remove(prim);
+ }
+ }
+
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(() =>
+ {
+ lstPrims.VirtualListSize = Prims.Count;
+ lstPrims.Invalidate();
+ }));
+ }
+ else
+ {
+ lstPrims.VirtualListSize = Prims.Count;
+ lstPrims.Invalidate();
+ }
+
+ }
+
+ private bool IncludePrim(Primitive prim)
+ {
+ if ((prim.ParentID == client.Self.LocalID) && (filter == ObjectConsoleFilter.Attached || filter == ObjectConsoleFilter.Both))
+ {
+ return true;
+ }
+ else if ((prim.ParentID == 0) && (filter == ObjectConsoleFilter.Rezzed || filter == ObjectConsoleFilter.Both))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private void AddAllObjects()
+ {
+ Vector3 location = client.Self.SimPosition;
+
+ lock (Prims)
+ {
+ /*
+ var prims = client.Network.CurrentSim.ObjectsPrimitives.FindAll(prim =>
+ {
+ return ((prim.ParentID == client.Self.LocalID) && (filter == ObjectConsoleFilter.Attached || filter == ObjectConsoleFilter.Both)) ||
+ ((prim.ParentID == 0) && (filter == ObjectConsoleFilter.Rezzed || filter == ObjectConsoleFilter.Both));
+ });
+ */
+ client.Network.CurrentSim.ObjectsPrimitives.ForEach(prim =>
+ {
+ int distance = (int)Vector3.Distance(prim.Position, location);
+ if (prim.ParentID == client.Self.LocalID)
+ {
+ distance = 0;
+ }
+ if (IncludePrim(prim) &&
+ (prim.Position != Vector3.Zero) &&
+ (distance < searchRadius) &&
+ (txtSearch.Text.Length == 0 || (prim.Properties != null && prim.Properties.Name.ToLower().Contains(txtSearch.Text.ToLower()))) && //root prims and attachments only
+ !Prims.Contains(prim))
+ {
+ Prims.Add(prim);
+ if (prim.Properties == null)
+ {
+ propRequester.RequestProps(prim);
+ }
+ }
+ });
+ Prims.Sort(PrimSorter);
+ lstPrims.VirtualListSize = Prims.Count;
+ lstPrims.Invalidate();
+ }
+ }
+
+ private void btnPointAt_Click(object sender, EventArgs e)
+ {
+ if (btnPointAt.Text == "Point At")
+ {
+ instance.State.SetPointing(currentPrim, 3);
+ btnPointAt.Text = "Unpoint";
+ }
+ else if (btnPointAt.Text == "Unpoint")
+ {
+ instance.State.UnSetPointing();
+ btnPointAt.Text = "Point At";
+ }
+ }
+
+ private void btnSitOn_Click(object sender, EventArgs e)
+ {
+ if (!instance.State.IsSitting)
+ {
+ instance.State.SetSitting(true, currentPrim.ID);
+ }
+ else
+ {
+ instance.State.SetSitting(false, currentPrim.ID);
+ }
+ }
+
+ private void btnTouch_Click(object sender, EventArgs e)
+ {
+ client.Self.Touch(currentPrim.LocalID);
+ }
+
+ private void txtSearch_TextChanged(object sender, EventArgs e)
+ {
+ btnRefresh_Click(null, null);
+ }
+
+ private void btnClear_Click(object sender, EventArgs e)
+ {
+ txtSearch.Clear();
+ txtSearch.Select();
+ btnRefresh_Click(null, null);
+ }
+
+ private void btnRefresh_Click(object sender, EventArgs e)
+ {
+ instance.State.SetDefaultCamera();
+ Cursor.Current = Cursors.WaitCursor;
+ Prims.Clear();
+ AddAllObjects();
+
+ Cursor.Current = Cursors.Default;
+ }
+
+ private void lstPrims_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (lstPrims.SelectedIndices.Count == 1)
+ {
+ lock (Prims)
+ {
+ try
+ {
+ currentPrim = Prims[lstPrims.SelectedIndices[0]];
+ }
+ catch
+ {
+ gbxInworld.Enabled = false;
+ return;
+ }
+ }
+
+ gbxInworld.Enabled = true;
+ btnBuy.Tag = currentPrim;
+
+ if (currentPrim.Properties == null || currentPrim.OwnerID == UUID.Zero || (currentPrim.Properties != null && currentPrim.Properties.CreatorID == UUID.Zero))
+ {
+ client.Objects.SelectObject(client.Network.CurrentSim, currentPrim.LocalID);
+ }
+
+ UpdateCurrentObject();
+ UpdateChildren();
+ }
+ else
+ {
+ lstChildren.Visible = false;
+ gbxInworld.Enabled = false;
+ }
+ }
+
+ private void lstChildren_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if (lstChildren.SelectedItems.Count == 1)
+ {
+ gbxInworld.Enabled = true;
+ currentPrim = lstChildren.SelectedItems[0].Tag as Primitive;
+ btnBuy.Tag = currentPrim;
+
+ if (currentPrim.Properties == null || (currentPrim.Properties != null && currentPrim.Properties.CreatorID == UUID.Zero))
+ {
+ client.Objects.SelectObject(client.Network.CurrentSim, currentPrim.LocalID);
+ }
+
+ UpdateCurrentObject();
+ }
+ else
+ {
+ gbxInworld.Enabled = false;
+ }
+ }
+
+ void UpdateChildren()
+ {
+ if (currentPrim == null) return;
+ var prims = client.Network.CurrentSim.ObjectsPrimitives.FindAll((Primitive p) => p.ParentID == currentPrim.LocalID);
+ if (prims == null || prims.Count == 0) return;
+ List<uint> toGetNames = new List<uint>();
+
+ lstChildren.BeginUpdate();
+ lock (lstChildren.Items)
+ {
+ lstChildren.Items.Clear();
+ foreach (var prim in prims)
+ {
+ var item = new ListViewItem();
+
+ if (prim.Properties != null)
+ {
+ item.Text = prim.Properties.Name;
+ }
+ else
+ {
+ item.Text = "Loading...";
+ toGetNames.Add(prim.LocalID);
+ }
+
+ item.Tag = prim;
+ item.Name = prim.ID.ToString();
+ lstChildren.Items.Add(item);
+ }
+ }
+ lstChildren.EndUpdate();
+ lstChildren.Visible = true;
+ if (toGetNames.Count > 0)
+ {
+ client.Objects.SelectObjects(client.Network.CurrentSim, toGetNames.ToArray(), true);
+ }
+ }
+
+ private void btnPay_Click(object sender, EventArgs e)
+ {
+ (new frmPay(instance, currentPrim.ID, currentPrim.Properties.Name, true)).ShowDialog();
+ }
+
+ private void btnDetach_Click(object sender, EventArgs e)
+ {
+ var toDetach = CurrentOutfitFolder.GetAttachmentItem(currentPrim);
+ if (toDetach != UUID.Zero)
+ {
+ if (client.Inventory.Store.Contains(toDetach))
+ {
+ instance.COF.Detach(client.Inventory.Store[toDetach] as InventoryItem);
+ }
+ }
+ }
+
+ private void btnView_Click(object sender, EventArgs e)
+ {
+ if (currentPrim.PrimData.PCode != PCode.Prim)
+ {
+ instance.TabConsole.DisplayNotificationInChat("Cannot display objects of that type", ChatBufferTextStyle.Error);
+ return;
+ }
+
+ Rendering.frmPrimWorkshop pw = new Rendering.frmPrimWorkshop(instance, currentPrim.LocalID);
+ pw.Show();
+ }
+
+ private void nudRadius_ValueChanged(object sender, EventArgs e)
+ {
+ searchRadius = (float)nudRadius.Value;
+ btnRefresh_Click(null, null);
+ }
+
+ private void btnBuy_Click(object sender, EventArgs e)
+ {
+ if (lstPrims.SelectedIndices.Count != 1) return;
+ btnBuy.Enabled = false;
+ client.Objects.BuyObject(client.Network.CurrentSim, currentPrim.LocalID, currentPrim.Properties.SaleType, currentPrim.Properties.SalePrice, client.Self.ActiveGroup, client.Inventory.FindFolderForType(AssetType.Object));
+ }
+
+ private void rbDistance_CheckedChanged(object sender, EventArgs e)
+ {
+ if (rbDistance.Checked)
+ {
+ PrimSorter.SortByName = false;
+ lock (Prims) Prims.Sort(PrimSorter);
+ lstPrims.Invalidate();
+ }
+ }
+
+ private void rbName_CheckedChanged(object sender, EventArgs e)
+ {
+ if (rbName.Checked)
+ {
+ PrimSorter.SortByName = true;
+ lock (Prims) Prims.Sort(PrimSorter);
+ lstPrims.Invalidate();
+ }
+ }
+
+ private void btnTurnTo_Click(object sender, EventArgs e)
+ {
+ if (lstPrims.SelectedIndices.Count != 1) return;
+ client.Self.Movement.TurnToward(currentPrim.Position);
+ }
+
+ private void btnWalkTo_Click(object sender, EventArgs e)
+ {
+ if (lstPrims.SelectedIndices.Count != 1) return;
+
+ if (instance.State.IsWalking)
+ {
+ instance.State.EndWalking();
+ }
+ else
+ {
+ instance.State.WalkTo(currentPrim);
+ }
+ }
+
+ void State_OnWalkStateCanged(bool walking)
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(delegate() { State_OnWalkStateCanged(walking); }));
+ return;
+ }
+
+ if (walking)
+ {
+ btnWalkTo.Text = "Stop";
+ }
+ else
+ {
+ btnWalkTo.Text = "Walk to";
+ btnRefresh_Click(null, null);
+ }
+ }
+
+ private void nudRadius_KeyUp(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Enter)
+ {
+ e.SuppressKeyPress = true;
+ }
+ }
+
+ private void nudRadius_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Enter)
+ {
+ e.SuppressKeyPress = true;
+ }
+ }
+
+ private void ctxMenuObjects_Opening(object sender, System.ComponentModel.CancelEventArgs e)
+ {
+ e.Cancel = false;
+
+ if (lstPrims.SelectedIndices.Count != 1)
+ {
+ e.Cancel = true;
+ return;
+ }
+
+ ctxMenuObjects.Items.Clear();
+ ctxMenuObjects.Items.Add("Click/Touch", null, btnTouch_Click);
+
+ if (currentPrim.ParentID == client.Self.LocalID)
+ ctxMenuObjects.Items.Add("Detach", null, btnDetach_Click);
+
+ if ((currentPrim.Flags & PrimFlags.Money) != 0)
+ ctxMenuObjects.Items.Add("Pay", null, btnPay_Click);
+
+ if (currentPrim.Properties != null && currentPrim.Properties.SaleType != SaleType.Not)
+ ctxMenuObjects.Items.Add(string.Format("Buy for ${0}", currentPrim.Properties.SalePrice), null, btnBuy_Click);
+
+ if (gbxInworld.Visible)
+ ctxMenuObjects.Items.Add("Show Contents", null, btnContents_Click);
+ else
+ ctxMenuObjects.Items.Add("Hide Contents", null, btnCloseContents_Click);
+
+ ctxMenuObjects.Items.Add(this.instance.State.IsSitting ? "Stand Up" : "Sit On", null, btnSitOn_Click);
+ ctxMenuObjects.Items.Add("Turn To", null, btnTurnTo_Click);
+ ctxMenuObjects.Items.Add("Walk To", null, btnWalkTo_Click);
+ ctxMenuObjects.Items.Add(this.instance.State.IsPointing ? "Unpoint" : "Point At", null, btnPointAt_Click);
+ ctxMenuObjects.Items.Add("3D View", null, btnView_Click);
+ ctxMenuObjects.Items.Add("Take", null, btnTake_Click);
+ ctxMenuObjects.Items.Add("Delete", null, btnDelete_Click);
+ ctxMenuObjects.Items.Add("Return", null, btnReturn_Click);
+
+ if (currentPrim.Properties != null)
+ {
+ if (currentPrim.Properties.CreatorID == client.Self.AgentID &&
+ currentPrim.Properties.OwnerID == client.Self.AgentID)
+ {
+ ctxMenuObjects.Items.Add("Export", null, btnExport_Click);
+ }
+ }
+
+ if (currentPrim.Properties != null)
+ {
+ bool isMuted = null != client.Self.MuteList.Find(me => me.Type == MuteType.Object && me.ID == currentPrim.ID);
+
+ if (isMuted)
+ {
+ ctxMenuObjects.Items.Add("Unmute", null, (a, b) =>
+ {
+ client.Self.RemoveMuteListEntry(currentPrim.ID, currentPrim.Properties.Name);
+ });
+ }
+ else
+ {
+ ctxMenuObjects.Items.Add("Mute", null, (a, b) =>
+ {
+ client.Self.UpdateMuteListEntry(MuteType.Object, currentPrim.ID, currentPrim.Properties.Name);
+ });
+ }
+ }
+
+ //if (currentPrim.MediaURL != null && currentPrim.MediaURL.StartsWith("x-mv:"))
+ //{
+ // ctxMenuObjects.Items.Add("Test", null, (object menuSender, EventArgs menuE) =>
+ // {
+ // client.Objects.RequestObjectMedia(currentPrim.ID, client.Network.CurrentSim, (bool success, string version, MediaEntry[] faceMedia) =>
+ // {
+ // int foo = 1;
+ // }
+ // );
+ // }
+ // );
+ //}
+
+ instance.ContextActionManager.AddContributions(ctxMenuObjects, currentPrim);
+ }
+
+ public RadegastContextMenuStrip GetContextMenu()
+ {
+ return ctxMenuObjects;
+ }
+
+ private void btnTake_Click(object sender, EventArgs e)
+ {
+ instance.MediaManager.PlayUISound(UISounds.ObjectDelete);
+ client.Inventory.RequestDeRezToInventory(currentPrim.LocalID);
+ }
+
+ private void btnDelete_Click(object sender, EventArgs e)
+ {
+ if (currentPrim.Properties != null && currentPrim.Properties.OwnerID != client.Self.AgentID)
+ btnReturn_Click(sender, e);
+ else
+ {
+ instance.MediaManager.PlayUISound(UISounds.ObjectDelete);
+ client.Inventory.RequestDeRezToInventory(currentPrim.LocalID, DeRezDestination.AgentInventoryTake, client.Inventory.FindFolderForType(AssetType.TrashFolder), UUID.Random());
+ }
+ }
+
+ private void btnReturn_Click(object sender, EventArgs e)
+ {
+ instance.MediaManager.PlayUISound(UISounds.ObjectDelete);
+ client.Inventory.RequestDeRezToInventory(currentPrim.LocalID, DeRezDestination.ReturnToOwner, UUID.Zero, UUID.Random());
+ }
+
+ private void btnCloseContents_Click(object sender, EventArgs e)
+ {
+ gbxContents.Hide();
+ gbxInworld.Show();
+ lstPrims.Focus();
+ }
+
+ private void btnContents_Click(object sender, EventArgs e)
+ {
+ gbxInworld.Hide();
+ gbxContents.Show();
+ UpdateObjectContents();
+ lstContents.Focus();
+ }
+
+ private void btnExport_Click(object sender, EventArgs e)
+ {
+ instance.MainForm.DisplayExportConsole(currentPrim.LocalID);
+ }
+
+ private void lstContents_MouseDoubleClick(object sender, MouseEventArgs e)
+ {
+ if (lstContents.SelectedItems.Count != 1) return;
+
+ ListViewItem contentItem = lstContents.SelectedItems[0];
+
+ if (contentItem.Tag is InventoryLSL)
+ {
+ InventoryLSL inv = (InventoryLSL)contentItem.Tag;
+ Primitive prim = (Primitive)lstContents.Tag;
+ new ScriptEditor(instance, inv, prim) { Detached = true };
+ }
+ else if (contentItem.Tag is InventoryNotecard)
+ {
+ InventoryNotecard inv = (InventoryNotecard)contentItem.Tag;
+ Primitive prim = (Primitive)lstContents.Tag;
+ new Notecard(instance, inv, prim) { Detached = true };
+ }
+
+ }
+
+ private void lstContents_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.KeyCode == Keys.Enter)
+ {
+ lstContents_MouseDoubleClick(null, null);
+
+ e.SuppressKeyPress = e.Handled = true;
+ return;
+ }
+ //else if (e.KeyCode == Keys.Apps)
+ //{
+ // Point pos = new Point(50, 30);
+
+ // if (lstContents.SelectedItems.Count > 0)
+ // {
+ // pos = lstContents.SelectedItems[0].Position;
+ // pos.Y += 10;
+ // pos.X += 120;
+ // }
+
+ // ctxContents.Show(lstContents, pos);
+
+ // e.SuppressKeyPress = e.Handled = true;
+ // return;
+ //}
+ }
+
+ void Self_MuteListUpdated(object sender, EventArgs e)
+ {
+ if (InvokeRequired)
+ {
+ if (!instance.MonoRuntime || IsHandleCreated)
+ {
+ BeginInvoke(new MethodInvoker(() => Self_MuteListUpdated(sender, e)));
+ }
+ return;
+ }
+
+ if (lstPrims.SelectedIndices.Count != 1) return;
+
+ UpdateMuteButton();
+ }
+
+ void UpdateMuteButton()
+ {
+ bool isMuted = null != client.Self.MuteList.Find(me => me.Type == MuteType.Object && me.ID == currentPrim.ID);
+
+ if (isMuted)
+ {
+ btnMute.Text = "Unmute";
+ }
+ else
+ {
+ btnMute.Text = "Mute";
+ }
+ }
+
+ private void btnMute_Click(object sender, EventArgs e)
+ {
+ if (lstPrims.SelectedIndices.Count != 1) return;
+
+ if (currentPrim.Properties == null) return;
+
+ if (btnMute.Text == "Mute")
+ {
+ client.Self.UpdateMuteListEntry(MuteType.Object, currentPrim.ID, currentPrim.Properties.Name);
+ }
+ else
+ {
+ client.Self.RemoveMuteListEntry(currentPrim.ID, currentPrim.Properties.Name);
+ }
+ }
+
+ private void txtObjectName_Leave(object sender, EventArgs e)
+ {
+ if (currentPrim == null) return;
+ if (currentPrim.Properties == null || (currentPrim.Properties != null && currentPrim.Properties.Name != txtObjectName.Text))
+ {
+ client.Objects.SetName(client.Network.CurrentSim, currentPrim.LocalID, txtObjectName.Text);
+ }
+ }
+
+ private void txtDescription_Leave(object sender, EventArgs e)
+ {
+ if (currentPrim == null) return;
+ if (currentPrim.Properties == null || (currentPrim.Properties != null && currentPrim.Properties.Description != txtDescription.Text))
+ {
+ client.Objects.SetDescription(client.Network.CurrentSim, currentPrim.LocalID, txtDescription.Text);
+ }
+ }
+
+ private void cbNextOwnerUpdate_CheckedChanged(object sender, EventArgs e)
+ {
+ CheckBox cb = (CheckBox)sender;
+ PermissionMask pm = PermissionMask.None;
+
+ if (cb == cbNextOwnCopy) pm = PermissionMask.Copy;
+ if (cb == cbNextOwnModify) pm = PermissionMask.Modify;
+ if (cb == cbNextOwnTransfer) pm = PermissionMask.Transfer;
+
+ if (pm == PermissionMask.None) return;
+
+ client.Objects.SetPermissions(client.Network.CurrentSim, new List<uint>() { currentPrim.LocalID }, PermissionWho.NextOwner, pm, cb.Checked);
+ }
+
+ private void lstPrims_Enter(object sender, EventArgs e)
+ {
+ lstPrims_SelectedIndexChanged(sender, EventArgs.Empty);
+ }
+
+ private void lstChildren_Enter(object sender, EventArgs e)
+ {
+ lstChildren_SelectedIndexChanged(sender, EventArgs.Empty);
+ }
+
+ private void lstPrims_DoubleClick(object sender, EventArgs e)
+ {
+ btnView.PerformClick();
+ }
+
+ private void lstPrims_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
+ {
+ Primitive prim = null;
+ try
+ {
+ lock (Prims)
+ {
+ prim = Prims[e.ItemIndex];
+ }
+ }
+ catch
+ {
+ e.Item = new ListViewItem();
+ return;
+ }
+
+ string name = GetObjectName(prim);
+ var item = new ListViewItem(name);
+ item.Tag = prim;
+ item.Name = prim.ID.ToString();
+ e.Item = item;
+ }
+
+ }
+
+ public enum ObjectConsoleFilter : int
+ {
+ Rezzed = 0,
+ Attached = 1,
+ Both = 2
+ }
+
+ public class ObjectSorter : IComparer<Primitive>
+ {
+ private AgentManager me;
+ private bool sortByName = false;
+
+ public bool SortByName { get { return sortByName; } set { sortByName = value; } }
+
+ public ObjectSorter(AgentManager me)
+ {
+ this.me = me;
+ }
+
+ private int NameCompare(Primitive prim1, Primitive prim2)
+ {
+ if (prim1.Properties == null && prim2.Properties == null)
+ {
+ return 0;
+ }
+ else if (prim1.Properties != null && prim2.Properties == null)
+ {
+ return -1;
+ }
+ else if (prim1.Properties == null && prim2.Properties != null)
+ {
+ return 1;
+ }
+
+ return string.Compare(prim1.Properties.Name, prim2.Properties.Name);
+ }
+ //this routine should return -1 if xy and 0 if x==y.
+ // for our sample we'll just use string comparison
+ public int Compare(Primitive prim1, Primitive prim2)
+ {
+ if (sortByName)
+ {
+ return NameCompare(prim1, prim2);
+ }
+
+ float dist1 = prim1.ParentID == me.LocalID ? 0 : Vector3.Distance(me.SimPosition, prim1.Position);
+ float dist2 = prim2.ParentID == me.LocalID ? 0 : Vector3.Distance(me.SimPosition, prim2.Position);
+
+ if (dist1 == dist2)
+ {
+ return NameCompare(prim1, prim2);
+ }
+ else
+ {
+ if (dist1 < dist2)
+ {
+ return -1;
+ }
+ return 1;
+ }
+ }
+ }
+
+ public class PropertiesQueue : IDisposable
+ {
+ Object sync = new Object();
+ RadegastInstance instance;
+ System.Timers.Timer qTimer;
+ Queue<Primitive> props = new Queue<Primitive>();
+
+ public delegate void TickCallback(int remaining);
+ public event TickCallback OnTick;
+
+ public PropertiesQueue(RadegastInstance instance)
+ {
+ this.instance = instance;
+ qTimer = new System.Timers.Timer(2500);
+ qTimer.Enabled = true;
+ qTimer.Elapsed += new ElapsedEventHandler(qTimer_Elapsed);
+ }
+
+ public void RequestProps(Primitive prim)
+ {
+ lock (sync)
+ {
+ if (!props.Contains(prim))
+ {
+ props.Enqueue(prim);
+ }
+ }
+ }
+
+ void qTimer_Elapsed(object sender, ElapsedEventArgs e)
+ {
+ lock (sync)
+ {
+ for (int i = 0; i < 25 && props.Count > 0; i++)
+ {
+ Primitive prim = props.Dequeue();
+ if (prim.ParentID == 0)
+ {
+ instance.Client.Objects.RequestObjectPropertiesFamily(
+ instance.Client.Network.CurrentSim, prim.ID, true);
+ }
+ else
+ {
+ instance.Client.Objects.SelectObject(instance.Client.Network.CurrentSim,
+ prim.LocalID, true);
+ }
+ }
+
+ if (OnTick != null)
+ {
+ OnTick(props.Count);
+ }
+ }
+ }
+
+ public void Dispose()
+ {
+ if (qTimer != null)
+ {
+ qTimer.Elapsed -= new ElapsedEventHandler(qTimer_Elapsed);
+ qTimer.Enabled = false;
+ qTimer = null;
+ }
+ props = null;
+ instance = null;
+ }
+ }
+
}
\ No newline at end of file
-#region Copyright\r
-// \r
-// Radegast SimpleBuilder plugin extension\r
-//\r
-// Copyright (c) 2014, Ano Nymous <anonymously@hotmail.de> | SecondLife-IM: anno1986 Resident\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
-#endregion\r
-\r
-#region Usings\r
-using System;\r
-using System.Collections.Generic;\r
-using System.ComponentModel;\r
-using System.Drawing;\r
-using System.Data;\r
-using System.Linq;\r
-using System.Text;\r
-using System.Windows.Forms;\r
-using Radegast;\r
-using OpenMetaverse;\r
-#endregion\r
-\r
-namespace SimpleBuilderNamespace\r
-{\r
- /// <summary>\r
- /// Example implementation of a control that can be used\r
- /// as Radegast tab and loeaded as a plugin\r
- /// </summary>\r
- [Radegast.Plugin(Name = "SimpleBuilder Plugin", Description = "Allows you to build some basic prims, like boxes, cylinder, tubes, ... (requires permission!)", Version = "1.0")]\r
- public partial class SimpleBuilder : RadegastTabControl, IRadegastPlugin\r
- {\r
- private string pluginName = "SimpleBuilder";\r
- // Methods needed for proper registration of a GUI tab\r
- #region Template for GUI radegast tab\r
- /// <summary>String for internal identification of the tab (change this!)</summary>\r
- static string tabID = "demo_tab";\r
- /// <summary>Text displayed in the plugins menu and the tab label (change this!)</summary>\r
- static string tabLabel = "Build Prims";\r
-\r
- /// <summary>Menu item that gets added to the Plugins menu</summary>\r
- ToolStripMenuItem ActivateTabButton;\r
-\r
- /// <summary>Default constructor. Never used. Needed for VS designer</summary>\r
- public SimpleBuilder()\r
- {\r
- }\r
-\r
- /// <summary>\r
- /// Main constructor used when actually creating the tab control for display\r
- /// Register client and instance events\r
- /// </summary>\r
- /// <param name="instance">RadegastInstance</param>\r
- /// <param name="unused">This param is not used, but needs to be there to keep the constructor signature</param>\r
- public SimpleBuilder(RadegastInstance instance, bool unused)\r
- : base(instance)\r
- {\r
- InitializeComponent();\r
- Disposed += new EventHandler(DemoTab_Disposed);\r
- instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);\r
- RegisterClientEvents(client);\r
- }\r
-\r
- /// <summary>\r
- /// Cleanup after the tab is closed\r
- /// Unregister event handler hooks we have installed\r
- /// </summary>\r
- /// <param name="sender"></param>\r
- /// <param name="e"></param>\r
- void DemoTab_Disposed(object sender, EventArgs e)\r
- {\r
- UnregisterClientEvents(client);\r
- instance.ClientChanged -= new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);\r
- }\r
-\r
- /// <summary>\r
- /// Plugin loader calls this at the time plugin gets created\r
- /// We add a button to the Plugins menu on the main window\r
- /// for this tab\r
- /// </summary>\r
- /// <param name="inst">Main RadegastInstance</param>\r
- public void StartPlugin(RadegastInstance inst)\r
- {\r
- this.instance = inst;\r
- ActivateTabButton = new ToolStripMenuItem(tabLabel, null, MenuButtonClicked);\r
- instance.MainForm.PluginsMenu.DropDownItems.Add(ActivateTabButton);\r
- }\r
-\r
- /// <summary>\r
- /// Called when the plugin manager unloads our plugin. \r
- /// Close the tab if it's active and remove the menu button\r
- /// </summary>\r
- /// <param name="inst"></param>\r
- public void StopPlugin(RadegastInstance inst)\r
- {\r
- ActivateTabButton.Dispose();\r
- instance.TabConsole.Tabs[tabID].Close();\r
- }\r
-\r
- /// <summary>\r
- /// Hadle case when GridClient is changed (relog haa occured without\r
- /// quiting Radegast). We need to unregister events from the old client\r
- /// and re-register them with the new\r
- /// </summary>\r
- /// <param name="sender"></param>\r
- /// <param name="e"></param>\r
- void instance_ClientChanged(object sender, ClientChangedEventArgs e)\r
- {\r
- UnregisterClientEvents(e.OldClient);\r
- RegisterClientEvents(e.Client);\r
- }\r
-\r
- /// <summary>\r
- /// Registration of all GridClient (libomv) events go here\r
- /// </summary>\r
- /// <param name="client"></param>\r
- void RegisterClientEvents(GridClient client)\r
- {\r
- client.Self.ChatFromSimulator += new EventHandler<ChatEventArgs>(Self_ChatFromSimulator);\r
- }\r
-\r
- /// <summary>\r
- /// Unregistration of GridClient (libomv) events.\r
- /// Important that this be symetric to RegisterClientEvents() calls\r
- /// </summary>\r
- /// <param name="client"></param>\r
- void UnregisterClientEvents(GridClient client)\r
- {\r
- if (client == null) return;\r
- client.Self.ChatFromSimulator -= new EventHandler<ChatEventArgs>(Self_ChatFromSimulator);\r
- }\r
-\r
- /// <summary>\r
- /// Handling the click on Plugins -> Demo Tab button\r
- /// Check if we already have a tab. If we do make it active tab.\r
- /// If not, create a new tab and make it active.\r
- /// </summary>\r
- /// <param name="sender"></param>\r
- /// <param name="e"></param>\r
- void MenuButtonClicked(object sender, EventArgs e)\r
- {\r
- if (instance.TabConsole.TabExists(tabID))\r
- {\r
- instance.TabConsole.Tabs[tabID].Select();\r
- }\r
- else\r
- {\r
- instance.TabConsole.AddTab(tabID, tabLabel, new SimpleBuilder(instance, true));\r
- instance.TabConsole.Tabs[tabID].Select();\r
- }\r
- }\r
- #endregion Template for GUI radegast tab\r
-\r
- #region Implementation of the custom tab functionality\r
- void Self_ChatFromSimulator(object sender, ChatEventArgs e)\r
- {\r
- // Boilerplate, make sure to be on the GUI thread\r
- if (InvokeRequired)\r
- {\r
- BeginInvoke(new MethodInvoker(() => Self_ChatFromSimulator(sender, e)));\r
- return;\r
- }\r
-\r
- //txtChat.Text = e.Message;\r
- }\r
-\r
- private void btnBuild_Click(object sender, EventArgs e)\r
- {\r
- Button btn = sender as Button;\r
-\r
- if (btn == null) return;\r
-\r
- PrimType primType = (PrimType)Enum.Parse(typeof(PrimType), btn.Text);\r
-\r
- this.BuildAndRez(primType);\r
- }\r
-\r
- private void BuildAndRez(PrimType primType)\r
- {\r
- float size, distance;\r
- if (!float.TryParse(tbox_Size.Text, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out size))\r
- {\r
- instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": Invalid size", ChatBufferTextStyle.Error);\r
- return;\r
- }\r
-\r
- if (!float.TryParse(tbox_Distance.Text, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out distance))\r
- {\r
- instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": Invalid distance", ChatBufferTextStyle.Error);\r
- return;\r
- }\r
-\r
- Primitive.ConstructionData primData = ObjectManager.BuildBasicShape(primType);\r
-\r
- Vector3 rezpos = new Vector3(distance, 0, 0);\r
- rezpos = client.Self.SimPosition + rezpos * client.Self.Movement.BodyRotation;\r
-\r
- client.Objects.AddPrim(client.Network.CurrentSim, primData, UUID.Zero, rezpos, new Vector3(size), Quaternion.Identity);\r
-\r
- instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": Object built and rezzed", ChatBufferTextStyle.Normal);\r
- }\r
-\r
- #endregion Implementation of the custom tab functionality\r
-\r
- \r
- }\r
-}\r
+#region Copyright
+//
+// Radegast SimpleBuilder plugin extension
+//
+// Copyright (c) 2014, Ano Nymous <anonymously@hotmail.de> | SecondLife-IM: anno1986 Resident
+// 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$
+//
+#endregion
+
+#region Usings
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using Radegast;
+using OpenMetaverse;
+#endregion
+
+namespace SimpleBuilderNamespace
+{
+ /// <summary>
+ /// Example implementation of a control that can be used
+ /// as Radegast tab and loeaded as a plugin
+ /// </summary>
+ [Radegast.Plugin(Name = "SimpleBuilder Plugin", Description = "Allows you to build some basic prims, like boxes, cylinder, tubes, ... (requires permission!)", Version = "1.0")]
+ public partial class SimpleBuilder : RadegastTabControl, IRadegastPlugin
+ {
+ private string pluginName = "SimpleBuilder";
+ // Methods needed for proper registration of a GUI tab
+ #region Template for GUI radegast tab
+ /// <summary>String for internal identification of the tab (change this!)</summary>
+ static string tabID = "demo_tab";
+ /// <summary>Text displayed in the plugins menu and the tab label (change this!)</summary>
+ static string tabLabel = "Build Prims";
+
+ /// <summary>Menu item that gets added to the Plugins menu</summary>
+ ToolStripMenuItem ActivateTabButton;
+
+ /// <summary>Default constructor. Never used. Needed for VS designer</summary>
+ public SimpleBuilder()
+ {
+ }
+
+ /// <summary>
+ /// Main constructor used when actually creating the tab control for display
+ /// Register client and instance events
+ /// </summary>
+ /// <param name="instance">RadegastInstance</param>
+ /// <param name="unused">This param is not used, but needs to be there to keep the constructor signature</param>
+ public SimpleBuilder(RadegastInstance instance, bool unused)
+ : base(instance)
+ {
+ InitializeComponent();
+ Disposed += new EventHandler(DemoTab_Disposed);
+ instance.ClientChanged += new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);
+ RegisterClientEvents(client);
+ }
+
+ /// <summary>
+ /// Cleanup after the tab is closed
+ /// Unregister event handler hooks we have installed
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ void DemoTab_Disposed(object sender, EventArgs e)
+ {
+ UnregisterClientEvents(client);
+ instance.ClientChanged -= new EventHandler<ClientChangedEventArgs>(instance_ClientChanged);
+ }
+
+ /// <summary>
+ /// Plugin loader calls this at the time plugin gets created
+ /// We add a button to the Plugins menu on the main window
+ /// for this tab
+ /// </summary>
+ /// <param name="inst">Main RadegastInstance</param>
+ public void StartPlugin(RadegastInstance inst)
+ {
+ this.instance = inst;
+ ActivateTabButton = new ToolStripMenuItem(tabLabel, null, MenuButtonClicked);
+ instance.MainForm.PluginsMenu.DropDownItems.Add(ActivateTabButton);
+ }
+
+ /// <summary>
+ /// Called when the plugin manager unloads our plugin.
+ /// Close the tab if it's active and remove the menu button
+ /// </summary>
+ /// <param name="inst"></param>
+ public void StopPlugin(RadegastInstance inst)
+ {
+ ActivateTabButton.Dispose();
+ instance.TabConsole.Tabs[tabID].Close();
+ }
+
+ /// <summary>
+ /// Hadle case when GridClient is changed (relog haa occured without
+ /// quiting Radegast). We need to unregister events from the old client
+ /// and re-register them with the new
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ void instance_ClientChanged(object sender, ClientChangedEventArgs e)
+ {
+ UnregisterClientEvents(e.OldClient);
+ RegisterClientEvents(e.Client);
+ }
+
+ /// <summary>
+ /// Registration of all GridClient (libomv) events go here
+ /// </summary>
+ /// <param name="client"></param>
+ void RegisterClientEvents(GridClient client)
+ {
+ client.Self.ChatFromSimulator += new EventHandler<ChatEventArgs>(Self_ChatFromSimulator);
+ }
+
+ /// <summary>
+ /// Unregistration of GridClient (libomv) events.
+ /// Important that this be symetric to RegisterClientEvents() calls
+ /// </summary>
+ /// <param name="client"></param>
+ void UnregisterClientEvents(GridClient client)
+ {
+ if (client == null) return;
+ client.Self.ChatFromSimulator -= new EventHandler<ChatEventArgs>(Self_ChatFromSimulator);
+ }
+
+ /// <summary>
+ /// Handling the click on Plugins -> Demo Tab button
+ /// Check if we already have a tab. If we do make it active tab.
+ /// If not, create a new tab and make it active.
+ /// </summary>
+ /// <param name="sender"></param>
+ /// <param name="e"></param>
+ void MenuButtonClicked(object sender, EventArgs e)
+ {
+ if (instance.TabConsole.TabExists(tabID))
+ {
+ instance.TabConsole.Tabs[tabID].Select();
+ }
+ else
+ {
+ instance.TabConsole.AddTab(tabID, tabLabel, new SimpleBuilder(instance, true));
+ instance.TabConsole.Tabs[tabID].Select();
+ }
+ }
+ #endregion Template for GUI radegast tab
+
+ #region Implementation of the custom tab functionality
+ void Self_ChatFromSimulator(object sender, ChatEventArgs e)
+ {
+ // Boilerplate, make sure to be on the GUI thread
+ if (InvokeRequired)
+ {
+ BeginInvoke(new MethodInvoker(() => Self_ChatFromSimulator(sender, e)));
+ return;
+ }
+
+ //txtChat.Text = e.Message;
+ }
+
+ private void btnBuild_Click(object sender, EventArgs e)
+ {
+ Button btn = sender as Button;
+
+ if (btn == null) return;
+
+ PrimType primType = (PrimType)Enum.Parse(typeof(PrimType), btn.Text);
+
+ this.BuildAndRez(primType);
+ }
+
+ private void BuildAndRez(PrimType primType)
+ {
+ float size, distance;
+ if (!float.TryParse(tbox_Size.Text, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out size))
+ {
+ instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": Invalid size", ChatBufferTextStyle.Error);
+ return;
+ }
+
+ if (!float.TryParse(tbox_Distance.Text, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out distance))
+ {
+ instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": Invalid distance", ChatBufferTextStyle.Error);
+ return;
+ }
+
+ Primitive.ConstructionData primData = ObjectManager.BuildBasicShape(primType);
+
+ Vector3 rezpos = new Vector3(distance, 0, 0);
+ rezpos = client.Self.SimPosition + rezpos * client.Self.Movement.BodyRotation;
+
+ client.Objects.AddPrim(client.Network.CurrentSim, primData, UUID.Zero, rezpos, new Vector3(size), Quaternion.Identity);
+
+ instance.MainForm.TabConsole.DisplayNotificationInChat(pluginName + ": Object built and rezzed", ChatBufferTextStyle.Normal);
+ }
+
+ #endregion Implementation of the custom tab functionality
+
+
+ }
+}