diff --git a/renderdocui/Code/Helpers.cs b/renderdocui/Code/Helpers.cs
index 5214dccf8..10f68604e 100644
--- a/renderdocui/Code/Helpers.cs
+++ b/renderdocui/Code/Helpers.cs
@@ -132,6 +132,11 @@ namespace renderdocui.Code
return ret;
}
+ public static bool IsAlpha(this char c)
+ {
+ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+ }
+
public static string SafeGetFileName(string filename)
{
try
diff --git a/renderdocui/Code/RenderManager.cs b/renderdocui/Code/RenderManager.cs
index 9bb790b4b..822ee09c9 100644
--- a/renderdocui/Code/RenderManager.cs
+++ b/renderdocui/Code/RenderManager.cs
@@ -145,6 +145,36 @@ namespace renderdocui.Code
return new string[0];
}
+ public delegate void DirectoryBrowseMethod(string path, DirectoryFile[] contents);
+
+ public void GetHomeFolder(DirectoryBrowseMethod cb)
+ {
+ if (m_Remote != null)
+ {
+ if (Running && m_Thread != Thread.CurrentThread)
+ {
+ BeginInvoke((ReplayRenderer r) => { cb(m_Remote.GetHomeFolder(), null); });
+ return;
+ }
+
+ cb(m_Remote.GetHomeFolder(), null);
+ }
+ }
+
+ public void ListFolder(string path, DirectoryBrowseMethod cb)
+ {
+ if (m_Remote != null)
+ {
+ if (Running && m_Thread != Thread.CurrentThread)
+ {
+ BeginInvoke((ReplayRenderer r) => { cb(path, m_Remote.ListFolder(path)); });
+ return;
+ }
+
+ cb(path, m_Remote.ListFolder(path));
+ }
+ }
+
public string CopyCaptureToRemote(string localpath, Form window)
{
if (m_Remote != null)
diff --git a/renderdocui/Properties/Resources.Designer.cs b/renderdocui/Properties/Resources.Designer.cs
index 7859af013..03a609fe6 100644
--- a/renderdocui/Properties/Resources.Designer.cs
+++ b/renderdocui/Properties/Resources.Designer.cs
@@ -140,6 +140,16 @@ namespace renderdocui.Properties {
}
}
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap back {
+ get {
+ object obj = ResourceManager.GetObject("back", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Looks up a localized resource of type System.Drawing.Bitmap.
///
@@ -280,6 +290,16 @@ namespace renderdocui.Properties {
}
}
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap forward {
+ get {
+ object obj = ResourceManager.GetObject("forward", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Looks up a localized resource of type System.Drawing.Bitmap.
///
@@ -610,6 +630,16 @@ namespace renderdocui.Properties {
}
}
+ ///
+ /// Looks up a localized resource of type System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap upfolder {
+ get {
+ object obj = ResourceManager.GetObject("upfolder", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
///
/// Looks up a localized resource of type System.Drawing.Bitmap.
///
diff --git a/renderdocui/Properties/Resources.resx b/renderdocui/Properties/Resources.resx
index fcfdb9e1d..972fd251f 100644
--- a/renderdocui/Properties/Resources.resx
+++ b/renderdocui/Properties/Resources.resx
@@ -295,4 +295,13 @@
..\Resources\house.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+ ..\Resources\back.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\forward.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\upfolder.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
\ No newline at end of file
diff --git a/renderdocui/Resources/back.png b/renderdocui/Resources/back.png
new file mode 100644
index 000000000..5ab6096ad
Binary files /dev/null and b/renderdocui/Resources/back.png differ
diff --git a/renderdocui/Resources/forward.png b/renderdocui/Resources/forward.png
new file mode 100644
index 000000000..3eefcde92
Binary files /dev/null and b/renderdocui/Resources/forward.png differ
diff --git a/renderdocui/Resources/upfolder.png b/renderdocui/Resources/upfolder.png
new file mode 100644
index 000000000..2e7a88087
Binary files /dev/null and b/renderdocui/Resources/upfolder.png differ
diff --git a/renderdocui/Windows/Dialogs/CaptureDialog.cs b/renderdocui/Windows/Dialogs/CaptureDialog.cs
index 71220a37d..54059ffd2 100644
--- a/renderdocui/Windows/Dialogs/CaptureDialog.cs
+++ b/renderdocui/Windows/Dialogs/CaptureDialog.cs
@@ -365,7 +365,17 @@ namespace renderdocui.Windows.Dialogs
// invalid path or similar
}
- exeBrowser.ShowDialog();
+ if (m_Core.Renderer.Remote == null)
+ {
+ exeBrowser.ShowDialog();
+ }
+ else
+ {
+ VirtualOpenFileDialog remoteBrowser = new VirtualOpenFileDialog(m_Core.Renderer);
+ remoteBrowser.Opened += new EventHandler(this.virtualExeBrowser_Opened);
+
+ remoteBrowser.ShowDialog(this);
+ }
}
private void exeBrowser_FileOk(object sender, CancelEventArgs e)
@@ -373,6 +383,13 @@ namespace renderdocui.Windows.Dialogs
SetExecutableFilename(exeBrowser.FileName);
}
+ private void virtualExeBrowser_Opened(object sender, FileOpenedEventArgs e)
+ {
+ exePath.Text = e.FileName;
+
+ UpdateWorkDirHint();
+ }
+
private void exePath_DragEnter(object sender, DragEventArgs e)
{
if (ValidData(e.Data).Length > 0)
@@ -406,14 +423,33 @@ namespace renderdocui.Windows.Dialogs
// invalid path or similar
}
- var res = workDirBrowser.ShowDialog();
-
- if (res == DialogResult.Yes || res == DialogResult.OK)
+ if (m_Core.Renderer.Remote == null)
{
- workDirPath.Text = workDirBrowser.SelectedPath;
- workDirHint = false;
- workDirPath.ForeColor = SystemColors.WindowText;
+ var res = workDirBrowser.ShowDialog();
+
+ if (res == DialogResult.Yes || res == DialogResult.OK)
+ {
+ workDirPath.Text = workDirBrowser.SelectedPath;
+ workDirHint = false;
+ workDirPath.ForeColor = SystemColors.WindowText;
+ }
}
+ else
+ {
+ VirtualOpenFileDialog remoteBrowser = new VirtualOpenFileDialog(m_Core.Renderer);
+ remoteBrowser.Opened += new EventHandler(this.virtualWorkDirBrowser_Opened);
+
+ remoteBrowser.DirectoryBrowse = true;
+
+ remoteBrowser.ShowDialog(this);
+ }
+ }
+
+ private void virtualWorkDirBrowser_Opened(object sender, FileOpenedEventArgs e)
+ {
+ workDirPath.Text = e.FileName;
+ workDirHint = false;
+ workDirPath.ForeColor = SystemColors.WindowText;
}
private void workDirPath_TextChanged(object sender, EventArgs e)
diff --git a/renderdocui/Windows/Dialogs/VirtualOpenFileDialog.Designer.cs b/renderdocui/Windows/Dialogs/VirtualOpenFileDialog.Designer.cs
new file mode 100644
index 000000000..f8a405714
--- /dev/null
+++ b/renderdocui/Windows/Dialogs/VirtualOpenFileDialog.Designer.cs
@@ -0,0 +1,319 @@
+namespace renderdocui.Windows.Dialogs
+{
+ partial class VirtualOpenFileDialog
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ this.components = new System.ComponentModel.Container();
+ System.Windows.Forms.TableLayoutPanel mainTable;
+ System.Windows.Forms.ToolStrip toolStrip;
+ System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+ System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
+ System.Windows.Forms.ToolStripLabel locLabel;
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(VirtualOpenFileDialog));
+ System.Windows.Forms.Label fnLabel;
+ System.Windows.Forms.Button cancel;
+ this.back = new System.Windows.Forms.ToolStripButton();
+ this.forward = new System.Windows.Forms.ToolStripButton();
+ this.up = new System.Windows.Forms.ToolStripButton();
+ this.location = new renderdocui.Controls.ToolStripSpringTextBox();
+ this.directoryTree = new System.Windows.Forms.TreeView();
+ this.iconList = new System.Windows.Forms.ImageList(this.components);
+ this.fileList = new System.Windows.Forms.ListView();
+ this.filename = new System.Windows.Forms.TextBox();
+ this.fileType = new System.Windows.Forms.ComboBox();
+ this.open = new System.Windows.Forms.Button();
+ this.showHidden = new System.Windows.Forms.CheckBox();
+ mainTable = new System.Windows.Forms.TableLayoutPanel();
+ toolStrip = new System.Windows.Forms.ToolStrip();
+ toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+ toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
+ locLabel = new System.Windows.Forms.ToolStripLabel();
+ fnLabel = new System.Windows.Forms.Label();
+ cancel = new System.Windows.Forms.Button();
+ mainTable.SuspendLayout();
+ toolStrip.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // mainTable
+ //
+ mainTable.ColumnCount = 4;
+ mainTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ mainTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ mainTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ mainTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle());
+ mainTable.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
+ mainTable.Controls.Add(toolStrip, 0, 0);
+ mainTable.Controls.Add(this.directoryTree, 0, 1);
+ mainTable.Controls.Add(this.fileList, 1, 1);
+ mainTable.Controls.Add(fnLabel, 0, 3);
+ mainTable.Controls.Add(this.filename, 1, 3);
+ mainTable.Controls.Add(this.fileType, 2, 3);
+ mainTable.Controls.Add(this.open, 2, 4);
+ mainTable.Controls.Add(cancel, 3, 4);
+ mainTable.Controls.Add(this.showHidden, 1, 4);
+ mainTable.Dock = System.Windows.Forms.DockStyle.Fill;
+ mainTable.Location = new System.Drawing.Point(0, 0);
+ mainTable.Margin = new System.Windows.Forms.Padding(3, 3, 3, 0);
+ mainTable.Name = "mainTable";
+ mainTable.RowCount = 5;
+ mainTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ mainTable.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ mainTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ mainTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ mainTable.RowStyles.Add(new System.Windows.Forms.RowStyle());
+ mainTable.Size = new System.Drawing.Size(764, 486);
+ mainTable.TabIndex = 0;
+ //
+ // toolStrip
+ //
+ toolStrip.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ mainTable.SetColumnSpan(toolStrip, 4);
+ toolStrip.Dock = System.Windows.Forms.DockStyle.None;
+ toolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
+ toolStrip.ImageScalingSize = new System.Drawing.Size(24, 24);
+ toolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.back,
+ this.forward,
+ toolStripSeparator1,
+ this.up,
+ toolStripSeparator2,
+ locLabel,
+ this.location});
+ toolStrip.Location = new System.Drawing.Point(0, 0);
+ toolStrip.Name = "toolStrip";
+ toolStrip.Size = new System.Drawing.Size(764, 31);
+ toolStrip.TabIndex = 3;
+ toolStrip.Text = "toolStrip1";
+ //
+ // back
+ //
+ this.back.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.back.Image = global::renderdocui.Properties.Resources.back;
+ this.back.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.back.Margin = new System.Windows.Forms.Padding(0, 1, 5, 2);
+ this.back.Name = "back";
+ this.back.Size = new System.Drawing.Size(28, 28);
+ this.back.Click += new System.EventHandler(this.back_Click);
+ //
+ // forward
+ //
+ this.forward.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.forward.Image = global::renderdocui.Properties.Resources.forward;
+ this.forward.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.forward.Name = "forward";
+ this.forward.Size = new System.Drawing.Size(28, 28);
+ this.forward.Click += new System.EventHandler(this.forward_Click);
+ //
+ // toolStripSeparator1
+ //
+ toolStripSeparator1.Name = "toolStripSeparator1";
+ toolStripSeparator1.Size = new System.Drawing.Size(6, 31);
+ //
+ // up
+ //
+ this.up.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this.up.Image = global::renderdocui.Properties.Resources.upfolder;
+ this.up.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this.up.Name = "up";
+ this.up.Size = new System.Drawing.Size(28, 28);
+ this.up.Click += new System.EventHandler(this.up_Click);
+ //
+ // toolStripSeparator2
+ //
+ toolStripSeparator2.Name = "toolStripSeparator2";
+ toolStripSeparator2.Size = new System.Drawing.Size(6, 31);
+ //
+ // locLabel
+ //
+ locLabel.Name = "locLabel";
+ locLabel.Size = new System.Drawing.Size(51, 28);
+ locLabel.Text = "Location:";
+ //
+ // location
+ //
+ this.location.Name = "location";
+ this.location.Size = new System.Drawing.Size(578, 31);
+ this.location.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.location_KeyPress);
+ //
+ // directoryTree
+ //
+ this.directoryTree.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.directoryTree.FullRowSelect = true;
+ this.directoryTree.HideSelection = false;
+ this.directoryTree.HotTracking = true;
+ this.directoryTree.ImageIndex = 2;
+ this.directoryTree.ImageList = this.iconList;
+ this.directoryTree.Location = new System.Drawing.Point(3, 34);
+ this.directoryTree.Name = "directoryTree";
+ this.directoryTree.PathSeparator = "/";
+ this.directoryTree.SelectedImageIndex = 0;
+ this.directoryTree.Size = new System.Drawing.Size(251, 381);
+ this.directoryTree.TabIndex = 5;
+ this.directoryTree.BeforeExpand += new System.Windows.Forms.TreeViewCancelEventHandler(this.directoryTree_BeforeExpand);
+ this.directoryTree.BeforeSelect += new System.Windows.Forms.TreeViewCancelEventHandler(this.directoryTree_BeforeSelect);
+ //
+ // iconList
+ //
+ this.iconList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("iconList.ImageStream")));
+ this.iconList.TransparentColor = System.Drawing.Color.Transparent;
+ this.iconList.Images.SetKeyName(0, "drive");
+ this.iconList.Images.SetKeyName(1, "folder");
+ this.iconList.Images.SetKeyName(2, "folder_faded");
+ this.iconList.Images.SetKeyName(3, "file");
+ this.iconList.Images.SetKeyName(4, "file_faded");
+ this.iconList.Images.SetKeyName(5, "executable");
+ this.iconList.Images.SetKeyName(6, "executable_faded");
+ //
+ // fileList
+ //
+ mainTable.SetColumnSpan(this.fileList, 3);
+ this.fileList.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.fileList.Location = new System.Drawing.Point(260, 34);
+ this.fileList.Name = "fileList";
+ this.fileList.Size = new System.Drawing.Size(501, 381);
+ this.fileList.SmallImageList = this.iconList;
+ this.fileList.TabIndex = 6;
+ this.fileList.UseCompatibleStateImageBehavior = false;
+ this.fileList.View = System.Windows.Forms.View.List;
+ this.fileList.SelectedIndexChanged += new System.EventHandler(this.fileList_SelectedIndexChanged);
+ this.fileList.DoubleClick += new System.EventHandler(this.fileList_DoubleClick);
+ //
+ // fnLabel
+ //
+ fnLabel.Anchor = System.Windows.Forms.AnchorStyles.Right;
+ fnLabel.AutoSize = true;
+ fnLabel.Location = new System.Drawing.Point(205, 425);
+ fnLabel.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
+ fnLabel.Name = "fnLabel";
+ fnLabel.Size = new System.Drawing.Size(52, 13);
+ fnLabel.TabIndex = 7;
+ fnLabel.Text = "Filename:";
+ fnLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // filename
+ //
+ this.filename.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.filename.Location = new System.Drawing.Point(260, 421);
+ this.filename.Margin = new System.Windows.Forms.Padding(3, 3, 15, 3);
+ this.filename.Name = "filename";
+ this.filename.Size = new System.Drawing.Size(315, 20);
+ this.filename.TabIndex = 8;
+ this.filename.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.filename_KeyPress);
+ //
+ // fileType
+ //
+ this.fileType.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ mainTable.SetColumnSpan(this.fileType, 2);
+ this.fileType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.fileType.FormattingEnabled = true;
+ this.fileType.Items.AddRange(new object[] {
+ "Executables",
+ "All Files"});
+ this.fileType.Location = new System.Drawing.Point(593, 421);
+ this.fileType.Margin = new System.Windows.Forms.Padding(3, 3, 15, 3);
+ this.fileType.Name = "fileType";
+ this.fileType.Size = new System.Drawing.Size(156, 21);
+ this.fileType.TabIndex = 9;
+ this.fileType.SelectedIndexChanged += new System.EventHandler(this.fileType_SelectedIndexChanged);
+ //
+ // open
+ //
+ this.open.Location = new System.Drawing.Point(593, 448);
+ this.open.Name = "open";
+ this.open.Size = new System.Drawing.Size(75, 23);
+ this.open.TabIndex = 10;
+ this.open.Text = "Open";
+ this.open.UseVisualStyleBackColor = true;
+ this.open.Click += new System.EventHandler(this.open_Click);
+ //
+ // cancel
+ //
+ cancel.Location = new System.Drawing.Point(674, 448);
+ cancel.Margin = new System.Windows.Forms.Padding(3, 3, 15, 15);
+ cancel.Name = "cancel";
+ cancel.Size = new System.Drawing.Size(75, 23);
+ cancel.TabIndex = 11;
+ cancel.Text = "Cancel";
+ cancel.UseVisualStyleBackColor = true;
+ cancel.Click += new System.EventHandler(this.cancel_Click);
+ //
+ // showHidden
+ //
+ this.showHidden.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this.showHidden.AutoSize = true;
+ this.showHidden.Location = new System.Drawing.Point(466, 451);
+ this.showHidden.Margin = new System.Windows.Forms.Padding(3, 6, 15, 3);
+ this.showHidden.Name = "showHidden";
+ this.showHidden.Size = new System.Drawing.Size(109, 17);
+ this.showHidden.TabIndex = 12;
+ this.showHidden.Text = "Show hidden files";
+ this.showHidden.UseVisualStyleBackColor = true;
+ this.showHidden.CheckedChanged += new System.EventHandler(this.showHidden_CheckedChanged);
+ //
+ // VirtualOpenFileDialog
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(764, 486);
+ this.Controls.Add(mainTable);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "VirtualOpenFileDialog";
+ this.ShowInTaskbar = false;
+ this.Text = "Open";
+ this.Load += new System.EventHandler(this.VirtualOpenFileDialog_Load);
+ mainTable.ResumeLayout(false);
+ mainTable.PerformLayout();
+ toolStrip.ResumeLayout(false);
+ toolStrip.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.TreeView directoryTree;
+ private System.Windows.Forms.ListView fileList;
+ private System.Windows.Forms.ImageList iconList;
+ private System.Windows.Forms.TextBox filename;
+ private System.Windows.Forms.ComboBox fileType;
+ private System.Windows.Forms.CheckBox showHidden;
+ private renderdocui.Controls.ToolStripSpringTextBox location;
+ private System.Windows.Forms.ToolStripButton back;
+ private System.Windows.Forms.ToolStripButton forward;
+ private System.Windows.Forms.ToolStripButton up;
+ private System.Windows.Forms.Button open;
+
+ }
+}
\ No newline at end of file
diff --git a/renderdocui/Windows/Dialogs/VirtualOpenFileDialog.cs b/renderdocui/Windows/Dialogs/VirtualOpenFileDialog.cs
new file mode 100644
index 000000000..5fec683e7
--- /dev/null
+++ b/renderdocui/Windows/Dialogs/VirtualOpenFileDialog.cs
@@ -0,0 +1,659 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Windows.Forms;
+using renderdoc;
+using renderdocui.Code;
+using System.Text.RegularExpressions;
+
+namespace renderdocui.Windows.Dialogs
+{
+ public partial class VirtualOpenFileDialog : Form
+ {
+ private const int ICON_DRIVE = 0;
+ private const int ICON_DIRECTORY = 1;
+ private const int ICON_DIRECTORY_FADED = 2;
+ private const int ICON_FILE = 3;
+ private const int ICON_FILE_FADED = 4;
+ private const int ICON_EXECUTABLE = 5;
+ private const int ICON_EXECUTABLE_FADED = 6;
+
+ private const int TYPE_EXES = 0;
+ private const int TYPE_ALL = 1;
+
+ private RenderManager m_RM = null;
+ private List currentFiles = new List();
+ private string currentDir = "";
+ private List history = new List();
+ private int historyidx = 0;
+
+ private List roots = new List();
+
+ #region Events
+
+ private static readonly object FileOkEvent = new object();
+ public event EventHandler Opened
+ {
+ add { Events.AddHandler(FileOkEvent, value); }
+ remove { Events.RemoveHandler(FileOkEvent, value); }
+ }
+ protected virtual void OnOpened(FileOpenedEventArgs e)
+ {
+ EventHandler handler = (EventHandler)Events[FileOkEvent];
+ if (handler != null)
+ handler(this, e);
+ }
+
+ #endregion
+
+ public VirtualOpenFileDialog(RenderManager rm)
+ {
+ InitializeComponent();
+
+ m_RM = rm;
+
+ showHidden.Checked = false;
+ fileType.SelectedIndex = 0;
+ back.Enabled = forward.Enabled = up.Enabled = false;
+ }
+
+ private string Directory { get { return NTPaths ? currentDir.Replace('/', '\\') : currentDir; } }
+ private string FileName { get { return filename.Text.Trim(); } }
+
+ private bool m_DirBrowse = false;
+ public bool DirectoryBrowse
+ {
+ set
+ {
+ m_DirBrowse = value;
+ Text = "Browse for folder";
+ open.Text = "Select folder";
+ }
+ }
+
+ public string ChosenPath
+ {
+ get
+ {
+ return Directory + (NTPaths ? "\\" : "/") + FileName;
+ }
+ }
+
+ private bool NTPaths = false;
+
+ private bool IsRoot
+ {
+ get
+ {
+ // X: (we remove trailing slashes)
+ return NTPaths ? currentDir.Length == 2 : currentDir == "/";
+ }
+ }
+
+ private DirectoryFileTreeNode GetNode(string path)
+ {
+ if (NTPaths)
+ {
+ for (int i = 0; i < roots.Count; i++)
+ {
+ if (roots[i].Filename == path)
+ return roots[i];
+
+ if (roots[i].Filename[0] == path[0])
+ return roots[i].GetNode(path.Substring(3));
+ }
+
+ return null;
+ }
+ else
+ {
+ if (path == "/" || path == "")
+ return roots[0];
+
+ return roots[0].GetNode(path.Substring(1));
+ }
+ }
+
+ private void InitialPopulate()
+ {
+ bool populated = false;
+
+ m_RM.GetHomeFolder((string path, DirectoryFile[] f) =>
+ {
+ currentDir = path;
+ history.Add(currentDir);
+
+ // check if we're NT paths or unix paths, and populate the roots
+ if (currentDir[0].IsAlpha() && currentDir[1] == ':')
+ {
+ NTPaths = true;
+
+ m_RM.ListFolder("/", (string p, DirectoryFile[] files) =>
+ {
+ foreach (var root in files)
+ {
+ DirectoryFileTreeNode node = new DirectoryFileTreeNode();
+ node.Path = node.Filename = root.filename;
+ node.IsDirectory = true;
+ roots.Add(node);
+
+ m_RM.ListFolder(root.filename, (string a, DirectoryFile[] b) => { node.Populate(a, b); });
+ }
+ });
+ }
+ else
+ {
+ NTPaths = false;
+
+ DirectoryFileTreeNode node = new DirectoryFileTreeNode();
+ node.Path = node.Filename = "/";
+ node.IsDirectory = true;
+ roots.Add(node);
+ m_RM.ListFolder("/", (string a, DirectoryFile[] b) => { node.Populate(a, b); });
+ }
+
+ // we will populate the rest of the folders when expanding to the current directory
+
+ populated = true;
+
+ BeginInvoke(new Action(UpdateViewsFromData));
+ });
+
+ // wait a second for the results to come in
+ SpinWait.SpinUntil((Func)(() => { return populated; }), 1000);
+ }
+
+ private void PopulateNode(TreeNode treenode)
+ {
+ DirectoryFileTreeNode node = treenode.Tag as DirectoryFileTreeNode;
+
+ if (node.ChildrenPopulated || node.children.Count == 0)
+ return;
+
+ node.ChildrenPopulated = true;
+
+ m_RM.ListFolder(node.children[0].Path, (string path, DirectoryFile[] files) =>
+ {
+ node.children[0].Populate(path, files);
+
+ // do the rest on-thread
+ for(int i = 1; i < node.children.Count; i++)
+ {
+ if (!node.children[i].IsDirectory || node.children[i].HasPopulated)
+ continue;
+
+ m_RM.ListFolder(node.children[i].Path, (string a, DirectoryFile[] b) =>
+ {
+ node.children[i].Populate(a, b);
+ });
+ }
+ });
+
+ BeginInvoke(new Action(UpdateViewsFromData));
+ }
+
+ private void AddDirTreeNodeRecursive(DirectoryFileTreeNode node, TreeNode parent)
+ {
+ if (!node.IsDirectory)
+ return;
+
+ if (node.directoryNode == null)
+ {
+ TreeNode treenode = new TreeNode();
+ treenode.Text = node.Filename;
+ treenode.SelectedImageIndex = treenode.ImageIndex = ICON_DIRECTORY;
+ treenode.Tag = node;
+ node.directoryNode = treenode;
+
+ parent.Nodes.Add(treenode);
+ }
+
+ foreach (var child in node.children)
+ {
+ AddDirTreeNodeRecursive(child, node.directoryNode);
+ }
+ }
+
+ private void UpdateViewsFromData()
+ {
+ location.Text = Directory;
+
+ directoryTree.BeginUpdate();
+
+ foreach (var root in roots)
+ {
+ if (root.directoryNode == null)
+ {
+ TreeNode treenode = new TreeNode();
+ treenode.Text = root.Filename;
+ treenode.SelectedImageIndex = treenode.ImageIndex = ICON_DRIVE;
+ treenode.Tag = root;
+ root.directoryNode = treenode;
+
+ directoryTree.Nodes.Add(treenode);
+ }
+
+ AddDirTreeNodeRecursive(root, root.directoryNode);
+ }
+
+ directoryTree.EndUpdate();
+
+ string[] components = Directory.Split('/');
+
+ // expand down to the current directory
+ for (int i = 1; i < components.Length; i++)
+ {
+ string dir = NTPaths ? components[0] : "";
+
+ for (int j = 1; j < i; j++)
+ dir += "/" + components[j];
+
+ if (dir == "")
+ dir = "/";
+
+ DirectoryFileTreeNode node = GetNode(dir);
+ node.directoryNode.Expand();
+ }
+
+ directoryTree.SelectedNode = GetNode(Directory).directoryNode;
+
+ UpdateFileList();
+
+ up.Enabled = !IsRoot;
+ back.Enabled = history.Count > 0 && historyidx > 0;
+ forward.Enabled = historyidx < history.Count - 1;
+ }
+
+ private bool ChangeDirectory(string dir, bool recordHistory)
+ {
+ if (Directory == dir)
+ return true;
+
+ // normalise input
+ dir = dir.Replace('\\', '/');
+ if (dir[dir.Length - 1] == '/')
+ dir = dir.Substring(0, dir.Length - 1);
+
+ DirectoryFileTreeNode node = GetNode(dir);
+
+ if (node != null && node.AccessDenied)
+ {
+ ShowAccessDeniedMessage(dir);
+ return false;
+ }
+
+ if (node == null)
+ {
+ bool immediateError = false;
+
+ m_RM.ListFolder(dir, (string a, DirectoryFile[] b) =>
+ {
+ if (b.Length == 1 && b[0].flags.HasFlag(DirectoryFileProperty.ErrorInvalidPath))
+ {
+ ShowFileNotFoundMessage(dir);
+ immediateError = true;
+ return;
+ }
+
+ if (b.Length == 1 && b[0].flags.HasFlag(DirectoryFileProperty.ErrorAccessDenied))
+ {
+ ShowAccessDeniedMessage(dir);
+ immediateError = true;
+ return;
+ }
+
+ if (recordHistory)
+ {
+ if (historyidx < history.Count - 1)
+ history.RemoveRange(historyidx, history.Count - 1 - historyidx);
+
+ history.Add(dir);
+ historyidx = history.Count - 1;
+ }
+ currentDir = dir;
+
+ UpdateViewsFromData();
+ });
+
+ if (immediateError)
+ return false;
+
+ return true;
+ }
+
+ if (recordHistory)
+ {
+ if (historyidx < history.Count - 1)
+ history.RemoveRange(historyidx, history.Count - 1 - historyidx);
+
+ history.Add(dir);
+ historyidx = history.Count - 1;
+ }
+ currentDir = dir;
+
+ UpdateViewsFromData();
+
+ return true;
+ }
+
+ private bool ChangeDirectory(string dir)
+ {
+ return ChangeDirectory(dir, true);
+ }
+
+ private void UpdateFileList()
+ {
+ fileList.Items.Clear();
+ currentFiles.Clear();
+
+ // return, we haven't populated anything yet
+ if (roots.Count == 0)
+ return;
+
+ DirectoryFileTreeNode node = GetNode(Directory);
+
+ if (node == null)
+ return;
+
+ string match = ".*";
+
+ if (FileName.IndexOf('*') != -1 || FileName.IndexOf('?') != -1)
+ match = Regex.Escape(FileName).Replace( @"\*", ".*" ).Replace( @"\?", "." );
+
+ foreach (var child in node.children)
+ {
+ if (child.IsHidden && !showHidden.Checked)
+ continue;
+
+ var res = Regex.Match(child.Filename, match);
+
+ // always display directories even if they don't match a glob
+ if (!res.Success && !child.IsDirectory)
+ continue;
+
+ int imgidx = ICON_FILE;
+ if (child.IsDirectory)
+ imgidx = ICON_DIRECTORY;
+ else if (child.IsExecutable)
+ imgidx = ICON_EXECUTABLE;
+
+ // skip non-executables
+ if(imgidx == ICON_FILE && fileType.SelectedIndex == 0)
+ continue;
+
+ if (child.IsHidden)
+ {
+ imgidx = ICON_FILE_FADED;
+ if (child.IsDirectory)
+ imgidx = ICON_DIRECTORY_FADED;
+ else if (child.IsExecutable)
+ imgidx = ICON_EXECUTABLE_FADED;
+ }
+
+ ListViewItem item = new ListViewItem(child.Filename, imgidx);
+ item.Tag = child;
+
+ fileList.Items.Add(item);
+
+ currentFiles.Add(child);
+ }
+ }
+
+ private bool TryOpenFile(bool doubleclick)
+ {
+ // double clicking enters directories, it doesn't choose them
+ if (m_DirBrowse && !doubleclick)
+ {
+ DirectoryFileTreeNode node = GetNode(Directory);
+
+ if (node != null)
+ {
+ OnOpened(new FileOpenedEventArgs(Directory));
+ Close();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ int idx = currentFiles.FindIndex(f => f.Filename == FileName);
+ if (idx >= 0)
+ {
+ if (currentFiles[idx].IsDirectory)
+ {
+ ChangeDirectory(Directory + "/" + currentFiles[idx].Filename);
+ return true;
+ }
+
+ OnOpened(new FileOpenedEventArgs(ChosenPath));
+ Close();
+
+ return true;
+ }
+
+ return false;
+ }
+
+ private void ShowFileNotFoundMessage(string fn)
+ {
+ MessageBox.Show(String.Format("{0}\nFile not found.\nCheck the file name and try again.", fn), "File not found", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
+ }
+
+ private void ShowAccessDeniedMessage(string fn)
+ {
+ MessageBox.Show(String.Format("{0} is not accessible\n\nAccess is denied.", fn), "Access is denied", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+
+ #region Handlers
+
+ private void VirtualOpenFileDialog_Load(object sender, EventArgs e)
+ {
+ InitialPopulate();
+ }
+
+ private void showHidden_CheckedChanged(object sender, EventArgs e)
+ {
+ UpdateFileList();
+ }
+
+ private void fileType_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ UpdateFileList();
+ }
+
+ private void filename_KeyPress(object sender, KeyPressEventArgs e)
+ {
+ if (e.KeyChar == '\r' || e.KeyChar == '\n')
+ {
+ if (TryOpenFile(false))
+ return;
+
+ if (FileName.IndexOf('*') == -1 && FileName.IndexOf('?') == -1)
+ {
+ ShowFileNotFoundMessage(FileName);
+ return;
+ }
+
+ UpdateFileList();
+ }
+ }
+
+ private void open_Click(object sender, EventArgs e)
+ {
+ if (TryOpenFile(false))
+ return;
+ else if (FileName != "")
+ ShowFileNotFoundMessage(FileName);
+ }
+
+ private void cancel_Click(object sender, EventArgs e)
+ {
+ Close();
+ }
+
+ private void location_KeyPress(object sender, KeyPressEventArgs e)
+ {
+ if (e.KeyChar == '\r' || e.KeyChar == '\n')
+ {
+ ChangeDirectory(location.Text);
+ }
+ }
+
+ private void directoryTree_BeforeSelect(object sender, TreeViewCancelEventArgs e)
+ {
+ // for unix paths we need to drop the leading /
+ bool success = true;
+
+ if(!NTPaths)
+ success = ChangeDirectory(e.Node.FullPath.Substring(1));
+ else
+ success = ChangeDirectory(e.Node.FullPath);
+
+ if (!success)
+ e.Cancel = true;
+ }
+
+ private void directoryTree_BeforeExpand(object sender, TreeViewCancelEventArgs e)
+ {
+ PopulateNode(e.Node);
+ }
+
+ private void back_Click(object sender, EventArgs e)
+ {
+ historyidx--;
+ ChangeDirectory(history[historyidx], false);
+ }
+
+ private void forward_Click(object sender, EventArgs e)
+ {
+ historyidx++;
+ ChangeDirectory(history[historyidx], false);
+ }
+
+ private void up_Click(object sender, EventArgs e)
+ {
+ string dir = Directory;
+
+ int idx = dir.LastIndexOf('/');
+
+ if (idx == 0)
+ ChangeDirectory("/");
+ else if (idx >= 0)
+ ChangeDirectory(dir.Substring(0, idx));
+ }
+
+ private void fileList_DoubleClick(object sender, EventArgs e)
+ {
+ if(fileList.SelectedItems.Count == 1)
+ {
+ filename.Text = fileList.SelectedItems[0].Text;
+
+ if (TryOpenFile(true))
+ return;
+ else
+ ShowFileNotFoundMessage(FileName);
+ }
+ }
+
+ private void fileList_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ if(fileList.SelectedItems.Count > 0)
+ filename.Text = fileList.SelectedItems[0].Text;
+ }
+
+ #endregion
+ }
+
+ public class FileOpenedEventArgs : EventArgs
+ {
+ private string m_fn;
+
+ public FileOpenedEventArgs(string fn)
+ {
+ m_fn = fn;
+ }
+
+ public string FileName
+ {
+ get { return m_fn; }
+ }
+ }
+
+ public class DirectoryFileTreeNode
+ {
+ public string Filename = "";
+ public string Path = "";
+ public bool IsHidden = false;
+ public bool IsExecutable = false;
+ public bool IsDirectory = false;
+
+ public bool AccessDenied = false;
+
+ public TreeNode directoryNode = null;
+
+ public bool HasPopulated = false;
+ public bool ChildrenPopulated = false;
+ public List children = new List();
+
+ public void Populate(string path, DirectoryFile[] files)
+ {
+ HasPopulated = true;
+
+ if (files.Length == 1 && files[0].flags.HasFlag(DirectoryFileProperty.ErrorAccessDenied))
+ {
+ AccessDenied = true;
+ return;
+ }
+
+ foreach (DirectoryFile file in files)
+ {
+ DirectoryFileTreeNode child = new DirectoryFileTreeNode();
+ child.Filename = file.filename;
+ if (Path == "/")
+ child.Path = Path + file.filename;
+ else
+ child.Path = Path + "/" + file.filename;
+ child.IsHidden = file.flags.HasFlag(DirectoryFileProperty.Hidden);
+ child.IsExecutable = file.flags.HasFlag(DirectoryFileProperty.Executable);
+ child.IsDirectory = file.flags.HasFlag(DirectoryFileProperty.Directory);
+ children.Add(child);
+ }
+ }
+
+ public DirectoryFileTreeNode GetNode(string path)
+ {
+ int idx = path.IndexOf('/');
+
+ string dirname = "";
+ string rest = "";
+
+ if (idx >= 0)
+ {
+ rest = path.Substring(idx + 1);
+ dirname = path.Substring(0, idx);
+ }
+
+ foreach (DirectoryFileTreeNode child in children)
+ {
+ if (child.Filename == path)
+ return child;
+ else if (child.Filename == dirname)
+ return child.GetNode(rest);
+ }
+
+ return null;
+ }
+
+ public override string ToString()
+ {
+ return Path;
+ }
+ }
+}
diff --git a/renderdocui/Windows/Dialogs/VirtualOpenFileDialog.resx b/renderdocui/Windows/Dialogs/VirtualOpenFileDialog.resx
new file mode 100644
index 000000000..6754df298
--- /dev/null
+++ b/renderdocui/Windows/Dialogs/VirtualOpenFileDialog.resx
@@ -0,0 +1,308 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ False
+
+
+ False
+
+
+ 17, 17
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ 116, 17
+
+
+
+ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
+ LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
+ ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADu
+ IwAAAk1TRnQBSQFMAgEBBwEAAbABAAGwAQABEAEAARABAAT/ASEBAAj/AUIBTQE2BwABNgMAASgDAAFA
+ AwABIAMAAQEBAAEgBgABIBYAASUCJAE2ATsBOQE4AV4BSAFFAUIBdwFLAUYBQwF8AUsBRgFDAXwBSwFG
+ AUMBfAFLAUYBQwF8AUsBRgFDAXwBSwFGAUMBfAFLAUYBQwF8AUsBRgFDAXwBSQFFAUMBeAE7ATkBOAFf
+ AyIBMsgAAUQBQQE/AW8BTQJMAXkBUQFQAU8BfwJRAVABgAJRAVABgAJRAVABgAJRAVABgAFSAlEBgAFS
+ AlEBgAFSAlEBgAJSAVEBgAJRAVABfwNMAXgBQgE/AT0Ba8gAAUsBRwFDAXsCUAFPAX8BUgFOAUkBgAFS
+ AU4BSQGAAVIBTgFIAYABUgFOAUgBgAFSAU4BSAGAAVIBTgFIAYABUgFOAUgBgAFSAU4BSAGAAVIBTgFI
+ AYABUgFOAUgBgANRAX8BSgFGAUMBegQAA1IBqQHDAY4BUgH/AcABiwFQAf8BvgGIAU4B/wG7AYUBSwH/
+ AbkBgwFJAf8BtAFoAUYB/wGyAWYBRAH/AbEBZQFCAf8BrgFjAUEB/wGtAWABQAH/AasBXwE+Af8BqQFd
+ AT0B/wGpAVsBOwH/A1IBqQQAATYCNQFVAU4BSwFJAYABTgFLAUgBgAFOAUsBSAGAAU4BSgFIAYABTgFK
+ AUgBgAFNAUoBSAGAAU0BSgFIAYABTQFKAUgBgAFNAUoBSAGAAU0BSQFHAYABTQFJAUcBgAFNAUkBRwGA
+ AU0BSQFHAYABNgI1AVVIAAFMAUcBRAF8AVIBUQFQAYABUgFOAUkBgAFSAVABTAGAAVIBUAFMAYABUgFP
+ AUwBgAFSAVABTAGAAVIBTwFLAYABUgFPAUsBgAFSAU8BSwGAAVIBTwFLAYABUgFOAUgBgAJSAVEBgAFL
+ AUYBQwF8BAAByAGSAVY1/wGpAVwBOwH/BAABTwFLAUkBgANSAYADUgGAA1IBgANSAYADUgGAA1IBgANS
+ AYADUgGAA1IBgANSAYADUgGAA1IBgANSAYABTQFJAUcBgEgAAUwBRwFEAXwBUgFRAVABgAFSAU0BRwGA
+ AVIBTQFHAYABUgFNAUcBgAFSAU0BRwGAAVIBTQFHAYABUgFNAUcBgAFSAU0BRwGAAVIBTQFHAYABUgFN
+ AUcBgAFSAU0BRwGAAlIBUQGAAUsBRwFEAXwEAAHKAZQBWAv/Af4D/wH9Af8C/gH9Af8C/gH8Af8C/gH8
+ Af8C/gH8Af8C/gH8Af8C/gH6Af8C/gH6Af8C/AH5Bf8BqgFdAT0B/wQAAU8BSwFJAYADUgGAA1IBgANS
+ AYADUgGAA1IBgANSAYADUgGAA1IBgANSAYADUgGAA1IBgANSAYADUgGAAU0BSQFHAYBIAAFMAUgBRAF8
+ AVICUQGAAVIBUAFPAYABUgFQAU8BgAFSAVABTwGAAVIBUAFPAYABUgFQAU8BgAFSAVABTwGAAVIBUAFP
+ AYABUgFQAU8BgAFSAVABTwGAAVIBUAFPAYADUgGAAUwBRwFEAXwEAAHMAZcBWQf/AfwD/wH9Af8C/gH8
+ Af8C/gH8Af8C/gH7Af8C/QH6Af8C/QH6Af8C/QH6Af8C/QH6Af8C/AH3Af8C+wH2Bf8BrAFfAT4B/wQA
+ AU8BTAFJAYADUgGAA1IBgANSAYADUgGAA1IBgANSAYADUgGAA1IBgANSAYADUgGAA1IBgAJSAVEBgANS
+ AYABTQFJAUcBgEgAAUwBSAFFAXwBUgJRAYABUgFRAU8BgAFSAVEBTwGAAVIBUQFPAYABUgFRAU8BgAFS
+ AVABTwGAAVIBUAFPAYABUgFQAU8BgAFSAVABTwGAAVIBUAFPAYABUgFQAU8BgAJSAVEBgAFMAUcBRAF8
+ BAAB0QGcAV0F/wL+AfwB/wL+AfwB/wL+AfwB/wL9AfsB/wL9AfsB/wL9AfoB/wL9AfgB/wL7AfkB/wH7
+ AfoB9wH/AfsB+gH2Af8B+wH4AfQF/wGwAWQBQgH/BAABTwFMAUkBgANSAYADUgGAA1IBgANSAYADUgGA
+ A1IBgANSAYADUgGAA1IBgANSAYACUgFRAYACUgFRAYADUgGAAU0BSgFIAYBIAAFMAUgBRQF8AVICUQGA
+ AVIBUQFPAYABUgFRAVABgAFSAVEBTwGAAVIBUQFPAYABUgFRAU8BgAFSAVABTwGAAVIBUAFPAYABUgFQ
+ AU8BgAFSAVABTwGAAVIBUAFOAYABUgJRAYABTAFIAUQBfAQAAdQBngFfBf8C/gH8Af8C/QH7Af8C/QH8
+ Af8C/QH7Af8C/QH5Af8C/AH4Af8B+wH5AfcB/wH7AfkB9QH/AfsB+AH0Af8B+wH3AfIB/wH7AfUB8gX/
+ AbIBZgFEAf8EAAFPAUwBSQGAA1IBgANSAYADUgGAA1IBgANSAYADUgGAA1IBgANSAYACUgFRAYACUgFR
+ AYACUgFRAYABUgJRAYADUgGAAU0BSgFIAYBIAAFMAUgBRQF8AVICUQGAAVIBUQFQAYABUgFRAVABgAFS
+ AVEBUAGAAVIBUQFPAYABUgFQAU8BgAFSAVABTwGAAVIBUAFPAYABUgFQAU8BgAFSAVABTgGAAVIBUAFO
+ AYABUgJRAYABTAFIAUUBfAQAAdUBoAFgBf8C/QH8Af8C/QH7Af8C/QH6Af8C/AH5Af8B/AH7AfcB/wH7
+ AfkB9QH/AfsB+AH0Af8B+wH3AfMB/wH7AfUB8gH/AfoB8wHvAf8B+AHyAewF/wG1AWgBRgH/BAABTwFM
+ AUkBgANSAYADUgGAA1IBgANSAYADUgGAA1IBgAJSAVEBgAJSAVEBgAJSAVEBgAFSAlEBgAFSAlEBgAFS
+ AlEBgANSAYABTQFKAUgBgEgAAUwBSAFFAXwBUgJRAYABUgFRAVABgAFSAVEBTwGAAVIBUQFPAYABUgFQ
+ AU8BgAFSAVABTwGAAVIBUAFPAYABUgFQAU8BgAFSAVABTgGAAVEBUAFOAYABUQFQAU4BgAFSAlEBgAFM
+ AUgBRQF8BAAB2AGiAWMF/wL9AfoB/wL8AfoB/wH8AfsB+QH/AfsB+gH2Af8B+wH4AfUB/wH7AfcB9AH/
+ AfsB9gHxAf8B+AH0Ae4B/wH3AfIB6wH/AfcB8AHqAf8B9gHsAegF/wG3AYEBSAH/BAABUAFMAUoBgANS
+ AYADUgGAA1IBgANSAYACUgFRAYACUgFRAYACUgFRAYABUgJRAYABUgJRAYABUgJRAYABUgJRAYADUQGA
+ A1IBgAFOAUoBSAGASAABTAFIAUUBfAFSAlEBgAFSAVABTwGAAVIBUAFPAYABUgFRAU8BgAFSAVABTwGA
+ AVIBUAFPAYABUgFQAU8BgAFSAVABTgGAAVEBTwFOAYABUQFPAU0BgAFRAU8BTQGAAVICUQGAAUwBSAFF
+ AXwEAAHZAaMBYwX/AfwB+wH5Af8B/AH7AfgB/wH7AfkB9wH/AfsB9wH0Af8B+gH3AfIB/wH5AfUB8AH/
+ AfcB8wHtAf8B9gHvAeoB/wH1AesB5wH/AfMB6gHkAf8B8gHnAd4F/wG6AYUBSgH/BAABUAFMAUoBgANS
+ AYADUgGAA1IBgANSAYACUgFRAYACUgFRAYABUgJRAYABUgJRAYADUQGAA1EBgAJRAVABgAJRAVABgANS
+ AYABTgFKAUgBgEgAAUwBSAFFAXwBUgJRAYABUgFQAU8BgAFSAVABTwGAAVIBUAFPAYABUgFQAU8BgAFS
+ AVABTwGAAVIBUAFOAYABUQFQAU4BgAJRAVABgAFSAlEBgAJSAVEBgANRAYABTQFJAUUBfgQAAdsBpAFk
+ Nf8BvQGHAU0B/wQAAVABTAFKAYADUgGAA1IBgANSAYADUgGAA1IBgANSAYADUgGAA1IBgANSAYADUgGA
+ A1IBgANSAYADUgGAAU4BSwFIAYBIAAFLAUgBRQF7AVICUQGAAVIBUAFPAYABUgFQAU8BgAFSAVABTwGA
+ AVIBUAFPAYABUgFQAU8BgAFSAVABTgGAAVEBTwFOAYADUgGAAVIBUAFPAYABUgFQAU8BgAFQAU0BSgGA
+ ATUBNAEzAVMEAAHcAacBZQH/AdwBpwFlAf8B3AGnAWUB/wHcAacBZQH/AdwBpwFlAf8B3AGnAWUB/wHc
+ AacBZQH/AdwBpwFlAf8B3AGnAWUB/wHcAacBZQH/AdwBpwFlAf8B3AGnAWUB/wHcAacBZQH/AdwBpwFl
+ Af8BwAGLAVAB/wQAAVABTQFKAYABUAFNAUoBgAFQAU0BSgGAAVABTQFKAYABUAFNAUoBgAFQAU0BSgGA
+ AVABTQFKAYABUAFNAUoBgAFQAU0BSgGAAVABTQFKAYABUAFNAUoBgAFQAU0BSgGAAVABTQFKAYABUAFN
+ AUoBgAFOAUsBSAGASAABSAFFAUIBdQNQAX4BUgFQAU8BgAFSAVABTwGAAVIBUAFPAYABUgFQAU8BgAFS
+ AVABTgGAAVIBUAFOAYABUQFPAU4BgANSAYABUQFQAU0BgAFQAU0BSgGAAUwBSAFGAXsDAwEEBAABswGo
+ AYUB/QHoAbkBkgH/AegBuQGSAf8B6AG5AZIB/wHoAbkBkgH/AegBuQGSAf8B6AG5AZIB/wHoAbkBkgH/
+ AegBuQGSAf8B6AG5AZIB/wHoAbkBkgH/AegBuQGSAf8B6AG5AZIB/wHoAbkBkgH/AaoBkAFMAf0EAAFP
+ AUwBSQF/AVEBTgFLAYABUQFOAUsBgAFRAU4BSwGAAVEBTgFLAYABUQFOAUsBgAFRAU4BSwGAAVEBTgFL
+ AYABUQFOAUsBgAFRAU4BSwGAAVEBTgFLAYABUQFOAUsBgAFRAU4BSwGAAVEBTgFLAYABTQFKAUgBf0gA
+ AT0BPAE6AWIBSwJKAXYDUAF+AVICUQGAAVICUQGAAVICUQGAAVICUQGAAVICUQGAAVICUQGAAVECUAGA
+ AVABTQFKAYABTAFIAUYBewMDAQQIAAM+AWsBcAJlAfQB3AGnAWUB/wHcAaYBZAH/AdoBpAFkAf8B2AGi
+ AWMB/wHVAaABYAH/AdQBngFfAf8B0gGdAV0B/wHPAZoBXAH/Ac4BmQFaAf8BywGWAVkB/wHJAZQBVgH/
+ AWoCZQH0Az4BawQAASUCJAE2AUwBSQFHAXoBUAFNAUoBgAFQAUwBSgGAAVABTAFKAYABUAFMAUoBgAFP
+ AUwBSQGAAU8BTAFJAYABTwFMAUkBgAFPAUwBSQGAAU8BTAFJAYABTwFLAUkBgAFPAUsBSQGAAUoBSAFH
+ AXoBJQIkATZIAAMhATABOwE6ATkBXgFJAUcBRAF3AUsBSAFFAXsBTAFIAUUBfAFMAUgBRQF8AUwBSQFF
+ AXwBTAFIAUUBfAFMAUgBRQF8AUEBQAE+AWoBMAIvAUkDAgED/wCRAAM+AWsCWAFWAbwBYgJdAe0BgQFm
+ AVEB9wGBAWYBUQH3AYEBZgFRAfcBgQFlAVEB9wGBAWUBUQH3AYABZQFRAfcBgAFlAVEB9wGAAWQBUQH3
+ AmIBWAHvAloBVwG9AzsBY8gAAmABWgHeA28B8gG8AbgBtAH9AfYB6wHeAf8B9gHqAd4B/wH2AeoB3AH/
+ AfYB6gHcAf8B+gHzAesB/wH6AfMB6wH/AfoB8gHqAf8B/AH3AfMB/wG9AbwBuwH9AmgBZwHwAl4BWgHV
+ BAADVwG3A6AB/wOaAf8DkwH/A40B/wOGAf8DgAH/A2QB/wNeAf8DWQH/A1QB/wNPAf8DSwH/A0gB/wNF
+ Af8DVwG3BAADQAFwAVICVAGmAVUBXAFeAeoBUAFtAYUB9wFQAW0BhQH3AVABbQGFAfcBUAFtAYUB9wFQ
+ AW0BhQH3AVABbQGFAfcBUAFtAYUB9wFQAW0BhQH3AVABbQGFAfcBUwFkAW0B8QNMAZMIAAMmATgBMwE0
+ ATUBUwFBAUUBSQF1AUMBSAFNAXwBQwFIAU0BfAFDAUgBTQF8AUMBSAFNAXwBQwFIAU0BfAFDAUgBTQF8
+ AUMBSAFNAXwBQwFIAU0BfAFDAUgBTQF8AUIBRwFLAXkBLwIwAUoIAAFtAVkBQgH1AcoBwAG0Af4B/QG/
+ AVIB/wH8Ab0BUQH/AfsBvgFPAf8B/AG+AU4B/wH8Ab4BTgH/AfwBvQFMAf8B+wG9AU0B/wH7AbwBSwH/
+ AfwBvgFKAf8B/AG8AUwB/wG+Ab0BvAH9AWsBXwFMAfMEAAOuAf8D6QH/A9MB/wPSAf8D0QH/A9AB/wPO
+ Af8DzQH/A80B/wPLAf8DywH/A8oB/wPJAf8DyAH/A+IB/wNFAf8EAAFYAmEB5gFmAmcB8AGnAbMBuwH9
+ AZ4B2wH0Af8BlgHaAfMB/wGOAdgB8wH/AYYB1wHzAf8BaQHUAfIB/wFjAdMB8gH/AVwB0gHxAf8BVgHQ
+ AfEB/wFTAc8B8QH/AZcBvwHNAf4BTgFdAWUB8AgAAUEBRQFHAXMCSwFMAXgBTAFPAVABfwFMAVABUQGA
+ AUsBUAFRAYABSwFQAVEBgAFKAVABUQGAAUoBTwFRAYABSgFPAVEBgAFJAU8BUQGAAUkBTwFRAYABSQFP
+ AVEBgAFNAVABUQF/AUMBRwFLAXgIAAGCAW0BUQL3Ae0B4wH/Af0BwgFYAv8B2AGgAv8B1wGeAv8B1gGb
+ Av8B1wGYAv8B1gGWAv8B1gGVAv8B1QGUAv8B1AGTAf8B+wG+AU8B/wH7AfcB9AH/AYEBZwFRAfcEAAO1
+ Af8D1gH/A7sB/wO5Af8DtgH/A7QB/wOyAf8DsQH/A64B/wOsAf8DqwH/A6kB/wOoAf8DpwH/A8gB/wNJ
+ Af8EAAFRAW0BhgH3Ae8B+gH+Af8BoQHpAfkB/wGRAeUB+AH/AYEB4QH3Af8BXAHeAfYB/wFNAdoB9QH/
+ AT4B1wH0Af8BMQHTAfMB/wEjAdAB8gH/ARgBzQHxAf8BEAHLAfAB/wHKAfIB+wH/AVEBbQGGAfcIAAFE
+ AUkBTQF8AVECUgGAAUwBUQFSAYABSwFQAVIBgAFKAVABUgGAAUkBUAFRAYABSAFQAVEBgAFHAVABUQGA
+ AUcBTwFRAYABRgFPAVEBgAFFAU8BUQGAAUQBTwFRAYABTwFRAVIBgAFEAUkBTQF8CAABggFtAVEC9wHw
+ AeYB/wH4AbQBPwH/AfcBtAFAAf8B9wG1AT4B/wH4AbQBPQH/AfgBsgE9Af8B9wGzATwB/wH3AbMBPAH/
+ AfcBsgE7Af8B9wGyATkB/wH3AbIBOQH/AfwB+QH1Af8BgQFtAVEB9wQAA7wB/wPZAf8DvgH/A7sB/wOO
+ Af8DjwH/A5AB/wOQAf8DjwH/A48B/wONAf8DiwH/A6oB/wOpAf8DygH/A04B/wQAAT4BcwGFAfgB8gH6
+ Af0B/wGzAe0B+gH/AaQB6QH5Af8BlQHmAfgB/wGFAeIB9wH/AWAB3gH2Af8BTwHbAfUB/wFBAdcB9AH/
+ ATMB1AHzAf8BJQHRAfIB/wEaAc4B8QH/AcwB8gH7Af8BUQFtAYYB9wgAAUQBSQFNAXwBUQJSAYABTQFR
+ AVIBgAFMAVEBUgGAAUsBUAFSAYABSgFQAVIBgAFJAVABUQGAAUgBUAFRAYABSAFQAVEBgAFHAU8BUQGA
+ AUYBTwFRAYABRQFPAVEBgAFPAVEBUgGAAUQBSQFNAXwIAAGDAW0BUQH3AfgB8QHoAf8B/gHlAdUB/wH9
+ AeUB0wH/Af0B5QHTAf8B/AHlAdMB/wH8AeUB0wH/AfwB5AHRAf8B/AHiAc4B/wH8AeIBzAH/AfsB4AHJ
+ Af8B+wHhAcgB/wH9AfoB9wH/AYIBbQFRAfcEAAPDAf8D3QH/A8IB/wO+Af8DkQH/A5IB/wOUAf8DlAH/
+ A5MB/wOSAf8DkQH/A48B/wOtAf8DrQH/A88B/wNTAf8EAAFBAX0BiwH5AfYB/AH+Af8ByAHyAfwB/wG5
+ Ae8B+wH/AawB7AH6Af8BnAHoAfkB/wGLAeMB9wH/AWYB4AH2Af8BVgHcAfYB/wFHAdkB9QH/ATkB1gH0
+ Af8BLgHTAfMB/wHQAfMB/AH/AVEBcQGGAfcIAAFEAUsBTgF9AVECUgGAAU8BUQFSAYABTgFRAVIBgAFN
+ AVEBUgGAAUwBUQFSAYABSwFQAVIBgAFKAVABUQGAAUkBUAFRAYABSAFQAVEBgAFHAU8BUQGAAUYBTwFR
+ AYABTwFRAVIBgAFEAUoBTQF8CAABgwFtAVEB9wH4AfIB6wH/Af4B5wHWAf8B/QHnAdYB/wH9AecB1gH/
+ Af0B5wHWAf8B/QHmAdUB/wH9AeUB0wH/AfwB5AHRAf8B/AHiAc0B/wH7AeEBywH/AfsB4QHJAf8B+wH3
+ AfIB/wGDAW0BUQH3BAADWgG9A90B/wPIAf8DwQH/A8AB/wO+Af8DuwH/A7kB/wO4Af8DtgH/A7QB/wOx
+ Af8DsAH/A7QB/wPAAf8DWgG9BAABTQF4AY8B+gH+A/8B+AH9Av8B9gH9Av8B9QH8Av8B8wH8Af4B/wHY
+ AfYB/AH/AZQB5gH4Af8BhQHjAfcB/wFgAd8B9gH/AVIB2wH1Af8BRgHYAfQB/wHXAfQB/AH/AVEBdwGG
+ AfcIAAFEAUsBTgF9A1IBgANSAYABUQJSAYABUQJSAYABUQJSAYABUAFRAVIBgAFLAVABUgGAAUoBUAFS
+ AYABSQFQAVEBgAFJAVABUQGAAUgBUAFRAYABUAFRAVIBgAFEAUoBTQF8CAABgwFtAVEB9wH5AfMB7AH/
+ Af4B6AHWAf8B/gHoAdcB/wH9AecB1gH/Af0B5wHWAf8B/QHnAdUB/wH9AeUB0wH/AfsB5AHQAf8B+wHj
+ AcwB/wH6Ad8BxwH/AfoB3wHGAf8B+gHyAeoB/wGDAW0BUQH3BAADWgG9A+gB/wPnAf8D4QH/A+AB/wPg
+ Af8D3wH/A98B/wPeAf8D3QH/A90B/wPcAf8D2wH/A+AB/wPNAf8DWgG9BAABSwF6AY8B+gHoAfYB+wH/
+ AZQB1AHvAf8BiAHOAe4B/wFdAcEB6QH/AckB6QH2Af8B8gH8Af4B/wHzAfwB/gH/AfIB/AH+Af8B8AH8
+ Af4B/wHvAfsB/gH/Ae4B+wH+Af8B/gP/AVEBfQGGAfcIAAFEAUsBTgF9AlEBUgGAAUsBTwFRAYABSwFP
+ AVEBgAFJAU4BUQGAAU8CUQGAAVECUgGAAVECUgGAAVECUgGAAVECUgGAAVECUgGAAVECUgGAA1IBgAFE
+ AUoBTQF8CAABgwFtAVEB9wH5AfQB7QH/Af4B6AHYAf8B/gHoAdgB/wH+AegB1wH/Af4B5wHWAf8B/QHl
+ AdMB/wH8AeQB0QH/AfsB4QHMAf8B+gHgAccB/wH5Ad0BwwH/AfgB3AHCAf8B+gH0Ae0B/wGDAW0BUQH3
+ BAADKQE/A9kB/wPsAf8D3gH/A9gB/wPSAf8DzAH/A8gB/wPHAf8DyAH/A8sB/wPQAf8D3QH/A+gB/wOg
+ Af8DKwFCBAABWQFnAWoB8gHxAfoB/QH/AZQB3gH1Af8BkwHcAfQB/wGBAdUB8gH/AVQBygHtAf8BVgHL
+ AeoB/wGFAdMB7wH/AYAB0gHvAf8BZAHQAe8B/wFgAc8B7gH/AVwBzwHuAf8B6QH3AfsB/wFMAWoBbwHz
+ CAABQwFJAUsBeQFRAlIBgAFLAVABUQGAAUsBUAFRAYABSgFPAVEBgAFJAU8BUQGAAUkBTwFRAYABSgFP
+ AVEBgAFKAU8BUQGAAUoBTwFRAYABSQFPAVEBgAFJAU8BUQGAAVECUgGAAUMBSQFMAXoIAAGDAW0BUQH3
+ AfkB9AHvAf8B/gHnAdcB/wH9AecB1gH/Af0B5wHVAf8B/QHmAdQB/wH8AeYB0gH/AfsB4QHMAf8B+gHf
+ AccB/wH4AdwBwgH/AfYB2gG9Af8B9gHYAbsB/wH6AfQB7wH/AYMBbQFRAfcIAANaAb0D6AH/A9sB/wPi
+ Af8D4gH/A+EB/wPgAf8D4AH/A+AB/wPfAf8DwwH/A9EB/wPSAf8DWgG9CAABTgFfAWYB8AH3AfwB/gH/
+ AY4B5AH4Af8BkQHeAfUB/wGfAeAB9QH/AawB4QH2Af8B7wH7Af4B/wH0Af0B/gH/AfMB/AH+Af8B8QH8
+ Af4B/wHvAfsB/gH/Ae4B+wH+Af8BkAKSAfkBXAJgAdQIAAFDAUkBSwF4A1IBgAFLAVABUgGAAUsBUAFR
+ AYABTAFQAVEBgAFNAVABUQGAAVECUgGAAVECUgGAAVECUgGAAVECUgGAAVECUgGAAVECUgGAA1ABfQE9
+ AUEBQgFqCAABgwFtAVEB9wH5AfQB8AH/AfwB5gHTAf8B/AHmAdQB/wH9AecB0wH/AfwB5AHRAf8B+wHj
+ Ac0B/wH6AeAByAH/AfgB3AHCAf8B9QHWAbsB/wHzAdQBtQH/AfEB0gGzAf8B+AH0AfAB/wGCAW0BUQH3
+ CAADKQE/A94B/wPzAf8D7QH/A+0B/wPtAf8D7QH/A+0B/wPsAf8D7AH/A+wB/wPxAf8DsQH/AysBQggA
+ AT4BegGFAfgB/QL+Af8B/gP/Av4C/wH9Af4C/wH+A/8B6gH3AfsB/wFqAYgBjAH5AVwBfgGKAfgBXAF+
+ AYoB+AFcAX4BigH4AW0BhAGHAfcDYQHhAzUBVggAAUQBSwFNAXwDUgGAA1IBgANSAYADUgGAA1IBgAFR
+ AlIBgAFHAU0BTgF9AUYBTAFNAXwBRgFMAU0BfAFGAUwBTQF8AUcBTAFNAXwBQgFFAUcBcQMeASsIAAGD
+ AW0BUQH3AfkB9QHxAf8B/AHjAc8B/wH7AeQB0AH/AfwB5AHPAf8B/AHjAc0B/wH6AeEBygH/AfkB3QHE
+ Af8B9gHZAbwB/wH0AekB3wH/AfcB8gHsAf8B+wH3AfMB/wH1Ae8B6QH/AY4BXwFFAfsMAANaAb0D1QH/
+ A9IB/wPOAf8DyQH/A8QB/wO/Af8DuQH/A7MB/wOtAf8DpgH/A1oBvQwAAVsCXgHQAU0BgAGVAfoBTQGB
+ AZUB+gFNAYEBlQH6AU0BgQGVAfoBTQGBAZUB+gFYAl4B3QMQARYDCwEPAwsBDwMLAQ8DCwEPAwsBDwMD
+ AQQIAAE8AUABQQFoAUcBTQFOAX0BRwFNAU4BfQFHAU0BTgF9AUcBTQFOAX0BRwFNAU4BfQE/AUQBRQFv
+ AwgBCwMGAQgDBgEIAwYBCAMGAQgDBgEIAwEBAggAAW4BYgFJAfYB+QH1AfEB/wH8AeMBzQH/AfsB4wHO
+ Af8B+wHjAc0B/wH7AeIBywH/AfkB4AHIAf8B+AHcAcIB/wH1AdYBugH/Af0B+wH4Af8B/AHmAc0B/wH6
+ AeUByQH/AeIBtgGEAf8CVAFSAabIAAFdAVwBVQHqAbABrwGtAfwB+gHgAccB/wH7AeEByQH/AfsB4gHJ
+ Af8B+wHgAcgB/wH5Ad8BxQH/AfgB2wHBAf8B9AHWAbgC/wH7AfgB/wH2AdgBtAH/AeEBsAFnAf8BcwJi
+ AfYDBQEHyAACWwFZAcMDZAHsAa8BrQGrAfwB+AH0Ae0B/wH4AfMB7QH/AfgB8wHtAf8B+AHzAe0B/wH4
+ AfIB7AH/AfcB8gHsAf8B8gHmAdcB/wHiAbIBZwH/AXABZAFZAfUDBQEHzAADOgFgAlgBVgG7AmEBVAHu
+ AW4BYgFJAfYBgwFtAVEB9wGDAW0BUQH3AYMBbQFRAfcBgwFtAVEB9wGDAW0BUQH3AmABXAHUAk0BTAGR
+ AwQBBgwAAUIBTQE+BwABPgMAASgDAAFAAwABIAMAAQEBAAEBBgABARYAA/8BAAGAAQEE/wIAAYABAQT/
+ AgABgAEBAQABAQEAAQECAAGAAQEBAAEBAQABAQIAAYABAQEAAQEBAAEBAgABgAEBAQABAQEAAQECAAGA
+ AQEBAAEBAQABAQIAAYABAQEAAQEBAAEBAgABgAEBAQABAQEAAQECAAGAAQEBAAEBAQABAQIAAYABAQEA
+ AQEBAAEBAgABgAEBAQABAQEAAQECAAGAAQEBAAEBAQABAQIAAYABAQEAAQEBAAEBAgABgAEDAQABAQEA
+ AQECAAGAAQcE/wIABv8BgAEBBv8BgAEBAgABgAEBAYABAQGAAQECAAGAAQEBgAEBAYABAQIAAYABAQGA
+ AQEBgAEBAgABgAEBAYABAQGAAQECAAGAAQEBgAEBAYABAQIAAYABAQGAAQEBgAEBAgABgAEBAYABAQGA
+ AQECAAGAAQEBgAEBAYABAQGAAQEBgAEBAYABAQGAAQEBgAEBAYABAQGAAQEBgAEBAcABAwGAAQEBgAEB
+ AYABAQb/AYABAQb/AYABAwb/AYABBws=
+
+
+
+ False
+
+
+ False
+
+
\ No newline at end of file
diff --git a/renderdocui/renderdocui.csproj b/renderdocui/renderdocui.csproj
index 3a92f1fea..c4ff3d1bc 100644
--- a/renderdocui/renderdocui.csproj
+++ b/renderdocui/renderdocui.csproj
@@ -277,6 +277,12 @@
UpdateDialog.cs
+
+ Form
+
+
+ VirtualOpenFileDialog.cs
+
Form
@@ -421,6 +427,9 @@
UpdateDialog.cs
+
+ VirtualOpenFileDialog.cs
+
EventBrowser.cs
@@ -521,6 +530,7 @@
false
+
@@ -553,6 +563,8 @@
+
+