2 // Radegast Metaverse Client
3 // Copyright (c) 2009-2013, Radegast Development Team
4 // All rights reserved.
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
9 // * Redistributions of source code must retain the above copyright notice,
10 // this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above copyright
12 // notice, this list of conditions and the following disclaimer in the
13 // documentation and/or other materials provided with the distribution.
14 // * Neither the name of the application "Radegast", nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 using System.Collections;
33 using System.Collections.Generic;
34 using System.ComponentModel;
37 using System.Windows.Forms;
38 #if (COGBOT_LIBOMV || USE_STHREADS)
40 using Thread = ThreadPoolUtil.Thread;
41 using ThreadPool = ThreadPoolUtil.ThreadPool;
42 using Monitor = ThreadPoolUtil.Monitor;
44 using System.Threading;
47 using OpenMetaverse.StructuredData;
52 public partial class InventoryConsole : UserControl
54 RadegastInstance instance;
55 GridClient client { get { return instance.Client; } }
56 Dictionary<UUID, TreeNode> FolderNodes = new Dictionary<UUID, TreeNode>();
58 private InventoryManager Manager;
59 private OpenMetaverse.Inventory Inventory;
60 private TreeNode invRootNode;
61 private string newItemName = string.Empty;
62 private List<UUID> fetchedFolders = new List<UUID>();
63 private System.Threading.Timer _EditTimer;
64 private TreeNode _EditNode;
65 private Dictionary<UUID, AttachmentInfo> attachments = new Dictionary<UUID, AttachmentInfo>();
66 private System.Timers.Timer TreeUpdateTimer;
67 private Queue<InventoryBase> ItemsToAdd = new Queue<InventoryBase>();
68 private Queue<InventoryBase> ItemsToUpdate = new Queue<InventoryBase>();
69 private bool TreeUpdateInProgress = false;
70 private Dictionary<UUID, TreeNode> UUID2NodeCache = new Dictionary<UUID, TreeNode>();
71 private int updateInterval = 1000;
72 private Thread InventoryUpdate;
73 private List<UUID> WornItems = new List<UUID>();
74 private bool appearnceWasBusy;
75 private InvNodeSorter sorter;
76 private List<UUID> QueuedFolders = new List<UUID>();
77 private Dictionary<UUID, int> FolderFetchRetries = new Dictionary<UUID, int>();
79 #region Construction and disposal
80 public InventoryConsole(RadegastInstance instance)
82 InitializeComponent();
83 Disposed += new EventHandler(InventoryConsole_Disposed);
85 TreeUpdateTimer = new System.Timers.Timer()
87 Interval = updateInterval,
89 SynchronizingObject = invTree
91 TreeUpdateTimer.Elapsed += TreeUpdateTimerTick;
93 this.instance = instance;
94 Manager = client.Inventory;
95 Inventory = Manager.Store;
96 Inventory.RootFolder.OwnerID = client.Self.AgentID;
97 invTree.ImageList = frmMain.ResourceImages;
98 invRootNode = AddDir(null, Inventory.RootFolder);
99 UpdateStatus("Reading cache");
105 ThreadPool.QueueUserWorkItem(sync =>
107 Logger.Log("Reading inventory cache from " + instance.InventoryCacheFileName, Helpers.LogLevel.Debug, client);
108 Inventory.RestoreFromDisk(instance.InventoryCacheFileName);
115 if (instance.MainForm.InvokeRequired)
117 instance.MainForm.BeginInvoke(new MethodInvoker(() => Init2()));
121 AddFolderFromStore(invRootNode, Inventory.RootFolder);
123 sorter = new InvNodeSorter();
125 if (!instance.GlobalSettings.ContainsKey("inv_sort_bydate"))
126 instance.GlobalSettings["inv_sort_bydate"] = OSD.FromBoolean(true);
127 if (!instance.GlobalSettings.ContainsKey("inv_sort_sysfirst"))
128 instance.GlobalSettings["inv_sort_sysfirst"] = OSD.FromBoolean(true);
130 sorter.ByDate = instance.GlobalSettings["inv_sort_bydate"].AsBoolean();
131 sorter.SystemFoldersFirst = instance.GlobalSettings["inv_sort_sysfirst"].AsBoolean();
133 tbtnSortByDate.Checked = sorter.ByDate;
134 tbtbSortByName.Checked = !sorter.ByDate;
135 tbtnSystemFoldersFirst.Checked = sorter.SystemFoldersFirst;
137 invTree.TreeViewNodeSorter = sorter;
139 if (instance.MonoRuntime)
141 invTree.BackColor = Color.FromKnownColor(KnownColor.Window);
142 invTree.ForeColor = invTree.LineColor = Color.FromKnownColor(KnownColor.WindowText);
143 InventoryFolder f = new InventoryFolder(UUID.Random());
145 f.ParentUUID = UUID.Zero;
146 f.PreferredType = AssetType.Unknown;
147 TreeNode dirNode = new TreeNode();
148 dirNode.Name = f.UUID.ToString();
149 dirNode.Text = f.Name;
151 dirNode.ImageIndex = GetDirImageIndex(f.PreferredType.ToString().ToLower());
152 dirNode.SelectedImageIndex = dirNode.ImageIndex;
153 invTree.Nodes.Add(dirNode);
157 saveAllTToolStripMenuItem.Enabled = false;
158 InventoryUpdate = new Thread(new ThreadStart(StartTraverseNodes));
159 InventoryUpdate.Name = "InventoryUpdate";
160 InventoryUpdate.IsBackground = true;
161 InventoryUpdate.Start();
163 invRootNode.Expand();
165 invTree.AfterExpand += new TreeViewEventHandler(TreeView_AfterExpand);
166 invTree.NodeMouseClick += new TreeNodeMouseClickEventHandler(invTree_MouseClick);
167 invTree.NodeMouseDoubleClick += new TreeNodeMouseClickEventHandler(invTree_NodeMouseDoubleClick);
169 _EditTimer = new System.Threading.Timer(OnLabelEditTimer, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
172 Inventory.InventoryObjectAdded += new EventHandler<InventoryObjectAddedEventArgs>(Inventory_InventoryObjectAdded);
173 Inventory.InventoryObjectUpdated += new EventHandler<InventoryObjectUpdatedEventArgs>(Inventory_InventoryObjectUpdated);
174 Inventory.InventoryObjectRemoved += new EventHandler<InventoryObjectRemovedEventArgs>(Inventory_InventoryObjectRemoved);
176 client.Objects.ObjectUpdate += new EventHandler<PrimEventArgs>(Objects_AttachmentUpdate);
177 client.Objects.KillObject += new EventHandler<KillObjectEventArgs>(Objects_KillObject);
178 client.Appearance.AppearanceSet += new EventHandler<AppearanceSetEventArgs>(Appearance_AppearanceSet);
181 void InventoryConsole_Disposed(object sender, EventArgs e)
183 if (TreeUpdateTimer != null)
185 TreeUpdateTimer.Stop();
186 TreeUpdateTimer.Dispose();
187 TreeUpdateTimer = null;
189 if (InventoryUpdate != null)
191 if (InventoryUpdate.IsAlive)
192 InventoryUpdate.Abort();
193 InventoryUpdate = null;
196 Inventory.InventoryObjectAdded -= new EventHandler<InventoryObjectAddedEventArgs>(Inventory_InventoryObjectAdded);
197 Inventory.InventoryObjectUpdated -= new EventHandler<InventoryObjectUpdatedEventArgs>(Inventory_InventoryObjectUpdated);
198 Inventory.InventoryObjectRemoved -= new EventHandler<InventoryObjectRemovedEventArgs>(Inventory_InventoryObjectRemoved);
200 client.Objects.ObjectUpdate -= new EventHandler<PrimEventArgs>(Objects_AttachmentUpdate);
201 client.Objects.KillObject -= new EventHandler<KillObjectEventArgs>(Objects_KillObject);
202 client.Appearance.AppearanceSet -= new EventHandler<AppearanceSetEventArgs>(Appearance_AppearanceSet);
206 #region Network callbacks
207 void Appearance_AppearanceSet(object sender, AppearanceSetEventArgs e)
210 if (appearnceWasBusy)
212 appearnceWasBusy = false;
213 client.Appearance.RequestSetAppearance(true);
217 void Objects_KillObject(object sender, KillObjectEventArgs e)
219 AttachmentInfo attachment = null;
222 foreach (AttachmentInfo att in attachments.Values)
224 if (att.Prim != null && att.Prim.LocalID == e.ObjectLocalID)
231 if (attachment != null)
233 attachments.Remove(attachment.InventoryID);
234 UpdateNodeLabel(attachment.InventoryID);
239 void Objects_AttachmentUpdate(object sender, PrimEventArgs e)
241 Primitive prim = e.Prim;
243 if (client.Self.LocalID == 0 ||
244 prim.ParentID != client.Self.LocalID ||
245 prim.NameValues == null) return;
247 for (int i = 0; i < prim.NameValues.Length; i++)
249 if (prim.NameValues[i].Name == "AttachItemID")
251 AttachmentInfo attachment = new AttachmentInfo();
252 attachment.Prim = prim;
253 attachment.InventoryID = new UUID(prim.NameValues[i].Value.ToString());
254 attachment.PrimID = prim.ID;
258 // Add new attachment info
259 if (!attachments.ContainsKey(attachment.InventoryID))
261 attachments.Add(attachment.InventoryID, attachment);
266 attachment = attachments[attachment.InventoryID];
267 if (attachment.Prim == null)
269 attachment.Prim = prim;
273 // Don't update the tree yet if we're still updating invetory tree from server
274 if (!TreeUpdateInProgress)
276 if (Inventory.Contains(attachment.InventoryID))
278 if (attachment.Item == null)
280 InventoryItem item = (InventoryItem)Inventory[attachment.InventoryID];
281 attachment.Item = item;
283 if (!attachment.MarkedAttached)
285 attachment.MarkedAttached = true;
286 UpdateNodeLabel(attachment.InventoryID);
291 client.Inventory.RequestFetchInventory(attachment.InventoryID, client.Self.AgentID);
300 void Inventory_InventoryObjectAdded(object sender, InventoryObjectAddedEventArgs e)
302 if (TreeUpdateInProgress)
306 ItemsToAdd.Enqueue(e.Obj);
311 Exec_OnInventoryObjectAdded(e.Obj);
315 void Exec_OnInventoryObjectAdded(InventoryBase obj)
319 Invoke(new MethodInvoker(delegate()
321 Exec_OnInventoryObjectAdded(obj);
329 if (attachments.ContainsKey(obj.UUID))
331 attachments[obj.UUID].Item = (InventoryItem)obj;
335 TreeNode parent = findNodeForItem(obj.ParentUUID);
339 TreeNode newNode = AddBase(parent, obj);
340 if (obj.Name == newItemName)
342 if (newNode.Parent.IsExpanded)
348 newNode.Parent.Expand();
352 newItemName = string.Empty;
355 void Inventory_InventoryObjectRemoved(object sender, InventoryObjectRemovedEventArgs e)
359 BeginInvoke(new MethodInvoker(() => Inventory_InventoryObjectRemoved(sender, e)));
365 if (attachments.ContainsKey(e.Obj.UUID))
367 attachments.Remove(e.Obj.UUID);
371 TreeNode currentNode = findNodeForItem(e.Obj.UUID);
372 if (currentNode != null)
374 removeNode(currentNode);
378 void Inventory_InventoryObjectUpdated(object sender, InventoryObjectUpdatedEventArgs e)
380 if (TreeUpdateInProgress)
384 if (e.NewObject is InventoryFolder)
386 TreeNode currentNode = findNodeForItem(e.NewObject.UUID);
387 if (currentNode != null && currentNode.Text == e.NewObject.Name) return;
390 if (!ItemsToUpdate.Contains(e.NewObject))
392 ItemsToUpdate.Enqueue(e.NewObject);
398 Exec_OnInventoryObjectUpdated(e.OldObject, e.NewObject);
402 void Exec_OnInventoryObjectUpdated(InventoryBase oldObject, InventoryBase newObject)
404 if (newObject == null) return;
408 BeginInvoke(new MethodInvoker(() => Exec_OnInventoryObjectUpdated(oldObject, newObject)));
414 if (attachments.ContainsKey(newObject.UUID))
416 attachments[newObject.UUID].Item = (InventoryItem)newObject;
420 // Find our current node in the tree
421 TreeNode currentNode = findNodeForItem(newObject.UUID);
423 // Find which node should be our parrent
424 TreeNode parent = findNodeForItem(newObject.ParentUUID);
426 if (parent == null) return;
428 if (currentNode != null)
430 // Did we move to a different folder
431 if (currentNode.Parent != parent)
433 TreeNode movedNode = (TreeNode)currentNode.Clone();
434 movedNode.Tag = newObject;
435 parent.Nodes.Add(movedNode);
436 removeNode(currentNode);
437 cacheNode(movedNode);
441 currentNode.Tag = newObject;
442 currentNode.Text = ItemLabel(newObject, false);
443 currentNode.Name = newObject.Name;
446 else // We are not in the tree already, add
448 AddBase(parent, newObject);
453 #region Node manipulation
454 public static int GetDirImageIndex(string t)
456 t = System.Text.RegularExpressions.Regex.Replace(t, @"folder$", "");
457 int res = frmMain.ImageNames.IndexOf("inv_folder_" + t);
462 case "currentoutfit":
464 return frmMain.ImageNames.IndexOf("inv_folder_outfit");
466 return frmMain.ImageNames.IndexOf("inv_folder_script");
468 return frmMain.ImageNames.IndexOf("inv_folder_plain_closed");
473 public static int GetItemImageIndex(string t)
475 int res = frmMain.ImageNames.IndexOf("inv_item_" + t);
480 return frmMain.ImageNames.IndexOf("inv_item_script");
482 else if (t == "callingcard")
484 return frmMain.ImageNames.IndexOf("inv_item_callingcard_offline");
490 TreeNode AddBase(TreeNode parent, InventoryBase obj)
492 if (obj is InventoryItem)
494 return AddItem(parent, (InventoryItem)obj);
498 return AddDir(parent, (InventoryFolder)obj);
502 TreeNode AddDir(TreeNode parentNode, InventoryFolder f)
504 TreeNode dirNode = new TreeNode();
505 dirNode.Name = f.UUID.ToString();
506 dirNode.Text = f.Name;
508 dirNode.ImageIndex = GetDirImageIndex(f.PreferredType.ToString().ToLower());
509 dirNode.SelectedImageIndex = dirNode.ImageIndex;
510 if (parentNode == null)
512 invTree.Nodes.Add(dirNode);
516 parentNode.Nodes.Add(dirNode);
518 lock (UUID2NodeCache)
520 UUID2NodeCache[f.UUID] = dirNode;
526 TreeNode AddItem(TreeNode parent, InventoryItem item)
528 TreeNode itemNode = new TreeNode();
529 itemNode.Name = item.UUID.ToString();
530 itemNode.Text = ItemLabel(item, false);
533 InventoryItem linkedItem = null;
535 if (item.IsLink() && Inventory.Contains(item.AssetUUID) && Inventory[item.AssetUUID] is InventoryItem)
537 linkedItem = (InventoryItem)Inventory[item.AssetUUID];
544 if (linkedItem is InventoryWearable)
546 InventoryWearable w = linkedItem as InventoryWearable;
547 img = GetItemImageIndex(w.WearableType.ToString().ToLower());
551 img = GetItemImageIndex(linkedItem.AssetType.ToString().ToLower());
554 itemNode.ImageIndex = img;
555 itemNode.SelectedImageIndex = img;
556 parent.Nodes.Add(itemNode);
557 lock (UUID2NodeCache)
559 UUID2NodeCache[item.UUID] = itemNode;
564 TreeNode findNodeForItem(UUID itemID)
566 lock (UUID2NodeCache)
568 if (UUID2NodeCache.ContainsKey(itemID))
570 return UUID2NodeCache[itemID];
576 void cacheNode(TreeNode node)
578 InventoryBase item = (InventoryBase)node.Tag;
581 foreach (TreeNode child in node.Nodes)
585 lock (UUID2NodeCache)
587 UUID2NodeCache[item.UUID] = node;
592 void removeNode(TreeNode node)
594 InventoryBase item = (InventoryBase)node.Tag;
597 foreach (TreeNode child in node.Nodes)
602 lock (UUID2NodeCache)
604 UUID2NodeCache.Remove(item.UUID);
612 #region Private methods
613 private void UpdateStatus(string text)
617 Invoke(new MethodInvoker(delegate() { UpdateStatus(text); }));
623 saveAllTToolStripMenuItem.Enabled = true;
626 tlabelStatus.Text = text;
629 private void UpdateNodeLabel(UUID itemID)
631 if (instance.MainForm.InvokeRequired)
633 instance.MainForm.BeginInvoke(new MethodInvoker(() => UpdateNodeLabel(itemID)));
637 TreeNode node = findNodeForItem(itemID);
640 node.Text = ItemLabel((InventoryBase)node.Tag, false);
644 private void AddFolderFromStore(TreeNode parent, InventoryFolder f)
646 List<InventoryBase> contents = Inventory.GetContents(f);
647 foreach (InventoryBase item in contents)
649 TreeNode node = AddBase(parent, item);
650 if (item is InventoryFolder)
652 AddFolderFromStore(node, (InventoryFolder)item);
657 private void TraverseAndQueueNodes(InventoryNode start)
659 bool has_items = false;
661 foreach (InventoryNode node in start.Nodes.Values)
663 if (node.Data is InventoryItem)
670 if (!has_items || start.NeedsUpdate)
674 lock (FolderFetchRetries)
677 FolderFetchRetries.TryGetValue(start.Data.UUID, out retries);
680 if (!QueuedFolders.Contains(start.Data.UUID))
682 QueuedFolders.Add(start.Data.UUID);
685 FolderFetchRetries[start.Data.UUID] = retries + 1;
690 foreach (InventoryBase item in Inventory.GetContents((InventoryFolder)start.Data))
692 if (item is InventoryFolder)
694 TraverseAndQueueNodes(Inventory.GetNodeFor(item.UUID));
699 private void TraverseNodes(InventoryNode start)
701 bool has_items = false;
703 foreach (InventoryNode node in start.Nodes.Values)
705 if (node.Data is InventoryItem)
712 if (!has_items || start.NeedsUpdate)
714 InventoryFolder f = (InventoryFolder)start.Data;
715 AutoResetEvent gotFolderEvent = new AutoResetEvent(false);
716 bool success = false;
718 EventHandler<FolderUpdatedEventArgs> callback = delegate(object sender, FolderUpdatedEventArgs ea)
720 if (f.UUID == ea.FolderID)
722 if (((InventoryFolder)Inventory.Items[ea.FolderID].Data).DescendentCount <= Inventory.Items[ea.FolderID].Nodes.Count)
725 gotFolderEvent.Set();
730 client.Inventory.FolderUpdated += callback;
731 fetchFolder(f.UUID, f.OwnerID, true);
732 gotFolderEvent.WaitOne(30 * 1000, false);
733 client.Inventory.FolderUpdated -= callback;
737 Logger.Log(string.Format("Failed fetching folder {0}, got {1} items out of {2}", f.Name, Inventory.Items[f.UUID].Nodes.Count, ((InventoryFolder)Inventory.Items[f.UUID].Data).DescendentCount), Helpers.LogLevel.Error, client);
741 foreach (InventoryBase item in Inventory.GetContents((InventoryFolder)start.Data))
743 if (item is InventoryFolder)
745 TraverseNodes(Inventory.GetNodeFor(item.UUID));
750 private void StartTraverseNodes()
752 if (!client.Network.CurrentSim.Caps.IsEventQueueRunning)
754 AutoResetEvent EQRunning = new AutoResetEvent(false);
755 EventHandler<EventQueueRunningEventArgs> handler = (sender, e) =>
759 client.Network.EventQueueRunning += handler;
760 EQRunning.WaitOne(10 * 1000, false);
761 client.Network.EventQueueRunning -= handler;
764 if (!client.Network.CurrentSim.Caps.IsEventQueueRunning)
769 UpdateStatus("Loading...");
770 TreeUpdateInProgress = true;
771 TreeUpdateTimer.Start();
773 lock (FolderFetchRetries)
775 FolderFetchRetries.Clear();
782 QueuedFolders.Clear();
784 TraverseAndQueueNodes(Inventory.RootNode);
785 if (QueuedFolders.Count == 0) break;
786 Logger.DebugLog(string.Format("Queued {0} folders for update", QueuedFolders.Count));
788 Parallel.ForEach<UUID>(Math.Min(QueuedFolders.Count, 6), QueuedFolders, folderID =>
790 bool success = false;
792 AutoResetEvent gotFolder = new AutoResetEvent(false);
793 EventHandler<FolderUpdatedEventArgs> handler = (sender, ev) =>
795 if (ev.FolderID == folderID)
797 success = ev.Success;
802 client.Inventory.FolderUpdated += handler;
803 client.Inventory.RequestFolderContents(folderID, client.Self.AgentID, true, true, InventorySortOrder.ByDate);
804 if (!gotFolder.WaitOne(15 * 1000, false))
808 client.Inventory.FolderUpdated -= handler;
811 while (QueuedFolders.Count > 0);
813 TreeUpdateTimer.Stop();
816 Invoke(new MethodInvoker(() => TreeUpdateTimerTick(null, null)));
818 TreeUpdateInProgress = false;
820 instance.TabConsole.DisplayNotificationInChat("Inventory update completed.");
822 // Updated labels on clothes that we are wearing
825 // Update attachments now that we are done
828 foreach (AttachmentInfo a in attachments.Values)
832 if (Inventory.Contains(a.InventoryID))
834 a.MarkedAttached = true;
835 a.Item = (InventoryItem)Inventory[a.InventoryID];
836 UpdateNodeLabel(a.InventoryID);
840 client.Inventory.RequestFetchInventory(a.InventoryID, client.Self.AgentID);
847 Logger.Log("Finished updating invenory folders, saving cache...", Helpers.LogLevel.Debug, client);
848 ThreadPool.QueueUserWorkItem((object state) => Inventory.SaveToDisk(instance.InventoryCacheFileName));
850 if (!instance.MonoRuntime || IsHandleCreated)
851 Invoke(new MethodInvoker(() =>
860 public void ReloadInventory()
862 if (TreeUpdateInProgress)
864 TreeUpdateTimer.Stop();
865 InventoryUpdate.Abort();
866 InventoryUpdate = null;
869 saveAllTToolStripMenuItem.Enabled = false;
871 Inventory.Items = new Dictionary<UUID, InventoryNode>();
872 Inventory.RootFolder = Inventory.RootFolder;
874 invTree.Nodes.Clear();
875 UUID2NodeCache.Clear();
876 invRootNode = AddDir(null, Inventory.RootFolder);
877 Inventory.RootNode.NeedsUpdate = true;
879 InventoryUpdate = new Thread(new ThreadStart(StartTraverseNodes));
880 InventoryUpdate.Name = "InventoryUpdate";
881 InventoryUpdate.IsBackground = true;
882 InventoryUpdate.Start();
883 invRootNode.Expand();
886 private void reloadInventoryToolStripMenuItem_Click(object sender, EventArgs e)
891 private void TreeUpdateTimerTick(Object sender, EventArgs e)
895 if (ItemsToAdd.Count > 0)
897 invTree.BeginUpdate();
898 while (ItemsToAdd.Count > 0)
900 InventoryBase item = ItemsToAdd.Dequeue();
901 TreeNode node = findNodeForItem(item.ParentUUID);
913 if (ItemsToUpdate.Count > 0)
915 invTree.BeginUpdate();
916 while (ItemsToUpdate.Count > 0)
918 InventoryBase item = ItemsToUpdate.Dequeue();
919 Exec_OnInventoryObjectUpdated(item, item);
925 UpdateStatus("Loading... " + UUID2NodeCache.Count.ToString() + " items");
930 private void btnProfile_Click(object sender, EventArgs e)
932 instance.MainForm.ShowAgentProfile(txtCreator.Text, txtCreator.AgentID);
935 void UpdateItemInfo(InventoryItem item)
937 foreach (Control c in pnlDetail.Controls)
941 pnlDetail.Controls.Clear();
942 pnlItemProperties.Tag = item;
946 pnlItemProperties.Visible = false;
950 pnlItemProperties.Visible = true;
951 btnProfile.Enabled = true;
952 txtItemName.Text = item.Name;
953 txtItemDescription.Text = item.Description;
954 txtCreator.AgentID = item.CreatorID;
955 txtCreator.Tag = item.CreatorID;
956 txtCreated.Text = item.CreationDate.ToString();
958 if (item.AssetUUID != UUID.Zero)
960 txtAssetID.Text = item.AssetUUID.ToString();
964 txtAssetID.Text = String.Empty;
967 txtInvID.Text = item.UUID.ToString();
969 Permissions p = item.Permissions;
970 cbOwnerModify.Checked = (p.OwnerMask & PermissionMask.Modify) != 0;
971 cbOwnerCopy.Checked = (p.OwnerMask & PermissionMask.Copy) != 0;
972 cbOwnerTransfer.Checked = (p.OwnerMask & PermissionMask.Transfer) != 0;
974 cbNextOwnModify.CheckedChanged -= cbNextOwnerUpdate_CheckedChanged;
975 cbNextOwnCopy.CheckedChanged -= cbNextOwnerUpdate_CheckedChanged;
976 cbNextOwnTransfer.CheckedChanged -= cbNextOwnerUpdate_CheckedChanged;
978 cbNextOwnModify.Checked = (p.NextOwnerMask & PermissionMask.Modify) != 0;
979 cbNextOwnCopy.Checked = (p.NextOwnerMask & PermissionMask.Copy) != 0;
980 cbNextOwnTransfer.Checked = (p.NextOwnerMask & PermissionMask.Transfer) != 0;
982 cbNextOwnModify.CheckedChanged += cbNextOwnerUpdate_CheckedChanged;
983 cbNextOwnCopy.CheckedChanged += cbNextOwnerUpdate_CheckedChanged;
984 cbNextOwnTransfer.CheckedChanged += cbNextOwnerUpdate_CheckedChanged;
987 switch (item.AssetType)
989 case AssetType.Texture:
990 SLImageHandler image = new SLImageHandler(instance, item.AssetUUID, item.Name, IsFullPerm(item));
991 image.Dock = DockStyle.Fill;
992 pnlDetail.Controls.Add(image);
995 case AssetType.Notecard:
996 Notecard note = new Notecard(instance, (InventoryNotecard)item);
997 note.Dock = DockStyle.Fill;
1000 pnlDetail.Controls.Add(note);
1001 note.rtbContent.Focus();
1004 case AssetType.Landmark:
1005 Landmark landmark = new Landmark(instance, (InventoryLandmark)item);
1006 landmark.Dock = DockStyle.Fill;
1007 pnlDetail.Controls.Add(landmark);
1010 case AssetType.LSLText:
1011 ScriptEditor script = new ScriptEditor(instance, (InventoryLSL)item);
1012 script.Dock = DockStyle.Fill;
1013 script.TabIndex = 3;
1014 script.TabStop = true;
1015 pnlDetail.Controls.Add(script);
1018 case AssetType.Gesture:
1019 Guesture gesture = new Guesture(instance, (InventoryGesture)item);
1020 gesture.Dock = DockStyle.Fill;
1021 pnlDetail.Controls.Add(gesture);
1026 tabsInventory.SelectedTab = tabDetail;
1029 void cbNextOwnerUpdate_CheckedChanged(object sender, EventArgs e)
1031 InventoryItem item = null;
1032 if (pnlItemProperties.Tag != null && pnlItemProperties.Tag is InventoryItem)
1034 item = (InventoryItem)pnlItemProperties.Tag;
1036 if (item == null) return;
1038 PermissionMask pm = PermissionMask.Move;
1039 if (cbNextOwnCopy.Checked) pm |= PermissionMask.Copy;
1040 if (cbNextOwnModify.Checked) pm |= PermissionMask.Modify;
1041 if (cbNextOwnTransfer.Checked) pm |= PermissionMask.Transfer;
1042 item.Permissions.NextOwnerMask = pm;
1044 client.Inventory.RequestUpdateItem(item);
1045 client.Inventory.RequestFetchInventory(item.UUID, item.OwnerID);
1048 private void txtItemName_Leave(object sender, EventArgs e)
1050 InventoryItem item = null;
1051 if (pnlItemProperties.Tag != null && pnlItemProperties.Tag is InventoryItem)
1053 item = (InventoryItem)pnlItemProperties.Tag;
1055 if (item == null) return;
1057 item.Name = txtItemName.Text;
1059 client.Inventory.RequestUpdateItem(item);
1060 client.Inventory.RequestFetchInventory(item.UUID, item.OwnerID);
1063 private void txtItemDescription_Leave(object sender, EventArgs e)
1065 InventoryItem item = null;
1066 if (pnlItemProperties.Tag != null && pnlItemProperties.Tag is InventoryItem)
1068 item = (InventoryItem)pnlItemProperties.Tag;
1070 if (item == null) return;
1072 item.Description = txtItemDescription.Text;
1074 client.Inventory.RequestUpdateItem(item);
1075 client.Inventory.RequestFetchInventory(item.UUID, item.OwnerID);
1078 void invTree_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
1080 if (invTree.SelectedNode.Tag is InventoryItem)
1082 InventoryItem item = invTree.SelectedNode.Tag as InventoryItem;
1083 switch (item.AssetType)
1086 case AssetType.Landmark:
1087 instance.TabConsole.DisplayNotificationInChat("Teleporting to " + item.Name);
1088 client.Self.RequestTeleport(item.AssetUUID);
1091 case AssetType.Gesture:
1092 client.Self.PlayGesture(item.AssetUUID);
1095 case AssetType.Notecard:
1096 Notecard note = new Notecard(instance, (InventoryNotecard)item);
1097 note.Dock = DockStyle.Fill;
1098 note.ShowDetached();
1101 case AssetType.LSLText:
1102 ScriptEditor script = new ScriptEditor(instance, (InventoryLSL)item);
1103 script.Dock = DockStyle.Fill;
1104 script.ShowDetached();
1110 private void fetchFolder(UUID folderID, UUID ownerID, bool force)
1112 if (force || !fetchedFolders.Contains(folderID))
1114 if (!fetchedFolders.Contains(folderID))
1116 fetchedFolders.Add(folderID);
1119 client.Inventory.RequestFolderContents(folderID, ownerID, true, true, InventorySortOrder.ByDate);
1123 public bool IsWorn(InventoryItem item)
1125 bool worn = client.Appearance.IsItemWorn(item) != WearableType.Invalid;
1129 if (worn && !WornItems.Contains(item.UUID))
1130 WornItems.Add(item.UUID);
1135 public AttachmentPoint AttachedTo(InventoryItem item)
1139 if (attachments.ContainsKey(item.UUID))
1141 return attachments[item.UUID].Point;
1145 return AttachmentPoint.Default;
1148 public bool IsAttached(InventoryItem item)
1150 List<Primitive> myAtt = client.Network.CurrentSim.ObjectsPrimitives.FindAll((Primitive p) => p.ParentID == client.Self.LocalID);
1151 foreach (Primitive prim in myAtt)
1153 if (prim.NameValues == null) continue;
1154 UUID invID = UUID.Zero;
1155 for (int i = 0; i < prim.NameValues.Length; i++)
1157 if (prim.NameValues[i].Name == "AttachItemID")
1159 invID = (UUID)prim.NameValues[i].Value.ToString();
1163 if (invID == item.UUID)
1167 AttachmentInfo inf = new AttachmentInfo();
1168 inf.InventoryID = item.UUID;
1170 inf.MarkedAttached = true;
1172 inf.PrimID = prim.ID;
1173 attachments[invID] = inf;
1182 public InventoryItem AttachmentAt(AttachmentPoint point)
1186 foreach (KeyValuePair<UUID, AttachmentInfo> att in attachments)
1188 if (att.Value.Point == point)
1190 return att.Value.Item;
1198 /// Returns text of the label
1200 /// <param name="invBase">Inventory item</param>
1201 /// <param name="returnRaw">Should we return raw text, or if false decorated text with (worn) info, and (no copy) etc. permission info</param>
1202 /// <returns></returns>
1203 public string ItemLabel(InventoryBase invBase, bool returnRaw)
1205 if (returnRaw || (invBase is InventoryFolder))
1206 return invBase.Name;
1208 InventoryItem item = (InventoryItem)invBase;
1210 string raw = item.Name;
1215 item = instance.COF.RealInventoryItem(item);
1216 if (Inventory.Contains(item.AssetUUID) && Inventory[item.AssetUUID] is InventoryItem)
1218 item = (InventoryItem)Inventory[item.AssetUUID];
1222 if ((item.Permissions.OwnerMask & PermissionMask.Modify) == 0)
1223 raw += " (no modify)";
1225 if ((item.Permissions.OwnerMask & PermissionMask.Copy) == 0)
1226 raw += " (no copy)";
1228 if ((item.Permissions.OwnerMask & PermissionMask.Transfer) == 0)
1229 raw += " (no transfer)";
1234 if (IsAttached(item))
1236 raw += " (worn on " + AttachedTo(item).ToString() + ")";
1242 public static bool IsFullPerm(InventoryItem item)
1245 ((item.Permissions.OwnerMask & PermissionMask.Modify) != 0) &&
1246 ((item.Permissions.OwnerMask & PermissionMask.Copy) != 0) &&
1247 ((item.Permissions.OwnerMask & PermissionMask.Transfer) != 0)
1258 void invTree_MouseClick(object sender, TreeNodeMouseClickEventArgs e)
1260 TreeNode node = e.Node;
1262 if (e.Button == MouseButtons.Left)
1264 invTree.SelectedNode = node;
1265 if (node.Tag is InventoryItem)
1267 UpdateItemInfo(instance.COF.RealInventoryItem(node.Tag as InventoryItem));
1271 UpdateItemInfo(null);
1274 else if (e.Button == MouseButtons.Right)
1276 invTree.SelectedNode = node;
1277 ctxInv.Show(invTree, e.X, e.Y);
1281 private void ctxInv_Opening(object sender, CancelEventArgs e)
1284 TreeNode node = invTree.SelectedNode;
1291 #region Folder context menu
1292 if (node.Tag is InventoryFolder)
1294 InventoryFolder folder = (InventoryFolder)node.Tag;
1295 ctxInv.Items.Clear();
1297 ToolStripMenuItem ctxItem;
1299 if ((int)folder.PreferredType >= (int)AssetType.EnsembleStart &&
1300 (int)folder.PreferredType <= (int)AssetType.EnsembleEnd)
1302 ctxItem = new ToolStripMenuItem("Fix type", null, OnInvContextClick);
1303 ctxItem.Name = "fix_type";
1304 ctxInv.Items.Add(ctxItem);
1305 ctxInv.Items.Add(new ToolStripSeparator());
1308 ctxItem = new ToolStripMenuItem("New Folder", null, OnInvContextClick);
1309 ctxItem.Name = "new_folder";
1310 ctxInv.Items.Add(ctxItem);
1312 ctxItem = new ToolStripMenuItem("New Note", null, OnInvContextClick);
1313 ctxItem.Name = "new_notecard";
1314 ctxInv.Items.Add(ctxItem);
1316 ctxItem = new ToolStripMenuItem("New Script", null, OnInvContextClick);
1317 ctxItem.Name = "new_script";
1318 ctxInv.Items.Add(ctxItem);
1320 ctxItem = new ToolStripMenuItem("Refresh", null, OnInvContextClick);
1321 ctxItem.Name = "refresh";
1322 ctxInv.Items.Add(ctxItem);
1324 ctxItem = new ToolStripMenuItem("Backup...", null, OnInvContextClick);
1325 ctxItem.Name = "backup";
1326 ctxInv.Items.Add(ctxItem);
1328 ctxInv.Items.Add(new ToolStripSeparator());
1330 ctxItem = new ToolStripMenuItem("Expand", null, OnInvContextClick);
1331 ctxItem.Name = "expand";
1332 ctxInv.Items.Add(ctxItem);
1334 ctxItem = new ToolStripMenuItem("Expand All", null, OnInvContextClick);
1335 ctxItem.Name = "expand_all";
1336 ctxInv.Items.Add(ctxItem);
1338 ctxItem = new ToolStripMenuItem("Collapse", null, OnInvContextClick);
1339 ctxItem.Name = "collapse";
1340 ctxInv.Items.Add(ctxItem);
1342 if (folder.PreferredType == AssetType.TrashFolder)
1344 ctxItem = new ToolStripMenuItem("Empty Trash", null, OnInvContextClick);
1345 ctxItem.Name = "empty_trash";
1346 ctxInv.Items.Add(ctxItem);
1349 if (folder.PreferredType == AssetType.LostAndFoundFolder)
1351 ctxItem = new ToolStripMenuItem("Empty Lost and Found", null, OnInvContextClick);
1352 ctxItem.Name = "empty_lost_found";
1353 ctxInv.Items.Add(ctxItem);
1356 if (folder.PreferredType == AssetType.Unknown ||
1357 folder.PreferredType == AssetType.OutfitFolder)
1359 ctxItem = new ToolStripMenuItem("Rename", null, OnInvContextClick);
1360 ctxItem.Name = "rename_folder";
1361 ctxInv.Items.Add(ctxItem);
1363 ctxInv.Items.Add(new ToolStripSeparator());
1365 ctxItem = new ToolStripMenuItem("Cut", null, OnInvContextClick);
1366 ctxItem.Name = "cut_folder";
1367 ctxInv.Items.Add(ctxItem);
1369 ctxItem = new ToolStripMenuItem("Copy", null, OnInvContextClick);
1370 ctxItem.Name = "copy_folder";
1371 ctxInv.Items.Add(ctxItem);
1374 if (instance.InventoryClipboard != null)
1376 ctxItem = new ToolStripMenuItem("Paste", null, OnInvContextClick);
1377 ctxItem.Name = "paste_folder";
1378 ctxInv.Items.Add(ctxItem);
1380 if (instance.InventoryClipboard.Item is InventoryItem)
1382 ctxItem = new ToolStripMenuItem("Paste as Link", null, OnInvContextClick);
1383 ctxItem.Name = "paste_folder_link";
1384 ctxInv.Items.Add(ctxItem);
1388 if (folder.PreferredType == AssetType.Unknown ||
1389 folder.PreferredType == AssetType.OutfitFolder)
1391 ctxItem = new ToolStripMenuItem("Delete", null, OnInvContextClick);
1392 ctxItem.Name = "delete_folder";
1393 ctxInv.Items.Add(ctxItem);
1395 ctxInv.Items.Add(new ToolStripSeparator());
1398 if (folder.PreferredType == AssetType.Unknown || folder.PreferredType == AssetType.OutfitFolder)
1400 ctxItem = new ToolStripMenuItem("Take off Items", null, OnInvContextClick);
1401 ctxItem.Name = "outfit_take_off";
1402 ctxInv.Items.Add(ctxItem);
1404 ctxItem = new ToolStripMenuItem("Add to Outfit", null, OnInvContextClick);
1405 ctxItem.Name = "outfit_add";
1406 ctxInv.Items.Add(ctxItem);
1408 ctxItem = new ToolStripMenuItem("Replace Outfit", null, OnInvContextClick);
1409 ctxItem.Name = "outfit_replace";
1410 ctxInv.Items.Add(ctxItem);
1413 instance.ContextActionManager.AddContributions(ctxInv, folder);
1414 #endregion Folder context menu
1416 else if (node.Tag is InventoryItem)
1418 #region Item context menu
1419 InventoryItem item = instance.COF.RealInventoryItem((InventoryItem)node.Tag);
1420 ctxInv.Items.Clear();
1422 ToolStripMenuItem ctxItem;
1424 if (item.InventoryType == InventoryType.LSL)
1426 ctxItem = new ToolStripMenuItem("Edit script", null, OnInvContextClick);
1427 ctxItem.Name = "edit_script";
1428 ctxInv.Items.Add(ctxItem);
1431 if (item.AssetType == AssetType.Texture)
1433 ctxItem = new ToolStripMenuItem("View", null, OnInvContextClick);
1434 ctxItem.Name = "view_image";
1435 ctxInv.Items.Add(ctxItem);
1438 if (item.InventoryType == InventoryType.Landmark)
1440 ctxItem = new ToolStripMenuItem("Teleport", null, OnInvContextClick);
1441 ctxItem.Name = "lm_teleport";
1442 ctxInv.Items.Add(ctxItem);
1444 ctxItem = new ToolStripMenuItem("Info", null, OnInvContextClick);
1445 ctxItem.Name = "lm_info";
1446 ctxInv.Items.Add(ctxItem);
1449 if (item.InventoryType == InventoryType.Notecard)
1451 ctxItem = new ToolStripMenuItem("Open", null, OnInvContextClick);
1452 ctxItem.Name = "notecard_open";
1453 ctxInv.Items.Add(ctxItem);
1456 if (item.InventoryType == InventoryType.Gesture)
1458 ctxItem = new ToolStripMenuItem("Play", null, OnInvContextClick);
1459 ctxItem.Name = "gesture_play";
1460 ctxInv.Items.Add(ctxItem);
1462 ctxItem = new ToolStripMenuItem("Info", null, OnInvContextClick);
1463 ctxItem.Name = "gesture_info";
1464 ctxInv.Items.Add(ctxItem);
1467 if (item.InventoryType == InventoryType.Animation)
1469 if (!client.Self.SignaledAnimations.ContainsKey(item.AssetUUID))
1471 ctxItem = new ToolStripMenuItem("Play", null, OnInvContextClick);
1472 ctxItem.Name = "animation_play";
1473 ctxInv.Items.Add(ctxItem);
1477 ctxItem = new ToolStripMenuItem("Stop", null, OnInvContextClick);
1478 ctxItem.Name = "animation_stop";
1479 ctxInv.Items.Add(ctxItem);
1483 if (item.InventoryType == InventoryType.Object)
1485 ctxItem = new ToolStripMenuItem("Rez inworld", null, OnInvContextClick);
1486 ctxItem.Name = "rez_inworld";
1487 ctxInv.Items.Add(ctxItem);
1490 ctxItem = new ToolStripMenuItem("Rename", null, OnInvContextClick);
1491 ctxItem.Name = "rename_item";
1492 ctxInv.Items.Add(ctxItem);
1494 ctxInv.Items.Add(new ToolStripSeparator());
1496 ctxItem = new ToolStripMenuItem("Cut", null, OnInvContextClick);
1497 ctxItem.Name = "cut_item";
1498 ctxInv.Items.Add(ctxItem);
1500 ctxItem = new ToolStripMenuItem("Copy", null, OnInvContextClick);
1501 ctxItem.Name = "copy_item";
1502 ctxInv.Items.Add(ctxItem);
1504 if (instance.InventoryClipboard != null)
1506 ctxItem = new ToolStripMenuItem("Paste", null, OnInvContextClick);
1507 ctxItem.Name = "paste_item";
1508 ctxInv.Items.Add(ctxItem);
1510 if (instance.InventoryClipboard.Item is InventoryItem)
1512 ctxItem = new ToolStripMenuItem("Paste as Link", null, OnInvContextClick);
1513 ctxItem.Name = "paste_item_link";
1514 ctxInv.Items.Add(ctxItem);
1518 ctxItem = new ToolStripMenuItem("Delete", null, OnInvContextClick);
1519 ctxItem.Name = "delete_item";
1521 if (IsAttached(item) || IsWorn(item))
1523 ctxItem.Enabled = false;
1525 ctxInv.Items.Add(ctxItem);
1527 if (IsAttached(item) && instance.RLV.AllowDetach(attachments[item.UUID]))
1529 ctxItem = new ToolStripMenuItem("Detach from yourself", null, OnInvContextClick);
1530 ctxItem.Name = "detach";
1531 ctxInv.Items.Add(ctxItem);
1534 if (!IsAttached(item) && (item.InventoryType == InventoryType.Object || item.InventoryType == InventoryType.Attachment))
1536 ToolStripMenuItem ctxItemAttach = new ToolStripMenuItem("Attach to");
1537 ctxInv.Items.Add(ctxItemAttach);
1539 ToolStripMenuItem ctxItemAttachHUD = new ToolStripMenuItem("Attach to HUD");
1540 ctxInv.Items.Add(ctxItemAttachHUD);
1542 foreach (AttachmentPoint pt in Enum.GetValues(typeof(AttachmentPoint)))
1544 if (!pt.ToString().StartsWith("HUD"))
1546 string name = Utils.EnumToText(pt);
1548 InventoryItem alreadyAttached = null;
1549 if ((alreadyAttached = AttachmentAt(pt)) != null)
1551 name += " (" + alreadyAttached.Name + ")";
1554 ToolStripMenuItem ptItem = new ToolStripMenuItem(name, null, OnInvContextClick);
1555 ptItem.Name = pt.ToString();
1557 ptItem.Name = "attach_to";
1558 ctxItemAttach.DropDownItems.Add(ptItem);
1562 string name = Utils.EnumToText(pt).Substring(3);
1564 InventoryItem alreadyAttached = null;
1565 if ((alreadyAttached = AttachmentAt(pt)) != null)
1567 name += " (" + alreadyAttached.Name + ")";
1570 ToolStripMenuItem ptItem = new ToolStripMenuItem(name, null, OnInvContextClick);
1571 ptItem.Name = pt.ToString();
1573 ptItem.Name = "attach_to";
1574 ctxItemAttachHUD.DropDownItems.Add(ptItem);
1578 ctxItem = new ToolStripMenuItem("Add to Worn", null, OnInvContextClick);
1579 ctxItem.Name = "wear_attachment_add";
1580 ctxInv.Items.Add(ctxItem);
1582 ctxItem = new ToolStripMenuItem("Wear", null, OnInvContextClick);
1583 ctxItem.Name = "wear_attachment";
1584 ctxInv.Items.Add(ctxItem);
1587 if (item is InventoryWearable)
1589 ctxInv.Items.Add(new ToolStripSeparator());
1593 ctxItem = new ToolStripMenuItem("Take off", null, OnInvContextClick);
1594 ctxItem.Name = "item_take_off";
1595 ctxInv.Items.Add(ctxItem);
1599 ctxItem = new ToolStripMenuItem("Wear", null, OnInvContextClick);
1600 ctxItem.Name = "item_wear";
1601 ctxInv.Items.Add(ctxItem);
1605 instance.ContextActionManager.AddContributions(ctxInv, item);
1606 #endregion Item context menu
1611 #region Context menu folder
1612 private void OnInvContextClick(object sender, EventArgs e)
1614 if (invTree.SelectedNode == null || !(invTree.SelectedNode.Tag is InventoryBase))
1619 string cmd = ((ToolStripMenuItem)sender).Name;
1621 if (invTree.SelectedNode.Tag is InventoryFolder)
1623 #region Folder actions
1624 InventoryFolder f = (InventoryFolder)invTree.SelectedNode.Tag;
1629 foreach (TreeNode old in invTree.SelectedNode.Nodes)
1631 if (!(old.Tag is InventoryFolder))
1636 fetchFolder(f.UUID, f.OwnerID, true);
1640 (new InventoryBackup(instance, f.UUID)).Show();
1644 invTree.SelectedNode.Expand();
1648 invTree.SelectedNode.ExpandAll();
1652 invTree.SelectedNode.Collapse();
1656 newItemName = "New folder";
1657 client.Inventory.CreateFolder(f.UUID, "New folder");
1661 client.Inventory.UpdateFolderProperties(f.UUID, f.ParentUUID, f.Name, AssetType.Unknown);
1665 case "new_notecard":
1666 client.Inventory.RequestCreateItem(f.UUID, "New Note", "Radegast note: " + DateTime.Now.ToString(),
1667 AssetType.Notecard, UUID.Zero, InventoryType.Notecard, PermissionMask.All, NotecardCreated);
1671 client.Inventory.RequestCreateItem(f.UUID, "New script", "Radegast script: " + DateTime.Now.ToString(),
1672 AssetType.LSLText, UUID.Zero, InventoryType.LSL, PermissionMask.All, ScriptCreated);
1676 instance.InventoryClipboard = new InventoryClipboard(ClipboardOperation.Cut, f);
1680 instance.InventoryClipboard = new InventoryClipboard(ClipboardOperation.Copy, f);
1683 case "paste_folder":
1684 PerformClipboardOperation(invTree.SelectedNode.Tag as InventoryFolder);
1687 case "paste_folder_link":
1688 PerformLinkOperation(invTree.SelectedNode.Tag as InventoryFolder);
1692 case "delete_folder":
1693 client.Inventory.MoveFolder(f.UUID, client.Inventory.FindFolderForType(AssetType.TrashFolder), f.Name);
1698 DialogResult res = MessageBox.Show("Are you sure you want to empty your trash?", "Confirmation", MessageBoxButtons.OKCancel);
1699 if (res == DialogResult.OK)
1701 client.Inventory.EmptyTrash();
1706 case "empty_lost_found":
1708 DialogResult res = MessageBox.Show("Are you sure you want to empty your lost and found folder?", "Confirmation", MessageBoxButtons.OKCancel);
1709 if (res == DialogResult.OK)
1711 client.Inventory.EmptyLostAndFound();
1716 case "rename_folder":
1717 invTree.SelectedNode.BeginEdit();
1720 case "outfit_replace":
1721 List<InventoryItem> newOutfit = new List<InventoryItem>();
1722 foreach (InventoryBase item in Inventory.GetContents(f))
1724 if (item is InventoryItem)
1725 newOutfit.Add((InventoryItem)item);
1727 appearnceWasBusy = client.Appearance.ManagerBusy;
1728 instance.COF.ReplaceOutfit(newOutfit);
1733 List<InventoryItem> addToOutfit = new List<InventoryItem>();
1734 foreach (InventoryBase item in Inventory.GetContents(f))
1736 if (item is InventoryItem)
1737 addToOutfit.Add((InventoryItem)item);
1739 appearnceWasBusy = client.Appearance.ManagerBusy;
1740 instance.COF.AddToOutfit(addToOutfit, true);
1744 case "outfit_take_off":
1745 List<InventoryItem> removeFromOutfit = new List<InventoryItem>();
1746 foreach (InventoryBase item in Inventory.GetContents(f))
1748 if (item is InventoryItem)
1749 removeFromOutfit.Add((InventoryItem)item);
1751 appearnceWasBusy = client.Appearance.ManagerBusy;
1752 instance.COF.RemoveFromOutfit(removeFromOutfit);
1758 else if (invTree.SelectedNode.Tag is InventoryItem)
1760 #region Item actions
1761 InventoryItem item = (InventoryItem)invTree.SelectedNode.Tag;
1763 // Copy, cut, and delete works on links directly
1764 // The rest operate on the item that is pointed by the link
1765 if (cmd != "copy_item" && cmd != "cut_item" && cmd != "delete_item")
1767 item = instance.COF.RealInventoryItem(item);
1773 instance.InventoryClipboard = new InventoryClipboard(ClipboardOperation.Copy, item);
1777 instance.InventoryClipboard = new InventoryClipboard(ClipboardOperation.Cut, item);
1781 PerformClipboardOperation(invTree.SelectedNode.Parent.Tag as InventoryFolder);
1784 case "paste_item_link":
1785 PerformLinkOperation(invTree.SelectedNode.Parent.Tag as InventoryFolder);
1789 client.Inventory.MoveItem(item.UUID, client.Inventory.FindFolderForType(AssetType.TrashFolder), item.Name);
1793 invTree.SelectedNode.BeginEdit();
1797 instance.COF.Detach(item);
1798 lock (attachments) attachments.Remove(item.UUID);
1799 invTree.SelectedNode.Text = ItemLabel(item, false);
1802 case "wear_attachment":
1803 instance.COF.Attach(item, AttachmentPoint.Default, true);
1806 case "wear_attachment_add":
1807 instance.COF.Attach(item, AttachmentPoint.Default, false);
1811 AttachmentPoint pt = (AttachmentPoint)((ToolStripMenuItem)sender).Tag;
1812 instance.COF.Attach(item, pt, true);
1816 ScriptEditor se = new ScriptEditor(instance, (InventoryLSL)item);
1821 UpdateItemInfo(item);
1824 case "item_take_off":
1825 appearnceWasBusy = client.Appearance.ManagerBusy;
1826 instance.COF.RemoveFromOutfit(item);
1827 invTree.SelectedNode.Text = ItemLabel(item, false);
1830 if (WornItems.Contains(item.UUID))
1832 WornItems.Remove(item.UUID);
1838 appearnceWasBusy = client.Appearance.ManagerBusy;
1839 instance.COF.AddToOutfit(item, true);
1840 invTree.SelectedNode.Text = ItemLabel(item, false);
1844 instance.TabConsole.DisplayNotificationInChat("Teleporting to " + item.Name);
1845 client.Self.RequestTeleport(item.AssetUUID);
1849 UpdateItemInfo(item);
1852 case "notecard_open":
1853 UpdateItemInfo(item);
1856 case "gesture_info":
1857 UpdateItemInfo(item);
1860 case "gesture_play":
1861 client.Self.PlayGesture(item.AssetUUID);
1864 case "animation_play":
1865 Dictionary<UUID, bool> anim = new Dictionary<UUID, bool>();
1866 anim.Add(item.AssetUUID, true);
1867 client.Self.Animate(anim, true);
1870 case "animation_stop":
1871 Dictionary<UUID, bool> animStop = new Dictionary<UUID, bool>();
1872 animStop.Add(item.AssetUUID, false);
1873 client.Self.Animate(animStop, true);
1877 instance.MediaManager.PlayUISound(UISounds.ObjectRez);
1878 Vector3 rezpos = new Vector3(2, 0, 0);
1879 rezpos = client.Self.SimPosition + rezpos * client.Self.Movement.BodyRotation;
1880 client.Inventory.RequestRezFromInventory(client.Network.CurrentSim, Quaternion.Identity, rezpos, item);
1887 void NotecardCreated(bool success, InventoryItem item)
1891 BeginInvoke(new MethodInvoker(() => NotecardCreated(success, item)));
1897 instance.TabConsole.DisplayNotificationInChat("Creation of notecard failed");
1901 instance.TabConsole.DisplayNotificationInChat("New notecard created, enter notecard name and press enter", ChatBufferTextStyle.Invisible);
1902 var node = findNodeForItem(item.ParentUUID);
1903 if (node != null) node.Expand();
1904 node = findNodeForItem(item.UUID);
1907 invTree.SelectedNode = node;
1912 void ScriptCreated(bool success, InventoryItem item)
1916 BeginInvoke(new MethodInvoker(() => ScriptCreated(success, item)));
1922 instance.TabConsole.DisplayNotificationInChat("Creation of script failed");
1926 instance.TabConsole.DisplayNotificationInChat("New script created, enter script name and press enter", ChatBufferTextStyle.Invisible);
1927 var node = findNodeForItem(item.ParentUUID);
1928 if (node != null) node.Expand();
1929 node = findNodeForItem(item.UUID);
1932 invTree.SelectedNode = node;
1937 void PerformClipboardOperation(InventoryFolder dest)
1939 if (instance.InventoryClipboard == null) return;
1941 if (dest == null) return;
1943 if (instance.InventoryClipboard.Operation == ClipboardOperation.Cut)
1945 if (instance.InventoryClipboard.Item is InventoryItem)
1947 client.Inventory.MoveItem(instance.InventoryClipboard.Item.UUID, dest.UUID, instance.InventoryClipboard.Item.Name);
1949 else if (instance.InventoryClipboard.Item is InventoryFolder)
1951 if (instance.InventoryClipboard.Item.UUID != dest.UUID)
1953 client.Inventory.MoveFolder(instance.InventoryClipboard.Item.UUID, dest.UUID, instance.InventoryClipboard.Item.Name);
1957 instance.InventoryClipboard = null;
1959 else if (instance.InventoryClipboard.Operation == ClipboardOperation.Copy)
1961 if (instance.InventoryClipboard.Item is InventoryItem)
1963 client.Inventory.RequestCopyItem(instance.InventoryClipboard.Item.UUID, dest.UUID, instance.InventoryClipboard.Item.Name, instance.InventoryClipboard.Item.OwnerID, (InventoryBase target) =>
1968 else if (instance.InventoryClipboard.Item is InventoryFolder)
1970 ThreadPool.QueueUserWorkItem((object state) =>
1972 UUID newFolderID = client.Inventory.CreateFolder(dest.UUID, instance.InventoryClipboard.Item.Name, AssetType.Unknown);
1975 // FIXME: for some reason copying a bunch of items in one operation does not work
1977 //List<UUID> items = new List<UUID>();
1978 //List<UUID> folders = new List<UUID>();
1979 //List<string> names = new List<string>();
1980 //UUID oldOwner = UUID.Zero;
1982 foreach (InventoryBase oldItem in Inventory.GetContents((InventoryFolder)instance.InventoryClipboard.Item))
1984 //folders.Add(newFolderID);
1985 //names.Add(oldItem.Name);
1986 //items.Add(oldItem.UUID);
1987 //oldOwner = oldItem.OwnerID;
1988 client.Inventory.RequestCopyItem(oldItem.UUID, newFolderID, oldItem.Name, oldItem.OwnerID, (InventoryBase target) => { });
1991 //if (folders.Count > 0)
1993 // client.Inventory.RequestCopyItems(items, folders, names, oldOwner, (InventoryBase target) => { });
2001 void PerformLinkOperation(InventoryFolder dest)
2003 if (instance.InventoryClipboard == null) return;
2005 if (dest == null) return;
2007 client.Inventory.CreateLink(dest.UUID, instance.InventoryClipboard.Item, (bool success, InventoryItem item) => { });
2012 private void UpdateWornLabels()
2016 BeginInvoke(new MethodInvoker(UpdateWornLabels));
2020 invTree.BeginUpdate();
2021 foreach (UUID itemID in WornItems)
2023 TreeNode node = findNodeForItem(itemID);
2026 node.Text = ItemLabel((InventoryBase)node.Tag, false);
2030 foreach (AppearanceManager.WearableData wearable in client.Appearance.GetWearables().Values)
2032 TreeNode node = findNodeForItem(wearable.ItemID);
2035 node.Text = ItemLabel((InventoryBase)node.Tag, false);
2038 invTree.EndUpdate();
2041 void TreeView_AfterExpand(object sender, TreeViewEventArgs e)
2043 // Check if we need to go into edit mode for new items
2044 if (newItemName != string.Empty)
2046 foreach (TreeNode n in e.Node.Nodes)
2048 if (n.Name == newItemName)
2054 newItemName = string.Empty;
2058 private bool _EditingNode = false;
2060 private void OnLabelEditTimer(object sender)
2062 if (_EditNode == null || !(_EditNode.Tag is InventoryBase))
2067 BeginInvoke(new MethodInvoker(delegate()
2069 OnLabelEditTimer(sender);
2075 _EditingNode = true;
2076 _EditNode.Text = ItemLabel((InventoryBase)_EditNode.Tag, true);
2077 _EditNode.BeginEdit();
2080 private void invTree_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
2082 if (e.Node == null ||
2083 !(e.Node.Tag is InventoryBase) ||
2084 (e.Node.Tag is InventoryFolder &&
2085 ((InventoryFolder)e.Node.Tag).PreferredType != AssetType.Unknown &&
2086 ((InventoryFolder)e.Node.Tag).PreferredType != AssetType.OutfitFolder)
2089 e.CancelEdit = true;
2095 _EditingNode = false;
2099 e.CancelEdit = true;
2101 _EditTimer.Change(20, System.Threading.Timeout.Infinite);
2105 private void invTree_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
2107 if (string.IsNullOrEmpty(e.Label))
2109 if (e.Node.Tag is InventoryBase)
2111 e.Node.Text = ItemLabel((InventoryBase)e.Node.Tag, false);
2113 e.CancelEdit = true;
2117 if (e.Node.Tag is InventoryFolder)
2119 InventoryFolder f = (InventoryFolder)e.Node.Tag;
2121 client.Inventory.MoveFolder(f.UUID, f.ParentUUID, f.Name);
2123 else if (e.Node.Tag is InventoryItem)
2125 InventoryItem item = (InventoryItem)e.Node.Tag;
2126 item.Name = e.Label;
2127 e.Node.Text = ItemLabel((InventoryBase)item, false);
2128 client.Inventory.MoveItem(item.UUID, item.ParentUUID, item.Name);
2129 UpdateItemInfo(item);
2134 private void invTree_KeyUp(object sender, KeyEventArgs e)
2136 if (e.KeyCode == Keys.F2 && invTree.SelectedNode != null)
2138 invTree.SelectedNode.BeginEdit();
2140 else if (e.KeyCode == Keys.F5 && invTree.SelectedNode != null)
2142 if (invTree.SelectedNode.Tag is InventoryFolder)
2144 InventoryFolder f = (InventoryFolder)invTree.SelectedNode.Tag;
2145 fetchFolder(f.UUID, f.OwnerID, true);
2148 else if (e.KeyCode == Keys.Delete && invTree.SelectedNode != null)
2150 if (invTree.SelectedNode.Tag is InventoryItem)
2152 InventoryItem item = invTree.SelectedNode.Tag as InventoryItem;
2153 client.Inventory.MoveItem(item.UUID, client.Inventory.FindFolderForType(AssetType.TrashFolder), item.Name);
2155 else if (invTree.SelectedNode.Tag is InventoryFolder)
2157 InventoryFolder f = invTree.SelectedNode.Tag as InventoryFolder;
2158 client.Inventory.MoveFolder(f.UUID, client.Inventory.FindFolderForType(AssetType.TrashFolder), f.Name);
2161 else if (e.KeyCode == Keys.Apps && invTree.SelectedNode != null)
2167 #region Drag and Drop
2168 private void invTree_ItemDrag(object sender, ItemDragEventArgs e)
2170 invTree.SelectedNode = e.Item as TreeNode;
2171 if (invTree.SelectedNode.Tag is InventoryFolder && ((InventoryFolder)invTree.SelectedNode.Tag).PreferredType != AssetType.Unknown)
2175 invTree.DoDragDrop(e.Item, DragDropEffects.Move);
2178 private void invTree_DragDrop(object sender, DragEventArgs e)
2180 if (highlightedNode != null)
2182 highlightedNode.BackColor = invTree.BackColor;
2183 highlightedNode = null;
2186 TreeNode sourceNode = e.Data.GetData(typeof(TreeNode)) as TreeNode;
2187 if (sourceNode == null) return;
2189 Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
2190 TreeNode destinationNode = ((TreeView)sender).GetNodeAt(pt);
2192 if (destinationNode == null) return;
2194 if (sourceNode == destinationNode) return;
2196 // If droping to item within folder drop to its folder
2197 if (destinationNode.Tag is InventoryItem)
2199 destinationNode = destinationNode.Parent;
2202 InventoryFolder dest = destinationNode.Tag as InventoryFolder;
2204 if (dest == null) return;
2206 if (sourceNode.Tag is InventoryItem)
2208 InventoryItem item = (InventoryItem)sourceNode.Tag;
2209 client.Inventory.MoveItem(item.UUID, dest.UUID, item.Name);
2211 else if (sourceNode.Tag is InventoryFolder)
2213 InventoryFolder f = (InventoryFolder)sourceNode.Tag;
2214 client.Inventory.MoveFolder(f.UUID, dest.UUID, f.Name);
2218 private void invTree_DragEnter(object sender, DragEventArgs e)
2220 TreeNode node = e.Data.GetData(typeof(TreeNode)) as TreeNode;
2223 e.Effect = DragDropEffects.None;
2227 e.Effect = DragDropEffects.Move;
2231 TreeNode highlightedNode = null;
2233 private void invTree_DragOver(object sender, DragEventArgs e)
2235 TreeNode node = e.Data.GetData(typeof(TreeNode)) as TreeNode;
2238 e.Effect = DragDropEffects.None;
2241 Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
2242 TreeNode destinationNode = ((TreeView)sender).GetNodeAt(pt);
2244 if (highlightedNode != destinationNode)
2246 if (highlightedNode != null)
2248 highlightedNode.BackColor = invTree.BackColor;
2249 highlightedNode = null;
2252 if (destinationNode != null)
2254 highlightedNode = destinationNode;
2255 highlightedNode.BackColor = Color.LightSlateGray;
2259 if (destinationNode == null)
2261 e.Effect = DragDropEffects.None;
2265 e.Effect = DragDropEffects.Move;
2270 private void saveAllTToolStripMenuItem_Click(object sender, EventArgs e)
2272 (new InventoryBackup(instance, Inventory.RootFolder.UUID)).Show();
2275 private void tbtnSystemFoldersFirst_Click(object sender, EventArgs e)
2277 sorter.SystemFoldersFirst = tbtnSystemFoldersFirst.Checked = !sorter.SystemFoldersFirst;
2278 instance.GlobalSettings["inv_sort_sysfirst"] = OSD.FromBoolean(sorter.SystemFoldersFirst);
2282 private void tbtbSortByName_Click(object sender, EventArgs e)
2284 if (tbtbSortByName.Checked) return;
2286 tbtbSortByName.Checked = true;
2287 tbtnSortByDate.Checked = sorter.ByDate = false;
2288 instance.GlobalSettings["inv_sort_bydate"] = OSD.FromBoolean(sorter.ByDate);
2293 private void tbtnSortByDate_Click(object sender, EventArgs e)
2295 if (tbtnSortByDate.Checked) return;
2297 tbtbSortByName.Checked = false;
2298 tbtnSortByDate.Checked = sorter.ByDate = true;
2299 instance.GlobalSettings["inv_sort_bydate"] = OSD.FromBoolean(sorter.ByDate);
2306 public class SearchResult
2308 public InventoryBase Inv;
2311 public SearchResult(InventoryBase inv, int level)
2318 List<SearchResult> searchRes;
2319 string searchString;
2320 Dictionary<int, ListViewItem> searchItemCache = new Dictionary<int, ListViewItem>();
2321 ListViewItem emptyItem = null;
2324 void PerformRecursiveSearch(int level, UUID folderID)
2326 var me = Inventory.Items[folderID].Data;
2327 searchRes.Add(new SearchResult(me, level));
2328 var sorted = Inventory.GetContents(folderID);
2330 sorted.Sort((InventoryBase b1, InventoryBase b2) =>
2332 if (b1 is InventoryFolder && !(b2 is InventoryFolder))
2336 else if (!(b1 is InventoryFolder) && b2 is InventoryFolder)
2342 return string.Compare(b1.Name, b2.Name);
2346 foreach (var item in sorted)
2348 if (item is InventoryFolder)
2350 PerformRecursiveSearch(level + 1, item.UUID);
2354 var it = item as InventoryItem;
2357 if (cbSrchName.Checked && it.Name.ToLower().Contains(searchString))
2361 else if (cbSrchDesc.Checked && it.Description.ToLower().Contains(searchString))
2366 if (cbSrchWorn.Checked && add &&
2368 (it.InventoryType == InventoryType.Wearable && IsWorn(it)) ||
2369 ((it.InventoryType == InventoryType.Attachment || it.InventoryType == InventoryType.Object) && IsAttached(it))
2376 if (cbSrchRecent.Checked && add && it.CreationDate < instance.StartupTimeUTC)
2384 searchRes.Add(new SearchResult(it, level + 1));
2389 if (searchRes[searchRes.Count - 1].Inv == me)
2391 searchRes.RemoveAt(searchRes.Count - 1);
2395 public void UpdateSearch()
2399 if (instance.MonoRuntime)
2401 lstInventorySearch.VirtualMode = false;
2402 lstInventorySearch.Items.Clear();
2403 lstInventorySearch.VirtualMode = true;
2406 lstInventorySearch.VirtualListSize = 0;
2407 searchString = txtSearch.Text.Trim().ToLower();
2409 //if (searchString == string.Empty && rbSrchAll.Checked)
2411 // lblSearchStatus.Text = "0 results";
2415 if (emptyItem == null)
2417 emptyItem = new ListViewItem(string.Empty);
2420 searchRes = new List<SearchResult>(Inventory.Items.Count);
2421 searchItemCache.Clear();
2422 PerformRecursiveSearch(0, Inventory.RootFolder.UUID);
2423 lstInventorySearch.VirtualListSize = searchRes.Count;
2424 lblSearchStatus.Text = string.Format("{0} results", found);
2427 private void lstInventorySearch_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
2429 if (searchItemCache.ContainsKey(e.ItemIndex))
2431 e.Item = searchItemCache[e.ItemIndex];
2433 else if (e.ItemIndex < searchRes.Count)
2435 InventoryBase inv = searchRes[e.ItemIndex].Inv;
2436 string desc = inv.Name;
2437 if (inv is InventoryItem)
2439 desc += string.Format(" - {0}", ((InventoryItem)inv).Description);
2441 ListViewItem item = new ListViewItem(desc);
2442 item.Tag = searchRes[e.ItemIndex];
2444 searchItemCache[e.ItemIndex] = item;
2452 private void btnInvSearch_Click(object sender, EventArgs e)
2457 private void cbSrchName_CheckedChanged(object sender, EventArgs e)
2459 if (!cbSrchName.Checked && !cbSrchDesc.Checked && !cbSrchCreator.Checked)
2461 cbSrchName.Checked = true;
2466 private void cbSrchWorn_CheckedChanged(object sender, EventArgs e)
2471 private void txtSearch_KeyDown(object sender, KeyEventArgs e)
2473 if (e.KeyCode == Keys.Enter)
2475 e.Handled = e.SuppressKeyPress = true;
2476 if (txtSearch.Text.Trim().Length > 0)
2483 private void lstInventorySearch_DrawItem(object sender, DrawListViewItemEventArgs e)
2485 Graphics g = e.Graphics;
2488 if (!(e.Item.Tag is SearchResult))
2491 if (e.Item.Selected)
2493 g.FillRectangle(SystemBrushes.Highlight, e.Bounds);
2496 SearchResult res = e.Item.Tag as SearchResult;
2497 int offset = 20 * (res.Level + 1);
2498 Rectangle rec = new Rectangle(e.Bounds.X + offset, e.Bounds.Y, e.Bounds.Width - offset, e.Bounds.Height);
2503 if (res.Inv is InventoryFolder)
2505 iconIx = GetDirImageIndex(((InventoryFolder)res.Inv).PreferredType.ToString().ToLower());
2507 else if (res.Inv is InventoryWearable)
2509 iconIx = GetItemImageIndex(((InventoryWearable)res.Inv).WearableType.ToString().ToLower());
2511 else if (res.Inv is InventoryItem)
2513 iconIx = GetItemImageIndex(((InventoryItem)res.Inv).AssetType.ToString().ToLower());
2523 icon = frmMain.ResourceImages.Images[iconIx];
2524 g.DrawImageUnscaled(icon, e.Bounds.X + offset - 18, e.Bounds.Y);
2528 using (StringFormat sf = new StringFormat(StringFormatFlags.NoWrap | StringFormatFlags.LineLimit))
2530 string label = ItemLabel(res.Inv, false);
2531 SizeF len = e.Graphics.MeasureString(label, lstInventorySearch.Font, rec.Width, sf);
2533 e.Graphics.DrawString(
2534 ItemLabel(res.Inv, false),
2535 lstInventorySearch.Font,
2536 e.Item.Selected ? SystemBrushes.HighlightText : SystemBrushes.WindowText,
2540 if (res.Inv is InventoryItem)
2542 string desc = ((InventoryItem)res.Inv).Description.Trim();
2543 if (desc != string.Empty)
2545 using (Font descFont = new Font(lstInventorySearch.Font, FontStyle.Italic))
2547 e.Graphics.DrawString(desc,
2549 e.Item.Selected ? SystemBrushes.HighlightText : SystemBrushes.GrayText,
2550 rec.X + len.Width + 5,
2560 private void lstInventorySearch_SizeChanged(object sender, EventArgs e)
2562 chResItemName.Width = lstInventorySearch.Width - 30;
2565 private void txtSearch_TextChanged(object sender, EventArgs e)
2570 private void rbSrchAll_CheckedChanged(object sender, EventArgs e)
2575 private void lstInventorySearch_KeyDown(object sender, KeyEventArgs e)
2577 if ((e.KeyCode == Keys.Apps) || (e.Control && e.KeyCode == RadegastContextMenuStrip.ContexMenuKeyCode))
2579 lstInventorySearch_MouseClick(sender, new MouseEventArgs(MouseButtons.Right, 1, 50, 150, 0));
2584 /// Finds and higlights inventory node
2586 /// <param name="itemID">Inventory of ID of the item to select</param>
2587 public void SelectInventoryNode(UUID itemID)
2589 TreeNode node = findNodeForItem(itemID);
2592 invTree.SelectedNode = node;
2593 if (node.Tag is InventoryItem)
2595 UpdateItemInfo(node.Tag as InventoryItem);
2599 private void lstInventorySearch_MouseClick(object sender, MouseEventArgs e)
2601 if (lstInventorySearch.SelectedIndices.Count != 1)
2606 SearchResult res = searchRes[lstInventorySearch.SelectedIndices[0]];
2607 TreeNode node = findNodeForItem(res.Inv.UUID);
2610 invTree.SelectedNode = node;
2611 if (e.Button == MouseButtons.Right)
2613 ctxInv.Show(lstInventorySearch, e.X, e.Y);
2619 private void lstInventorySearch_MouseDoubleClick(object sender, MouseEventArgs e)
2621 if (lstInventorySearch.SelectedIndices.Count != 1)
2626 SearchResult res = searchRes[lstInventorySearch.SelectedIndices[0]];
2627 TreeNode node = findNodeForItem(res.Inv.UUID);
2630 invTree.SelectedNode = node;
2631 invTree_NodeMouseDoubleClick(null, null);
2638 private void txtAssetID_Enter(object sender, EventArgs e)
2640 txtAssetID.SelectAll();
2643 private void txtInvID_Enter(object sender, EventArgs e)
2645 txtInvID.SelectAll();
2648 private void copyInitialOutfitsToolStripMenuItem_Click(object sender, EventArgs e)
2650 var c = new FolderCopy(instance);
2651 c.GetFolders("Initial Outfits");
2657 #region Sorter class
2658 // Create a node sorter that implements the IComparer interface.
2659 public class InvNodeSorter : System.Collections.IComparer
2661 bool _sysfirst = true;
2662 bool _bydate = true;
2664 int CompareFolders(InventoryFolder x, InventoryFolder y)
2668 if (x.PreferredType != AssetType.Unknown && y.PreferredType == AssetType.Unknown)
2672 else if (x.PreferredType == AssetType.Unknown && y.PreferredType != AssetType.Unknown)
2677 return String.Compare(x.Name, y.Name);
2680 public bool SystemFoldersFirst { set { _sysfirst = value; } get { return _sysfirst; } }
2681 public bool ByDate { set { _bydate = value; } get { return _bydate; } }
2683 public int Compare(object x, object y)
2685 TreeNode tx = x as TreeNode;
2686 TreeNode ty = y as TreeNode;
2688 if (tx.Tag is InventoryFolder && ty.Tag is InventoryFolder)
2690 return CompareFolders(tx.Tag as InventoryFolder, ty.Tag as InventoryFolder);
2692 else if (tx.Tag is InventoryFolder && ty.Tag is InventoryItem)
2696 else if (tx.Tag is InventoryItem && ty.Tag is InventoryFolder)
2702 if (!(tx.Tag is InventoryItem) || !(ty.Tag is InventoryItem))
2707 InventoryItem item1 = (InventoryItem)tx.Tag;
2708 InventoryItem item2 = (InventoryItem)ty.Tag;
2712 if (item1.CreationDate < item2.CreationDate)
2716 else if (item1.CreationDate > item2.CreationDate)
2721 return string.Compare(item1.Name, item2.Name);
2726 public class AttachmentInfo
2728 public Primitive Prim;
2729 public InventoryItem Item;
2730 public UUID InventoryID;
2732 public bool MarkedAttached = false;
2734 public AttachmentPoint Point
2740 return Prim.PrimData.AttachmentPoint;
2744 return AttachmentPoint.Default;