PageRenderTime 32ms CodeModel.GetById 15ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

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