PageRenderTime 56ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/IARModifierGUI/Modules/IAREditor.cs

https://bitbucket.org/VirtualReality/optional-modules
C# | 1003 lines | 696 code | 112 blank | 195 comment | 73 complexity | ffec0c146094f0b1966bae648d313a9d MD5 | raw file
  1. /*
  2. * Copyright (c) Contributors, http://aurora-sim.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the Aurora-Sim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections.Generic;
  29. using System.ComponentModel;
  30. using System.Drawing;
  31. using System.Linq;
  32. using System.IO;
  33. using System.IO.Compression;
  34. using System.Reflection;
  35. using System.Text;
  36. using System.Windows.Forms;
  37. using System.Xml;
  38. using Aurora.Framework;
  39. using Aurora.Framework.Serialization;
  40. using Aurora.Framework.Serialization.External;
  41. using OpenSim.Services.Interfaces;
  42. using log4net;
  43. using Nini.Config;
  44. using OpenMetaverse;
  45. using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver;
  46. namespace IARModifierGUI
  47. {
  48. public partial class IAREditor : Form
  49. {
  50. #region Declares/Constructors
  51. private string m_iarName;
  52. private Dictionary<string, AssetBase> m_loadedAssets = new Dictionary<string, AssetBase> ();
  53. private List<InventoryFolderBase> m_rootFolders = new List<InventoryFolderBase>();
  54. private Dictionary<UUID, List<InventoryItemBase>> m_items = new Dictionary<UUID, List<InventoryItemBase>> ();
  55. private List<InventoryFolderBase> m_folders = new List<InventoryFolderBase> ();
  56. private Dictionary<UUID, List<InventoryFolderBase>> m_childFolders = new Dictionary<UUID, List<InventoryFolderBase>> ();
  57. private Dictionary<UUID, InventoryItemBase> m_itemList = new Dictionary<UUID, InventoryItemBase> ();
  58. private Dictionary<UUID, InventoryFolderBase> m_folderList = new Dictionary<UUID, InventoryFolderBase> ();
  59. public IAREditor (string IARName)
  60. {
  61. InitializeComponent ();
  62. m_iarName = IARName;
  63. }
  64. public IAREditor ()
  65. {
  66. InitializeComponent ();
  67. m_iarName = SelectTextFile (Environment.CurrentDirectory);
  68. if (m_iarName == null)
  69. Environment.Exit(0);
  70. }
  71. #endregion
  72. #region Startup/Rebuild
  73. private void IAREditor_Load (object sender, EventArgs e)
  74. {
  75. LoadIAR (m_iarName);
  76. }
  77. private void RebuildTreeView ()
  78. {
  79. m_rootFolders.Clear ();
  80. UUID previouslySelectedID = treeView1.SelectedNode != null ? UUID.Parse (treeView1.SelectedNode.Name) : UUID.Zero;
  81. TreeNode selectedNode = null;
  82. TreeNode rootNode = new TreeNode ("My Inventory");
  83. Dictionary<UUID, TreeNode> nodes = new Dictionary<UUID, TreeNode> ();
  84. foreach (InventoryFolderBase folder in m_folders)
  85. {
  86. if (folder.ParentID == UUID.Zero)
  87. {
  88. TreeNode node = new TreeNode (folder.Name);
  89. node.Name = folder.ID.ToString ();
  90. if (previouslySelectedID == folder.ID)
  91. selectedNode = node;
  92. if (m_items.ContainsKey (folder.ID))
  93. {
  94. foreach (InventoryItemBase item in m_items[folder.ID])
  95. {
  96. TreeNode inventoryNode = new TreeNode (item.Name);
  97. inventoryNode.Name = item.ID.ToString ();
  98. if (previouslySelectedID == item.ID)
  99. selectedNode = inventoryNode;
  100. node.Nodes.Add (inventoryNode);
  101. }
  102. }
  103. nodes.Add (folder.ID, node);
  104. rootNode.Nodes.Add (node);
  105. m_rootFolders.Add(folder);
  106. }
  107. else
  108. {
  109. TreeNode parentNode = nodes[folder.ParentID];
  110. TreeNode node = new TreeNode (folder.Name);
  111. node.Name = folder.ID.ToString ();
  112. if (previouslySelectedID == folder.ID)
  113. selectedNode = node;
  114. if (m_items.ContainsKey (folder.ID))
  115. {
  116. foreach (InventoryItemBase item in m_items[folder.ID])
  117. {
  118. TreeNode inventoryNode = new TreeNode (item.Name);
  119. inventoryNode.Name = item.ID.ToString ();
  120. if (previouslySelectedID == item.ID)
  121. selectedNode = inventoryNode;
  122. node.Nodes.Add (inventoryNode);
  123. }
  124. }
  125. nodes.Add (folder.ID, node);
  126. parentNode.Nodes.Add (node);
  127. }
  128. }
  129. treeView1.Nodes.Clear();
  130. treeView1.Nodes.Add(rootNode);
  131. if (selectedNode != null)
  132. {
  133. treeView1.Select ();
  134. List<TreeNode> parentNodes = new List<TreeNode>();
  135. TreeNode node = selectedNode;
  136. while (true)
  137. {
  138. if (node.Parent == null)
  139. break;
  140. node.Parent.Toggle ();
  141. node = node.Parent;
  142. }
  143. treeView1.Update ();
  144. }
  145. }
  146. #endregion
  147. #region IAR Loading
  148. private void LoadIAR (string fileName)
  149. {
  150. //Load the iar into memory
  151. TarArchiveReader archive = new TarArchiveReader (new GZipStream (ArchiveHelpers.GetStream (fileName), CompressionMode.Decompress));
  152. byte[] data;
  153. TarArchiveReader.TarEntryType entryType;
  154. string filePath;
  155. InventoryFolderBase rootDestFolder = new InventoryFolderBase (UUID.Zero, UUID.Zero);
  156. Dictionary<string, InventoryFolderBase> resolvedFolders = new Dictionary<string, InventoryFolderBase> ();
  157. while ((data = archive.ReadEntry (out filePath, out entryType)) != null)
  158. {
  159. if (filePath.StartsWith (ArchiveConstants.ASSETS_PATH))
  160. {
  161. LoadAsset (filePath, data);
  162. }
  163. else if (filePath.StartsWith (ArchiveConstants.INVENTORY_PATH))
  164. {
  165. filePath = filePath.Substring (ArchiveConstants.INVENTORY_PATH.Length);
  166. // Trim off the file portion if we aren't already dealing with a directory path
  167. if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
  168. filePath = filePath.Remove (filePath.LastIndexOf ("/") + 1);
  169. InventoryFolderBase foundFolder
  170. = ReplicateArchivePathToUserInventory (
  171. filePath, rootDestFolder, ref resolvedFolders);
  172. if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
  173. {
  174. LoadItem (data, foundFolder);
  175. }
  176. }
  177. }
  178. archive.Close ();
  179. //Got the .iar loaded into memory now
  180. // Time to put it into the GUI
  181. RebuildTreeView ();
  182. }
  183. /// <summary>
  184. /// Replicate the inventory paths in the archive to the user's inventory as necessary.
  185. /// </summary>
  186. /// <param name="iarPath">The item archive path to replicate</param>
  187. /// <param name="rootDestinationFolder">The root folder for the inventory load</param>
  188. /// <param name="resolvedFolders">
  189. /// The folders that we have resolved so far for a given archive path.
  190. /// This method will add more folders if necessary
  191. /// </param>
  192. /// <param name="loadedNodes">
  193. /// Track the inventory nodes created.
  194. /// </param>
  195. /// <returns>The last user inventory folder created or found for the archive path</returns>
  196. public InventoryFolderBase ReplicateArchivePathToUserInventory (
  197. string iarPath,
  198. InventoryFolderBase rootDestFolder,
  199. ref Dictionary<string, InventoryFolderBase> resolvedFolders)
  200. {
  201. string iarPathExisting = iarPath;
  202. // m_log.DebugFormat(
  203. // "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID);
  204. InventoryFolderBase destFolder
  205. = ResolveDestinationFolder (rootDestFolder, ref iarPathExisting, ref resolvedFolders);
  206. // m_log.DebugFormat(
  207. // "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]",
  208. // iarPath, iarPathExisting);
  209. string iarPathToCreate = iarPath.Substring (iarPathExisting.Length);
  210. CreateFoldersForPath (destFolder, iarPathExisting, iarPathToCreate, ref resolvedFolders);
  211. return destFolder;
  212. }
  213. /// <summary>
  214. /// Resolve a destination folder
  215. /// </summary>
  216. ///
  217. /// We require here a root destination folder (usually the root of the user's inventory) and the archive
  218. /// path. We also pass in a list of previously resolved folders in case we've found this one previously.
  219. ///
  220. /// <param name="archivePath">
  221. /// The item archive path to resolve. The portion of the path passed back is that
  222. /// which corresponds to the resolved desintation folder.
  223. /// <param name="rootDestinationFolder">
  224. /// The root folder for the inventory load
  225. /// </param>
  226. /// <param name="resolvedFolders">
  227. /// The folders that we have resolved so far for a given archive path.
  228. /// </param>
  229. /// <returns>
  230. /// The folder in the user's inventory that matches best the archive path given. If no such folder was found
  231. /// then the passed in root destination folder is returned.
  232. /// </returns>
  233. protected InventoryFolderBase ResolveDestinationFolder (
  234. InventoryFolderBase rootDestFolder,
  235. ref string archivePath,
  236. ref Dictionary<string, InventoryFolderBase> resolvedFolders)
  237. {
  238. // string originalArchivePath = archivePath;
  239. while (archivePath.Length > 0)
  240. {
  241. // m_log.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath);
  242. if (resolvedFolders.ContainsKey (archivePath))
  243. {
  244. // m_log.DebugFormat(
  245. // "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath);
  246. return resolvedFolders[archivePath];
  247. }
  248. else
  249. {
  250. // Don't include the last slash so find the penultimate one
  251. int penultimateSlashIndex = archivePath.LastIndexOf ("/", archivePath.Length - 2);
  252. if (penultimateSlashIndex >= 0)
  253. {
  254. // Remove the last section of path so that we can see if we've already resolved the parent
  255. archivePath = archivePath.Remove (penultimateSlashIndex + 1);
  256. }
  257. else
  258. {
  259. // m_log.DebugFormat(
  260. // "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}",
  261. // originalArchivePath);
  262. archivePath = string.Empty;
  263. return rootDestFolder;
  264. }
  265. }
  266. }
  267. return rootDestFolder;
  268. }
  269. /// <summary>
  270. /// Create a set of folders for the given path.
  271. /// </summary>
  272. /// <param name="destFolder">
  273. /// The root folder from which the creation will take place.
  274. /// </param>
  275. /// <param name="iarPathExisting">
  276. /// the part of the iar path that already exists
  277. /// </param>
  278. /// <param name="iarPathToReplicate">
  279. /// The path to replicate in the user's inventory from iar
  280. /// </param>
  281. /// <param name="resolvedFolders">
  282. /// The folders that we have resolved so far for a given archive path.
  283. /// </param>
  284. /// <param name="loadedNodes">
  285. /// Track the inventory nodes created.
  286. /// </param>
  287. protected void CreateFoldersForPath (
  288. InventoryFolderBase destFolder,
  289. string iarPathExisting,
  290. string iarPathToReplicate,
  291. ref Dictionary<string, InventoryFolderBase> resolvedFolders)
  292. {
  293. string[] rawDirsToCreate = iarPathToReplicate.Split (new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
  294. for (int i = 0; i < rawDirsToCreate.Length; i++)
  295. {
  296. // m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0} from IAR", rawDirsToCreate[i]);
  297. if (!rawDirsToCreate[i].Contains (ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR))
  298. continue;
  299. int identicalNameIdentifierIndex
  300. = rawDirsToCreate[i].LastIndexOf (
  301. ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR);
  302. string newFolderName = rawDirsToCreate[i].Remove (identicalNameIdentifierIndex);
  303. newFolderName = InventoryArchiveUtils.UnescapeArchivePath (newFolderName);
  304. UUID newFolderId = UUID.Random ();
  305. // Asset type has to be Unknown here rather than Folder, otherwise the created folder can't be
  306. // deleted once the client has relogged.
  307. // The root folder appears to be labelled AssetType.Folder (shows up as "Category" in the client)
  308. // even though there is a AssetType.RootCategory
  309. destFolder
  310. = new InventoryFolderBase (
  311. newFolderId, newFolderName, UUID.Zero,
  312. (short)AssetType.Unknown, destFolder.ID, 1);
  313. // Record that we have now created this folder
  314. iarPathExisting += rawDirsToCreate[i] + "/";
  315. resolvedFolders[iarPathExisting] = destFolder;
  316. m_folders.Add (destFolder);
  317. if(!m_childFolders.ContainsKey(destFolder.ParentID))
  318. m_childFolders.Add (destFolder.ParentID, new List<InventoryFolderBase>());
  319. m_childFolders[destFolder.ParentID].Add (destFolder);
  320. m_folderList.Add (destFolder.ID, destFolder);
  321. }
  322. }
  323. /// <summary>
  324. /// Load an item from the archive
  325. /// </summary>
  326. /// <param name="filePath">The archive path for the item</param>
  327. /// <param name="data">The raw item data</param>
  328. /// <param name="rootDestinationFolder">The root destination folder for loaded items</param>
  329. /// <param name="nodesLoaded">All the inventory nodes (items and folders) loaded so far</param>
  330. protected InventoryItemBase LoadItem (byte[] data, InventoryFolderBase loadFolder)
  331. {
  332. InventoryItemBase item = UserInventoryItemSerializer.Deserialize (data);
  333. item.Folder = loadFolder.ID;
  334. if(!m_items.ContainsKey(item.Folder))
  335. m_items.Add (item.Folder, new List<InventoryItemBase>());
  336. m_items[item.Folder].Add (item);
  337. m_itemList[item.ID] = item;
  338. return item;
  339. }
  340. /// <summary>
  341. /// Load an asset
  342. /// </summary>
  343. /// <param name="assetFilename"></param>
  344. /// <param name="data"></param>
  345. /// <returns>true if asset was successfully loaded, false otherwise</returns>
  346. private bool LoadAsset (string assetPath, byte[] data)
  347. {
  348. //IRegionSerialiser serialiser = scene.RequestModuleInterface<IRegionSerialiser>();
  349. // Right now we're nastily obtaining the UUID from the filename
  350. string filename = assetPath.Remove (0, ArchiveConstants.ASSETS_PATH.Length);
  351. int i = filename.LastIndexOf (ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
  352. if (i == -1)
  353. {
  354. return false;
  355. }
  356. string extension = filename.Substring (i);
  357. string uuid = filename.Remove (filename.Length - extension.Length);
  358. if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey (extension))
  359. {
  360. AssetType assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
  361. //m_log.DebugFormat("[INVENTORY ARCHIVER]: Importing asset {0}, type {1}", uuid, assetType);
  362. AssetBase asset = new AssetBase (new UUID (uuid), "RandomName", assetType, UUID.Zero);
  363. asset.Data = data;
  364. asset.Flags = AssetFlags.Normal;
  365. m_loadedAssets[asset.IDString] = asset;
  366. return true;
  367. }
  368. else
  369. {
  370. return false;
  371. }
  372. }
  373. #endregion
  374. #region Click actions
  375. private void delete_Click (object sender, EventArgs e)
  376. {
  377. //First see if it is a folder to delete
  378. UUID id = UUID.Parse(treeView1.SelectedNode.Name);
  379. if(m_folderList.ContainsKey(id))
  380. {
  381. RemoveFolder (id);
  382. }
  383. else
  384. {
  385. //Its an item!
  386. InventoryItemBase item = m_itemList[id];
  387. //Remove it from the lists
  388. m_itemList.Remove (id);
  389. m_items[item.Folder].Remove (item);
  390. }
  391. //Update the GUI now
  392. RebuildTreeView ();
  393. }
  394. private void RemoveFolder (UUID id)
  395. {
  396. InventoryFolderBase folder = m_folderList[id];
  397. //Remove all the items of the folder
  398. if (m_items.ContainsKey (id))
  399. {
  400. foreach (InventoryItemBase item in m_items[id])
  401. {
  402. m_itemList.Remove (item.ID);
  403. }
  404. }
  405. //Go recursive on the folders
  406. if (m_childFolders.ContainsKey (id))
  407. {
  408. foreach (InventoryFolderBase childFolder in new List<InventoryFolderBase>(m_childFolders[id]))
  409. {
  410. RemoveFolder (childFolder.ID);
  411. }
  412. }
  413. m_items.Remove (id);
  414. //Remove from the lists
  415. m_folders.Remove (folder);
  416. m_folderList.Remove (id);
  417. m_childFolders.Remove (id);
  418. m_childFolders[folder.ParentID].Remove (folder);
  419. }
  420. private void rename_Click (object sender, EventArgs e)
  421. {
  422. string value = "";
  423. Aurora.Framework.Utilities.InputBox ("Rename", "What should we rename this object to?", ref value);
  424. UUID id = UUID.Parse (treeView1.SelectedNode.Name);
  425. if (m_folderList.ContainsKey (id))
  426. {
  427. InventoryFolderBase folder = m_folderList[id];
  428. folder.Name = value;
  429. }
  430. else
  431. {
  432. //Its an item!
  433. InventoryItemBase item = m_itemList[id];
  434. item.Name = value;
  435. }
  436. //Update the GUI now
  437. RebuildTreeView ();
  438. }
  439. private bool m_nameChanged = false;
  440. private void textBox1_TextChanged (object sender, EventArgs e)
  441. {
  442. m_nameChanged = true;
  443. }
  444. private void textBox1_Leave (object sender, EventArgs e)
  445. {
  446. if (!m_nameChanged)
  447. return;
  448. m_nameChanged = false;
  449. string value = textBox1.Text;
  450. UUID id = UUID.Parse (treeView1.SelectedNode.Name);
  451. if (m_folderList.ContainsKey (id))
  452. {
  453. InventoryFolderBase folder = m_folderList[id];
  454. folder.Name = value;
  455. }
  456. else
  457. {
  458. //Its an item!
  459. InventoryItemBase item = m_itemList[id];
  460. item.Name = value;
  461. }
  462. //Update the GUI now
  463. RebuildTreeView ();
  464. }
  465. private bool m_typeChanged = false;
  466. private void textBox2_TextChanged (object sender, EventArgs e)
  467. {
  468. m_typeChanged = true;
  469. }
  470. private void textBox2_Leave (object sender, EventArgs e)
  471. {
  472. if (!m_typeChanged)
  473. return;
  474. m_typeChanged = false;
  475. bool isitem = false;
  476. try
  477. {
  478. UUID id = UUID.Parse (treeView1.SelectedNode.Name);
  479. if (m_folderList.ContainsKey (id))
  480. {
  481. AssetType value = (AssetType)Enum.Parse (typeof (AssetType), textBox2.Text);
  482. InventoryFolderBase folder = m_folderList[id];
  483. folder.Type = (short)value;
  484. }
  485. else
  486. {
  487. InventoryType value = (InventoryType)Enum.Parse (typeof (InventoryType), textBox2.Text);
  488. isitem = true;
  489. //Its an item!
  490. InventoryItemBase item = m_itemList[id];
  491. item.InvType = (int)value;
  492. }
  493. }
  494. catch
  495. {
  496. if(isitem)
  497. MessageBox.Show (@"Valid types are:
  498. Unknown
  499. Texture
  500. Sound
  501. CallingCard
  502. Landmark
  503. Object
  504. Notecard
  505. Category
  506. Folder
  507. RootCategory
  508. LSL
  509. Snapshot
  510. Attachment
  511. Wearable
  512. Animation
  513. Gesture
  514. Mesh");
  515. else
  516. MessageBox.Show (@"Valid types are:
  517. Unknown
  518. Texture
  519. Sound
  520. CallingCard
  521. Landmark
  522. Clothing
  523. Object
  524. Notecard
  525. Folder
  526. RootFolder
  527. LSLText
  528. TextureTGA
  529. Bodypart
  530. TrashFolder
  531. SnapshotFolder
  532. LostAndFoundFolder
  533. Animation
  534. Gesture
  535. Simstate
  536. FavoriteFolder
  537. LinkFolder
  538. CurrentOutfitFolder
  539. OutfitFolder
  540. MyOutfitsFolder
  541. Mesh");
  542. }
  543. }
  544. private void treeView1_NodeMouseDoubleClick (object sender, TreeNodeMouseClickEventArgs e)
  545. {
  546. try
  547. {
  548. UUID id = UUID.Parse (e.Node.Name);
  549. if (m_folderList.ContainsKey (id))
  550. {
  551. InventoryFolderBase folder = m_folderList[id];
  552. textBox1.Text = folder.Name;
  553. textBox2.Text = ((AssetType)folder.Type).ToString();
  554. }
  555. else
  556. {
  557. //Its an item!
  558. if (m_itemList.ContainsKey (id))
  559. {
  560. InventoryItemBase item = m_itemList[id];
  561. textBox1.Text = item.Name;
  562. textBox2.Text = ((InventoryType)item.InvType).ToString ();
  563. }
  564. }
  565. }
  566. catch
  567. {
  568. }
  569. }
  570. private void treeView1_NodeMouseClick_1 (object sender, TreeNodeMouseClickEventArgs e)
  571. {
  572. treeView1_NodeMouseDoubleClick (sender, e);
  573. }
  574. private UUID m_movingObject = UUID.Zero;
  575. private bool m_moveContents = false;
  576. private void move_Click (object sender, EventArgs e)
  577. {
  578. m_movingObject = UUID.Parse (treeView1.SelectedNode.Name);
  579. m_moveContents = false;
  580. MessageBox.Show ("Select the folder you wish to put this object in.");
  581. //Move the object to the next place the user clicks
  582. treeView1.NodeMouseClick += new TreeNodeMouseClickEventHandler (treeView1_NodeMouseClick);
  583. }
  584. private void move_contents_Click (object sender, EventArgs e)
  585. {
  586. m_movingObject = UUID.Parse (treeView1.SelectedNode.Name);
  587. if (!m_folderList.ContainsKey (m_movingObject))
  588. {
  589. MessageBox.Show ("Select a valid folder to move it's contents.");
  590. return;
  591. }
  592. m_moveContents = true;
  593. MessageBox.Show ("Select the folder you wish to put the contents in.");
  594. //Move the object to the next place the user clicks
  595. treeView1.NodeMouseClick += new TreeNodeMouseClickEventHandler (treeView1_NodeMouseClick);
  596. }
  597. private void cancelMove_Click (object sender, EventArgs e)
  598. {
  599. treeView1.NodeMouseClick -= new TreeNodeMouseClickEventHandler (treeView1_NodeMouseClick);
  600. MessageBox.Show ("Move canceled.");
  601. }
  602. void treeView1_NodeMouseClick (object sender, TreeNodeMouseClickEventArgs e)
  603. {
  604. //Only move once!
  605. treeView1.NodeMouseClick -= treeView1_NodeMouseClick;
  606. UUID id = UUID.Parse (e.Node.Name);
  607. if (m_folderList.ContainsKey (id))
  608. {
  609. InventoryFolderBase newfolder = m_folderList[id];
  610. if (!m_moveContents)
  611. {
  612. if (m_folderList.ContainsKey (m_movingObject))
  613. {
  614. InventoryFolderBase folder = m_folderList[m_movingObject];
  615. //We don't have to move any items, since they all reference the parentID, which is the folder
  616. // and the folder is changing its parentID, which doesn't affect the items
  617. folder.ParentID = id;
  618. }
  619. else
  620. {
  621. //Its an item!
  622. InventoryItemBase item = m_itemList[m_movingObject];
  623. //Remove us from the old folder
  624. m_items[item.Folder].Remove (item);
  625. //Set the new folderID
  626. item.Folder = id;
  627. //Add it in the right place now
  628. if (!m_items.ContainsKey (id))
  629. m_items.Add (id, new List<InventoryItemBase> ());
  630. m_items[id].Add (item);
  631. }
  632. }
  633. else
  634. {
  635. //We need to move all items in this folder, but not the folder itself
  636. MoveFolder (m_movingObject, id);
  637. }
  638. //Update the GUI now
  639. RebuildTreeView ();
  640. }
  641. else
  642. {
  643. //Its an item!
  644. MessageBox.Show ("Select a valid folder.");
  645. treeView1.NodeMouseClick += treeView1_NodeMouseClick;
  646. return;
  647. }
  648. }
  649. private void MoveFolder (UUID id, UUID newID)
  650. {
  651. if (m_items.ContainsKey (id))
  652. {
  653. foreach (InventoryItemBase item in m_items[id])
  654. {
  655. //Set the new folderID
  656. item.Folder = newID;
  657. //Add it in the right place now
  658. if (!m_items.ContainsKey (newID))
  659. m_items.Add (newID, new List<InventoryItemBase> ());
  660. m_items[newID].Add (item);
  661. }
  662. //Remove all items from the original folder
  663. m_items.Remove (m_movingObject);
  664. }
  665. if (m_childFolders.ContainsKey (id))
  666. {
  667. foreach (InventoryFolderBase folder in m_childFolders[id])
  668. {
  669. //Set the new folderID
  670. folder.ParentID = newID;
  671. //Add it in the right place now
  672. if (!m_childFolders.ContainsKey (newID))
  673. m_childFolders.Add (newID, new List<InventoryFolderBase> ());
  674. m_childFolders[newID].Add (folder);
  675. }
  676. //Remove all items from the original folder
  677. m_childFolders.Remove (id);
  678. }
  679. }
  680. private void merge_Click (object sender, EventArgs e)
  681. {
  682. string fileName = SelectTextFile (Environment.CurrentDirectory);
  683. if (fileName != null)
  684. LoadIAR (fileName);
  685. }
  686. private string SelectTextFile (string initialDirectory)
  687. {
  688. OpenFileDialog dialog = new OpenFileDialog ();
  689. dialog.Filter =
  690. "iar files (*.iar)|*.iar|All files (*.*)|*.*";
  691. dialog.InitialDirectory = initialDirectory;
  692. dialog.Title = "Select an iar file";
  693. return (dialog.ShowDialog () == DialogResult.OK)
  694. ? dialog.FileName : null;
  695. }
  696. private string SaveTextFile (string initialDirectory)
  697. {
  698. SaveFileDialog saveFileDialog1 = new SaveFileDialog ();
  699. saveFileDialog1.Filter = "iar files (*.iar)|*.iar|All files (*.*)|*.*";
  700. saveFileDialog1.InitialDirectory = initialDirectory;
  701. saveFileDialog1.Title = "Save an iar file";
  702. return (saveFileDialog1.ShowDialog () == DialogResult.OK)
  703. ? saveFileDialog1.FileName : null;
  704. }
  705. private void save_Click (object sender, EventArgs e)
  706. {
  707. string fileName = SaveTextFile (Environment.CurrentDirectory);
  708. if (fileName != null)
  709. Execute (fileName);
  710. }
  711. private void button2_Click (object sender, EventArgs e)
  712. {
  713. AddAsset assetFinder = new AddAsset (this);
  714. assetFinder.ShowDialog ();
  715. }
  716. public void AddAsset (string id, byte[] data)
  717. {
  718. AssetBase a = new AssetBase (id, "Unknown asset", (sbyte)AssetType.Texture, UUID.Zero);
  719. a.Data = data;
  720. m_loadedAssets[id] = a;
  721. }
  722. #endregion
  723. #region Save IAR
  724. protected TarArchiveWriter m_archiveWriter;
  725. protected void SaveInvItem (InventoryItemBase inventoryItem, string path)
  726. {
  727. string filename = path + CreateArchiveItemName (inventoryItem);
  728. InventoryItemBase saveItem = (InventoryItemBase)inventoryItem.Clone ();
  729. string serialization = UserInventoryItemSerializer.Serialize (saveItem);
  730. m_archiveWriter.WriteFile (filename, serialization);
  731. }
  732. /// <summary>
  733. /// Save an inventory folder
  734. /// </summary>
  735. /// <param name="inventoryFolder">The inventory folder to save</param>
  736. /// <param name="path">The path to which the folder should be saved</param>
  737. /// <param name="saveThisFolderItself">If true, save this folder itself. If false, only saves contents</param>
  738. protected void SaveInvFolder (InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself)
  739. {
  740. if (saveThisFolderItself)
  741. {
  742. path += CreateArchiveFolderName (inventoryFolder);
  743. // We need to make sure that we record empty folders
  744. m_archiveWriter.WriteDir (path);
  745. }
  746. InventoryCollection contents = FindInventoryCollection (inventoryFolder.Owner, inventoryFolder.ID);
  747. foreach (InventoryFolderBase childFolder in contents.Folders)
  748. {
  749. SaveInvFolder (childFolder, path, true);
  750. }
  751. foreach (InventoryItemBase item in contents.Items)
  752. {
  753. SaveInvItem (item, path);
  754. }
  755. }
  756. private InventoryCollection FindInventoryCollection (UUID userID, UUID folderID)
  757. {
  758. InventoryCollection collection = new InventoryCollection();
  759. collection.UserID = userID;
  760. collection.Items = new List<InventoryItemBase> ();
  761. if (m_items.ContainsKey (folderID))
  762. collection.Items = m_items[folderID];
  763. collection.Folders = new List<InventoryFolderBase> ();
  764. if (m_childFolders.ContainsKey (folderID))
  765. collection.Folders = m_childFolders[folderID];
  766. return collection;
  767. }
  768. /// <summary>
  769. /// Execute the inventory write request
  770. /// </summary>
  771. public void Execute (string fileName)
  772. {
  773. Stream m_saveStream = new GZipStream (new FileStream (fileName, FileMode.Create), CompressionMode.Compress);
  774. try
  775. {
  776. InventoryFolderBase inventoryFolder = new InventoryFolderBase (UUID.Zero, UUID.Zero);
  777. if (m_rootFolders.Count == 1)
  778. inventoryFolder = m_rootFolders[0];
  779. bool saveFolderContentsOnly = false;
  780. m_archiveWriter = new TarArchiveWriter (m_saveStream);
  781. if (inventoryFolder != null)
  782. {
  783. //recurse through all dirs getting dirs and files
  784. SaveInvFolder (inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly);
  785. }
  786. }
  787. catch (Exception)
  788. {
  789. m_saveStream.Close ();
  790. throw;
  791. }
  792. foreach (AssetBase asset in m_loadedAssets.Values)
  793. {
  794. WriteData (asset);
  795. }
  796. m_saveStream.Close ();
  797. MessageBox.Show ("Save complete!");
  798. }
  799. protected void WriteData (AssetBase asset)
  800. {
  801. // It appears that gtar, at least, doesn't need the intermediate directory entries in the tar
  802. //archive.AddDir("assets");
  803. string extension = string.Empty;
  804. if (ArchiveConstants.ASSET_TYPE_TO_EXTENSION.ContainsKey (asset.Type))
  805. {
  806. extension = ArchiveConstants.ASSET_TYPE_TO_EXTENSION[asset.Type];
  807. }
  808. else
  809. {
  810. }
  811. m_archiveWriter.WriteFile (
  812. ArchiveConstants.ASSETS_PATH + asset.IDString + extension,
  813. asset.Data);
  814. }
  815. /// <summary>
  816. /// Create the archive name for a particular folder.
  817. /// </summary>
  818. ///
  819. /// These names are prepended with an inventory folder's UUID so that more than one folder can have the
  820. /// same name
  821. ///
  822. /// <param name="folder"></param>
  823. /// <returns></returns>
  824. public static string CreateArchiveFolderName (InventoryFolderBase folder)
  825. {
  826. return CreateArchiveFolderName (folder.Name, folder.ID);
  827. }
  828. /// <summary>
  829. /// Create the archive name for a particular item.
  830. /// </summary>
  831. ///
  832. /// These names are prepended with an inventory item's UUID so that more than one item can have the
  833. /// same name
  834. ///
  835. /// <param name="item"></param>
  836. /// <returns></returns>
  837. public static string CreateArchiveItemName (InventoryItemBase item)
  838. {
  839. return CreateArchiveItemName (item.Name, item.ID);
  840. }
  841. /// <summary>
  842. /// Create an archive folder name given its constituent components
  843. /// </summary>
  844. /// <param name="name"></param>
  845. /// <param name="id"></param>
  846. /// <returns></returns>
  847. public static string CreateArchiveFolderName (string name, UUID id)
  848. {
  849. return string.Format (
  850. "{0}{1}{2}/",
  851. InventoryArchiveUtils.EscapeArchivePath (name),
  852. ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR,
  853. id);
  854. }
  855. /// <summary>
  856. /// Create an archive item name given its constituent components
  857. /// </summary>
  858. /// <param name="name"></param>
  859. /// <param name="id"></param>
  860. /// <returns></returns>
  861. public static string CreateArchiveItemName (string name, UUID id)
  862. {
  863. return string.Format (
  864. "{0}{1}{2}.xml",
  865. InventoryArchiveUtils.EscapeArchivePath (name),
  866. ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR,
  867. id);
  868. }
  869. /// <summary>
  870. /// Create the control file for a 0.1 version archive
  871. /// </summary>
  872. /// <returns></returns>
  873. public static string Create0p1ControlFile ()
  874. {
  875. StringWriter sw = new StringWriter ();
  876. XmlTextWriter xtw = new XmlTextWriter (sw);
  877. xtw.Formatting = Formatting.Indented;
  878. xtw.WriteStartDocument ();
  879. xtw.WriteStartElement ("archive");
  880. xtw.WriteAttributeString ("major_version", "0");
  881. xtw.WriteAttributeString ("minor_version", "1");
  882. xtw.WriteEndElement ();
  883. xtw.Flush ();
  884. xtw.Close ();
  885. String s = sw.ToString ();
  886. sw.Close ();
  887. return s;
  888. }
  889. #endregion
  890. }
  891. }