2 // Radegast Metaverse Client
3 // Copyright (c) 2009-2014, 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>();
78 AutoResetEvent trashCreated = new AutoResetEvent(false);
80 #region Construction and disposal
81 public InventoryConsole(RadegastInstance instance)
83 InitializeComponent();
84 Disposed += new EventHandler(InventoryConsole_Disposed);
86 TreeUpdateTimer = new System.Timers.Timer()
88 Interval = updateInterval,
90 SynchronizingObject = invTree
92 TreeUpdateTimer.Elapsed += TreeUpdateTimerTick;
94 this.instance = instance;
95 Manager = client.Inventory;
96 Inventory = Manager.Store;
97 Inventory.RootFolder.OwnerID = client.Self.AgentID;
98 invTree.ImageList = frmMain.ResourceImages;
99 invRootNode = AddDir(null, Inventory.RootFolder);
100 UpdateStatus("Reading cache");
106 WorkPool.QueueUserWorkItem(sync =>
108 Logger.Log("Reading inventory cache from " + instance.InventoryCacheFileName, Helpers.LogLevel.Debug, client);
109 Inventory.RestoreFromDisk(instance.InventoryCacheFileName);
116 if (instance.MainForm.InvokeRequired)
118 instance.MainForm.BeginInvoke(new MethodInvoker(() => Init2()));
122 AddFolderFromStore(invRootNode, Inventory.RootFolder);
124 sorter = new InvNodeSorter();
126 if (!instance.GlobalSettings.ContainsKey("inv_sort_bydate"))
127 instance.GlobalSettings["inv_sort_bydate"] = OSD.FromBoolean(true);
128 if (!instance.GlobalSettings.ContainsKey("inv_sort_sysfirst"))
129 instance.GlobalSettings["inv_sort_sysfirst"] = OSD.FromBoolean(true);
131 sorter.ByDate = instance.GlobalSettings["inv_sort_bydate"].AsBoolean();
132 sorter.SystemFoldersFirst = instance.GlobalSettings["inv_sort_sysfirst"].AsBoolean();
134 tbtnSortByDate.Checked = sorter.ByDate;
135 tbtbSortByName.Checked = !sorter.ByDate;
136 tbtnSystemFoldersFirst.Checked = sorter.SystemFoldersFirst;
138 invTree.TreeViewNodeSorter = sorter;
140 if (instance.MonoRuntime)
142 invTree.BackColor = Color.FromKnownColor(KnownColor.Window);
143 invTree.ForeColor = invTree.LineColor = Color.FromKnownColor(KnownColor.WindowText);
144 InventoryFolder f = new InventoryFolder(UUID.Random());
146 f.ParentUUID = UUID.Zero;
147 f.PreferredType = AssetType.Unknown;
148 TreeNode dirNode = new TreeNode();
149 dirNode.Name = f.UUID.ToString();
150 dirNode.Text = f.Name;
152 dirNode.ImageIndex = GetDirImageIndex(f.PreferredType.ToString().ToLower());
153 dirNode.SelectedImageIndex = dirNode.ImageIndex;
154 invTree.Nodes.Add(dirNode);
158 saveAllTToolStripMenuItem.Enabled = false;
159 InventoryUpdate = new Thread(new ThreadStart(StartTraverseNodes));
160 InventoryUpdate.Name = "InventoryUpdate";
161 InventoryUpdate.IsBackground = true;
162 InventoryUpdate.Start();
164 invRootNode.Expand();
166 invTree.AfterExpand += new TreeViewEventHandler(TreeView_AfterExpand);
167 invTree.NodeMouseClick += new TreeNodeMouseClickEventHandler(invTree_MouseClick);
168 invTree.NodeMouseDoubleClick += new TreeNodeMouseClickEventHandler(invTree_NodeMouseDoubleClick);
170 _EditTimer = new System.Threading.Timer(OnLabelEditTimer, null, System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);
173 Inventory.InventoryObjectAdded += new EventHandler<InventoryObjectAddedEventArgs>(Inventory_InventoryObjectAdded);
174 Inventory.InventoryObjectUpdated += new EventHandler<InventoryObjectUpdatedEventArgs>(Inventory_InventoryObjectUpdated);
175 Inventory.InventoryObjectRemoved += new EventHandler<InventoryObjectRemovedEventArgs>(Inventory_InventoryObjectRemoved);
177 client.Objects.ObjectUpdate += new EventHandler<PrimEventArgs>(Objects_AttachmentUpdate);
178 client.Objects.KillObject += new EventHandler<KillObjectEventArgs>(Objects_KillObject);
179 client.Appearance.AppearanceSet += new EventHandler<AppearanceSetEventArgs>(Appearance_AppearanceSet);
182 void InventoryConsole_Disposed(object sender, EventArgs e)
184 if (TreeUpdateTimer != null)
186 TreeUpdateTimer.Stop();
187 TreeUpdateTimer.Dispose();
188 TreeUpdateTimer = null;
190 if (InventoryUpdate != null)
192 if (InventoryUpdate.IsAlive)
193 InventoryUpdate.Abort();
194 InventoryUpdate = null;
197 Inventory.InventoryObjectAdded -= new EventHandler<InventoryObjectAddedEventArgs>(Inventory_InventoryObjectAdded);
198 Inventory.InventoryObjectUpdated -= new EventHandler<InventoryObjectUpdatedEventArgs>(Inventory_InventoryObjectUpdated);
199 Inventory.InventoryObjectRemoved -= new EventHandler<InventoryObjectRemovedEventArgs>(Inventory_InventoryObjectRemoved);
201 client.Objects.ObjectUpdate -= new EventHandler<PrimEventArgs>(Objects_AttachmentUpdate);
202 client.Objects.KillObject -= new EventHandler<KillObjectEventArgs>(Objects_KillObject);
203 client.Appearance.AppearanceSet -= new EventHandler<AppearanceSetEventArgs>(Appearance_AppearanceSet);
207 #region Network callbacks
208 void Appearance_AppearanceSet(object sender, AppearanceSetEventArgs e)
211 if (appearnceWasBusy)
213 appearnceWasBusy = false;
214 client.Appearance.RequestSetAppearance(true);
218 void Objects_KillObject(object sender, KillObjectEventArgs e)
220 AttachmentInfo attachment = null;
223 foreach (AttachmentInfo att in attachments.Values)
225 if (att.Prim != null && att.Prim.LocalID == e.ObjectLocalID)
232 if (attachment != null)
234 attachments.Remove(attachment.InventoryID);
235 UpdateNodeLabel(attachment.InventoryID);
240 void Objects_AttachmentUpdate(object sender, PrimEventArgs e)
242 Primitive prim = e.Prim;
244 if (client.Self.LocalID == 0 ||
245 prim.ParentID != client.Self.LocalID ||
246 prim.NameValues == null) return;
248 for (int i = 0; i < prim.NameValues.Length; i++)
250 if (prim.NameValues[i].Name == "AttachItemID")
252 AttachmentInfo attachment = new AttachmentInfo();
253 attachment.Prim = prim;
254 attachment.InventoryID = new UUID(prim.NameValues[i].Value.ToString());
255 attachment.PrimID = prim.ID;
259 // Add new attachment info
260 if (!attachments.ContainsKey(attachment.InventoryID))
262 attachments.Add(attachment.InventoryID, attachment);
267 attachment = attachments[attachment.InventoryID];
268 if (attachment.Prim == null)
270 attachment.Prim = prim;
274 // Don't update the tree yet if we're still updating invetory tree from server
275 if (!TreeUpdateInProgress)
277 if (Inventory.Contains(attachment.InventoryID))
279 if (attachment.Item == null)
281 InventoryItem item = (InventoryItem)Inventory[attachment.InventoryID];
282 attachment.Item = item;
284 if (!attachment.MarkedAttached)
286 attachment.MarkedAttached = true;
287 UpdateNodeLabel(attachment.InventoryID);
292 client.Inventory.RequestFetchInventory(attachment.InventoryID, client.Self.AgentID);
301 void Inventory_InventoryObjectAdded(object sender, InventoryObjectAddedEventArgs e)
303 if (e.Obj is InventoryFolder && ((InventoryFolder)e.Obj).PreferredType == AssetType.TrashFolder)
308 if (TreeUpdateInProgress)
312 ItemsToAdd.Enqueue(e.Obj);
317 Exec_OnInventoryObjectAdded(e.Obj);
321 void Exec_OnInventoryObjectAdded(InventoryBase obj)
325 Invoke(new MethodInvoker(delegate()
327 Exec_OnInventoryObjectAdded(obj);
335 if (attachments.ContainsKey(obj.UUID))
337 attachments[obj.UUID].Item = (InventoryItem)obj;
341 TreeNode parent = findNodeForItem(obj.ParentUUID);
345 TreeNode newNode = AddBase(parent, obj);
346 if (obj.Name == newItemName)
348 if (newNode.Parent.IsExpanded)
354 newNode.Parent.Expand();
358 newItemName = string.Empty;
361 void Inventory_InventoryObjectRemoved(object sender, InventoryObjectRemovedEventArgs e)
365 BeginInvoke(new MethodInvoker(() => Inventory_InventoryObjectRemoved(sender, e)));
371 if (attachments.ContainsKey(e.Obj.UUID))
373 attachments.Remove(e.Obj.UUID);
377 TreeNode currentNode = findNodeForItem(e.Obj.UUID);
378 if (currentNode != null)
380 removeNode(currentNode);
384 void Inventory_InventoryObjectUpdated(object sender, InventoryObjectUpdatedEventArgs e)
386 if (TreeUpdateInProgress)
390 if (e.NewObject is InventoryFolder)
392 TreeNode currentNode = findNodeForItem(e.NewObject.UUID);
393 if (currentNode != null && currentNode.Text == e.NewObject.Name) return;
396 if (!ItemsToUpdate.Contains(e.NewObject))
398 ItemsToUpdate.Enqueue(e.NewObject);
404 Exec_OnInventoryObjectUpdated(e.OldObject, e.NewObject);
408 void Exec_OnInventoryObjectUpdated(InventoryBase oldObject, InventoryBase newObject)
410 if (newObject == null) return;
414 BeginInvoke(new MethodInvoker(() => Exec_OnInventoryObjectUpdated(oldObject, newObject)));
420 if (attachments.ContainsKey(newObject.UUID))
422 attachments[newObject.UUID].Item = (InventoryItem)newObject;
426 // Find our current node in the tree
427 TreeNode currentNode = findNodeForItem(newObject.UUID);
429 // Find which node should be our parrent
430 TreeNode parent = findNodeForItem(newObject.ParentUUID);
432 if (parent == null) return;
434 if (currentNode != null)
436 // Did we move to a different folder
437 if (currentNode.Parent != parent)
439 TreeNode movedNode = (TreeNode)currentNode.Clone();
440 movedNode.Tag = newObject;
441 parent.Nodes.Add(movedNode);
442 removeNode(currentNode);
443 cacheNode(movedNode);
447 currentNode.Tag = newObject;
448 currentNode.Text = ItemLabel(newObject, false);
449 currentNode.Name = newObject.Name;
452 else // We are not in the tree already, add
454 AddBase(parent, newObject);
459 #region Node manipulation
460 public static int GetDirImageIndex(string t)
462 t = System.Text.RegularExpressions.Regex.Replace(t, @"folder$", "");
463 int res = frmMain.ImageNames.IndexOf("inv_folder_" + t);
468 case "currentoutfit":
470 return frmMain.ImageNames.IndexOf("inv_folder_outfit");
472 return frmMain.ImageNames.IndexOf("inv_folder_script");
474 return frmMain.ImageNames.IndexOf("inv_folder_plain_closed");
479 public static int GetItemImageIndex(string t)
481 int res = frmMain.ImageNames.IndexOf("inv_item_" + t);
486 return frmMain.ImageNames.IndexOf("inv_item_script");
488 else if (t == "callingcard")
490 return frmMain.ImageNames.IndexOf("inv_item_callingcard_offline");
496 TreeNode AddBase(TreeNode parent, InventoryBase obj)
498 if (obj is InventoryItem)
500 return AddItem(parent, (InventoryItem)obj);
504 return AddDir(parent, (InventoryFolder)obj);
508 TreeNode AddDir(TreeNode parentNode, InventoryFolder f)
510 TreeNode dirNode = new TreeNode();
511 dirNode.Name = f.UUID.ToString();
512 dirNode.Text = f.Name;
514 dirNode.ImageIndex = GetDirImageIndex(f.PreferredType.ToString().ToLower());
515 dirNode.SelectedImageIndex = dirNode.ImageIndex;
516 if (parentNode == null)
518 invTree.Nodes.Add(dirNode);
522 parentNode.Nodes.Add(dirNode);
524 lock (UUID2NodeCache)
526 UUID2NodeCache[f.UUID] = dirNode;
532 TreeNode AddItem(TreeNode parent, InventoryItem item)
534 TreeNode itemNode = new TreeNode();
535 itemNode.Name = item.UUID.ToString();
536 itemNode.Text = ItemLabel(item, false);
539 InventoryItem linkedItem = null;
541 if (item.IsLink() && Inventory.Contains(item.AssetUUID) && Inventory[item.AssetUUID] is InventoryItem)
543 linkedItem = (InventoryItem)Inventory[item.AssetUUID];
550 if (linkedItem is InventoryWearable)
552 InventoryWearable w = linkedItem as InventoryWearable;
553 img = GetItemImageIndex(w.WearableType.ToString().ToLower());
557 img = GetItemImageIndex(linkedItem.AssetType.ToString().ToLower());
560 itemNode.ImageIndex = img;
561 itemNode.SelectedImageIndex = img;
562 parent.Nodes.Add(itemNode);
563 lock (UUID2NodeCache)
565 UUID2NodeCache[item.UUID] = itemNode;
570 TreeNode findNodeForItem(UUID itemID)
572 lock (UUID2NodeCache)
574 if (UUID2NodeCache.ContainsKey(itemID))
576 return UUID2NodeCache[itemID];
582 void cacheNode(TreeNode node)
584 InventoryBase item = (InventoryBase)node.Tag;
587 foreach (TreeNode child in node.Nodes)
591 lock (UUID2NodeCache)
593 UUID2NodeCache[item.UUID] = node;
598 void removeNode(TreeNode node)
600 InventoryBase item = (InventoryBase)node.Tag;
603 foreach (TreeNode child in node.Nodes)
608 lock (UUID2NodeCache)
610 UUID2NodeCache.Remove(item.UUID);
618 #region Private methods
619 private void UpdateStatus(string text)
623 Invoke(new MethodInvoker(delegate() { UpdateStatus(text); }));
629 saveAllTToolStripMenuItem.Enabled = true;
632 tlabelStatus.Text = text;
635 private void UpdateNodeLabel(UUID itemID)
637 if (instance.MainForm.InvokeRequired)
639 instance.MainForm.BeginInvoke(new MethodInvoker(() => UpdateNodeLabel(itemID)));
643 TreeNode node = findNodeForItem(itemID);
646 node.Text = ItemLabel((InventoryBase)node.Tag, false);
650 private void AddFolderFromStore(TreeNode parent, InventoryFolder f)
652 List<InventoryBase> contents = Inventory.GetContents(f);
653 foreach (InventoryBase item in contents)
655 TreeNode node = AddBase(parent, item);
656 if (item is InventoryFolder)
658 AddFolderFromStore(node, (InventoryFolder)item);
663 private void TraverseAndQueueNodes(InventoryNode start)
665 bool has_items = false;
667 foreach (InventoryNode node in start.Nodes.Values)
669 if (node.Data is InventoryItem)
676 if (!has_items || start.NeedsUpdate)
680 lock (FolderFetchRetries)
683 FolderFetchRetries.TryGetValue(start.Data.UUID, out retries);
686 if (!QueuedFolders.Contains(start.Data.UUID))
688 QueuedFolders.Add(start.Data.UUID);
691 FolderFetchRetries[start.Data.UUID] = retries + 1;
696 foreach (InventoryBase item in Inventory.GetContents((InventoryFolder)start.Data))
698 if (item is InventoryFolder)
700 TraverseAndQueueNodes(Inventory.GetNodeFor(item.UUID));
705 private void TraverseNodes(InventoryNode start)
707 bool has_items = false;
709 foreach (InventoryNode node in start.Nodes.Values)
711 if (node.Data is InventoryItem)
718 if (!has_items || start.NeedsUpdate)
720 InventoryFolder f = (InventoryFolder)start.Data;
721 AutoResetEvent gotFolderEvent = new AutoResetEvent(false);
722 bool success = false;
724 EventHandler<FolderUpdatedEventArgs> callback = delegate(object sender, FolderUpdatedEventArgs ea)
726 if (f.UUID == ea.FolderID)
728 if (((InventoryFolder)Inventory.Items[ea.FolderID].Data).DescendentCount <= Inventory.Items[ea.FolderID].Nodes.Count)
731 gotFolderEvent.Set();
736 client.Inventory.FolderUpdated += callback;
737 fetchFolder(f.UUID, f.OwnerID, true);
738 gotFolderEvent.WaitOne(30 * 1000, false);
739 client.Inventory.FolderUpdated -= callback;
743 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);
747 foreach (InventoryBase item in Inventory.GetContents((InventoryFolder)start.Data))
749 if (item is InventoryFolder)
751 TraverseNodes(Inventory.GetNodeFor(item.UUID));
756 private void StartTraverseNodes()
758 if (!client.Network.CurrentSim.Caps.IsEventQueueRunning)
760 AutoResetEvent EQRunning = new AutoResetEvent(false);
761 EventHandler<EventQueueRunningEventArgs> handler = (sender, e) =>
765 client.Network.EventQueueRunning += handler;
766 EQRunning.WaitOne(10 * 1000, false);
767 client.Network.EventQueueRunning -= handler;
770 if (!client.Network.CurrentSim.Caps.IsEventQueueRunning)
775 UpdateStatus("Loading...");
776 TreeUpdateInProgress = true;
777 TreeUpdateTimer.Start();
779 lock (FolderFetchRetries)
781 FolderFetchRetries.Clear();
788 QueuedFolders.Clear();
790 TraverseAndQueueNodes(Inventory.RootNode);
791 if (QueuedFolders.Count == 0) break;
792 Logger.DebugLog(string.Format("Queued {0} folders for update", QueuedFolders.Count));
794 Parallel.ForEach<UUID>(Math.Min(QueuedFolders.Count, 6), QueuedFolders, folderID =>
796 bool success = false;
798 AutoResetEvent gotFolder = new AutoResetEvent(false);
799 EventHandler<FolderUpdatedEventArgs> handler = (sender, ev) =>
801 if (ev.FolderID == folderID)
803 success = ev.Success;
808 client.Inventory.FolderUpdated += handler;
809 client.Inventory.RequestFolderContents(folderID, client.Self.AgentID, true, true, InventorySortOrder.ByDate);
810 if (!gotFolder.WaitOne(15 * 1000, false))
814 client.Inventory.FolderUpdated -= handler;
817 while (QueuedFolders.Count > 0);
819 TreeUpdateTimer.Stop();
822 Invoke(new MethodInvoker(() => TreeUpdateTimerTick(null, null)));
824 TreeUpdateInProgress = false;
826 instance.TabConsole.DisplayNotificationInChat("Inventory update completed.");
828 // Updated labels on clothes that we are wearing
831 // Update attachments now that we are done
834 foreach (AttachmentInfo a in attachments.Values)
838 if (Inventory.Contains(a.InventoryID))
840 a.MarkedAttached = true;
841 a.Item = (InventoryItem)Inventory[a.InventoryID];
842 UpdateNodeLabel(a.InventoryID);
846 client.Inventory.RequestFetchInventory(a.InventoryID, client.Self.AgentID);
853 Logger.Log("Finished updating invenory folders, saving cache...", Helpers.LogLevel.Debug, client);
854 WorkPool.QueueUserWorkItem((object state) => Inventory.SaveToDisk(instance.InventoryCacheFileName));
856 if (!instance.MonoRuntime || IsHandleCreated)
857 Invoke(new MethodInvoker(() =>
866 public void ReloadInventory()
868 if (TreeUpdateInProgress)
870 TreeUpdateTimer.Stop();
871 InventoryUpdate.Abort();
872 InventoryUpdate = null;
875 saveAllTToolStripMenuItem.Enabled = false;
877 Inventory.Items = new Dictionary<UUID, InventoryNode>();
878 Inventory.RootFolder = Inventory.RootFolder;
880 invTree.Nodes.Clear();
881 UUID2NodeCache.Clear();
882 invRootNode = AddDir(null, Inventory.RootFolder);
883 Inventory.RootNode.NeedsUpdate = true;
885 InventoryUpdate = new Thread(new ThreadStart(StartTraverseNodes));
886 InventoryUpdate.Name = "InventoryUpdate";
887 InventoryUpdate.IsBackground = true;
888 InventoryUpdate.Start();
889 invRootNode.Expand();
892 private void reloadInventoryToolStripMenuItem_Click(object sender, EventArgs e)
897 private void TreeUpdateTimerTick(Object sender, EventArgs e)
901 if (ItemsToAdd.Count > 0)
903 invTree.BeginUpdate();
904 while (ItemsToAdd.Count > 0)
906 InventoryBase item = ItemsToAdd.Dequeue();
907 TreeNode node = findNodeForItem(item.ParentUUID);
919 if (ItemsToUpdate.Count > 0)
921 invTree.BeginUpdate();
922 while (ItemsToUpdate.Count > 0)
924 InventoryBase item = ItemsToUpdate.Dequeue();
925 Exec_OnInventoryObjectUpdated(item, item);
931 UpdateStatus("Loading... " + UUID2NodeCache.Count.ToString() + " items");
936 private void btnProfile_Click(object sender, EventArgs e)
938 instance.MainForm.ShowAgentProfile(txtCreator.Text, txtCreator.AgentID);
941 void UpdateItemInfo(InventoryItem item)
943 foreach (Control c in pnlDetail.Controls)
947 pnlDetail.Controls.Clear();
948 pnlItemProperties.Tag = item;
952 pnlItemProperties.Visible = false;
956 pnlItemProperties.Visible = true;
957 btnProfile.Enabled = true;
958 txtItemName.Text = item.Name;
959 txtItemDescription.Text = item.Description;
960 txtCreator.AgentID = item.CreatorID;
961 txtCreator.Tag = item.CreatorID;
962 txtCreated.Text = item.CreationDate.ToString();
964 if (item.AssetUUID != UUID.Zero)
966 txtAssetID.Text = item.AssetUUID.ToString();
970 txtAssetID.Text = String.Empty;
973 txtInvID.Text = item.UUID.ToString();
975 Permissions p = item.Permissions;
976 cbOwnerModify.Checked = (p.OwnerMask & PermissionMask.Modify) != 0;
977 cbOwnerCopy.Checked = (p.OwnerMask & PermissionMask.Copy) != 0;
978 cbOwnerTransfer.Checked = (p.OwnerMask & PermissionMask.Transfer) != 0;
980 cbNextOwnModify.CheckedChanged -= cbNextOwnerUpdate_CheckedChanged;
981 cbNextOwnCopy.CheckedChanged -= cbNextOwnerUpdate_CheckedChanged;
982 cbNextOwnTransfer.CheckedChanged -= cbNextOwnerUpdate_CheckedChanged;
984 cbNextOwnModify.Checked = (p.NextOwnerMask & PermissionMask.Modify) != 0;
985 cbNextOwnCopy.Checked = (p.NextOwnerMask & PermissionMask.Copy) != 0;
986 cbNextOwnTransfer.Checked = (p.NextOwnerMask & PermissionMask.Transfer) != 0;
988 cbNextOwnModify.CheckedChanged += cbNextOwnerUpdate_CheckedChanged;
989 cbNextOwnCopy.CheckedChanged += cbNextOwnerUpdate_CheckedChanged;
990 cbNextOwnTransfer.CheckedChanged += cbNextOwnerUpdate_CheckedChanged;
993 switch (item.AssetType)
995 case AssetType.Texture:
996 SLImageHandler image = new SLImageHandler(instance, item.AssetUUID, item.Name, IsFullPerm(item));
997 image.Dock = DockStyle.Fill;
998 pnlDetail.Controls.Add(image);
1001 case AssetType.Notecard:
1002 Notecard note = new Notecard(instance, (InventoryNotecard)item);
1003 note.Dock = DockStyle.Fill;
1005 note.TabStop = true;
1006 pnlDetail.Controls.Add(note);
1007 note.rtbContent.Focus();
1010 case AssetType.Landmark:
1011 Landmark landmark = new Landmark(instance, (InventoryLandmark)item);
1012 landmark.Dock = DockStyle.Fill;
1013 pnlDetail.Controls.Add(landmark);
1016 case AssetType.LSLText:
1017 ScriptEditor script = new ScriptEditor(instance, (InventoryLSL)item);
1018 script.Dock = DockStyle.Fill;
1019 script.TabIndex = 3;
1020 script.TabStop = true;
1021 pnlDetail.Controls.Add(script);
1024 case AssetType.Gesture:
1025 Guesture gesture = new Guesture(instance, (InventoryGesture)item);
1026 gesture.Dock = DockStyle.Fill;
1027 pnlDetail.Controls.Add(gesture);
1032 tabsInventory.SelectedTab = tabDetail;
1035 void cbNextOwnerUpdate_CheckedChanged(object sender, EventArgs e)
1037 InventoryItem item = null;
1038 if (pnlItemProperties.Tag != null && pnlItemProperties.Tag is InventoryItem)
1040 item = (InventoryItem)pnlItemProperties.Tag;
1042 if (item == null) return;
1044 PermissionMask pm = PermissionMask.Move;
1045 if (cbNextOwnCopy.Checked) pm |= PermissionMask.Copy;
1046 if (cbNextOwnModify.Checked) pm |= PermissionMask.Modify;
1047 if (cbNextOwnTransfer.Checked) pm |= PermissionMask.Transfer;
1048 item.Permissions.NextOwnerMask = pm;
1050 client.Inventory.RequestUpdateItem(item);
1051 client.Inventory.RequestFetchInventory(item.UUID, item.OwnerID);
1054 private void txtItemName_Leave(object sender, EventArgs e)
1056 InventoryItem item = null;
1057 if (pnlItemProperties.Tag != null && pnlItemProperties.Tag is InventoryItem)
1059 item = (InventoryItem)pnlItemProperties.Tag;
1061 if (item == null) return;
1063 item.Name = txtItemName.Text;
1065 client.Inventory.RequestUpdateItem(item);
1066 client.Inventory.RequestFetchInventory(item.UUID, item.OwnerID);
1069 private void txtItemDescription_Leave(object sender, EventArgs e)
1071 InventoryItem item = null;
1072 if (pnlItemProperties.Tag != null && pnlItemProperties.Tag is InventoryItem)
1074 item = (InventoryItem)pnlItemProperties.Tag;
1076 if (item == null) return;
1078 item.Description = txtItemDescription.Text;
1080 client.Inventory.RequestUpdateItem(item);
1081 client.Inventory.RequestFetchInventory(item.UUID, item.OwnerID);
1084 void invTree_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
1086 if (invTree.SelectedNode.Tag is InventoryItem)
1088 InventoryItem item = invTree.SelectedNode.Tag as InventoryItem;
1089 switch (item.AssetType)
1092 case AssetType.Landmark:
1093 instance.TabConsole.DisplayNotificationInChat("Teleporting to " + item.Name);
1094 client.Self.RequestTeleport(item.AssetUUID);
1097 case AssetType.Gesture:
1098 client.Self.PlayGesture(item.AssetUUID);
1101 case AssetType.Notecard:
1102 Notecard note = new Notecard(instance, (InventoryNotecard)item);
1103 note.Dock = DockStyle.Fill;
1104 note.ShowDetached();
1107 case AssetType.LSLText:
1108 ScriptEditor script = new ScriptEditor(instance, (InventoryLSL)item);
1109 script.Dock = DockStyle.Fill;
1110 script.ShowDetached();
1116 private void fetchFolder(UUID folderID, UUID ownerID, bool force)
1118 if (force || !fetchedFolders.Contains(folderID))
1120 if (!fetchedFolders.Contains(folderID))
1122 fetchedFolders.Add(folderID);
1125 client.Inventory.RequestFolderContents(folderID, ownerID, true, true, InventorySortOrder.ByDate);
1129 public bool IsWorn(InventoryItem item)
1131 bool worn = client.Appearance.IsItemWorn(item) != WearableType.Invalid;
1135 if (worn && !WornItems.Contains(item.UUID))
1136 WornItems.Add(item.UUID);
1141 public AttachmentPoint AttachedTo(InventoryItem item)
1145 if (attachments.ContainsKey(item.UUID))
1147 return attachments[item.UUID].Point;
1151 return AttachmentPoint.Default;
1154 public bool IsAttached(InventoryItem item)
1156 List<Primitive> myAtt = client.Network.CurrentSim.ObjectsPrimitives.FindAll((Primitive p) => p.ParentID == client.Self.LocalID);
1157 foreach (Primitive prim in myAtt)
1159 if (prim.NameValues == null) continue;
1160 UUID invID = UUID.Zero;
1161 for (int i = 0; i < prim.NameValues.Length; i++)
1163 if (prim.NameValues[i].Name == "AttachItemID")
1165 invID = (UUID)prim.NameValues[i].Value.ToString();
1169 if (invID == item.UUID)
1173 AttachmentInfo inf = new AttachmentInfo();
1174 inf.InventoryID = item.UUID;
1176 inf.MarkedAttached = true;
1178 inf.PrimID = prim.ID;
1179 attachments[invID] = inf;
1188 public InventoryItem AttachmentAt(AttachmentPoint point)
1192 foreach (KeyValuePair<UUID, AttachmentInfo> att in attachments)
1194 if (att.Value.Point == point)
1196 return att.Value.Item;
1204 /// Returns text of the label
1206 /// <param name="invBase">Inventory item</param>
1207 /// <param name="returnRaw">Should we return raw text, or if false decorated text with (worn) info, and (no copy) etc. permission info</param>
1208 /// <returns></returns>
1209 public string ItemLabel(InventoryBase invBase, bool returnRaw)
1211 if (returnRaw || (invBase is InventoryFolder))
1212 return invBase.Name;
1214 InventoryItem item = (InventoryItem)invBase;
1216 string raw = item.Name;
1221 item = instance.COF.RealInventoryItem(item);
1222 if (Inventory.Contains(item.AssetUUID) && Inventory[item.AssetUUID] is InventoryItem)
1224 item = (InventoryItem)Inventory[item.AssetUUID];
1228 if ((item.Permissions.OwnerMask & PermissionMask.Modify) == 0)
1229 raw += " (no modify)";
1231 if ((item.Permissions.OwnerMask & PermissionMask.Copy) == 0)
1232 raw += " (no copy)";
1234 if ((item.Permissions.OwnerMask & PermissionMask.Transfer) == 0)
1235 raw += " (no transfer)";
1240 if (IsAttached(item))
1242 raw += " (worn on " + AttachedTo(item).ToString() + ")";
1248 public static bool IsFullPerm(InventoryItem item)
1251 ((item.Permissions.OwnerMask & PermissionMask.Modify) != 0) &&
1252 ((item.Permissions.OwnerMask & PermissionMask.Copy) != 0) &&
1253 ((item.Permissions.OwnerMask & PermissionMask.Transfer) != 0)
1264 void invTree_MouseClick(object sender, TreeNodeMouseClickEventArgs e)
1266 TreeNode node = e.Node;
1268 if (e.Button == MouseButtons.Left)
1270 invTree.SelectedNode = node;
1271 if (node.Tag is InventoryItem)
1273 UpdateItemInfo(instance.COF.RealInventoryItem(node.Tag as InventoryItem));
1277 UpdateItemInfo(null);
1280 else if (e.Button == MouseButtons.Right)
1282 invTree.SelectedNode = node;
1283 ctxInv.Show(invTree, e.X, e.Y);
1287 private void ctxInv_Opening(object sender, CancelEventArgs e)
1290 TreeNode node = invTree.SelectedNode;
1297 #region Folder context menu
1298 if (node.Tag is InventoryFolder)
1300 InventoryFolder folder = (InventoryFolder)node.Tag;
1301 ctxInv.Items.Clear();
1303 ToolStripMenuItem ctxItem;
1305 if ((int)folder.PreferredType >= (int)AssetType.EnsembleStart &&
1306 (int)folder.PreferredType <= (int)AssetType.EnsembleEnd)
1308 ctxItem = new ToolStripMenuItem("Fix type", null, OnInvContextClick);
1309 ctxItem.Name = "fix_type";
1310 ctxInv.Items.Add(ctxItem);
1311 ctxInv.Items.Add(new ToolStripSeparator());
1314 ctxItem = new ToolStripMenuItem("New Folder", null, OnInvContextClick);
1315 ctxItem.Name = "new_folder";
1316 ctxInv.Items.Add(ctxItem);
1318 ctxItem = new ToolStripMenuItem("New Note", null, OnInvContextClick);
1319 ctxItem.Name = "new_notecard";
1320 ctxInv.Items.Add(ctxItem);
1322 ctxItem = new ToolStripMenuItem("New Script", null, OnInvContextClick);
1323 ctxItem.Name = "new_script";
1324 ctxInv.Items.Add(ctxItem);
1326 ctxItem = new ToolStripMenuItem("Refresh", null, OnInvContextClick);
1327 ctxItem.Name = "refresh";
1328 ctxInv.Items.Add(ctxItem);
1330 ctxItem = new ToolStripMenuItem("Backup...", null, OnInvContextClick);
1331 ctxItem.Name = "backup";
1332 ctxInv.Items.Add(ctxItem);
1334 ctxInv.Items.Add(new ToolStripSeparator());
1336 ctxItem = new ToolStripMenuItem("Expand", null, OnInvContextClick);
1337 ctxItem.Name = "expand";
1338 ctxInv.Items.Add(ctxItem);
1340 ctxItem = new ToolStripMenuItem("Expand All", null, OnInvContextClick);
1341 ctxItem.Name = "expand_all";
1342 ctxInv.Items.Add(ctxItem);
1344 ctxItem = new ToolStripMenuItem("Collapse", null, OnInvContextClick);
1345 ctxItem.Name = "collapse";
1346 ctxInv.Items.Add(ctxItem);
1348 if (folder.PreferredType == AssetType.TrashFolder)
1350 ctxItem = new ToolStripMenuItem("Empty Trash", null, OnInvContextClick);
1351 ctxItem.Name = "empty_trash";
1352 ctxInv.Items.Add(ctxItem);
1355 if (folder.PreferredType == AssetType.LostAndFoundFolder)
1357 ctxItem = new ToolStripMenuItem("Empty Lost and Found", null, OnInvContextClick);
1358 ctxItem.Name = "empty_lost_found";
1359 ctxInv.Items.Add(ctxItem);
1362 if (folder.PreferredType == AssetType.Unknown ||
1363 folder.PreferredType == AssetType.OutfitFolder)
1365 ctxItem = new ToolStripMenuItem("Rename", null, OnInvContextClick);
1366 ctxItem.Name = "rename_folder";
1367 ctxInv.Items.Add(ctxItem);
1369 ctxInv.Items.Add(new ToolStripSeparator());
1371 ctxItem = new ToolStripMenuItem("Cut", null, OnInvContextClick);
1372 ctxItem.Name = "cut_folder";
1373 ctxInv.Items.Add(ctxItem);
1375 ctxItem = new ToolStripMenuItem("Copy", null, OnInvContextClick);
1376 ctxItem.Name = "copy_folder";
1377 ctxInv.Items.Add(ctxItem);
1380 if (instance.InventoryClipboard != null)
1382 ctxItem = new ToolStripMenuItem("Paste", null, OnInvContextClick);
1383 ctxItem.Name = "paste_folder";
1384 ctxInv.Items.Add(ctxItem);
1386 if (instance.InventoryClipboard.Item is InventoryItem)
1388 ctxItem = new ToolStripMenuItem("Paste as Link", null, OnInvContextClick);
1389 ctxItem.Name = "paste_folder_link";
1390 ctxInv.Items.Add(ctxItem);
1394 if (folder.PreferredType == AssetType.Unknown ||
1395 folder.PreferredType == AssetType.OutfitFolder)
1397 ctxItem = new ToolStripMenuItem("Delete", null, OnInvContextClick);
1398 ctxItem.Name = "delete_folder";
1399 ctxInv.Items.Add(ctxItem);
1401 ctxInv.Items.Add(new ToolStripSeparator());
1404 if (folder.PreferredType == AssetType.Unknown || folder.PreferredType == AssetType.OutfitFolder)
1406 ctxItem = new ToolStripMenuItem("Take off Items", null, OnInvContextClick);
1407 ctxItem.Name = "outfit_take_off";
1408 ctxInv.Items.Add(ctxItem);
1410 ctxItem = new ToolStripMenuItem("Add to Outfit", null, OnInvContextClick);
1411 ctxItem.Name = "outfit_add";
1412 ctxInv.Items.Add(ctxItem);
1414 ctxItem = new ToolStripMenuItem("Replace Outfit", null, OnInvContextClick);
1415 ctxItem.Name = "outfit_replace";
1416 ctxInv.Items.Add(ctxItem);
1419 instance.ContextActionManager.AddContributions(ctxInv, folder);
1420 #endregion Folder context menu
1422 else if (node.Tag is InventoryItem)
1424 #region Item context menu
1425 InventoryItem item = instance.COF.RealInventoryItem((InventoryItem)node.Tag);
1426 ctxInv.Items.Clear();
1428 ToolStripMenuItem ctxItem;
1430 if (item.InventoryType == InventoryType.LSL)
1432 ctxItem = new ToolStripMenuItem("Edit script", null, OnInvContextClick);
1433 ctxItem.Name = "edit_script";
1434 ctxInv.Items.Add(ctxItem);
1437 if (item.AssetType == AssetType.Texture)
1439 ctxItem = new ToolStripMenuItem("View", null, OnInvContextClick);
1440 ctxItem.Name = "view_image";
1441 ctxInv.Items.Add(ctxItem);
1444 if (item.InventoryType == InventoryType.Landmark)
1446 ctxItem = new ToolStripMenuItem("Teleport", null, OnInvContextClick);
1447 ctxItem.Name = "lm_teleport";
1448 ctxInv.Items.Add(ctxItem);
1450 ctxItem = new ToolStripMenuItem("Info", null, OnInvContextClick);
1451 ctxItem.Name = "lm_info";
1452 ctxInv.Items.Add(ctxItem);
1455 if (item.InventoryType == InventoryType.Notecard)
1457 ctxItem = new ToolStripMenuItem("Open", null, OnInvContextClick);
1458 ctxItem.Name = "notecard_open";
1459 ctxInv.Items.Add(ctxItem);
1462 if (item.InventoryType == InventoryType.Gesture)
1464 ctxItem = new ToolStripMenuItem("Play", null, OnInvContextClick);
1465 ctxItem.Name = "gesture_play";
1466 ctxInv.Items.Add(ctxItem);
1468 ctxItem = new ToolStripMenuItem("Info", null, OnInvContextClick);
1469 ctxItem.Name = "gesture_info";
1470 ctxInv.Items.Add(ctxItem);
1473 if (item.InventoryType == InventoryType.Animation)
1475 if (!client.Self.SignaledAnimations.ContainsKey(item.AssetUUID))
1477 ctxItem = new ToolStripMenuItem("Play", null, OnInvContextClick);
1478 ctxItem.Name = "animation_play";
1479 ctxInv.Items.Add(ctxItem);
1483 ctxItem = new ToolStripMenuItem("Stop", null, OnInvContextClick);
1484 ctxItem.Name = "animation_stop";
1485 ctxInv.Items.Add(ctxItem);
1489 if (item.InventoryType == InventoryType.Object)
1491 ctxItem = new ToolStripMenuItem("Rez inworld", null, OnInvContextClick);
1492 ctxItem.Name = "rez_inworld";
1493 ctxInv.Items.Add(ctxItem);
1496 ctxItem = new ToolStripMenuItem("Rename", null, OnInvContextClick);
1497 ctxItem.Name = "rename_item";
1498 ctxInv.Items.Add(ctxItem);
1500 ctxInv.Items.Add(new ToolStripSeparator());
1502 ctxItem = new ToolStripMenuItem("Cut", null, OnInvContextClick);
1503 ctxItem.Name = "cut_item";
1504 ctxInv.Items.Add(ctxItem);
1506 ctxItem = new ToolStripMenuItem("Copy", null, OnInvContextClick);
1507 ctxItem.Name = "copy_item";
1508 ctxInv.Items.Add(ctxItem);
1510 if (instance.InventoryClipboard != null)
1512 ctxItem = new ToolStripMenuItem("Paste", null, OnInvContextClick);
1513 ctxItem.Name = "paste_item";
1514 ctxInv.Items.Add(ctxItem);
1516 if (instance.InventoryClipboard.Item is InventoryItem)
1518 ctxItem = new ToolStripMenuItem("Paste as Link", null, OnInvContextClick);
1519 ctxItem.Name = "paste_item_link";
1520 ctxInv.Items.Add(ctxItem);
1524 ctxItem = new ToolStripMenuItem("Delete", null, OnInvContextClick);
1525 ctxItem.Name = "delete_item";
1527 if (IsAttached(item) || IsWorn(item))
1529 ctxItem.Enabled = false;
1531 ctxInv.Items.Add(ctxItem);
1533 if (IsAttached(item) && instance.RLV.AllowDetach(attachments[item.UUID]))
1535 ctxItem = new ToolStripMenuItem("Detach from yourself", null, OnInvContextClick);
1536 ctxItem.Name = "detach";
1537 ctxInv.Items.Add(ctxItem);
1540 if (!IsAttached(item) && (item.InventoryType == InventoryType.Object || item.InventoryType == InventoryType.Attachment))
1542 ToolStripMenuItem ctxItemAttach = new ToolStripMenuItem("Attach to");
1543 ctxInv.Items.Add(ctxItemAttach);
1545 ToolStripMenuItem ctxItemAttachHUD = new ToolStripMenuItem("Attach to HUD");
1546 ctxInv.Items.Add(ctxItemAttachHUD);
1548 foreach (AttachmentPoint pt in Enum.GetValues(typeof(AttachmentPoint)))
1550 if (!pt.ToString().StartsWith("HUD"))
1552 string name = Utils.EnumToText(pt);
1554 InventoryItem alreadyAttached = null;
1555 if ((alreadyAttached = AttachmentAt(pt)) != null)
1557 name += " (" + alreadyAttached.Name + ")";
1560 ToolStripMenuItem ptItem = new ToolStripMenuItem(name, null, OnInvContextClick);
1561 ptItem.Name = pt.ToString();
1563 ptItem.Name = "attach_to";
1564 ctxItemAttach.DropDownItems.Add(ptItem);
1568 string name = Utils.EnumToText(pt).Substring(3);
1570 InventoryItem alreadyAttached = null;
1571 if ((alreadyAttached = AttachmentAt(pt)) != null)
1573 name += " (" + alreadyAttached.Name + ")";
1576 ToolStripMenuItem ptItem = new ToolStripMenuItem(name, null, OnInvContextClick);
1577 ptItem.Name = pt.ToString();
1579 ptItem.Name = "attach_to";
1580 ctxItemAttachHUD.DropDownItems.Add(ptItem);
1584 ctxItem = new ToolStripMenuItem("Add to Worn", null, OnInvContextClick);
1585 ctxItem.Name = "wear_attachment_add";
1586 ctxInv.Items.Add(ctxItem);
1588 ctxItem = new ToolStripMenuItem("Wear", null, OnInvContextClick);
1589 ctxItem.Name = "wear_attachment";
1590 ctxInv.Items.Add(ctxItem);
1593 if (item is InventoryWearable)
1595 ctxInv.Items.Add(new ToolStripSeparator());
1599 ctxItem = new ToolStripMenuItem("Take off", null, OnInvContextClick);
1600 ctxItem.Name = "item_take_off";
1601 ctxInv.Items.Add(ctxItem);
1605 ctxItem = new ToolStripMenuItem("Wear", null, OnInvContextClick);
1606 ctxItem.Name = "item_wear";
1607 ctxInv.Items.Add(ctxItem);
1611 instance.ContextActionManager.AddContributions(ctxInv, item);
1612 #endregion Item context menu
1617 #region Context menu folder
1618 private void OnInvContextClick(object sender, EventArgs e)
1620 if (invTree.SelectedNode == null || !(invTree.SelectedNode.Tag is InventoryBase))
1625 string cmd = ((ToolStripMenuItem)sender).Name;
1627 if (invTree.SelectedNode.Tag is InventoryFolder)
1629 #region Folder actions
1630 InventoryFolder f = (InventoryFolder)invTree.SelectedNode.Tag;
1635 foreach (TreeNode old in invTree.SelectedNode.Nodes)
1637 if (!(old.Tag is InventoryFolder))
1642 fetchFolder(f.UUID, f.OwnerID, true);
1646 (new InventoryBackup(instance, f.UUID)).Show();
1650 invTree.SelectedNode.Expand();
1654 invTree.SelectedNode.ExpandAll();
1658 invTree.SelectedNode.Collapse();
1662 newItemName = "New folder";
1663 client.Inventory.CreateFolder(f.UUID, "New folder");
1667 client.Inventory.UpdateFolderProperties(f.UUID, f.ParentUUID, f.Name, AssetType.Unknown);
1671 case "new_notecard":
1672 client.Inventory.RequestCreateItem(f.UUID, "New Note", "Radegast note: " + DateTime.Now.ToString(),
1673 AssetType.Notecard, UUID.Zero, InventoryType.Notecard, PermissionMask.All, NotecardCreated);
1677 client.Inventory.RequestCreateItem(f.UUID, "New script", "Radegast script: " + DateTime.Now.ToString(),
1678 AssetType.LSLText, UUID.Zero, InventoryType.LSL, PermissionMask.All, ScriptCreated);
1682 instance.InventoryClipboard = new InventoryClipboard(ClipboardOperation.Cut, f);
1686 instance.InventoryClipboard = new InventoryClipboard(ClipboardOperation.Copy, f);
1689 case "paste_folder":
1690 PerformClipboardOperation(invTree.SelectedNode.Tag as InventoryFolder);
1693 case "paste_folder_link":
1694 PerformLinkOperation(invTree.SelectedNode.Tag as InventoryFolder);
1698 case "delete_folder":
1699 var trash = client.Inventory.FindFolderForType(AssetType.TrashFolder);
1700 if (trash == Inventory.RootFolder.UUID)
1702 WorkPool.QueueUserWorkItem(sync =>
1704 trashCreated.Reset();
1705 trash = client.Inventory.CreateFolder(Inventory.RootFolder.UUID, "Trash", AssetType.TrashFolder);
1706 trashCreated.WaitOne(20 * 1000, false);
1708 client.Inventory.MoveFolder(f.UUID, trash, f.Name);
1713 client.Inventory.MoveFolder(f.UUID, trash, f.Name);
1718 DialogResult res = MessageBox.Show("Are you sure you want to empty your trash?", "Confirmation", MessageBoxButtons.OKCancel);
1719 if (res == DialogResult.OK)
1721 client.Inventory.EmptyTrash();
1726 case "empty_lost_found":
1728 DialogResult res = MessageBox.Show("Are you sure you want to empty your lost and found folder?", "Confirmation", MessageBoxButtons.OKCancel);
1729 if (res == DialogResult.OK)
1731 client.Inventory.EmptyLostAndFound();
1736 case "rename_folder":
1737 invTree.SelectedNode.BeginEdit();
1740 case "outfit_replace":
1741 List<InventoryItem> newOutfit = new List<InventoryItem>();
1742 foreach (InventoryBase item in Inventory.GetContents(f))
1744 if (item is InventoryItem)
1745 newOutfit.Add((InventoryItem)item);
1747 appearnceWasBusy = client.Appearance.ManagerBusy;
1748 instance.COF.ReplaceOutfit(newOutfit);
1753 List<InventoryItem> addToOutfit = new List<InventoryItem>();
1754 foreach (InventoryBase item in Inventory.GetContents(f))
1756 if (item is InventoryItem)
1757 addToOutfit.Add((InventoryItem)item);
1759 appearnceWasBusy = client.Appearance.ManagerBusy;
1760 instance.COF.AddToOutfit(addToOutfit, true);
1764 case "outfit_take_off":
1765 List<InventoryItem> removeFromOutfit = new List<InventoryItem>();
1766 foreach (InventoryBase item in Inventory.GetContents(f))
1768 if (item is InventoryItem)
1769 removeFromOutfit.Add((InventoryItem)item);
1771 appearnceWasBusy = client.Appearance.ManagerBusy;
1772 instance.COF.RemoveFromOutfit(removeFromOutfit);
1778 else if (invTree.SelectedNode.Tag is InventoryItem)
1780 #region Item actions
1781 InventoryItem item = (InventoryItem)invTree.SelectedNode.Tag;
1783 // Copy, cut, and delete works on links directly
1784 // The rest operate on the item that is pointed by the link
1785 if (cmd != "copy_item" && cmd != "cut_item" && cmd != "delete_item")
1787 item = instance.COF.RealInventoryItem(item);
1793 instance.InventoryClipboard = new InventoryClipboard(ClipboardOperation.Copy, item);
1797 instance.InventoryClipboard = new InventoryClipboard(ClipboardOperation.Cut, item);
1801 PerformClipboardOperation(invTree.SelectedNode.Parent.Tag as InventoryFolder);
1804 case "paste_item_link":
1805 PerformLinkOperation(invTree.SelectedNode.Parent.Tag as InventoryFolder);
1809 var trash = client.Inventory.FindFolderForType(AssetType.TrashFolder);
1810 if (trash == Inventory.RootFolder.UUID)
1812 WorkPool.QueueUserWorkItem(sync =>
1814 trashCreated.Reset();
1815 trash = client.Inventory.CreateFolder(Inventory.RootFolder.UUID, "Trash", AssetType.TrashFolder);
1816 trashCreated.WaitOne(20 * 1000, false);
1818 client.Inventory.MoveItem(item.UUID, trash, item.Name);
1823 client.Inventory.MoveItem(item.UUID, client.Inventory.FindFolderForType(AssetType.TrashFolder), item.Name);
1827 invTree.SelectedNode.BeginEdit();
1831 instance.COF.Detach(item);
1832 lock (attachments) attachments.Remove(item.UUID);
1833 invTree.SelectedNode.Text = ItemLabel(item, false);
1836 case "wear_attachment":
1837 instance.COF.Attach(item, AttachmentPoint.Default, true);
1840 case "wear_attachment_add":
1841 instance.COF.Attach(item, AttachmentPoint.Default, false);
1845 AttachmentPoint pt = (AttachmentPoint)((ToolStripMenuItem)sender).Tag;
1846 instance.COF.Attach(item, pt, true);
1850 ScriptEditor se = new ScriptEditor(instance, (InventoryLSL)item);
1855 UpdateItemInfo(item);
1858 case "item_take_off":
1859 appearnceWasBusy = client.Appearance.ManagerBusy;
1860 instance.COF.RemoveFromOutfit(item);
1861 invTree.SelectedNode.Text = ItemLabel(item, false);
1864 if (WornItems.Contains(item.UUID))
1866 WornItems.Remove(item.UUID);
1872 appearnceWasBusy = client.Appearance.ManagerBusy;
1873 instance.COF.AddToOutfit(item, true);
1874 invTree.SelectedNode.Text = ItemLabel(item, false);
1878 instance.TabConsole.DisplayNotificationInChat("Teleporting to " + item.Name);
1879 client.Self.RequestTeleport(item.AssetUUID);
1883 UpdateItemInfo(item);
1886 case "notecard_open":
1887 UpdateItemInfo(item);
1890 case "gesture_info":
1891 UpdateItemInfo(item);
1894 case "gesture_play":
1895 client.Self.PlayGesture(item.AssetUUID);
1898 case "animation_play":
1899 Dictionary<UUID, bool> anim = new Dictionary<UUID, bool>();
1900 anim.Add(item.AssetUUID, true);
1901 client.Self.Animate(anim, true);
1904 case "animation_stop":
1905 Dictionary<UUID, bool> animStop = new Dictionary<UUID, bool>();
1906 animStop.Add(item.AssetUUID, false);
1907 client.Self.Animate(animStop, true);
1911 instance.MediaManager.PlayUISound(UISounds.ObjectRez);
1912 Vector3 rezpos = new Vector3(2, 0, 0);
1913 rezpos = client.Self.SimPosition + rezpos * client.Self.Movement.BodyRotation;
1914 client.Inventory.RequestRezFromInventory(client.Network.CurrentSim, Quaternion.Identity, rezpos, item);
1921 void NotecardCreated(bool success, InventoryItem item)
1925 BeginInvoke(new MethodInvoker(() => NotecardCreated(success, item)));
1931 instance.TabConsole.DisplayNotificationInChat("Creation of notecard failed");
1935 instance.TabConsole.DisplayNotificationInChat("New notecard created, enter notecard name and press enter", ChatBufferTextStyle.Invisible);
1936 var node = findNodeForItem(item.ParentUUID);
1937 if (node != null) node.Expand();
1938 node = findNodeForItem(item.UUID);
1941 invTree.SelectedNode = node;
1946 void ScriptCreated(bool success, InventoryItem item)
1950 BeginInvoke(new MethodInvoker(() => ScriptCreated(success, item)));
1956 instance.TabConsole.DisplayNotificationInChat("Creation of script failed");
1960 instance.TabConsole.DisplayNotificationInChat("New script created, enter script name and press enter", ChatBufferTextStyle.Invisible);
1961 var node = findNodeForItem(item.ParentUUID);
1962 if (node != null) node.Expand();
1963 node = findNodeForItem(item.UUID);
1966 invTree.SelectedNode = node;
1971 void PerformClipboardOperation(InventoryFolder dest)
1973 if (instance.InventoryClipboard == null) return;
1975 if (dest == null) return;
1977 if (instance.InventoryClipboard.Operation == ClipboardOperation.Cut)
1979 if (instance.InventoryClipboard.Item is InventoryItem)
1981 client.Inventory.MoveItem(instance.InventoryClipboard.Item.UUID, dest.UUID, instance.InventoryClipboard.Item.Name);
1983 else if (instance.InventoryClipboard.Item is InventoryFolder)
1985 if (instance.InventoryClipboard.Item.UUID != dest.UUID)
1987 client.Inventory.MoveFolder(instance.InventoryClipboard.Item.UUID, dest.UUID, instance.InventoryClipboard.Item.Name);
1991 instance.InventoryClipboard = null;
1993 else if (instance.InventoryClipboard.Operation == ClipboardOperation.Copy)
1995 if (instance.InventoryClipboard.Item is InventoryItem)
1997 client.Inventory.RequestCopyItem(instance.InventoryClipboard.Item.UUID, dest.UUID, instance.InventoryClipboard.Item.Name, instance.InventoryClipboard.Item.OwnerID, (InventoryBase target) =>
2002 else if (instance.InventoryClipboard.Item is InventoryFolder)
2004 WorkPool.QueueUserWorkItem((object state) =>
2006 UUID newFolderID = client.Inventory.CreateFolder(dest.UUID, instance.InventoryClipboard.Item.Name, AssetType.Unknown);
2009 // FIXME: for some reason copying a bunch of items in one operation does not work
2011 //List<UUID> items = new List<UUID>();
2012 //List<UUID> folders = new List<UUID>();
2013 //List<string> names = new List<string>();
2014 //UUID oldOwner = UUID.Zero;
2016 foreach (InventoryBase oldItem in Inventory.GetContents((InventoryFolder)instance.InventoryClipboard.Item))
2018 //folders.Add(newFolderID);
2019 //names.Add(oldItem.Name);
2020 //items.Add(oldItem.UUID);
2021 //oldOwner = oldItem.OwnerID;
2022 client.Inventory.RequestCopyItem(oldItem.UUID, newFolderID, oldItem.Name, oldItem.OwnerID, (InventoryBase target) => { });
2025 //if (folders.Count > 0)
2027 // client.Inventory.RequestCopyItems(items, folders, names, oldOwner, (InventoryBase target) => { });
2035 void PerformLinkOperation(InventoryFolder dest)
2037 if (instance.InventoryClipboard == null) return;
2039 if (dest == null) return;
2041 client.Inventory.CreateLink(dest.UUID, instance.InventoryClipboard.Item, (bool success, InventoryItem item) => { });
2046 private void UpdateWornLabels()
2050 BeginInvoke(new MethodInvoker(UpdateWornLabels));
2054 invTree.BeginUpdate();
2055 foreach (UUID itemID in WornItems)
2057 TreeNode node = findNodeForItem(itemID);
2060 node.Text = ItemLabel((InventoryBase)node.Tag, false);
2064 foreach (AppearanceManager.WearableData wearable in client.Appearance.GetWearables().Values)
2066 TreeNode node = findNodeForItem(wearable.ItemID);
2069 node.Text = ItemLabel((InventoryBase)node.Tag, false);
2072 invTree.EndUpdate();
2075 void TreeView_AfterExpand(object sender, TreeViewEventArgs e)
2077 // Check if we need to go into edit mode for new items
2078 if (newItemName != string.Empty)
2080 foreach (TreeNode n in e.Node.Nodes)
2082 if (n.Name == newItemName)
2088 newItemName = string.Empty;
2092 private bool _EditingNode = false;
2094 private void OnLabelEditTimer(object sender)
2096 if (_EditNode == null || !(_EditNode.Tag is InventoryBase))
2101 BeginInvoke(new MethodInvoker(delegate()
2103 OnLabelEditTimer(sender);
2109 _EditingNode = true;
2110 _EditNode.Text = ItemLabel((InventoryBase)_EditNode.Tag, true);
2111 _EditNode.BeginEdit();
2114 private void invTree_BeforeLabelEdit(object sender, NodeLabelEditEventArgs e)
2116 if (e.Node == null ||
2117 !(e.Node.Tag is InventoryBase) ||
2118 (e.Node.Tag is InventoryFolder &&
2119 ((InventoryFolder)e.Node.Tag).PreferredType != AssetType.Unknown &&
2120 ((InventoryFolder)e.Node.Tag).PreferredType != AssetType.OutfitFolder)
2123 e.CancelEdit = true;
2129 _EditingNode = false;
2133 e.CancelEdit = true;
2135 _EditTimer.Change(20, System.Threading.Timeout.Infinite);
2139 private void invTree_AfterLabelEdit(object sender, NodeLabelEditEventArgs e)
2141 if (string.IsNullOrEmpty(e.Label))
2143 if (e.Node.Tag is InventoryBase)
2145 e.Node.Text = ItemLabel((InventoryBase)e.Node.Tag, false);
2147 e.CancelEdit = true;
2151 if (e.Node.Tag is InventoryFolder)
2153 InventoryFolder f = (InventoryFolder)e.Node.Tag;
2155 client.Inventory.MoveFolder(f.UUID, f.ParentUUID, f.Name);
2157 else if (e.Node.Tag is InventoryItem)
2159 InventoryItem item = (InventoryItem)e.Node.Tag;
2160 item.Name = e.Label;
2161 e.Node.Text = ItemLabel((InventoryBase)item, false);
2162 client.Inventory.MoveItem(item.UUID, item.ParentUUID, item.Name);
2163 UpdateItemInfo(item);
2168 private void invTree_KeyUp(object sender, KeyEventArgs e)
2170 if (e.KeyCode == Keys.F2 && invTree.SelectedNode != null)
2172 invTree.SelectedNode.BeginEdit();
2174 else if (e.KeyCode == Keys.F5 && invTree.SelectedNode != null)
2176 if (invTree.SelectedNode.Tag is InventoryFolder)
2178 InventoryFolder f = (InventoryFolder)invTree.SelectedNode.Tag;
2179 fetchFolder(f.UUID, f.OwnerID, true);
2182 else if (e.KeyCode == Keys.Delete && invTree.SelectedNode != null)
2184 if (invTree.SelectedNode.Tag is InventoryItem)
2186 InventoryItem item = invTree.SelectedNode.Tag as InventoryItem;
2187 client.Inventory.MoveItem(item.UUID, client.Inventory.FindFolderForType(AssetType.TrashFolder), item.Name);
2189 else if (invTree.SelectedNode.Tag is InventoryFolder)
2191 InventoryFolder f = invTree.SelectedNode.Tag as InventoryFolder;
2192 client.Inventory.MoveFolder(f.UUID, client.Inventory.FindFolderForType(AssetType.TrashFolder), f.Name);
2195 else if (e.KeyCode == Keys.Apps && invTree.SelectedNode != null)
2201 #region Drag and Drop
2202 private void invTree_ItemDrag(object sender, ItemDragEventArgs e)
2204 invTree.SelectedNode = e.Item as TreeNode;
2205 if (invTree.SelectedNode.Tag is InventoryFolder && ((InventoryFolder)invTree.SelectedNode.Tag).PreferredType != AssetType.Unknown)
2209 invTree.DoDragDrop(e.Item, DragDropEffects.Move);
2212 private void invTree_DragDrop(object sender, DragEventArgs e)
2214 if (highlightedNode != null)
2216 highlightedNode.BackColor = invTree.BackColor;
2217 highlightedNode = null;
2220 TreeNode sourceNode = e.Data.GetData(typeof(TreeNode)) as TreeNode;
2221 if (sourceNode == null) return;
2223 Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
2224 TreeNode destinationNode = ((TreeView)sender).GetNodeAt(pt);
2226 if (destinationNode == null) return;
2228 if (sourceNode == destinationNode) return;
2230 // If droping to item within folder drop to its folder
2231 if (destinationNode.Tag is InventoryItem)
2233 destinationNode = destinationNode.Parent;
2236 InventoryFolder dest = destinationNode.Tag as InventoryFolder;
2238 if (dest == null) return;
2240 if (sourceNode.Tag is InventoryItem)
2242 InventoryItem item = (InventoryItem)sourceNode.Tag;
2243 client.Inventory.MoveItem(item.UUID, dest.UUID, item.Name);
2245 else if (sourceNode.Tag is InventoryFolder)
2247 InventoryFolder f = (InventoryFolder)sourceNode.Tag;
2248 client.Inventory.MoveFolder(f.UUID, dest.UUID, f.Name);
2252 private void invTree_DragEnter(object sender, DragEventArgs e)
2254 TreeNode node = e.Data.GetData(typeof(TreeNode)) as TreeNode;
2257 e.Effect = DragDropEffects.None;
2261 e.Effect = DragDropEffects.Move;
2265 TreeNode highlightedNode = null;
2267 private void invTree_DragOver(object sender, DragEventArgs e)
2269 TreeNode node = e.Data.GetData(typeof(TreeNode)) as TreeNode;
2272 e.Effect = DragDropEffects.None;
2275 Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
2276 TreeNode destinationNode = ((TreeView)sender).GetNodeAt(pt);
2278 if (highlightedNode != destinationNode)
2280 if (highlightedNode != null)
2282 highlightedNode.BackColor = invTree.BackColor;
2283 highlightedNode = null;
2286 if (destinationNode != null)
2288 highlightedNode = destinationNode;
2289 highlightedNode.BackColor = Color.LightSlateGray;
2293 if (destinationNode == null)
2295 e.Effect = DragDropEffects.None;
2299 e.Effect = DragDropEffects.Move;
2304 private void saveAllTToolStripMenuItem_Click(object sender, EventArgs e)
2306 (new InventoryBackup(instance, Inventory.RootFolder.UUID)).Show();
2309 private void tbtnSystemFoldersFirst_Click(object sender, EventArgs e)
2311 sorter.SystemFoldersFirst = tbtnSystemFoldersFirst.Checked = !sorter.SystemFoldersFirst;
2312 instance.GlobalSettings["inv_sort_sysfirst"] = OSD.FromBoolean(sorter.SystemFoldersFirst);
2316 private void tbtbSortByName_Click(object sender, EventArgs e)
2318 if (tbtbSortByName.Checked) return;
2320 tbtbSortByName.Checked = true;
2321 tbtnSortByDate.Checked = sorter.ByDate = false;
2322 instance.GlobalSettings["inv_sort_bydate"] = OSD.FromBoolean(sorter.ByDate);
2327 private void tbtnSortByDate_Click(object sender, EventArgs e)
2329 if (tbtnSortByDate.Checked) return;
2331 tbtbSortByName.Checked = false;
2332 tbtnSortByDate.Checked = sorter.ByDate = true;
2333 instance.GlobalSettings["inv_sort_bydate"] = OSD.FromBoolean(sorter.ByDate);
2340 public class SearchResult
2342 public InventoryBase Inv;
2345 public SearchResult(InventoryBase inv, int level)
2352 List<SearchResult> searchRes;
2353 string searchString;
2354 Dictionary<int, ListViewItem> searchItemCache = new Dictionary<int, ListViewItem>();
2355 ListViewItem emptyItem = null;
2358 void PerformRecursiveSearch(int level, UUID folderID)
2360 var me = Inventory.Items[folderID].Data;
2361 searchRes.Add(new SearchResult(me, level));
2362 var sorted = Inventory.GetContents(folderID);
2364 sorted.Sort((InventoryBase b1, InventoryBase b2) =>
2366 if (b1 is InventoryFolder && !(b2 is InventoryFolder))
2370 else if (!(b1 is InventoryFolder) && b2 is InventoryFolder)
2376 return string.Compare(b1.Name, b2.Name);
2380 foreach (var item in sorted)
2382 if (item is InventoryFolder)
2384 PerformRecursiveSearch(level + 1, item.UUID);
2388 var it = item as InventoryItem;
2391 if (cbSrchName.Checked && it.Name.ToLower().Contains(searchString))
2395 else if (cbSrchDesc.Checked && it.Description.ToLower().Contains(searchString))
2400 if (cbSrchWorn.Checked && add &&
2402 (it.InventoryType == InventoryType.Wearable && IsWorn(it)) ||
2403 ((it.InventoryType == InventoryType.Attachment || it.InventoryType == InventoryType.Object) && IsAttached(it))
2410 if (cbSrchRecent.Checked && add && it.CreationDate < instance.StartupTimeUTC)
2418 searchRes.Add(new SearchResult(it, level + 1));
2423 if (searchRes[searchRes.Count - 1].Inv == me)
2425 searchRes.RemoveAt(searchRes.Count - 1);
2429 public void UpdateSearch()
2433 if (instance.MonoRuntime)
2435 lstInventorySearch.VirtualMode = false;
2436 lstInventorySearch.Items.Clear();
2437 lstInventorySearch.VirtualMode = true;
2440 lstInventorySearch.VirtualListSize = 0;
2441 searchString = txtSearch.Text.Trim().ToLower();
2443 //if (searchString == string.Empty && rbSrchAll.Checked)
2445 // lblSearchStatus.Text = "0 results";
2449 if (emptyItem == null)
2451 emptyItem = new ListViewItem(string.Empty);
2454 searchRes = new List<SearchResult>(Inventory.Items.Count);
2455 searchItemCache.Clear();
2456 PerformRecursiveSearch(0, Inventory.RootFolder.UUID);
2457 lstInventorySearch.VirtualListSize = searchRes.Count;
2458 lblSearchStatus.Text = string.Format("{0} results", found);
2461 private void lstInventorySearch_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
2463 if (searchItemCache.ContainsKey(e.ItemIndex))
2465 e.Item = searchItemCache[e.ItemIndex];
2467 else if (e.ItemIndex < searchRes.Count)
2469 InventoryBase inv = searchRes[e.ItemIndex].Inv;
2470 string desc = inv.Name;
2471 if (inv is InventoryItem)
2473 desc += string.Format(" - {0}", ((InventoryItem)inv).Description);
2475 ListViewItem item = new ListViewItem(desc);
2476 item.Tag = searchRes[e.ItemIndex];
2478 searchItemCache[e.ItemIndex] = item;
2486 private void btnInvSearch_Click(object sender, EventArgs e)
2491 private void cbSrchName_CheckedChanged(object sender, EventArgs e)
2493 if (!cbSrchName.Checked && !cbSrchDesc.Checked && !cbSrchCreator.Checked)
2495 cbSrchName.Checked = true;
2500 private void cbSrchWorn_CheckedChanged(object sender, EventArgs e)
2505 private void txtSearch_KeyDown(object sender, KeyEventArgs e)
2507 if (e.KeyCode == Keys.Enter)
2509 e.Handled = e.SuppressKeyPress = true;
2510 if (txtSearch.Text.Trim().Length > 0)
2517 private void lstInventorySearch_DrawItem(object sender, DrawListViewItemEventArgs e)
2519 Graphics g = e.Graphics;
2522 if (!(e.Item.Tag is SearchResult))
2525 if (e.Item.Selected)
2527 g.FillRectangle(SystemBrushes.Highlight, e.Bounds);
2530 SearchResult res = e.Item.Tag as SearchResult;
2531 int offset = 20 * (res.Level + 1);
2532 Rectangle rec = new Rectangle(e.Bounds.X + offset, e.Bounds.Y, e.Bounds.Width - offset, e.Bounds.Height);
2537 if (res.Inv is InventoryFolder)
2539 iconIx = GetDirImageIndex(((InventoryFolder)res.Inv).PreferredType.ToString().ToLower());
2541 else if (res.Inv is InventoryWearable)
2543 iconIx = GetItemImageIndex(((InventoryWearable)res.Inv).WearableType.ToString().ToLower());
2545 else if (res.Inv is InventoryItem)
2547 iconIx = GetItemImageIndex(((InventoryItem)res.Inv).AssetType.ToString().ToLower());
2557 icon = frmMain.ResourceImages.Images[iconIx];
2558 g.DrawImageUnscaled(icon, e.Bounds.X + offset - 18, e.Bounds.Y);
2562 using (StringFormat sf = new StringFormat(StringFormatFlags.NoWrap | StringFormatFlags.LineLimit))
2564 string label = ItemLabel(res.Inv, false);
2565 SizeF len = e.Graphics.MeasureString(label, lstInventorySearch.Font, rec.Width, sf);
2567 e.Graphics.DrawString(
2568 ItemLabel(res.Inv, false),
2569 lstInventorySearch.Font,
2570 e.Item.Selected ? SystemBrushes.HighlightText : SystemBrushes.WindowText,
2574 if (res.Inv is InventoryItem)
2576 string desc = ((InventoryItem)res.Inv).Description.Trim();
2577 if (desc != string.Empty)
2579 using (Font descFont = new Font(lstInventorySearch.Font, FontStyle.Italic))
2581 e.Graphics.DrawString(desc,
2583 e.Item.Selected ? SystemBrushes.HighlightText : SystemBrushes.GrayText,
2584 rec.X + len.Width + 5,
2594 private void lstInventorySearch_SizeChanged(object sender, EventArgs e)
2596 chResItemName.Width = lstInventorySearch.Width - 30;
2599 private void txtSearch_TextChanged(object sender, EventArgs e)
2604 private void rbSrchAll_CheckedChanged(object sender, EventArgs e)
2609 private void lstInventorySearch_KeyDown(object sender, KeyEventArgs e)
2611 if ((e.KeyCode == Keys.Apps) || (e.Control && e.KeyCode == RadegastContextMenuStrip.ContexMenuKeyCode))
2613 lstInventorySearch_MouseClick(sender, new MouseEventArgs(MouseButtons.Right, 1, 50, 150, 0));
2618 /// Finds and higlights inventory node
2620 /// <param name="itemID">Inventory of ID of the item to select</param>
2621 public void SelectInventoryNode(UUID itemID)
2623 TreeNode node = findNodeForItem(itemID);
2626 invTree.SelectedNode = node;
2627 if (node.Tag is InventoryItem)
2629 UpdateItemInfo(node.Tag as InventoryItem);
2633 private void lstInventorySearch_MouseClick(object sender, MouseEventArgs e)
2635 if (lstInventorySearch.SelectedIndices.Count != 1)
2640 SearchResult res = searchRes[lstInventorySearch.SelectedIndices[0]];
2641 TreeNode node = findNodeForItem(res.Inv.UUID);
2644 invTree.SelectedNode = node;
2645 if (e.Button == MouseButtons.Right)
2647 ctxInv.Show(lstInventorySearch, e.X, e.Y);
2653 private void lstInventorySearch_MouseDoubleClick(object sender, MouseEventArgs e)
2655 if (lstInventorySearch.SelectedIndices.Count != 1)
2660 SearchResult res = searchRes[lstInventorySearch.SelectedIndices[0]];
2661 TreeNode node = findNodeForItem(res.Inv.UUID);
2664 invTree.SelectedNode = node;
2665 invTree_NodeMouseDoubleClick(null, null);
2672 private void txtAssetID_Enter(object sender, EventArgs e)
2674 txtAssetID.SelectAll();
2677 private void txtInvID_Enter(object sender, EventArgs e)
2679 txtInvID.SelectAll();
2682 private void copyInitialOutfitsToolStripMenuItem_Click(object sender, EventArgs e)
2684 var c = new FolderCopy(instance);
2685 c.GetFolders("Initial Outfits");
2691 #region Sorter class
2692 // Create a node sorter that implements the IComparer interface.
2693 public class InvNodeSorter : System.Collections.IComparer
2695 bool _sysfirst = true;
2696 bool _bydate = true;
2698 int CompareFolders(InventoryFolder x, InventoryFolder y)
2702 if (x.PreferredType != AssetType.Unknown && y.PreferredType == AssetType.Unknown)
2706 else if (x.PreferredType == AssetType.Unknown && y.PreferredType != AssetType.Unknown)
2711 return String.Compare(x.Name, y.Name);
2714 public bool SystemFoldersFirst { set { _sysfirst = value; } get { return _sysfirst; } }
2715 public bool ByDate { set { _bydate = value; } get { return _bydate; } }
2717 public int Compare(object x, object y)
2719 TreeNode tx = x as TreeNode;
2720 TreeNode ty = y as TreeNode;
2722 if (tx.Tag is InventoryFolder && ty.Tag is InventoryFolder)
2724 return CompareFolders(tx.Tag as InventoryFolder, ty.Tag as InventoryFolder);
2726 else if (tx.Tag is InventoryFolder && ty.Tag is InventoryItem)
2730 else if (tx.Tag is InventoryItem && ty.Tag is InventoryFolder)
2736 if (!(tx.Tag is InventoryItem) || !(ty.Tag is InventoryItem))
2741 InventoryItem item1 = (InventoryItem)tx.Tag;
2742 InventoryItem item2 = (InventoryItem)ty.Tag;
2746 if (item1.CreationDate < item2.CreationDate)
2750 else if (item1.CreationDate > item2.CreationDate)
2755 return string.Compare(item1.Name, item2.Name);
2760 public class AttachmentInfo
2762 public Primitive Prim;
2763 public InventoryItem Item;
2764 public UUID InventoryID;
2766 public bool MarkedAttached = false;
2768 public AttachmentPoint Point
2774 return Prim.PrimData.AttachmentPoint;
2778 return AttachmentPoint.Default;