PageRenderTime 60ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/tools/PhyreFly/src/controls/AssetManager.cs

https://bitbucket.org/drummertom999/phyreballs
C# | 480 lines | 393 code | 66 blank | 21 comment | 48 complexity | 8079e795fb4456030ce72fa1972f3696 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Data;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using System.IO;
  10. using System.Xml.Linq;
  11. using System.Diagnostics;
  12. using System.Threading;
  13. namespace PhyreFly
  14. {
  15. public partial class AssetManager : UserControl
  16. {
  17. #region Node Names
  18. private static string ROOT_NODE = "assets";
  19. private static string OUTPUT_NODE = "output";
  20. private static string ASSET_NODE = "asset";
  21. #endregion
  22. #region Column Names
  23. private const int COL_ICON = 0;
  24. private const int COL_SOURCE = 1;
  25. private const int COL_SYMBOL = 2;
  26. private const int COL_BTN_BUILD = 3;
  27. private const int COL_BTN_REBUILD = 4;
  28. #endregion
  29. public AssetManager(string assetListFilename, string platform, AssetProcessAction action)
  30. {
  31. InitializeComponent();
  32. // Setup globals
  33. PFGlobals.XmlFile = assetListFilename;
  34. PFGlobals.XmlFileDir = Path.GetDirectoryName(assetListFilename);
  35. PFUtils.RemoveReadOnlyFlag(assetListFilename);
  36. // Register for console log events
  37. PFConsole.OnWrite += new PFConsole.OutputFunction(PFConsole_OnWrite);
  38. // Load XML and initialize form
  39. if (!ValidateLoadXmlFile() || !InitForm())
  40. {
  41. PFGlobals.MainWindow.Close();
  42. return;
  43. }
  44. // Validate and set platform
  45. if (platform != null && m_supportedPlatforms.Contains(platform))
  46. {
  47. int count = 1;
  48. foreach(string supportedPlatform in m_supportedPlatforms)
  49. {
  50. if(platform == supportedPlatform)
  51. {
  52. ui_cb_platforms.SelectedIndex = count;
  53. break;
  54. }
  55. ++count;
  56. }
  57. }
  58. // Begin action?
  59. if (action != AssetProcessAction.None)
  60. {
  61. PFAssetProcessor.AutoClose = true;
  62. StartGlobalAction(action);
  63. }
  64. }
  65. #region XML Validate / Load / Save
  66. private bool ValidateLoadXmlFile()
  67. {
  68. try
  69. {
  70. m_assetListFile = XDocument.Load(PFGlobals.XmlFile, LoadOptions.SetLineInfo);
  71. }
  72. catch (Exception e)
  73. {
  74. MessageBox.Show("Could not open file: {0}", e.Message);
  75. return false;
  76. }
  77. if (m_assetListFile.Root.Name != ROOT_NODE)
  78. {
  79. MessageBox.Show(String.Format("Document is missing root node '{0}'", ROOT_NODE));
  80. return false;
  81. }
  82. XElement outputNode = m_assetListFile.Root.Element(OUTPUT_NODE);
  83. if (outputNode == null)
  84. {
  85. MessageBox.Show(String.Format("Document is missing '{0}' node", OUTPUT_NODE));
  86. return false;
  87. }
  88. m_outputAttributes = new PFOutputAttributes(outputNode);
  89. if (!m_outputAttributes.ReadFromFile())
  90. return false;
  91. // Collect Assets
  92. m_assets = (from c in m_assetListFile.Descendants(ASSET_NODE)
  93. select new Asset()
  94. {
  95. Source = c.Attribute("source").Value,
  96. Symbol = c.Attribute("symbol").Value,
  97. }).ToList<Asset>();
  98. return true;
  99. }
  100. private void SaveXmlFile()
  101. {
  102. // Remove nodes from XDocument
  103. foreach (XElement node in m_assetListFile.Descendants(ASSET_NODE).ToList())
  104. node.Remove();
  105. foreach (DataGridViewRow row in ui_dataGrid.Rows)
  106. {
  107. XElement assetNode = new XElement(ASSET_NODE);
  108. assetNode.SetAttributeValue("source", row.Cells[COL_SOURCE].Value);
  109. assetNode.SetAttributeValue("symbol", row.Cells[COL_SYMBOL].Value);
  110. m_assetListFile.Root.Add(assetNode);
  111. }
  112. m_assetListFile.Save(PFGlobals.XmlFile);
  113. }
  114. #endregion
  115. private bool InitForm()
  116. {
  117. try
  118. {
  119. // Dock user control
  120. this.Dock = DockStyle.Fill;
  121. // Register for asset processing events
  122. PFAssetProcessor.OnStart += (PFAssetProcessor.APEvent)delegate()
  123. {
  124. ui_pb_work.Invoke((MethodInvoker)delegate()
  125. {
  126. tableLayoutPanel1.RowStyles[1].Height = 25;
  127. ui_rtb_console.Margin = new Padding(3, 3, 3, 0);
  128. });
  129. };
  130. PFAssetProcessor.OnFinish += (PFAssetProcessor.APEvent)delegate()
  131. {
  132. ui_pb_work.Invoke((MethodInvoker)delegate()
  133. {
  134. ui_rtb_console.Margin = new Padding(3);
  135. tableLayoutPanel1.RowStyles[1].Height = 0;
  136. });
  137. };
  138. // Populate platforms drop-down
  139. ui_cb_platforms.Items.AddRange(m_supportedPlatforms);
  140. ui_cb_platforms.SelectedIndex = 1;
  141. // Initially collapse progress bar
  142. tableLayoutPanel1.RowStyles[1].Height = 0;
  143. // Assign right click menu to console window
  144. ui_rtb_console.ContextMenu = m_cm;
  145. // Bind form elements
  146. ui_tb_output_mode.DataBindings.Add("Text", m_outputAttributes.Mode, "Value");
  147. ui_tb_output_filename.DataBindings.Add("Text", m_outputAttributes.Filename, "Value");
  148. ui_tb_output_rcname.DataBindings.Add("Text", m_outputAttributes.RCName, "Value");
  149. ui_tb_output_filelist.DataBindings.Add("Text", m_outputAttributes.FileList, "Value");
  150. ui_tb_output_pathprefix.DataBindings.Add("Text", m_outputAttributes.PathPrefix, "Value");
  151. // Bind assets to grid view
  152. int count = 0;
  153. foreach (Asset asset in m_assets)
  154. {
  155. ui_dataGrid.Rows.Add(null, asset.Source, asset.Symbol);
  156. ui_dataGrid.Rows[count].Tag = asset;
  157. ++count;
  158. }
  159. m_bLoaded = true;
  160. return true;
  161. }
  162. catch (Exception e)
  163. {
  164. MessageBox.Show("Failed binding data to form: {0}", e.Message);
  165. return false;
  166. }
  167. }
  168. private void StartSingleAction(Asset asset, AssetProcessAction action)
  169. {
  170. if (PFAssetProcessor.IsWorking)
  171. {
  172. PFConsole.WriteLine(PFConsole.Severity.ERROR, "Busy, please wait...");
  173. return;
  174. }
  175. string[] selectedPlatform = new string[] { ui_cb_platforms.SelectedItem.ToString() };
  176. Thread th = new Thread(delegate()
  177. {
  178. foreach (string platformName in ((selectedPlatform[0] == "All Platforms") ? m_supportedPlatforms : selectedPlatform))
  179. PFAssetProcessor.ProcessSingleAsset(asset.Source, platformName, action);
  180. });
  181. th.Name = string.Format("Process Single Asset [{0}|{1}|{2}]", Path.GetFileName(asset.Source), selectedPlatform[0], action.ToString());
  182. th.Start();
  183. }
  184. private void StartGlobalAction(AssetProcessAction action)
  185. {
  186. if (PFAssetProcessor.IsWorking)
  187. {
  188. PFConsole.WriteLine(PFConsole.Severity.ERROR, "Busy, please wait...");
  189. return;
  190. }
  191. // Perform some sanity checks on all asset files
  192. SortedSet<string> symbolNameList = new SortedSet<string>();
  193. foreach (Asset asset in m_assets)
  194. {
  195. // Make sure asset exists on disk
  196. if (!PFUtils.EnsureAssetExists(asset.Source))
  197. return;
  198. // Check for duplicate symbol names
  199. if (!symbolNameList.Add(asset.Symbol))
  200. {
  201. MessageBox.Show(String.Format("Error: The symbol name {0} was used more than once", asset.Symbol));
  202. return;
  203. }
  204. }
  205. // Save XML file
  206. SaveXmlFile();
  207. // Begin global build (per chosen platform) on new thread
  208. string[] selectedPlatform = new string[] { ui_cb_platforms.SelectedItem.ToString() };
  209. Thread th = new Thread(delegate()
  210. {
  211. foreach (string platformName in ((selectedPlatform[0] == "All Platforms") ? m_supportedPlatforms : selectedPlatform))
  212. {
  213. PFAssetProcessor.ProcessAllAssets(PFGlobals.XmlFile, platformName, action);
  214. while (PFAssetProcessor.IsWorking)
  215. Thread.Sleep(300);
  216. }
  217. });
  218. th.Name = string.Format("Process All Assets [{0}|{1}]", selectedPlatform[0], action.ToString());
  219. th.Start();
  220. }
  221. #region Path Helpers
  222. public static bool HasRelativePaths()
  223. {
  224. foreach (Asset asset in m_assets)
  225. {
  226. if (!PFUtils.PathIsAbsolute(asset.Source))
  227. return true;
  228. }
  229. return false;
  230. }
  231. public static string FindAnAbsolutePath()
  232. {
  233. foreach (Asset asset in m_assets)
  234. {
  235. if (PFUtils.PathIsAbsolute(asset.Source))
  236. return asset.Source;
  237. }
  238. return string.Empty;
  239. }
  240. public static string FindARelativePath()
  241. {
  242. foreach (Asset asset in m_assets)
  243. {
  244. if (!PFUtils.PathIsAbsolute(asset.Source))
  245. return asset.Source;
  246. }
  247. return string.Empty;
  248. }
  249. public static string GetProjectRoot()
  250. {
  251. string startPath = FindAnAbsolutePath();
  252. if (startPath == string.Empty)
  253. {
  254. startPath = FindARelativePath();
  255. string workingDir = string.Empty;
  256. PFAssetProcessor.GetWorkingDir(ref workingDir);
  257. startPath = Path.Combine(workingDir, startPath);
  258. }
  259. // Should now have an absolute path to an asset. If not, user error!
  260. startPath = PFUtils.TidyPath(startPath);
  261. if (!File.Exists(startPath))
  262. {
  263. string msg = "There was an error finding the project root. ";
  264. msg += String.Format("Ensure that the working dir and '{0}' are set up correctly", PFGlobals.AssetSpecFile);
  265. MessageBox.Show(msg);
  266. PFAssetProcessor.WorkingDir = string.Empty;
  267. return string.Empty;
  268. }
  269. // Search back up directory tree to find Globals.AssetSpecFile
  270. while (startPath.Contains("\\"))
  271. {
  272. startPath = startPath.Substring(0, startPath.LastIndexOf("\\"));
  273. string testPath = Path.Combine(startPath, PFGlobals.AssetSpecFile);
  274. if (File.Exists(testPath))
  275. return startPath; // Found asset spec file
  276. }
  277. return string.Empty;
  278. }
  279. #endregion
  280. #region Form Events
  281. private void AssetManager_Load(object sender, EventArgs e)
  282. {
  283. GetProjectRoot();
  284. }
  285. private void ui_btn_save_Click(object sender, EventArgs e)
  286. {
  287. SaveXmlFile();
  288. }
  289. private void ui_btn_open_header_Click(object sender, EventArgs e)
  290. {
  291. string headerFilename = Path.Combine(PFGlobals.XmlFileDir, m_outputAttributes.Filename.Value);
  292. if (File.Exists(headerFilename))
  293. Process.Start(PFGlobals.TextEditor, headerFilename);
  294. }
  295. private void ui_btn_open_xml_Click(object sender, EventArgs e)
  296. {
  297. if (File.Exists(PFGlobals.XmlFile))
  298. Process.Start(PFGlobals.TextEditor, PFGlobals.XmlFile);
  299. }
  300. private void ui_cb_platforms_KeyDown(object sender, KeyEventArgs e)
  301. {
  302. e.SuppressKeyPress = true;
  303. }
  304. private void ui_btn_build_all_Click(object sender, EventArgs e)
  305. {
  306. StartGlobalAction(AssetProcessAction.Build);
  307. }
  308. private void ui_btn_rebuild_all_Click(object sender, EventArgs e)
  309. {
  310. StartGlobalAction(AssetProcessAction.Rebuild);
  311. }
  312. private void ui_btn_clean_all_Click(object sender, EventArgs e)
  313. {
  314. StartGlobalAction(AssetProcessAction.Clean);
  315. }
  316. private void ui_dataGrid_CellValueChanged(object sender, DataGridViewCellEventArgs e)
  317. {
  318. if (!m_bLoaded)
  319. return;
  320. Asset asset = ui_dataGrid.Rows[e.RowIndex].Tag as Asset;
  321. asset.Source = ui_dataGrid.Rows[e.RowIndex].Cells[COL_SOURCE].Value.ToString();
  322. asset.Symbol = ui_dataGrid.Rows[e.RowIndex].Cells[COL_SYMBOL].Value.ToString();
  323. }
  324. private void ui_dataGrid_CellClick(object sender, DataGridViewCellEventArgs e)
  325. {
  326. if ((e.ColumnIndex != COL_BTN_BUILD && e.ColumnIndex != COL_BTN_REBUILD) || e.RowIndex == -1)
  327. return;
  328. Asset asset = ui_dataGrid.Rows[e.RowIndex].Tag as Asset;
  329. if(asset != null)
  330. StartSingleAction(asset, (e.ColumnIndex == COL_BTN_BUILD) ? AssetProcessAction.Build : AssetProcessAction.Rebuild);
  331. }
  332. private void ui_btn_add_asset_Click(object sender, EventArgs e)
  333. {
  334. if (PFAssetProcessor.IsWorking)
  335. {
  336. PFConsole.WriteLine(PFConsole.Severity.ERROR, "Busy, please wait...");
  337. return;
  338. }
  339. Asset newAsset = new Asset();
  340. newAsset.Source = "MyAsset.dae";
  341. newAsset.Symbol = "g_myAssetIndex";
  342. m_assets.Add(newAsset);
  343. ui_dataGrid.Rows.Add(null, newAsset.Source, newAsset.Symbol);
  344. ui_dataGrid.Rows[ui_dataGrid.Rows.Count-1].Tag = newAsset;
  345. }
  346. private void ui_dataGrid_UserDeletedRow(object sender, DataGridViewRowEventArgs e)
  347. {
  348. Asset removedAsset = e.Row.Tag as Asset;
  349. m_assets.Remove(removedAsset);
  350. }
  351. private void ui_btn_show_info_Click(object sender, EventArgs e)
  352. {
  353. new InfoForm().ShowDialog();
  354. }
  355. void PFConsole_OnWrite(Color severity, string msg, params object[] args)
  356. {
  357. ui_rtb_console.Invoke((MethodInvoker) delegate()
  358. {
  359. ui_rtb_console.SelectionStart = ui_rtb_console.Text.Length;
  360. ui_rtb_console.SelectionColor = severity;
  361. ui_rtb_console.AppendText(String.Format(msg, args));
  362. ui_rtb_console.SelectionStart = ui_rtb_console.Text.Length;
  363. ui_rtb_console.ScrollToCaret();
  364. });
  365. }
  366. private void ui_rtb_console_MouseDown(object sender, MouseEventArgs e)
  367. {
  368. if (e.Button == MouseButtons.Right)
  369. {
  370. m_cm.MenuItems.Clear();
  371. if (ui_rtb_console.SelectionLength == 0)
  372. {
  373. if (ui_rtb_console.Text.Length != 0)
  374. {
  375. MenuItem mi = new MenuItem("Clear");
  376. mi.Click += new EventHandler(ConsoleRightClick_Clear);
  377. m_cm.MenuItems.Add(mi);
  378. }
  379. }
  380. else
  381. {
  382. MenuItem mi = new MenuItem("Copy");
  383. mi.Click += new EventHandler(ConsoleRightClick_Copy);
  384. m_cm.MenuItems.Add(mi);
  385. }
  386. m_cm.Show(ui_rtb_console, ui_rtb_console.PointToClient(MousePosition));
  387. }
  388. }
  389. void ConsoleRightClick_Copy(object sender, EventArgs e)
  390. {
  391. Clipboard.SetData(DataFormats.Text, ui_rtb_console.SelectedText);
  392. }
  393. void ConsoleRightClick_Clear(object sender, EventArgs e)
  394. {
  395. ui_rtb_console.Text = string.Empty;
  396. }
  397. #endregion
  398. private static List<Asset> m_assets;
  399. private static ContextMenu m_cm = new ContextMenu();
  400. private static XDocument m_assetListFile;
  401. private static PFOutputAttributes m_outputAttributes;
  402. public static PFOutputAttributes OutputAttributes
  403. {
  404. get { return m_outputAttributes; }
  405. }
  406. private static string[] m_supportedPlatforms = { "GL", "GXM", "GCM", "GLx64"};
  407. private bool m_bLoaded = false;
  408. }
  409. public class Asset
  410. {
  411. public string Source;
  412. public string Symbol;
  413. }
  414. }