├── .gitmodules ├── UAssetGUI ├── Resources │ ├── icon.ico │ └── dancing_cat.gif ├── UAGTheme.cs ├── FodyWeavers.xml ├── UAssetGUI.csproj.user ├── LICENSE ├── GlobalSuppressions.cs ├── ColorfulTreeView.cs ├── ProgressBarForm.cs ├── GitHubAPI.cs ├── TextPrompt.cs ├── MarkdownViewer.cs ├── MarkdownViewer.Designer.cs ├── Program.cs ├── AboutForm.cs ├── Properties │ ├── Resources.Designer.cs │ └── Resources.resx ├── ProgressBarForm.Designer.cs ├── TextPrompt.resx ├── AboutForm.Designer.cs ├── SettingsForm.resx ├── MarkdownViewer.resx ├── ProgressBarForm.resx ├── FindForm.resx ├── AboutForm.resx ├── MapStructTypeOverrideForm.resx ├── Form1.resx ├── FileContainerForm.resx ├── TextPrompt.Designer.cs ├── UAssetGUI.csproj ├── UAGUtils.cs ├── FodyWeavers.xsd ├── MapStructTypeOverrideForm.cs ├── UAGConfig.cs ├── FindForm.Designer.cs ├── MapStructTypeOverrideForm.Designer.cs ├── SettingsForm.cs └── FindForm.cs ├── .gitignore ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md └── workflows │ └── build.yml ├── LICENSE ├── README.md └── UAssetGUI.sln /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "UAssetAPI"] 2 | path = UAssetAPI 3 | url = https://github.com/atenfyr/UAssetAPI.git 4 | -------------------------------------------------------------------------------- /UAssetGUI/Resources/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atenfyr/UAssetGUI/HEAD/UAssetGUI/Resources/icon.ico -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | docs 3 | packages 4 | TestResults 5 | UAssetGUI/bin 6 | UAssetGUI/obj 7 | UAssetGUI/git_commit.txt 8 | -------------------------------------------------------------------------------- /UAssetGUI/Resources/dancing_cat.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atenfyr/UAssetGUI/HEAD/UAssetGUI/Resources/dancing_cat.gif -------------------------------------------------------------------------------- /UAssetGUI/UAGTheme.cs: -------------------------------------------------------------------------------- 1 | namespace UAssetGUI 2 | { 3 | public enum UAGTheme 4 | { 5 | Light, 6 | Dark 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /UAssetGUI/FodyWeavers.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /UAssetGUI/UAssetGUI.csproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Form 7 | 8 | 9 | Form 10 | 11 | 12 | Form 13 | 14 | 15 | Form 16 | 17 | 18 | 19 | 20 | Designer 21 | 22 | 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | Please provide a copy of an asset that can be used to reproduce the issue if needed, along with the game's Unreal Engine version. If the asset uses unversioned properties, you should also provide a set of mappings. Your issue will NOT be reviewed if your issue cannot be replicated due to no test asset being provided. 20 | 21 | **Expected behavior** 22 | A clear and concise description of what you expected to happen. 23 | 24 | **Screenshots** 25 | If applicable, add screenshots to help explain your problem. 26 | 27 | **Desktop (please complete the following information):** 28 | - OS: [e.g. Windows 10] 29 | - Version or Commit: [e.g. 1.0.2/c7d9f8d] 30 | 31 | **Additional context** 32 | Add any other context about the problem here. 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Atenfyr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /UAssetGUI/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Atenfyr 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /UAssetGUI/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 | 2 | // This file is used by Code Analysis to maintain SuppressMessage 3 | // attributes that are applied to this project. 4 | // Project-level suppressions either have no target or are given 5 | // a specific target and scoped to a namespace, type, member, etc. 6 | 7 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:UAssetGUI.Form1.openToolStripMenuItem_Click(System.Object,System.EventArgs)")] 8 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:UAssetGUI.Form1.saveToolStripMenuItem_Click(System.Object,System.EventArgs)")] 9 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:UAssetGUI.Form1.menuStrip1_ItemClicked(System.Object,System.Windows.Forms.ToolStripItemClickedEventArgs)")] 10 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:UAssetGUI.Form1.saveAsToolStripMenuItem_Click(System.Object,System.EventArgs)")] 11 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE1006:Naming Styles", Justification = "", Scope = "member", Target = "~M:UAssetGUI.Form1.frm_sizeChanged(System.Object,System.EventArgs)")] -------------------------------------------------------------------------------- /UAssetGUI/ColorfulTreeView.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Windows.Forms; 3 | 4 | namespace UAssetGUI 5 | { 6 | public class ColorfulTreeView : TreeView 7 | { 8 | public ColorfulTreeView() : base() 9 | { 10 | this.DrawMode = TreeViewDrawMode.OwnerDrawText; 11 | NodeMouseClick += (sender, args) => { if (args.Button == MouseButtons.Right) SelectedNode = args.Node; }; 12 | } 13 | 14 | protected override void OnDrawNode(DrawTreeNodeEventArgs e) 15 | { 16 | if (!e.Node.IsVisible) return; 17 | if (e.Node.Bounds.IsEmpty) return; 18 | 19 | Font font = e.Node.NodeFont ?? e.Node.TreeView.Font; 20 | Color fore = e.Node.ForeColor; 21 | if (fore == Color.Empty) fore = e.Node.TreeView.ForeColor; 22 | if (e.Node == e.Node.TreeView.SelectedNode) 23 | { 24 | fore = UAGPalette.HighlightForeColor; 25 | e.Graphics.FillRectangle(new SolidBrush(UAGPalette.HighlightBackColor), e.Bounds); 26 | ControlPaint.DrawFocusRectangle(e.Graphics, e.Bounds, fore, UAGPalette.HighlightBackColor); 27 | TextRenderer.DrawText(e.Graphics, e.Node.Text, font, e.Bounds, fore, UAGPalette.HighlightBackColor, TextFormatFlags.GlyphOverhangPadding); 28 | } 29 | else 30 | { 31 | e.Graphics.FillRectangle(new SolidBrush(UAGPalette.BackColor), e.Bounds); 32 | TextRenderer.DrawText(e.Graphics, e.Node.Text, font, e.Bounds, fore, TextFormatFlags.GlyphOverhangPadding); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /UAssetGUI/ProgressBarForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace UAssetGUI 12 | { 13 | public partial class ProgressBarForm : Form 14 | { 15 | public Form BaseForm; 16 | public int Value; 17 | public int Maximum; 18 | 19 | private const int CP_NOCLOSE_BUTTON = 0x200; 20 | protected override CreateParams CreateParams 21 | { 22 | get 23 | { 24 | CreateParams myCp = base.CreateParams; 25 | myCp.ClassStyle = myCp.ClassStyle | CP_NOCLOSE_BUTTON; 26 | return myCp; 27 | } 28 | } 29 | 30 | public void Progress(int numToAdd) 31 | { 32 | Value += numToAdd; 33 | UpdateGUI(); 34 | } 35 | 36 | public void UpdateGUI() 37 | { 38 | ProgressBar.Value = Value; 39 | label1.Text = ProgressBar.Value.ToString() + "/" + ProgressBar.Maximum.ToString(); 40 | } 41 | 42 | public ProgressBarForm() 43 | { 44 | InitializeComponent(); 45 | } 46 | 47 | private void cancelButton_Click(object sender, EventArgs e) 48 | { 49 | if (BaseForm is FileContainerForm fcForm) fcForm.extractAllBackgroundWorker.CancelAsync(); 50 | } 51 | 52 | private void ProgressBarForm_Load(object sender, EventArgs e) 53 | { 54 | ProgressBar.Value = Value; 55 | ProgressBar.Minimum = 0; 56 | ProgressBar.Maximum = Maximum; 57 | UAGPalette.RefreshTheme(this); 58 | this.AdjustFormPosition(BaseForm); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /UAssetGUI/GitHubAPI.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | namespace UAssetGUI 5 | { 6 | public static class GitHubAPI 7 | { 8 | public static string CombineURI(params string[] uris) 9 | { 10 | string output = ""; 11 | foreach (string uriBit in uris) 12 | { 13 | output += uriBit.Trim('/') + "/"; 14 | } 15 | return output.TrimEnd('/'); 16 | } 17 | 18 | public static string GetLatestVersionURL(string repo) 19 | { 20 | return CombineURI("https://github.com", repo, "releases", "latest"); 21 | } 22 | 23 | public static Version GetLatestVersionFromGitHub(string repo) 24 | { 25 | try 26 | { 27 | HttpWebRequest request = (HttpWebRequest)WebRequest.Create(GetLatestVersionURL(repo)); 28 | request.Method = "GET"; 29 | request.AllowAutoRedirect = false; 30 | request.ContentType = "application/json; charset=utf-8"; 31 | request.UserAgent = "UAssetGUI/" + UAGUtils._displayVersion; 32 | 33 | string newURL = null; 34 | using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 35 | { 36 | newURL = response.Headers["location"]; 37 | } 38 | 39 | if (string.IsNullOrEmpty(newURL)) return null; 40 | string[] splitURL = newURL.Split('/'); 41 | 42 | string finalVersionBit = splitURL[splitURL.Length - 1]; 43 | if (finalVersionBit[0] == 'v') finalVersionBit = finalVersionBit.Substring(1); 44 | finalVersionBit = finalVersionBit.Replace(".0-alpha.", "."); 45 | 46 | Version.TryParse(finalVersionBit, out Version foundVersion); 47 | return foundVersion; 48 | } 49 | catch (Exception ex) 50 | { 51 | if (ex is WebException || ex is FormatException) return null; 52 | throw; 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: 6 | - master 7 | paths-ignore: 8 | - ".github/**" 9 | - ".gitignore" 10 | - "*.md" 11 | 12 | jobs: 13 | build: 14 | runs-on: windows-latest 15 | permissions: 16 | contents: write 17 | 18 | env: 19 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 20 | 21 | steps: 22 | - name: Checkout 23 | uses: actions/checkout@v2 24 | with: 25 | fetch-depth: 0 26 | 27 | - name: .NET Setup 28 | uses: actions/setup-dotnet@v2 29 | with: 30 | dotnet-version: '8.0.x' 31 | 32 | - name: Fetch submodules 33 | run: git submodule update --init --recursive 34 | 35 | - name: Setup MSBuild 36 | uses: microsoft/setup-msbuild@v1.1 37 | 38 | - name: Setup NuGet 39 | uses: NuGet/setup-nuget@v1.0.2 40 | 41 | - name: Navigate to workspace 42 | run: cd $GITHUB_WORKSPACE 43 | 44 | - name: Restore packages 45 | run: nuget restore UAssetGUI.sln 46 | 47 | - name: Build All 48 | run: msbuild UAssetGUI.sln /p:Configuration=ReleaseX 49 | 50 | - name: Build Publish Binary 51 | run: dotnet publish --sc false -c ReleaseX -r win-x64 -p:PublishSingleFile=true -o ./build ./UAssetGUI/UAssetGUI.csproj 52 | 53 | - name: Get Short SHA 54 | id: vars 55 | shell: bash 56 | run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT 57 | 58 | - name: Get Project Version 59 | uses: bbonkr/get-version-action@v1 60 | id: get_version 61 | with: 62 | project: './UAssetGUI/UAssetGUI.csproj' 63 | show_log_message: true 64 | 65 | - name: Upload Build Artifact 66 | uses: actions/upload-artifact@v4.6.1 67 | with: 68 | name: v${{ steps.get_version.outputs.version }}-experimental-${{ steps.vars.outputs.sha_short }} 69 | path: ./build/*.exe 70 | 71 | - name: Make Experimental Pre-Release 72 | uses: softprops/action-gh-release@v2 73 | with: 74 | prerelease: true 75 | tag_name: experimental-latest 76 | name: v${{ steps.get_version.outputs.version }}-experimental-${{ steps.vars.outputs.sha_short }} 77 | files: ./build/*.exe 78 | -------------------------------------------------------------------------------- /UAssetGUI/TextPrompt.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Windows.Forms; 4 | 5 | namespace UAssetGUI 6 | { 7 | 8 | public partial class TextPrompt : Form 9 | { 10 | public string DisplayText = null; 11 | public string OutputText = null; 12 | public string PrefilledText = null; 13 | 14 | public TextPrompt() 15 | { 16 | InitializeComponent(); 17 | } 18 | 19 | private void InitialPathPrompt_Load(object sender, EventArgs e) 20 | { 21 | mainLabel.Text = DisplayText; 22 | if (this.Owner is Form1 parentForm) 23 | { 24 | this.Text = parentForm.Text; 25 | } 26 | if (this.Owner is FileContainerForm parentForm2) 27 | { 28 | this.Text = parentForm2.Text; 29 | } 30 | UAGPalette.RefreshTheme(this); 31 | this.AdjustFormPosition(); 32 | gamePathBox.Size = new Size(this.ClientSize.Width - 24, gamePathBox.ClientSize.Height); 33 | 34 | if (!string.IsNullOrEmpty(PrefilledText)) 35 | { 36 | gamePathBox.Text = PrefilledText; 37 | } 38 | } 39 | 40 | private void RunOKButton() 41 | { 42 | if (gamePathBox.Text != null && gamePathBox.Text.Length > 0) 43 | { 44 | OutputText = gamePathBox.Text; 45 | this.DialogResult = DialogResult.OK; 46 | this.Close(); 47 | } 48 | } 49 | 50 | private void okButton_Click(object sender, EventArgs e) 51 | { 52 | RunOKButton(); 53 | } 54 | 55 | private void RunCancelButton() 56 | { 57 | OutputText = null; 58 | this.DialogResult = DialogResult.Cancel; 59 | this.Close(); 60 | } 61 | 62 | private void cancelButton_Click(object sender, EventArgs e) 63 | { 64 | RunCancelButton(); 65 | } 66 | 67 | private void TextPrompt_KeyDown(object sender, KeyEventArgs e) 68 | { 69 | if (e.KeyCode == Keys.Return) 70 | { 71 | RunOKButton(); 72 | } 73 | else if (e.KeyCode == Keys.Escape) 74 | { 75 | RunCancelButton(); 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /UAssetGUI/MarkdownViewer.cs: -------------------------------------------------------------------------------- 1 | using Markdig; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.ComponentModel; 5 | using System.Data; 6 | using System.Drawing; 7 | using System.Linq; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | using System.Windows.Forms; 11 | 12 | namespace UAssetGUI 13 | { 14 | public partial class MarkdownViewer : Form 15 | { 16 | public string MarkdownToDisplay = string.Empty; 17 | 18 | public MarkdownViewer() 19 | { 20 | InitializeComponent(); 21 | } 22 | 23 | private void MarkdownViewer_Load(object sender, EventArgs e) 24 | { 25 | UAGPalette.RefreshTheme(this); 26 | this.AdjustFormPosition(); 27 | 28 | var pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build(); 29 | string stylingHTML = ""; 30 | string finalHTML = stylingHTML + "" + Markdown.ToHtml(MarkdownToDisplay, pipeline) + ""; 31 | 32 | this.browser1.DocumentText = finalHTML; 33 | 34 | ForceResize(); 35 | } 36 | 37 | private void closeButton_Click(object sender, EventArgs e) 38 | { 39 | this.Dispose(); 40 | } 41 | 42 | internal void ForceResize() 43 | { 44 | this.browser1.Size = new Size(this.ClientSize.Width, this.ClientSize.Height - this.closeButton.Height - 20); 45 | this.closeButton.Location = new Point(this.ClientSize.Width - this.closeButton.Width - 10, this.ClientSize.Height - this.closeButton.Height - 10); 46 | } 47 | 48 | private void MarkdownViewer_Resize(object sender, EventArgs e) 49 | { 50 | ForceResize(); 51 | } 52 | 53 | private void browser1_Navigating(object sender, WebBrowserNavigatingEventArgs e) 54 | { 55 | string scheme = e.Url?.Scheme; 56 | if (scheme == "http" || scheme == "https") 57 | { 58 | e.Cancel = true; 59 | UAGUtils.OpenURL(e.Url.ToString()); 60 | } 61 | // otherwise, presumably "navigating" to raw HTML (scheme == "about") 62 | // not really worried about implementing this in a more secure way 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /UAssetGUI/MarkdownViewer.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UAssetGUI 2 | { 3 | partial class MarkdownViewer 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | browser1 = new System.Windows.Forms.WebBrowser(); 32 | closeButton = new System.Windows.Forms.Button(); 33 | SuspendLayout(); 34 | // 35 | // browser1 36 | // 37 | browser1.Dock = System.Windows.Forms.DockStyle.Top; 38 | browser1.Location = new System.Drawing.Point(0, 0); 39 | browser1.Name = "browser1"; 40 | browser1.Size = new System.Drawing.Size(619, 408); 41 | browser1.TabIndex = 0; 42 | browser1.Navigating += browser1_Navigating; 43 | // 44 | // closeButton 45 | // 46 | closeButton.Anchor = System.Windows.Forms.AnchorStyles.None; 47 | closeButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 48 | closeButton.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Bold); 49 | closeButton.ForeColor = System.Drawing.SystemColors.ControlText; 50 | closeButton.Location = new System.Drawing.Point(518, 414); 51 | closeButton.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 52 | closeButton.Name = "closeButton"; 53 | closeButton.Size = new System.Drawing.Size(88, 30); 54 | closeButton.TabIndex = 5; 55 | closeButton.Text = "Close"; 56 | closeButton.UseVisualStyleBackColor = true; 57 | closeButton.Click += closeButton_Click; 58 | // 59 | // MarkdownViewer 60 | // 61 | AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); 62 | AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 63 | ClientSize = new System.Drawing.Size(619, 454); 64 | Controls.Add(closeButton); 65 | Controls.Add(browser1); 66 | Font = new System.Drawing.Font("Microsoft Sans Serif", 10F); 67 | Name = "MarkdownViewer"; 68 | Text = "MarkdownViewer"; 69 | Load += MarkdownViewer_Load; 70 | Resize += MarkdownViewer_Resize; 71 | ResumeLayout(false); 72 | } 73 | 74 | #endregion 75 | 76 | private System.Windows.Forms.WebBrowser browser1; 77 | private System.Windows.Forms.Button closeButton; 78 | } 79 | } -------------------------------------------------------------------------------- /UAssetGUI/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.IO; 4 | using System.Runtime.InteropServices; 5 | using System.Windows.Forms; 6 | using UAssetAPI; 7 | using UAssetAPI.UnrealTypes; 8 | using UAssetAPI.Unversioned; 9 | 10 | namespace UAssetGUI 11 | { 12 | static class Program 13 | { 14 | [DllImport("user32.dll")] 15 | private static extern bool SetProcessDPIAware(); 16 | 17 | /// 18 | /// The main entry point for the application. 19 | /// 20 | [STAThread] 21 | static void Main() 22 | { 23 | if (Environment.OSVersion.Version.Major >= 6) SetProcessDPIAware(); 24 | Application.EnableVisualStyles(); 25 | Application.SetCompatibleTextRenderingDefault(false); 26 | Application.SetDefaultFont(new Font(new FontFamily("Microsoft Sans Serif"), 8.25f)); // default font changed in .NET Core 3.0 27 | 28 | string[] args = Environment.GetCommandLineArgs(); 29 | if (args.Length >= 2) 30 | { 31 | Usmap selectedMappings = null; 32 | 33 | switch (args[1].ToLowerInvariant()) 34 | { 35 | // tojson [mappings name] 36 | // UAssetGUI tojson A.umap B.json 23 Outriders 37 | case "tojson": 38 | UAGConfig.LoadMappings(); 39 | 40 | if (args.Length < 5) break; 41 | if (args.Length >= 6) UAGConfig.TryGetMappings(args[5], out selectedMappings); 42 | 43 | EngineVersion selectedVer = EngineVersion.UNKNOWN; 44 | if (int.TryParse(args[4], out int selectedVerRaw)) selectedVer = EngineVersion.VER_UE4_0 + selectedVerRaw; 45 | else Enum.TryParse(args[4], out selectedVer); 46 | 47 | string jsonSerializedAsset = new UAsset(args[2], selectedVer, selectedMappings).SerializeJson(Newtonsoft.Json.Formatting.Indented); 48 | File.WriteAllText(args[3], jsonSerializedAsset); 49 | return; 50 | // fromjson [mappings name] 51 | // UAssetGUI fromjson B.json A.umap Outriders 52 | case "fromjson": 53 | UAGConfig.LoadMappings(); 54 | 55 | if (args.Length < 4) break; 56 | if (args.Length >= 5) UAGConfig.TryGetMappings(args[4], out selectedMappings); 57 | 58 | UAsset jsonDeserializedAsset = null; 59 | using (var sr = new FileStream(args[2], FileMode.Open)) 60 | { 61 | jsonDeserializedAsset = UAsset.DeserializeJson(sr); 62 | } 63 | 64 | if (jsonDeserializedAsset != null) 65 | { 66 | jsonDeserializedAsset.Mappings = selectedMappings; 67 | jsonDeserializedAsset.Write(args[3]); 68 | } 69 | return; 70 | } 71 | } 72 | 73 | Form1 f1 = new Form1 74 | { 75 | Size = new System.Drawing.Size(1000, 700) 76 | }; 77 | Application.Run(f1); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /UAssetGUI/AboutForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | using System.Windows.Forms; 5 | 6 | namespace UAssetGUI 7 | { 8 | public partial class AboutForm : Form 9 | { 10 | public string AboutText 11 | { 12 | get 13 | { 14 | return label1.Text; 15 | } 16 | set 17 | { 18 | label1.Text = value; 19 | } 20 | } 21 | 22 | public AboutForm() 23 | { 24 | InitializeComponent(); 25 | } 26 | 27 | private Form1 BaseForm; 28 | private void AboutForm_Load(object sender, EventArgs e) 29 | { 30 | if (this.Owner is Form1) BaseForm = (Form1)this.Owner; 31 | 32 | UAGPalette.RefreshTheme(this); 33 | this.AdjustFormPosition(); 34 | } 35 | 36 | private void closeButton_Click(object sender, EventArgs e) 37 | { 38 | this.Dispose(); 39 | } 40 | 41 | private void licenseButton_Click(object sender, EventArgs e) 42 | { 43 | UAGUtils.InvokeUI(() => 44 | { 45 | string rawMarkdownText = string.Empty; 46 | using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("UAssetGUI.LICENSE")) 47 | { 48 | if (stream != null) 49 | { 50 | using (StreamReader reader = new StreamReader(stream)) 51 | { 52 | if (reader != null) rawMarkdownText = reader.ReadToEnd().Trim(); 53 | } 54 | } 55 | } 56 | 57 | if (string.IsNullOrEmpty(rawMarkdownText)) 58 | { 59 | UAGUtils.OpenURL("https://github.com/" + Form1.GitHubRepo + "/blob/master/LICENSE"); 60 | return; 61 | } 62 | 63 | var formPopup = new MarkdownViewer(); 64 | formPopup.MarkdownToDisplay = "```\n" + rawMarkdownText + "\n```"; 65 | formPopup.Text = "License"; 66 | formPopup.StartPosition = FormStartPosition.CenterParent; 67 | formPopup.ShowDialog(this); 68 | }); 69 | } 70 | 71 | private void noticeButton_Click(object sender, EventArgs e) 72 | { 73 | UAGUtils.InvokeUI(() => 74 | { 75 | string rawMarkdownText = string.Empty; 76 | using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("UAssetGUI.NOTICE.md")) 77 | { 78 | if (stream != null) 79 | { 80 | using (StreamReader reader = new StreamReader(stream)) 81 | { 82 | if (reader != null) rawMarkdownText = reader.ReadToEnd().Trim(); 83 | } 84 | } 85 | } 86 | 87 | if (string.IsNullOrEmpty(rawMarkdownText)) 88 | { 89 | UAGUtils.OpenURL("https://github.com/" + Form1.GitHubRepo + "/blob/master/NOTICE.md"); 90 | return; 91 | } 92 | 93 | var formPopup = new MarkdownViewer(); 94 | formPopup.MarkdownToDisplay = rawMarkdownText; 95 | formPopup.Text = "List of 3rd-party software"; 96 | formPopup.StartPosition = FormStartPosition.CenterParent; 97 | formPopup.ShowDialog(this); 98 | }); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /UAssetGUI/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace UAssetGUI.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// Returns the cached ResourceManager instance used by this class. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("UAssetGUI.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// Overrides the current thread's CurrentUICulture property for all 51 | /// resource lookups using this strongly typed resource class. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// Looks up a localized resource of type System.Byte[]. 65 | /// 66 | internal static byte[] dancing_cat { 67 | get { 68 | object obj = ResourceManager.GetObject("dancing_cat", resourceCulture); 69 | return ((byte[])(obj)); 70 | } 71 | } 72 | 73 | /// 74 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). 75 | /// 76 | internal static System.Drawing.Icon icon { 77 | get { 78 | object obj = ResourceManager.GetObject("icon", resourceCulture); 79 | return ((System.Drawing.Icon)(obj)); 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /UAssetGUI/ProgressBarForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UAssetGUI 2 | { 3 | partial class ProgressBarForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | ProgressBar = new System.Windows.Forms.ProgressBar(); 32 | cancelButton = new System.Windows.Forms.Button(); 33 | label1 = new System.Windows.Forms.Label(); 34 | SuspendLayout(); 35 | // 36 | // ProgressBar 37 | // 38 | ProgressBar.Location = new System.Drawing.Point(18, 17); 39 | ProgressBar.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 40 | ProgressBar.Name = "ProgressBar"; 41 | ProgressBar.Size = new System.Drawing.Size(201, 51); 42 | ProgressBar.TabIndex = 14; 43 | // 44 | // cancelButton 45 | // 46 | cancelButton.Anchor = System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right; 47 | cancelButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 48 | cancelButton.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Bold); 49 | cancelButton.ForeColor = System.Drawing.SystemColors.ControlText; 50 | cancelButton.Location = new System.Drawing.Point(134, 79); 51 | cancelButton.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3); 52 | cancelButton.Name = "cancelButton"; 53 | cancelButton.Size = new System.Drawing.Size(90, 31); 54 | cancelButton.TabIndex = 15; 55 | cancelButton.Text = "Cancel..."; 56 | cancelButton.UseVisualStyleBackColor = true; 57 | cancelButton.Click += cancelButton_Click; 58 | // 59 | // label1 60 | // 61 | label1.Location = new System.Drawing.Point(16, 79); 62 | label1.Name = "label1"; 63 | label1.Size = new System.Drawing.Size(95, 30); 64 | label1.TabIndex = 16; 65 | label1.Text = "label1"; 66 | label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 67 | // 68 | // ProgressBarForm 69 | // 70 | AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); 71 | AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 72 | ClientSize = new System.Drawing.Size(237, 122); 73 | Controls.Add(label1); 74 | Controls.Add(cancelButton); 75 | Controls.Add(ProgressBar); 76 | FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 77 | MaximizeBox = false; 78 | MinimizeBox = false; 79 | Name = "ProgressBarForm"; 80 | Text = "ProgressBarForm"; 81 | Load += ProgressBarForm_Load; 82 | ResumeLayout(false); 83 | } 84 | 85 | #endregion 86 | 87 | public System.Windows.Forms.ProgressBar ProgressBar; 88 | private System.Windows.Forms.Button cancelButton; 89 | private System.Windows.Forms.Label label1; 90 | } 91 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UAssetGUI 2 | [![Release](https://img.shields.io/github/v/release/atenfyr/UAssetGUI.svg?style=flat-square)](https://github.com/atenfyr/UAssetGUI/releases/latest) 3 | [![Downloads](https://img.shields.io/github/downloads/atenfyr/UAssetGUI/total.svg?style=flat-square)](https://github.com/atenfyr/UAssetGUI/releases) 4 | [![Issues](https://img.shields.io/github/issues/atenfyr/UAssetGUI.svg?style=flat-square)](https://github.com/atenfyr/UAssetGUI/issues) 5 | [![CI Status](https://img.shields.io/github/actions/workflow/status/atenfyr/UAssetGUI/build.yml?label=CI)](https://github.com/atenfyr/UAssetGUI/actions) 6 | [![License](https://img.shields.io/github/license/atenfyr/UAssetGUI.svg?style=flat-square)](https://github.com/atenfyr/UAssetGUI/blob/master/LICENSE.md) 7 | 8 | UAssetGUI is a tool designed for low-level examination and modification of Unreal Engine game assets by hand. 9 | 10 | 11 | 12 | ## Installation 13 | You can find pre-built binaries of UAssetGUI in the [Releases tab of this repository](https://github.com/atenfyr/UAssetGUI/releases). 14 | 15 | ## Command line arguments 16 | You can run the program with command line arguments to perform various tasks, such as exporting and importing from UAssetAPI JSON without opening the GUI. 17 | 18 | In the following cases, the engine version can either be specified as an EngineVersion enum entry (e.g. `VER_UE4_23` to refer to 4.23, `VER_UE5_0` to refer to 5.0, etc.) or as an integer (e.g. `23` to refer to 4.23, `29` to refer to 5.0, etc.). Specifying a set of mappings is optional, but if specified, must be the name of a file within the Mappings config directory (with no extension). 19 | 20 | ### Export to JSON 21 | ``` 22 | UAssetGUI tojson [mappings name] 23 | ``` 24 | 25 | Example 1: `UAssetGUI tojson A.uasset B.json VER_UE5_1` 26 | 27 | Example 2: `UAssetGUI tojson A.uasset B.json 27 Astro` 28 | 29 | ### Import from JSON 30 | ``` 31 | UAssetGUI fromjson [mappings name] 32 | ``` 33 | 34 | Example 1: `UAssetGUI fromjson B.json A.umap` 35 | 36 | Example 2: `UAssetGUI fromjson B.json A.umap Outriders` 37 | 38 | ### Open a specific file in the GUI 39 | ``` 40 | UAssetGUI [file name] [engine version] [mappings name] 41 | ``` 42 | 43 | Example 1: `UAssetGUI` (to simply open the GUI without opening a file) 44 | 45 | Example 2: `UAssetGUI test.uasset` 46 | 47 | Example 3: `UAssetGUI test.uasset 23` 48 | 49 | Example 4: `UAssetGUI test.uasset VER_UE5_4 Bellwright` 50 | 51 | ## Compilation 52 | If you'd like to compile UAssetGUI for yourself, read on: 53 | 54 | ### Prerequisites 55 | * Visual Studio 2022 or later 56 | * Git 57 | 58 | ### Initial Setup 59 | 1. Clone the UAssetGUI repository: 60 | 61 | ```sh 62 | git clone https://github.com/atenfyr/UAssetGUI.git 63 | ``` 64 | 65 | 2. Switch to the new UAssetGUI directory: 66 | 67 | ```sh 68 | cd UAssetGUI 69 | ``` 70 | 71 | 3. Pull the required submodules: 72 | 73 | ```sh 74 | git submodule update --init 75 | ``` 76 | 77 | 4. Open the `UAssetGUI.sln` solution file in Visual Studio, right-click on the UAssetGUI project in the Solution Explorer, and click "Set as Startup Project." 78 | 79 | 5. Right-click on the solution name in the Solution Explorer, and press "Restore Nuget Packages." 80 | 81 | 6. Press the "Start" button or press F5 to compile and open UAssetGUI. 82 | 83 | ## Contributing 84 | Any contributions, whether through pull requests or issues, that you make are greatly appreciated. 85 | 86 | If you have an Unreal Engine .uasset file that displays "failed to maintain binary equality," feel free to submit an issue on [the UAssetAPI issues page](https://github.com/atenfyr/UAssetAPI/issues) with a copy of the asset in question along with the name of the game, the Unreal version that it was cooked with, and a mappings file for the game, if needed. 87 | 88 | ## License 89 | UAssetAPI and UAssetGUI are distributed under the MIT license, which you can view in detail in the [LICENSE file](LICENSE). 90 | -------------------------------------------------------------------------------- /UAssetGUI/TextPrompt.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /UAssetGUI/AboutForm.Designer.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace UAssetGUI 3 | { 4 | partial class AboutForm 5 | { 6 | /// 7 | /// Required designer variable. 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// Clean up any resources being used. 13 | /// 14 | /// true if managed resources should be disposed; otherwise, false. 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Windows Form Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | this.closeButton = new System.Windows.Forms.Button(); 33 | this.licenseButton = new System.Windows.Forms.Button(); 34 | this.label1 = new System.Windows.Forms.Label(); 35 | this.noticeButton = new System.Windows.Forms.Button(); 36 | this.SuspendLayout(); 37 | // 38 | // closeButton 39 | // 40 | this.closeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 41 | this.closeButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 42 | this.closeButton.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Bold); 43 | this.closeButton.ForeColor = System.Drawing.SystemColors.ControlText; 44 | this.closeButton.Location = new System.Drawing.Point(320, 274); 45 | this.closeButton.Name = "closeButton"; 46 | this.closeButton.Size = new System.Drawing.Size(75, 26); 47 | this.closeButton.TabIndex = 4; 48 | this.closeButton.Text = "Close"; 49 | this.closeButton.UseVisualStyleBackColor = true; 50 | this.closeButton.Click += new System.EventHandler(this.closeButton_Click); 51 | // 52 | // licenseButton 53 | // 54 | this.licenseButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 55 | this.licenseButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 56 | this.licenseButton.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Bold); 57 | this.licenseButton.ForeColor = System.Drawing.SystemColors.ControlText; 58 | this.licenseButton.Location = new System.Drawing.Point(12, 274); 59 | this.licenseButton.Name = "licenseButton"; 60 | this.licenseButton.Size = new System.Drawing.Size(103, 26); 61 | this.licenseButton.TabIndex = 2; 62 | this.licenseButton.Text = "View license..."; 63 | this.licenseButton.UseVisualStyleBackColor = true; 64 | this.licenseButton.Click += new System.EventHandler(this.licenseButton_Click); 65 | // 66 | // label1 67 | // 68 | this.label1.Dock = System.Windows.Forms.DockStyle.Top; 69 | this.label1.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F); 70 | this.label1.Location = new System.Drawing.Point(0, 0); 71 | this.label1.Name = "label1"; 72 | this.label1.Size = new System.Drawing.Size(407, 271); 73 | this.label1.TabIndex = 1; 74 | this.label1.Text = "AboutText should be overridden before displaying this form"; 75 | this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 76 | // 77 | // noticeButton 78 | // 79 | this.noticeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 80 | this.noticeButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 81 | this.noticeButton.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Bold); 82 | this.noticeButton.ForeColor = System.Drawing.SystemColors.ControlText; 83 | this.noticeButton.Location = new System.Drawing.Point(121, 274); 84 | this.noticeButton.Name = "noticeButton"; 85 | this.noticeButton.Size = new System.Drawing.Size(161, 26); 86 | this.noticeButton.TabIndex = 3; 87 | this.noticeButton.Text = "View 3rd-party software..."; 88 | this.noticeButton.UseVisualStyleBackColor = true; 89 | this.noticeButton.Click += new System.EventHandler(this.noticeButton_Click); 90 | // 91 | // AboutForm 92 | // 93 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 94 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 95 | this.ClientSize = new System.Drawing.Size(407, 312); 96 | this.Controls.Add(this.noticeButton); 97 | this.Controls.Add(this.label1); 98 | this.Controls.Add(this.licenseButton); 99 | this.Controls.Add(this.closeButton); 100 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 101 | this.Name = "AboutForm"; 102 | this.Text = "About"; 103 | this.Load += new System.EventHandler(this.AboutForm_Load); 104 | this.ResumeLayout(false); 105 | 106 | } 107 | 108 | #endregion 109 | 110 | private System.Windows.Forms.Button closeButton; 111 | private System.Windows.Forms.Button licenseButton; 112 | private System.Windows.Forms.Label label1; 113 | private System.Windows.Forms.Button noticeButton; 114 | } 115 | } -------------------------------------------------------------------------------- /UAssetGUI/SettingsForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /UAssetGUI/MarkdownViewer.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /UAssetGUI/ProgressBarForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /UAssetGUI/FindForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /UAssetGUI/AboutForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /UAssetGUI/MapStructTypeOverrideForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /UAssetGUI/Form1.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 166, 17 122 | 123 | 124 | 17, 17 125 | 126 | -------------------------------------------------------------------------------- /UAssetGUI/FileContainerForm.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | 124 | 132, 17 125 | 126 | -------------------------------------------------------------------------------- /UAssetGUI/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 122 | ..\Resources\dancing_cat.gif;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 123 | 124 | 125 | ..\Resources\icon.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a 126 | 127 | -------------------------------------------------------------------------------- /UAssetGUI/TextPrompt.Designer.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace UAssetGUI 4 | { 5 | partial class TextPrompt 6 | { 7 | /// 8 | /// Required designer variable. 9 | /// 10 | private System.ComponentModel.IContainer components = null; 11 | 12 | /// 13 | /// Clean up any resources being used. 14 | /// 15 | /// true if managed resources should be disposed; otherwise, false. 16 | protected override void Dispose(bool disposing) 17 | { 18 | if (disposing && (components != null)) 19 | { 20 | components.Dispose(); 21 | } 22 | base.Dispose(disposing); 23 | } 24 | 25 | #region Windows Form Designer generated code 26 | 27 | /// 28 | /// Required method for Designer support - do not modify 29 | /// the contents of this method with the code editor. 30 | /// 31 | private void InitializeComponent() 32 | { 33 | this.mainLabel = new System.Windows.Forms.Label(); 34 | this.gamePathBox = new System.Windows.Forms.TextBox(); 35 | this.cancelButton = new System.Windows.Forms.Button(); 36 | this.okButton = new System.Windows.Forms.Button(); 37 | this.SuspendLayout(); 38 | // 39 | // mainLabel 40 | // 41 | this.mainLabel.Anchor = System.Windows.Forms.AnchorStyles.Top; 42 | this.mainLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F); 43 | this.mainLabel.Location = new System.Drawing.Point(12, 13); 44 | this.mainLabel.Name = "mainLabel"; 45 | this.mainLabel.Size = new System.Drawing.Size(361, 20); 46 | this.mainLabel.TabIndex = 4; 47 | this.mainLabel.Text = "Select your game installation directory:"; 48 | this.mainLabel.TextAlign = System.Drawing.ContentAlignment.TopCenter; 49 | // 50 | // gamePathBox 51 | // 52 | this.gamePathBox.Anchor = System.Windows.Forms.AnchorStyles.Left; 53 | this.gamePathBox.Location = new System.Drawing.Point(12, 47); 54 | this.gamePathBox.Name = "gamePathBox"; 55 | this.gamePathBox.Size = new System.Drawing.Size(361, 20); 56 | this.gamePathBox.TabIndex = 0; 57 | this.gamePathBox.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextPrompt_KeyDown); 58 | // 59 | // cancelButton 60 | // 61 | this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 62 | this.cancelButton.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(51)))), ((int)(((byte)(51)))), ((int)(((byte)(51))))); 63 | this.cancelButton.FlatAppearance.BorderColor = System.Drawing.Color.Black; 64 | this.cancelButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 65 | this.cancelButton.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 66 | this.cancelButton.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(225)))), ((int)(((byte)(225)))), ((int)(((byte)(225))))); 67 | this.cancelButton.Location = new System.Drawing.Point(70, 79); 68 | this.cancelButton.MinimumSize = new System.Drawing.Size(0, 26); 69 | this.cancelButton.Name = "cancelButton"; 70 | this.cancelButton.Size = new System.Drawing.Size(67, 26); 71 | this.cancelButton.TabIndex = 3; 72 | this.cancelButton.Text = "Cancel"; 73 | this.cancelButton.UseVisualStyleBackColor = false; 74 | this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click); 75 | // 76 | // okButton 77 | // 78 | this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 79 | this.okButton.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(51)))), ((int)(((byte)(51)))), ((int)(((byte)(51))))); 80 | this.okButton.FlatAppearance.BorderColor = System.Drawing.Color.Black; 81 | this.okButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 82 | this.okButton.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); 83 | this.okButton.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(225)))), ((int)(((byte)(225)))), ((int)(((byte)(225))))); 84 | this.okButton.Location = new System.Drawing.Point(15, 79); 85 | this.okButton.MinimumSize = new System.Drawing.Size(0, 26); 86 | this.okButton.Name = "okButton"; 87 | this.okButton.Size = new System.Drawing.Size(49, 26); 88 | this.okButton.TabIndex = 2; 89 | this.okButton.Text = "OK"; 90 | this.okButton.UseVisualStyleBackColor = false; 91 | this.okButton.Click += new System.EventHandler(this.okButton_Click); 92 | // 93 | // TextPrompt 94 | // 95 | this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); 96 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; 97 | this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(40)))), ((int)(((byte)(42)))), ((int)(((byte)(45))))); 98 | this.ClientSize = new System.Drawing.Size(385, 114); 99 | this.Controls.Add(this.cancelButton); 100 | this.Controls.Add(this.okButton); 101 | this.Controls.Add(this.gamePathBox); 102 | this.Controls.Add(this.mainLabel); 103 | this.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(225)))), ((int)(((byte)(225)))), ((int)(((byte)(225))))); 104 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 105 | this.MaximizeBox = false; 106 | this.Name = "TextPrompt"; 107 | this.Text = "InitialPathPrompt"; 108 | this.Load += new System.EventHandler(this.InitialPathPrompt_Load); 109 | this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.TextPrompt_KeyDown); 110 | this.ResumeLayout(false); 111 | this.PerformLayout(); 112 | 113 | } 114 | 115 | #endregion 116 | 117 | private System.Windows.Forms.Label mainLabel; 118 | private System.Windows.Forms.TextBox gamePathBox; 119 | private Button okButton; 120 | private Button cancelButton; 121 | } 122 | } -------------------------------------------------------------------------------- /UAssetGUI/UAssetGUI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | {88A998F1-C512-416F-ADED-120E50AFE6F3} 4 | WinExe 5 | net8.0-windows 6 | true 7 | false 8 | true 9 | UAssetGUI 10 | UAssetGUI 11 | Copyright © Atenfyr 2024 12 | 1.0.4.0 13 | 1.0.4.0 14 | bin\$(Configuration)\ 15 | Debug;Release;DebugVerbose;DebugTracing;ReleaseX 16 | true 17 | false 18 | AnyCPU;x86 19 | 20 | 21 | full 22 | 23 | 24 | full 25 | 26 | 27 | full 28 | 29 | 30 | full 31 | 32 | 33 | full 34 | 35 | 36 | full 37 | 38 | 39 | embedded 40 | 41 | 42 | embedded 43 | True 44 | 45 | 46 | embedded 47 | 48 | 49 | embedded 50 | True 51 | 52 | 53 | Resources\icon.ico 54 | true 55 | 1.0.4 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | Component 73 | 74 | 75 | Form 76 | 77 | 78 | FindForm.cs 79 | 80 | 81 | Form 82 | 83 | 84 | AboutForm.cs 85 | 86 | 87 | Form 88 | 89 | 90 | Form1.cs 91 | 92 | 93 | Form 94 | 95 | 96 | MapStructTypeOverrideForm.cs 97 | 98 | 99 | Form 100 | 101 | 102 | SettingsForm.cs 103 | 104 | 105 | Form 106 | 107 | 108 | TextPrompt.cs 109 | 110 | 111 | FindForm.cs 112 | 113 | 114 | AboutForm.cs 115 | 116 | 117 | Form1.cs 118 | Designer 119 | 120 | 121 | MapStructTypeOverrideForm.cs 122 | 123 | 124 | ResXFileCodeGenerator 125 | Resources.Designer.cs 126 | Designer 127 | 128 | 129 | True 130 | Resources.resx 131 | True 132 | 133 | 134 | SettingsForm.cs 135 | 136 | 137 | TextPrompt.cs 138 | 139 | 140 | 141 | 142 | 143 | Never 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | all 155 | 156 | 157 | 158 | all 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /UAssetGUI/UAGUtils.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Drawing; 6 | using System.Reflection; 7 | using System.Text; 8 | using System.Windows.Forms; 9 | using UAssetAPI; 10 | using UAssetAPI.UnrealTypes; 11 | 12 | namespace UAssetGUI 13 | { 14 | public static class UAGUtils 15 | { 16 | internal static string _displayVersion = string.Empty; 17 | 18 | public static T TryGetElement(this T[] array, int index) 19 | { 20 | if (array != null && index < array.Length) 21 | { 22 | return array[index]; 23 | } 24 | return default(T); 25 | } 26 | 27 | public static object ArbitraryTryParse(this string input, Type type) 28 | { 29 | try 30 | { 31 | var converter = TypeDescriptor.GetConverter(type); 32 | if (converter != null) 33 | { 34 | return converter.ConvertFromString(input); 35 | } 36 | } 37 | catch (NotSupportedException) { } 38 | return null; 39 | } 40 | 41 | public static ContextMenuStrip MergeContextMenus(ContextMenuStrip one, ContextMenuStrip two) 42 | { 43 | if (one == null) return two; 44 | if (two == null) return one; 45 | 46 | one.Items.AddRange(two.Items); 47 | return one; 48 | } 49 | 50 | // ((Form1)x.DataGridView.Parent).nameMapContext; 51 | public static void UpdateContextMenuStripOfRow(DataGridViewRow x, ContextMenuStrip strip) 52 | { 53 | x.ContextMenuStrip = MergeContextMenus(x.ContextMenuStrip, strip); 54 | x.HeaderCell.ContextMenuStrip = MergeContextMenus(x.HeaderCell.ContextMenuStrip, strip); 55 | foreach (DataGridViewCell y in x.Cells) 56 | { 57 | y.ContextMenuStrip = MergeContextMenus(y.ContextMenuStrip, strip); 58 | } 59 | } 60 | 61 | public static void AdjustFormPosition(this Form frm1, Form overrideOwner = null) 62 | { 63 | if (overrideOwner == null) overrideOwner = frm1.Owner; 64 | if (overrideOwner != null) frm1.Location = new Point((overrideOwner.Location.X + overrideOwner.Width / 2) - (frm1.Width / 2), (overrideOwner.Location.Y + overrideOwner.Height / 2) - (frm1.Height / 2)); 65 | } 66 | 67 | public static void UpdateObjectPropertyValues(UAsset asset, DataGridViewRow row, DataGridView dgv, FPackageIndex objData, int column = 3) 68 | { 69 | if (dgv == null || row == null || objData == null) return; 70 | 71 | bool underlineStyle = false; 72 | if (objData.IsImport() && objData == null) 73 | { 74 | row.Cells[column].Value = string.Empty; 75 | } 76 | else 77 | { 78 | row.Cells[column].Value = objData.IsExport() ? "Jump" : (objData.IsImport() ? objData.ToImport(asset)?.ObjectName?.ToString() : string.Empty); 79 | row.Cells[column].Tag = "CategoryJump"; 80 | if (objData.IsExport()) underlineStyle = true; 81 | } 82 | row.Cells[column].ReadOnly = objData.IsImport(); 83 | 84 | DataGridViewCellStyle sty = new DataGridViewCellStyle(); 85 | if (underlineStyle) 86 | { 87 | Font styFont = new Font(dgv.Font.Name, UAGPalette.RecommendedFontSize, FontStyle.Underline); 88 | sty.Font = styFont; 89 | sty.ForeColor = UAGPalette.LinkColor; 90 | } 91 | row.Cells[column].Style = sty; 92 | } 93 | 94 | public static T[] StripNullsFromArray(this T[] usArr) 95 | { 96 | int c = 0; 97 | for (int num = 0; num < usArr.Length; num++) 98 | { 99 | if (usArr[num] != null) c++; 100 | } 101 | 102 | var newData = new T[c]; 103 | int indexAdded = 0; 104 | for (int num = 0; num < usArr.Length; num++) 105 | { 106 | if (usArr[num] != null) newData[indexAdded++] = usArr[num]; 107 | } 108 | return newData; 109 | } 110 | 111 | public static List StripNullsFromList(this List usList) 112 | { 113 | for (int num = 0; num < usList.Count; num++) 114 | { 115 | if (usList[num] == null) 116 | { 117 | usList.RemoveAt(num); 118 | num--; 119 | } 120 | } 121 | return usList; 122 | } 123 | 124 | public static string ConvertByteArrayToString(this byte[] val) 125 | { 126 | if (val == null) return ""; 127 | return BitConverter.ToString(val).Replace("-", " "); 128 | } 129 | 130 | public static byte[] ConvertStringToByteArray(this string val) 131 | { 132 | if (string.IsNullOrWhiteSpace(val)) return Array.Empty(); 133 | string[] rawStringArr = val.Split(' '); 134 | byte[] byteArr = new byte[rawStringArr.Length]; 135 | for (int i = 0; i < rawStringArr.Length; i++) byteArr[i] = Convert.ToByte(rawStringArr[i], 16); 136 | return byteArr; 137 | } 138 | 139 | public static string ShortcutToText(Keys shortcutKeys) 140 | { 141 | return TypeDescriptor.GetConverter(typeof(Keys)).ConvertToString(shortcutKeys); 142 | } 143 | 144 | /* 145 | UAssetGUI versions are formatted as follows: MAJOR.MINOR.BUILD 146 | * MAJOR - incremented for very big changes or backwards-incompatible changes 147 | * MINOR - incremented for notable changes 148 | * BUILD - incremented for bug fixes or very small improvements 149 | */ 150 | public static bool IsUAGVersionLower(this Version v1) 151 | { 152 | Version fullUagVersion = new Version(Assembly.GetExecutingAssembly().GetCustomAttribute().InformationalVersion); 153 | return v1.CompareTo(fullUagVersion) > 0; 154 | } 155 | 156 | public static string FEncode(this FString val) 157 | { 158 | if (val == null) return FString.NullCase; 159 | return val.Value.Replace("\n", "\\n").Replace("\r", "\\r"); 160 | } 161 | 162 | public static FString FDecode(this string val, string encodingHeaderName) 163 | { 164 | if (val == FString.NullCase) return null; 165 | return FString.FromString(val.Replace("\\n", "\n").Replace("\\r", "\r"), encodingHeaderName.Equals(Encoding.Unicode.HeaderName) ? Encoding.Unicode : Encoding.ASCII); 166 | } 167 | 168 | public static void OpenURL(string url) 169 | { 170 | Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }); 171 | } 172 | 173 | public static void OpenDirectory(string dir) 174 | { 175 | Process.Start(new ProcessStartInfo() 176 | { 177 | FileName = dir, 178 | UseShellExecute = true, 179 | Verb = "open" 180 | }); 181 | } 182 | 183 | private static Control internalForm; 184 | public static void InitializeInvoke(Control control) 185 | { 186 | internalForm = control; 187 | } 188 | 189 | public static bool InvokeUI(Action act) 190 | { 191 | if (internalForm == null) return false; 192 | if (internalForm.InvokeRequired) 193 | { 194 | internalForm.Invoke(act); 195 | } 196 | else 197 | { 198 | act(); 199 | } 200 | return true; 201 | } 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /UAssetGUI/FodyWeavers.xsd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks 13 | 14 | 15 | 16 | 17 | A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. 18 | 19 | 20 | 21 | 22 | A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks 23 | 24 | 25 | 26 | 27 | A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. 28 | 29 | 30 | 31 | 32 | A list of unmanaged 32 bit assembly names to include, delimited with line breaks. 33 | 34 | 35 | 36 | 37 | A list of unmanaged 64 bit assembly names to include, delimited with line breaks. 38 | 39 | 40 | 41 | 42 | The order of preloaded assemblies, delimited with line breaks. 43 | 44 | 45 | 46 | 47 | 48 | This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. 49 | 50 | 51 | 52 | 53 | Controls if .pdbs for reference assemblies are also embedded. 54 | 55 | 56 | 57 | 58 | Controls if runtime assemblies are also embedded. 59 | 60 | 61 | 62 | 63 | Controls whether the runtime assemblies are embedded with their full path or only with their assembly name. 64 | 65 | 66 | 67 | 68 | Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. 69 | 70 | 71 | 72 | 73 | As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. 74 | 75 | 76 | 77 | 78 | Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. 79 | 80 | 81 | 82 | 83 | Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. 84 | 85 | 86 | 87 | 88 | A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | 89 | 90 | 91 | 92 | 93 | A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. 94 | 95 | 96 | 97 | 98 | A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with | 99 | 100 | 101 | 102 | 103 | A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |. 104 | 105 | 106 | 107 | 108 | A list of unmanaged 32 bit assembly names to include, delimited with |. 109 | 110 | 111 | 112 | 113 | A list of unmanaged 64 bit assembly names to include, delimited with |. 114 | 115 | 116 | 117 | 118 | The order of preloaded assemblies, delimited with |. 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. 127 | 128 | 129 | 130 | 131 | A comma-separated list of error codes that can be safely ignored in assembly verification. 132 | 133 | 134 | 135 | 136 | 'false' to turn off automatic generation of the XML Schema file. 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /UAssetGUI/MapStructTypeOverrideForm.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Reflection; 6 | using System.Text; 7 | using System.Windows.Forms; 8 | using UAssetAPI; 9 | using UAssetAPI.UnrealTypes; 10 | 11 | namespace UAssetGUI 12 | { 13 | public partial class MapStructTypeOverrideForm : Form 14 | { 15 | public static Dictionary> MapStructTypeOverride = null; 16 | 17 | public MapStructTypeOverrideForm() 18 | { 19 | InitializeComponent(); 20 | 21 | infoLabel.Text = "This table maps MapProperty names to the type of the structs within them. You can use header dumps to determine these values if necessary."; 22 | 23 | if (!SystemInformation.TerminalServerSession) 24 | { 25 | Type ourGridType = mstoDataGridView.GetType(); 26 | PropertyInfo pi = ourGridType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic); 27 | pi.SetValue(mstoDataGridView, true, null); 28 | } 29 | } 30 | 31 | private static void CheckIfMapStructTypeOverrideIsNull() 32 | { 33 | if (MapStructTypeOverride == null) MapStructTypeOverride = new UAsset().MapStructTypeOverride; 34 | } 35 | 36 | private void MapStructTypeOverrideForm_Resize(object sender, EventArgs e) 37 | { 38 | ForceResize(); 39 | } 40 | 41 | public void ForceResize() 42 | { 43 | mstoDataGridView.Height = closeButton.Location.Y - infoLabel.Location.Y - infoLabel.Height - 9; 44 | } 45 | 46 | private void AddColumns(string[] ourColumns) 47 | { 48 | for (int i = 0; i < ourColumns.Length; i++) 49 | { 50 | DataGridViewColumn dgc = new DataGridViewTextBoxColumn 51 | { 52 | HeaderText = ourColumns[i] 53 | }; 54 | 55 | dgc.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells; 56 | if (i >= (ourColumns.Length - 1)) 57 | { 58 | dgc.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; 59 | } 60 | 61 | dgc.SortMode = DataGridViewColumnSortMode.NotSortable; 62 | mstoDataGridView.Columns.Add(dgc); 63 | } 64 | } 65 | 66 | private void MapStructTypeOverrideForm_Load(object sender, EventArgs e) 67 | { 68 | CheckIfMapStructTypeOverrideIsNull(); 69 | 70 | UAGPalette.RefreshTheme(this); 71 | ForceResize(); 72 | this.AdjustFormPosition(); 73 | 74 | LoadOntoDGV(); 75 | } 76 | 77 | private void SaveFromDGV() 78 | { 79 | CheckIfMapStructTypeOverrideIsNull(); 80 | 81 | MapStructTypeOverride.Clear(); 82 | foreach (DataGridViewRow row in mstoDataGridView.Rows) 83 | { 84 | string mapName = row.Cells[0].Value as string; 85 | string keyName = row.Cells[1].Value as string; 86 | string valueName = row.Cells[2].Value as string; 87 | if (mapName == null || keyName == null || valueName == null) continue; 88 | MapStructTypeOverride.Add(mapName, new Tuple(FString.FromString(keyName), FString.FromString(valueName))); 89 | } 90 | SaveToConfig(); 91 | } 92 | 93 | private void LoadOntoDGV() 94 | { 95 | CheckIfMapStructTypeOverrideIsNull(); 96 | 97 | mstoDataGridView.Visible = true; 98 | mstoDataGridView.Columns.Clear(); 99 | mstoDataGridView.Rows.Clear(); 100 | mstoDataGridView.AllowUserToAddRows = true; 101 | mstoDataGridView.ReadOnly = false; 102 | mstoDataGridView.BackgroundColor = UAGPalette.DataGridViewActiveColor; 103 | AddColumns(new string[] { "Map Name", "Key Struct Type Name", "Value Struct Type Name" }); 104 | 105 | foreach (KeyValuePair> entry in MapStructTypeOverride) 106 | { 107 | mstoDataGridView.Rows.Add(new object[] { entry.Key.ToString(), entry.Value.Item1?.ToString() ?? FString.NullCase, entry.Value.Item2?.ToString() ?? FString.NullCase }); 108 | } 109 | } 110 | 111 | internal static void SaveToConfig() 112 | { 113 | CheckIfMapStructTypeOverrideIsNull(); 114 | 115 | UAGConfig.Data.MapStructTypeOverride = ExportData(Formatting.None); 116 | UAGConfig.Save(); 117 | } 118 | 119 | internal static void LoadFromConfig() 120 | { 121 | CheckIfMapStructTypeOverrideIsNull(); 122 | 123 | ImportData(UAGConfig.Data.MapStructTypeOverride); 124 | } 125 | 126 | private static void ImportData(string data) 127 | { 128 | if (data == null) return; 129 | CheckIfMapStructTypeOverrideIsNull(); 130 | 131 | Dictionary temp = JsonConvert.DeserializeObject>(data); 132 | if (temp == null || temp.Count == 0) return; 133 | 134 | MapStructTypeOverride.Clear(); 135 | foreach (KeyValuePair entry in temp) 136 | { 137 | MapStructTypeOverride.Add(entry.Key, new Tuple(FString.FromString(entry.Value[0]), FString.FromString(entry.Value[1]))); 138 | } 139 | } 140 | 141 | private static string ExportData(Formatting formatting = Formatting.Indented) 142 | { 143 | CheckIfMapStructTypeOverrideIsNull(); 144 | 145 | StringBuilder sb = new StringBuilder(); 146 | StringWriter sw = new StringWriter(sb); 147 | 148 | using (JsonWriter writer = new JsonTextWriter(sw)) 149 | { 150 | writer.Formatting = formatting; 151 | 152 | writer.WriteStartObject(); 153 | foreach (KeyValuePair> entry in MapStructTypeOverride) 154 | { 155 | writer.WritePropertyName(entry.Key.ToString()); 156 | writer.WriteStartArray(); 157 | writer.WriteValue(entry.Value.Item1?.ToString()); 158 | writer.WriteValue(entry.Value.Item2?.ToString()); 159 | writer.WriteEnd(); 160 | } 161 | writer.WriteEndObject(); 162 | } 163 | 164 | return sb.ToString(); 165 | } 166 | 167 | private void mstoDataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e) 168 | { 169 | SaveFromDGV(); 170 | } 171 | 172 | private void refreshButton_Click(object sender, EventArgs e) 173 | { 174 | LoadOntoDGV(); 175 | } 176 | 177 | private void closeButton_Click(object sender, EventArgs e) 178 | { 179 | this.Close(); 180 | } 181 | 182 | private void importButton_Click(object sender, EventArgs e) 183 | { 184 | using (OpenFileDialog openFileDialog = new OpenFileDialog()) 185 | { 186 | openFileDialog.Filter = "Map Struct Type Override JSON (*.json)|*.json|All files (*.*)|*.*"; 187 | openFileDialog.FilterIndex = 1; 188 | openFileDialog.RestoreDirectory = true; 189 | 190 | if (openFileDialog.ShowDialog() == DialogResult.OK) 191 | { 192 | ImportData(File.ReadAllText(openFileDialog.FileName)); 193 | LoadOntoDGV(); 194 | SaveToConfig(); 195 | } 196 | } 197 | } 198 | 199 | private void exportButton_Click(object sender, EventArgs e) 200 | { 201 | using (SaveFileDialog dialog = new SaveFileDialog()) 202 | { 203 | dialog.Filter = "Map Struct Type Override JSON (*.json)|*.json|All files (*.*)|*.*"; 204 | dialog.FilterIndex = 1; 205 | dialog.RestoreDirectory = true; 206 | 207 | DialogResult res = dialog.ShowDialog(); 208 | if (res == DialogResult.OK) 209 | { 210 | SaveFromDGV(); 211 | File.WriteAllText(dialog.FileName, ExportData()); 212 | } 213 | } 214 | } 215 | 216 | private void resetButton_Click(object sender, EventArgs e) 217 | { 218 | DialogResult res = MessageBox.Show("Are you sure you want to reset the table to its defaults?", this.Text, MessageBoxButtons.OKCancel); 219 | if (res != DialogResult.OK) return; 220 | 221 | MapStructTypeOverride = null; 222 | CheckIfMapStructTypeOverrideIsNull(); 223 | LoadOntoDGV(); 224 | SaveToConfig(); 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /UAssetGUI/UAGConfig.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Windows.Forms; 6 | using UAssetAPI; 7 | using UAssetAPI.Unversioned; 8 | 9 | namespace UAssetGUI 10 | { 11 | public struct UAGConfigData 12 | { 13 | public string PreferredVersion; 14 | public string PreferredMappings; 15 | public string Theme; 16 | public string MapStructTypeOverride; 17 | public string FavoriteThing; 18 | public int DataZoom; 19 | public bool ChangeValuesOnScroll; 20 | public bool EnableDynamicTree; 21 | public bool EnableDiscordRPC; 22 | public bool DoubleClickToEdit; 23 | public bool EnableBak; 24 | public bool RestoreSize; 25 | public bool EnableUpdateNotice; 26 | public bool EnablePrettyBytecode; 27 | public int StartupWidth; 28 | public int StartupHeight; 29 | public int CustomSerializationFlags; 30 | 31 | public UAGConfigData() 32 | { 33 | PreferredVersion = string.Empty; 34 | Theme = string.Empty; 35 | MapStructTypeOverride = string.Empty; 36 | FavoriteThing = string.Empty; 37 | DataZoom = 0; 38 | ChangeValuesOnScroll = true; 39 | EnableDynamicTree = true; 40 | EnableDiscordRPC = true; 41 | DoubleClickToEdit = true; 42 | EnableBak = true; 43 | RestoreSize = true; 44 | EnableUpdateNotice = true; 45 | EnablePrettyBytecode = true; 46 | StartupWidth = 1000; 47 | StartupHeight = 700; 48 | CustomSerializationFlags = 0; 49 | } 50 | } 51 | 52 | public static class UAGConfig 53 | { 54 | public static UAGConfigData Data; 55 | public static Dictionary AllMappings = new Dictionary(); 56 | public readonly static string ConfigFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "UAssetGUI"); 57 | public readonly static string MappingsFolder = Path.Combine(ConfigFolder, "Mappings"); 58 | public readonly static string StagingFolder = Path.Combine(ConfigFolder, "Staging"); 59 | public readonly static string ExtractedFolder = Path.Combine(ConfigFolder, "Extracted"); 60 | 61 | internal static bool DifferentStagingPerPak = false; 62 | 63 | public static void LoadMappings() 64 | { 65 | Directory.CreateDirectory(ConfigFolder); 66 | Directory.CreateDirectory(MappingsFolder); 67 | 68 | AllMappings.Clear(); 69 | string[] allMappingFiles = Directory.GetFiles(MappingsFolder, "*.usmap", SearchOption.TopDirectoryOnly); 70 | foreach (string mappingPath in allMappingFiles) 71 | { 72 | AllMappings.Add(Path.GetFileNameWithoutExtension(mappingPath), mappingPath); 73 | } 74 | } 75 | 76 | public static string[] GetStagingFiles(string pakPath, out string[] fixedPathsOnDisk) 77 | { 78 | string rootDir = DifferentStagingPerPak ? Path.Combine(StagingFolder, Path.GetFileNameWithoutExtension(pakPath)) : StagingFolder; 79 | Directory.CreateDirectory(rootDir); 80 | 81 | fixedPathsOnDisk = Directory.GetFiles(rootDir, "*.*", SearchOption.AllDirectories); 82 | string[] res = new string[fixedPathsOnDisk.Length]; Array.Copy(fixedPathsOnDisk, res, fixedPathsOnDisk.Length); 83 | for (int i = 0; i < res.Length; i++) 84 | { 85 | res[i] = res[i].Replace(Path.DirectorySeparatorChar, '/').Substring(rootDir.Length).TrimStart('/'); 86 | } 87 | 88 | return res; 89 | } 90 | 91 | public static void StageFile(string rawPathOnDisk, string CurrentContainerPath, string newPath = null) 92 | { 93 | if (newPath == null) newPath = Path.GetFileName(rawPathOnDisk); 94 | newPath = newPath.Replace('/', Path.DirectorySeparatorChar); 95 | 96 | var finalPath = DifferentStagingPerPak ? Path.Combine(StagingFolder, Path.GetFileNameWithoutExtension(CurrentContainerPath), newPath) : Path.Combine(StagingFolder, newPath); 97 | try { Directory.CreateDirectory(Path.GetDirectoryName(finalPath)); } catch { return; } // fail silently if cant make the directory we need 98 | 99 | try { Directory.Delete(finalPath, true); } catch { } // if we turn a directory into a file, try and get rid of the directory 100 | 101 | File.Copy(rawPathOnDisk, finalPath, true); 102 | try { File.Copy(Path.ChangeExtension(rawPathOnDisk, ".uexp"), Path.ChangeExtension(finalPath, ".uexp"), true); } catch { } 103 | try { File.Copy(Path.ChangeExtension(rawPathOnDisk, ".ubulk"), Path.ChangeExtension(finalPath, ".ubulk"), true); } catch { } 104 | } 105 | 106 | public static void StageFile(DirectoryTreeItem item, string newPath = null) 107 | { 108 | // recursive if we were given a directory 109 | if (!item.IsFile) 110 | { 111 | foreach (var child in item.Children) StageFile(child.Value, newPath == null ? null : Path.Combine(newPath, child.Value.Name)); 112 | return; 113 | } 114 | 115 | if (newPath == null) newPath = item.FullPath; 116 | newPath = newPath.Replace('/', Path.DirectorySeparatorChar); 117 | 118 | string outputPath = item.SaveFileToTemp(); 119 | var finalPath = DifferentStagingPerPak ? Path.Combine(StagingFolder, Path.GetFileNameWithoutExtension(item.ParentForm.CurrentContainerPath), newPath) : Path.Combine(StagingFolder, newPath); 120 | if (outputPath == null || finalPath == null) return; 121 | try { Directory.CreateDirectory(Path.GetDirectoryName(finalPath)); } catch { return; } // fail silently if cant make the directory we need 122 | 123 | try { Directory.Delete(finalPath, true); } catch { } // if we turn a directory into a file, try and get rid of the directory 124 | 125 | File.Copy(outputPath, finalPath, true); 126 | try { File.Copy(Path.ChangeExtension(outputPath, ".uexp"), Path.ChangeExtension(finalPath, ".uexp"), true); } catch { } 127 | try { File.Copy(Path.ChangeExtension(outputPath, ".ubulk"), Path.ChangeExtension(finalPath, ".ubulk"), true); } catch { } 128 | try { File.Delete(outputPath); } catch { } 129 | try { File.Delete(Path.ChangeExtension(outputPath, ".uexp")); } catch { } 130 | try { File.Delete(Path.ChangeExtension(outputPath, ".ubulk")); } catch { } 131 | } 132 | 133 | public static string ExtractFile(DirectoryTreeItem item, FileStream stream2 = null, PakReader reader2 = null) 134 | { 135 | var finalPath = Path.Combine(ExtractedFolder, item.FullPath.Replace('/', Path.DirectorySeparatorChar)); 136 | 137 | // recursive if we were given a directory 138 | if (!item.IsFile) 139 | { 140 | foreach (var child in item.Children) ExtractFile(child.Value, stream2, reader2); 141 | return finalPath; 142 | } 143 | 144 | return item.SaveFileToTemp(ExtractedFolder, stream2, reader2); 145 | } 146 | 147 | public static bool TryGetMappings(string name, out Usmap mappings) 148 | { 149 | if (AllMappings.TryGetValue(name, out string value)) 150 | { 151 | try 152 | { 153 | mappings = new Usmap(value); 154 | return true; 155 | } 156 | catch 157 | { 158 | UAGUtils.InvokeUI(() => 159 | { 160 | MessageBox.Show("Failed to parse mappings: " + name, "Notice"); 161 | 162 | // update list of mappings for good measure 163 | foreach (var form in Application.OpenForms) 164 | { 165 | if (form is Form1 form1) 166 | { 167 | form1.UpdateMappings("No mappings", false); 168 | } 169 | } 170 | }); 171 | } 172 | } 173 | 174 | mappings = null; 175 | return false; 176 | } 177 | 178 | public static void Save() 179 | { 180 | SaveCustomFile("config.json", JsonConvert.SerializeObject(Data, Formatting.Indented)); 181 | } 182 | 183 | public static string SaveCustomFile(string name, string text, string subFolder = null) 184 | { 185 | string outPath = Path.Combine(ConfigFolder, name); 186 | if (!string.IsNullOrEmpty(subFolder)) outPath = Path.Combine(ConfigFolder, subFolder, name); 187 | 188 | Directory.CreateDirectory(Path.GetDirectoryName(outPath)); 189 | File.WriteAllText(outPath, text); 190 | 191 | return outPath; 192 | } 193 | 194 | public static void Load() 195 | { 196 | try 197 | { 198 | Directory.CreateDirectory(ConfigFolder); 199 | Data = JsonConvert.DeserializeObject(File.ReadAllText(Path.Combine(ConfigFolder, "config.json"))); 200 | } 201 | catch 202 | { 203 | Data = new UAGConfigData(); 204 | Save(); 205 | } 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /UAssetGUI/FindForm.Designer.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace UAssetGUI 3 | { 4 | partial class FindForm 5 | { 6 | /// 7 | /// Required designer variable. 8 | /// 9 | private System.ComponentModel.IContainer components = null; 10 | 11 | /// 12 | /// Clean up any resources being used. 13 | /// 14 | /// true if managed resources should be disposed; otherwise, false. 15 | protected override void Dispose(bool disposing) 16 | { 17 | if (disposing && (components != null)) 18 | { 19 | components.Dispose(); 20 | } 21 | base.Dispose(disposing); 22 | } 23 | 24 | #region Windows Form Designer generated code 25 | 26 | /// 27 | /// Required method for Designer support - do not modify 28 | /// the contents of this method with the code editor. 29 | /// 30 | private void InitializeComponent() 31 | { 32 | this.closeButton = new System.Windows.Forms.Button(); 33 | this.label1 = new System.Windows.Forms.Label(); 34 | this.searchForBox = new System.Windows.Forms.TextBox(); 35 | this.nextButton = new System.Windows.Forms.Button(); 36 | this.searchDirectionGroupBox = new System.Windows.Forms.GroupBox(); 37 | this.searchDirBackwardButton = new System.Windows.Forms.RadioButton(); 38 | this.searchDirForwardButton = new System.Windows.Forms.RadioButton(); 39 | this.optionsGroupBox = new System.Windows.Forms.GroupBox(); 40 | this.useRegexCheckBox = new System.Windows.Forms.CheckBox(); 41 | this.caseSensitiveCheckBox = new System.Windows.Forms.CheckBox(); 42 | this.progressBar1 = new System.Windows.Forms.ProgressBar(); 43 | this.searchDirectionGroupBox.SuspendLayout(); 44 | this.optionsGroupBox.SuspendLayout(); 45 | this.SuspendLayout(); 46 | // 47 | // closeButton 48 | // 49 | this.closeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 50 | this.closeButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 51 | this.closeButton.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Bold); 52 | this.closeButton.ForeColor = System.Drawing.SystemColors.ControlText; 53 | this.closeButton.Location = new System.Drawing.Point(224, 124); 54 | this.closeButton.Name = "closeButton"; 55 | this.closeButton.Size = new System.Drawing.Size(75, 26); 56 | this.closeButton.TabIndex = 6; 57 | this.closeButton.Text = "Close"; 58 | this.closeButton.UseVisualStyleBackColor = true; 59 | this.closeButton.Click += new System.EventHandler(this.closeButton_Click); 60 | // 61 | // label1 62 | // 63 | this.label1.AutoSize = true; 64 | this.label1.Location = new System.Drawing.Point(12, 19); 65 | this.label1.Name = "label1"; 66 | this.label1.Size = new System.Drawing.Size(59, 13); 67 | this.label1.TabIndex = 6; 68 | this.label1.Text = "Search for:"; 69 | // 70 | // searchForBox 71 | // 72 | this.searchForBox.Location = new System.Drawing.Point(77, 16); 73 | this.searchForBox.Name = "searchForBox"; 74 | this.searchForBox.Size = new System.Drawing.Size(222, 20); 75 | this.searchForBox.TabIndex = 0; 76 | // 77 | // nextButton 78 | // 79 | this.nextButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 80 | this.nextButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 81 | this.nextButton.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Bold); 82 | this.nextButton.ForeColor = System.Drawing.SystemColors.ControlText; 83 | this.nextButton.Location = new System.Drawing.Point(143, 124); 84 | this.nextButton.Name = "nextButton"; 85 | this.nextButton.Size = new System.Drawing.Size(75, 26); 86 | this.nextButton.TabIndex = 5; 87 | this.nextButton.Text = "Next"; 88 | this.nextButton.UseVisualStyleBackColor = true; 89 | this.nextButton.Click += new System.EventHandler(this.nextButton_Click); 90 | // 91 | // searchDirectionGroupBox 92 | // 93 | this.searchDirectionGroupBox.Controls.Add(this.searchDirBackwardButton); 94 | this.searchDirectionGroupBox.Controls.Add(this.searchDirForwardButton); 95 | this.searchDirectionGroupBox.Location = new System.Drawing.Point(200, 42); 96 | this.searchDirectionGroupBox.Name = "searchDirectionGroupBox"; 97 | this.searchDirectionGroupBox.Size = new System.Drawing.Size(99, 65); 98 | this.searchDirectionGroupBox.TabIndex = 11; 99 | this.searchDirectionGroupBox.TabStop = false; 100 | this.searchDirectionGroupBox.Text = "Search direction"; 101 | // 102 | // searchDirBackwardButton 103 | // 104 | this.searchDirBackwardButton.AutoSize = true; 105 | this.searchDirBackwardButton.Location = new System.Drawing.Point(6, 42); 106 | this.searchDirBackwardButton.Name = "searchDirBackwardButton"; 107 | this.searchDirBackwardButton.Size = new System.Drawing.Size(73, 17); 108 | this.searchDirBackwardButton.TabIndex = 4; 109 | this.searchDirBackwardButton.TabStop = true; 110 | this.searchDirBackwardButton.Text = "Backward"; 111 | this.searchDirBackwardButton.UseVisualStyleBackColor = true; 112 | // 113 | // searchDirForwardButton 114 | // 115 | this.searchDirForwardButton.AutoSize = true; 116 | this.searchDirForwardButton.Location = new System.Drawing.Point(6, 19); 117 | this.searchDirForwardButton.Name = "searchDirForwardButton"; 118 | this.searchDirForwardButton.Size = new System.Drawing.Size(63, 17); 119 | this.searchDirForwardButton.TabIndex = 3; 120 | this.searchDirForwardButton.TabStop = true; 121 | this.searchDirForwardButton.Text = "Forward"; 122 | this.searchDirForwardButton.UseVisualStyleBackColor = true; 123 | // 124 | // optionsGroupBox 125 | // 126 | this.optionsGroupBox.Controls.Add(this.useRegexCheckBox); 127 | this.optionsGroupBox.Controls.Add(this.caseSensitiveCheckBox); 128 | this.optionsGroupBox.Location = new System.Drawing.Point(15, 42); 129 | this.optionsGroupBox.Name = "optionsGroupBox"; 130 | this.optionsGroupBox.Size = new System.Drawing.Size(164, 65); 131 | this.optionsGroupBox.TabIndex = 12; 132 | this.optionsGroupBox.TabStop = false; 133 | this.optionsGroupBox.Text = "Options"; 134 | // 135 | // useRegexCheckBox 136 | // 137 | this.useRegexCheckBox.AutoSize = true; 138 | this.useRegexCheckBox.Location = new System.Drawing.Point(6, 42); 139 | this.useRegexCheckBox.Name = "useRegexCheckBox"; 140 | this.useRegexCheckBox.Size = new System.Drawing.Size(74, 17); 141 | this.useRegexCheckBox.TabIndex = 2; 142 | this.useRegexCheckBox.Text = "Use regex"; 143 | this.useRegexCheckBox.UseVisualStyleBackColor = true; 144 | // 145 | // caseSensitiveCheckBox 146 | // 147 | this.caseSensitiveCheckBox.AutoSize = true; 148 | this.caseSensitiveCheckBox.Location = new System.Drawing.Point(6, 19); 149 | this.caseSensitiveCheckBox.Name = "caseSensitiveCheckBox"; 150 | this.caseSensitiveCheckBox.Size = new System.Drawing.Size(94, 17); 151 | this.caseSensitiveCheckBox.TabIndex = 1; 152 | this.caseSensitiveCheckBox.Text = "Case sensitive"; 153 | this.caseSensitiveCheckBox.UseVisualStyleBackColor = true; 154 | // 155 | // progressBar1 156 | // 157 | this.progressBar1.Location = new System.Drawing.Point(15, 126); 158 | this.progressBar1.Name = "progressBar1"; 159 | this.progressBar1.Size = new System.Drawing.Size(114, 23); 160 | this.progressBar1.TabIndex = 13; 161 | // 162 | // FindForm 163 | // 164 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 165 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 166 | this.ClientSize = new System.Drawing.Size(311, 162); 167 | this.Controls.Add(this.progressBar1); 168 | this.Controls.Add(this.optionsGroupBox); 169 | this.Controls.Add(this.searchDirectionGroupBox); 170 | this.Controls.Add(this.nextButton); 171 | this.Controls.Add(this.searchForBox); 172 | this.Controls.Add(this.label1); 173 | this.Controls.Add(this.closeButton); 174 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 175 | this.Name = "FindForm"; 176 | this.Text = "Find"; 177 | this.Load += new System.EventHandler(this.FindForm_Load); 178 | this.searchDirectionGroupBox.ResumeLayout(false); 179 | this.searchDirectionGroupBox.PerformLayout(); 180 | this.optionsGroupBox.ResumeLayout(false); 181 | this.optionsGroupBox.PerformLayout(); 182 | this.ResumeLayout(false); 183 | this.PerformLayout(); 184 | 185 | } 186 | 187 | #endregion 188 | 189 | private System.Windows.Forms.Button closeButton; 190 | private System.Windows.Forms.Label label1; 191 | private System.Windows.Forms.TextBox searchForBox; 192 | private System.Windows.Forms.Button nextButton; 193 | private System.Windows.Forms.GroupBox searchDirectionGroupBox; 194 | private System.Windows.Forms.RadioButton searchDirBackwardButton; 195 | private System.Windows.Forms.RadioButton searchDirForwardButton; 196 | private System.Windows.Forms.GroupBox optionsGroupBox; 197 | private System.Windows.Forms.CheckBox useRegexCheckBox; 198 | private System.Windows.Forms.CheckBox caseSensitiveCheckBox; 199 | private System.Windows.Forms.ProgressBar progressBar1; 200 | } 201 | } -------------------------------------------------------------------------------- /UAssetGUI/MapStructTypeOverrideForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace UAssetGUI 2 | { 3 | partial class MapStructTypeOverrideForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle(); 32 | this.mstoDataGridView = new System.Windows.Forms.DataGridView(); 33 | this.infoLabel = new System.Windows.Forms.Label(); 34 | this.refreshButton = new System.Windows.Forms.Button(); 35 | this.closeButton = new System.Windows.Forms.Button(); 36 | this.exportButton = new System.Windows.Forms.Button(); 37 | this.importButton = new System.Windows.Forms.Button(); 38 | this.resetButton = new System.Windows.Forms.Button(); 39 | ((System.ComponentModel.ISupportInitialize)(this.mstoDataGridView)).BeginInit(); 40 | this.SuspendLayout(); 41 | // 42 | // mstoDataGridView 43 | // 44 | this.mstoDataGridView.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 45 | | System.Windows.Forms.AnchorStyles.Right))); 46 | this.mstoDataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells; 47 | this.mstoDataGridView.BackgroundColor = System.Drawing.Color.LightGray; 48 | this.mstoDataGridView.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; 49 | this.mstoDataGridView.ClipboardCopyMode = System.Windows.Forms.DataGridViewClipboardCopyMode.EnableWithoutHeaderText; 50 | this.mstoDataGridView.ColumnHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Single; 51 | dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft; 52 | dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Control; 53 | dataGridViewCellStyle1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F); 54 | dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText; 55 | dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight; 56 | dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText; 57 | dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True; 58 | this.mstoDataGridView.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1; 59 | this.mstoDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; 60 | this.mstoDataGridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnEnter; 61 | this.mstoDataGridView.EnableHeadersVisualStyles = false; 62 | this.mstoDataGridView.Location = new System.Drawing.Point(12, 52); 63 | this.mstoDataGridView.Name = "mstoDataGridView"; 64 | this.mstoDataGridView.RowHeadersBorderStyle = System.Windows.Forms.DataGridViewHeaderBorderStyle.Single; 65 | this.mstoDataGridView.RowHeadersWidth = 60; 66 | this.mstoDataGridView.RowHeadersWidthSizeMode = System.Windows.Forms.DataGridViewRowHeadersWidthSizeMode.DisableResizing; 67 | this.mstoDataGridView.Size = new System.Drawing.Size(545, 289); 68 | this.mstoDataGridView.TabIndex = 1; 69 | this.mstoDataGridView.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(this.mstoDataGridView_CellEndEdit); 70 | // 71 | // infoLabel 72 | // 73 | this.infoLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 74 | | System.Windows.Forms.AnchorStyles.Right))); 75 | this.infoLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.25F); 76 | this.infoLabel.Location = new System.Drawing.Point(13, 9); 77 | this.infoLabel.Name = "infoLabel"; 78 | this.infoLabel.Size = new System.Drawing.Size(544, 40); 79 | this.infoLabel.TabIndex = 0; 80 | this.infoLabel.Text = "blah blah blah"; 81 | this.infoLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 82 | // 83 | // refreshButton 84 | // 85 | this.refreshButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 86 | this.refreshButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 87 | this.refreshButton.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Bold); 88 | this.refreshButton.Location = new System.Drawing.Point(12, 347); 89 | this.refreshButton.Name = "refreshButton"; 90 | this.refreshButton.Size = new System.Drawing.Size(75, 26); 91 | this.refreshButton.TabIndex = 2; 92 | this.refreshButton.Text = "Refresh"; 93 | this.refreshButton.UseVisualStyleBackColor = true; 94 | this.refreshButton.Click += new System.EventHandler(this.refreshButton_Click); 95 | // 96 | // closeButton 97 | // 98 | this.closeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 99 | this.closeButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 100 | this.closeButton.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Bold); 101 | this.closeButton.ForeColor = System.Drawing.SystemColors.ControlText; 102 | this.closeButton.Location = new System.Drawing.Point(482, 347); 103 | this.closeButton.Name = "closeButton"; 104 | this.closeButton.Size = new System.Drawing.Size(75, 26); 105 | this.closeButton.TabIndex = 3; 106 | this.closeButton.Text = "Close"; 107 | this.closeButton.UseVisualStyleBackColor = true; 108 | this.closeButton.Click += new System.EventHandler(this.closeButton_Click); 109 | // 110 | // exportButton 111 | // 112 | this.exportButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 113 | this.exportButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 114 | this.exportButton.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Bold); 115 | this.exportButton.Location = new System.Drawing.Point(174, 347); 116 | this.exportButton.Name = "exportButton"; 117 | this.exportButton.Size = new System.Drawing.Size(75, 26); 118 | this.exportButton.TabIndex = 4; 119 | this.exportButton.Text = "Export"; 120 | this.exportButton.UseVisualStyleBackColor = true; 121 | this.exportButton.Click += new System.EventHandler(this.exportButton_Click); 122 | // 123 | // importButton 124 | // 125 | this.importButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); 126 | this.importButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 127 | this.importButton.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Bold); 128 | this.importButton.Location = new System.Drawing.Point(93, 347); 129 | this.importButton.Name = "importButton"; 130 | this.importButton.Size = new System.Drawing.Size(75, 26); 131 | this.importButton.TabIndex = 5; 132 | this.importButton.Text = "Import"; 133 | this.importButton.UseVisualStyleBackColor = true; 134 | this.importButton.Click += new System.EventHandler(this.importButton_Click); 135 | // 136 | // resetButton 137 | // 138 | this.resetButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 139 | this.resetButton.FlatStyle = System.Windows.Forms.FlatStyle.Flat; 140 | this.resetButton.Font = new System.Drawing.Font("Arial", 8F, System.Drawing.FontStyle.Bold); 141 | this.resetButton.Location = new System.Drawing.Point(401, 347); 142 | this.resetButton.Name = "resetButton"; 143 | this.resetButton.Size = new System.Drawing.Size(75, 26); 144 | this.resetButton.TabIndex = 6; 145 | this.resetButton.Text = "Reset"; 146 | this.resetButton.UseVisualStyleBackColor = true; 147 | this.resetButton.Click += new System.EventHandler(this.resetButton_Click); 148 | // 149 | // MapStructTypeOverrideForm 150 | // 151 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 152 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 153 | this.ClientSize = new System.Drawing.Size(569, 379); 154 | this.Controls.Add(this.resetButton); 155 | this.Controls.Add(this.importButton); 156 | this.Controls.Add(this.exportButton); 157 | this.Controls.Add(this.closeButton); 158 | this.Controls.Add(this.refreshButton); 159 | this.Controls.Add(this.infoLabel); 160 | this.Controls.Add(this.mstoDataGridView); 161 | this.Name = "MapStructTypeOverrideForm"; 162 | this.Text = "Map Struct Type Overrides"; 163 | this.Load += new System.EventHandler(this.MapStructTypeOverrideForm_Load); 164 | this.Resize += new System.EventHandler(this.MapStructTypeOverrideForm_Resize); 165 | ((System.ComponentModel.ISupportInitialize)(this.mstoDataGridView)).EndInit(); 166 | this.ResumeLayout(false); 167 | 168 | } 169 | 170 | #endregion 171 | private System.Windows.Forms.Label infoLabel; 172 | internal System.Windows.Forms.DataGridView mstoDataGridView; 173 | private System.Windows.Forms.Button refreshButton; 174 | private System.Windows.Forms.Button closeButton; 175 | private System.Windows.Forms.Button exportButton; 176 | private System.Windows.Forms.Button importButton; 177 | private System.Windows.Forms.Button resetButton; 178 | } 179 | } -------------------------------------------------------------------------------- /UAssetGUI/SettingsForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Windows.Forms; 7 | using UAssetAPI; 8 | 9 | namespace UAssetGUI 10 | { 11 | public partial class SettingsForm : Form 12 | { 13 | public SettingsForm() 14 | { 15 | InitializeComponent(); 16 | numericUpDown1.MouseWheel += NumericUpDown1_MouseWheel; 17 | } 18 | 19 | private Form1 BaseForm; 20 | private bool _readyToUpdateTheme = false; 21 | private void SettingsForm_Load(object sender, EventArgs e) 22 | { 23 | if (this.Owner is Form1) BaseForm = (Form1)this.Owner; 24 | 25 | customSerializationFlagsBox.BeginUpdate(); 26 | customSerializationFlagsBox.Items.Clear(); 27 | List allFlags = Enum.GetValues(typeof(CustomSerializationFlags)).Cast().ToList(); 28 | int entryIdx = 0; 29 | for (int i = 0; i < allFlags.Count; i++) 30 | { 31 | CustomSerializationFlags option = allFlags[i]; 32 | if (option == 0) continue; 33 | 34 | customSerializationFlagsBox.Items.Add(option.ToString()); 35 | customSerializationFlagsBox.SetItemChecked(entryIdx++, (UAGConfig.Data.CustomSerializationFlags & (int)option) > 0); 36 | } 37 | customSerializationFlagsBox.EndUpdate(); 38 | 39 | themeComboBox.DataSource = Enum.GetValues(typeof(UAGTheme)); 40 | themeComboBox.SelectedIndex = (int)UAGPalette.GetCurrentTheme(); 41 | valuesOnScroll.Checked = UAGConfig.Data.ChangeValuesOnScroll; 42 | doubleClickToEdit.Checked = UAGConfig.Data.DoubleClickToEdit; 43 | enableDiscordRpc.Checked = UAGConfig.Data.EnableDiscordRPC; 44 | enableDynamicTree.Checked = UAGConfig.Data.EnableDynamicTree; 45 | favoriteThingBox.Text = UAGConfig.Data.FavoriteThing; 46 | numericUpDown1.Value = UAGConfig.Data.DataZoom; 47 | enableBak.Checked = UAGConfig.Data.EnableBak; 48 | enablePrettyBytecode.Checked = UAGConfig.Data.EnablePrettyBytecode; 49 | restoreSize.Checked = UAGConfig.Data.RestoreSize; 50 | enableUpdateNotice.Checked = UAGConfig.Data.EnableUpdateNotice; 51 | 52 | UAGPalette.RefreshTheme(this); 53 | this.AdjustFormPosition(); 54 | _readyToUpdateTheme = true; 55 | } 56 | 57 | private void closeButton_Click(object sender, EventArgs e) 58 | { 59 | this.Close(); 60 | } 61 | 62 | private void aboutButton_Click(object sender, EventArgs e) 63 | { 64 | var softwareAgeInYears = (int.Parse(DateTime.Now.ToString("yyyyMMdd")) - 20200723) / 10000; 65 | 66 | UAGUtils.InvokeUI(() => 67 | { 68 | var formPopup = new AboutForm(); 69 | 70 | formPopup.AboutText = (this.Owner as Form1).DisplayVersion + "\n" + 71 | "By atenfyr\n" + 72 | "\nThank you to trumank, LongerWarrior, Kaiheilos, and others for all your generous contributions to this software\n" + 73 | "\nThank you to the love of my life for listening to me and supporting me despite not caring at all about any of this\n" + 74 | "\nThank you for using this thing even after " + softwareAgeInYears + " years\n"; 75 | 76 | formPopup.StartPosition = FormStartPosition.CenterParent; 77 | formPopup.ShowDialog(this); 78 | }); 79 | } 80 | 81 | private void themeComboBox_SelectedIndexChanged(object sender, EventArgs e) 82 | { 83 | if (!_readyToUpdateTheme) return; 84 | Enum.TryParse(themeComboBox.SelectedValue.ToString(), out UAGTheme nextTheme); 85 | UAGPalette.SetCurrentTheme(nextTheme); 86 | UAGPalette.RefreshTheme(BaseForm); 87 | UAGPalette.RefreshTheme(this); 88 | } 89 | 90 | private void valuesOnScroll_CheckedChanged(object sender, EventArgs e) 91 | { 92 | UAGConfig.Data.ChangeValuesOnScroll = valuesOnScroll.Checked; 93 | } 94 | 95 | private void enableDynamicTree_CheckedChanged(object sender, EventArgs e) 96 | { 97 | UAGConfig.Data.EnableDynamicTree = enableDynamicTree.Checked; 98 | } 99 | 100 | private void doubleClickToEdit_CheckedChanged(object sender, EventArgs e) 101 | { 102 | UAGConfig.Data.DoubleClickToEdit = doubleClickToEdit.Checked; 103 | //BaseForm.dataGridView1.EditMode = UAGConfig.Data.DoubleClickToEdit ? DataGridViewEditMode.EditProgrammatically : DataGridViewEditMode.EditOnEnter; 104 | } 105 | 106 | private void enableBak_CheckedChanged(object sender, EventArgs e) 107 | { 108 | UAGConfig.Data.EnableBak = enableBak.Checked; 109 | } 110 | 111 | private void restoreSize_CheckedChanged(object sender, EventArgs e) 112 | { 113 | UAGConfig.Data.RestoreSize = restoreSize.Checked; 114 | } 115 | 116 | private void enableUpdateNotice_CheckedChanged(object sender, EventArgs e) 117 | { 118 | UAGConfig.Data.EnableUpdateNotice = enableUpdateNotice.Checked; 119 | } 120 | 121 | private void enablePrettyBytecode_CheckedChanged(object sender, EventArgs e) 122 | { 123 | UAGConfig.Data.EnablePrettyBytecode = enablePrettyBytecode.Checked; 124 | } 125 | 126 | private void enableDiscordRpc_CheckedChanged(object sender, EventArgs e) 127 | { 128 | UAGConfig.Data.EnableDiscordRPC = enableDiscordRpc.Checked; 129 | if (UAGConfig.Data.EnableDiscordRPC) 130 | { 131 | BaseForm.UpdateRPC(); 132 | } 133 | else 134 | { 135 | BaseForm.DiscordRPC.ClearPresence(); 136 | } 137 | } 138 | 139 | private bool isCurrentlyComicSans = false; 140 | private void favoriteThingBox_TextChanged(object sender, EventArgs e) 141 | { 142 | UAGConfig.Data.FavoriteThing = favoriteThingBox.Text; 143 | string favoriteThingLowered = UAGConfig.Data.FavoriteThing.ToLowerInvariant().Trim(); 144 | 145 | if (UAGPalette.IsComicSans()) 146 | { 147 | isCurrentlyComicSans = true; 148 | UAGPalette.RefreshTheme(BaseForm); 149 | UAGPalette.RefreshTheme(this); 150 | } 151 | else if (isCurrentlyComicSans) 152 | { 153 | isCurrentlyComicSans = false; 154 | UAGPalette.RefreshTheme(BaseForm); 155 | UAGPalette.RefreshTheme(this); 156 | } 157 | 158 | if (favoriteThingLowered == "atenfyr" || favoriteThingLowered == "adolescent") 159 | { 160 | // need MemoryStream to remain open until we're done using the image 161 | // no need to dispose MemoryStream so let's just let GC handle it once image stops being used 162 | var strm = new MemoryStream(Properties.Resources.dancing_cat); 163 | this.pictureBox1.Image = Image.FromStream(strm); 164 | this.pictureBox1.Visible = true; 165 | } 166 | else 167 | { 168 | this.pictureBox1.Visible = false; 169 | } 170 | } 171 | 172 | private void SettingsForm_FormClosing(object sender, FormClosingEventArgs e) 173 | { 174 | UAGConfig.Save(); 175 | UAGPalette.RefreshTheme(BaseForm); 176 | UAGPalette.RefreshTheme(this); 177 | } 178 | 179 | private void numericUpDown1_ValueChanged(object sender, EventArgs e) 180 | { 181 | UAGConfig.Data.DataZoom = (int)numericUpDown1.Value; 182 | UAGPalette.RefreshTheme(BaseForm); 183 | UAGPalette.RefreshTheme(this); 184 | 185 | // Refresh dgv row heights 186 | UAGUtils.InvokeUI(() => 187 | { 188 | if (BaseForm.tableEditor != null) 189 | { 190 | BaseForm.tableEditor.Save(true); 191 | } 192 | }); 193 | } 194 | 195 | private void customSerializationFlagsBox_Click(object sender, EventArgs e) 196 | { 197 | // this logic is here to prevent default list box selection logic 198 | 199 | // The following block of code is modified and adapted from source code on StackOverflow created and licensed by user Hath, copyright 2008: https://stackoverflow.com/a/334672 200 | // The original code is adapted for usage in this software under the terms of the CC BY-SA 2.5 license: https://creativecommons.org/licenses/by-sa/2.5/ 201 | /* 202 | UNLESS OTHERWISE AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE 203 | WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND 204 | CONCERNING THE MATERIALS, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, 205 | INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS 206 | FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT 207 | OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR 208 | NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED 209 | WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. 210 | */ 211 | for (int i = 0; i < customSerializationFlagsBox.Items.Count; i++) 212 | { 213 | if (customSerializationFlagsBox.GetItemRectangle(i).Contains(customSerializationFlagsBox.PointToClient(MousePosition))) 214 | { 215 | customSerializationFlagsBox.SetItemChecked(i, !customSerializationFlagsBox.GetItemChecked(i)); 216 | } 217 | } 218 | 219 | // update config 220 | CustomSerializationFlags res = 0; 221 | for (int i = 0; i < customSerializationFlagsBox.Items.Count; i++) 222 | { 223 | string item = customSerializationFlagsBox.Items[i] as string; 224 | if (item == null) continue; 225 | if (customSerializationFlagsBox.GetItemChecked(i)) 226 | { 227 | res |= Enum.Parse(item); 228 | } 229 | } 230 | 231 | UAGConfig.Data.CustomSerializationFlags = (int)res; 232 | } 233 | 234 | private void NumericUpDown1_MouseWheel(object sender, MouseEventArgs e) 235 | { 236 | // override default scroll logic to prevent weird +3 problem 237 | if (e.Delta == 0) return; 238 | ((HandledMouseEventArgs)e).Handled = true; 239 | 240 | UAGUtils.InvokeUI(() => 241 | { 242 | decimal newValue = numericUpDown1.Value + (e.Delta > 0 ? 1 : -1); 243 | if (newValue < numericUpDown1.Minimum) newValue = numericUpDown1.Minimum; 244 | if (newValue > numericUpDown1.Maximum) newValue = numericUpDown1.Maximum; 245 | numericUpDown1.Value = newValue; 246 | }); 247 | } 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /UAssetGUI.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.4.33103.184 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UAssetAPI", "UAssetAPI\UAssetAPI\UAssetAPI.csproj", "{178417EC-1177-413E-BE85-C83AECD64279}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UAssetAPI.Tests", "UAssetAPI\UAssetAPI.Tests\UAssetAPI.Tests.csproj", "{CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UAssetGUI", "UAssetGUI\UAssetGUI.csproj", "{88A998F1-C512-416F-ADED-120E50AFE6F3}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UAssetAPI.Benchmark", "UAssetAPI\UAssetAPI.Benchmark\UAssetAPI.Benchmark.csproj", "{A74E7E85-1797-477C-AEC1-583AE7D109D0}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Debug|x64 = Debug|x64 18 | Debug|x86 = Debug|x86 19 | DebugTracing|Any CPU = DebugTracing|Any CPU 20 | DebugTracing|x64 = DebugTracing|x64 21 | DebugTracing|x86 = DebugTracing|x86 22 | DebugVerbose|Any CPU = DebugVerbose|Any CPU 23 | DebugVerbose|x64 = DebugVerbose|x64 24 | DebugVerbose|x86 = DebugVerbose|x86 25 | Release|Any CPU = Release|Any CPU 26 | Release|x64 = Release|x64 27 | Release|x86 = Release|x86 28 | ReleaseX|Any CPU = ReleaseX|Any CPU 29 | ReleaseX|x64 = ReleaseX|x64 30 | ReleaseX|x86 = ReleaseX|x86 31 | EndGlobalSection 32 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 33 | {178417EC-1177-413E-BE85-C83AECD64279}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 34 | {178417EC-1177-413E-BE85-C83AECD64279}.Debug|Any CPU.Build.0 = Debug|Any CPU 35 | {178417EC-1177-413E-BE85-C83AECD64279}.Debug|x64.ActiveCfg = Debug|Any CPU 36 | {178417EC-1177-413E-BE85-C83AECD64279}.Debug|x64.Build.0 = Debug|Any CPU 37 | {178417EC-1177-413E-BE85-C83AECD64279}.Debug|x86.ActiveCfg = Debug|x86 38 | {178417EC-1177-413E-BE85-C83AECD64279}.Debug|x86.Build.0 = Debug|x86 39 | {178417EC-1177-413E-BE85-C83AECD64279}.DebugTracing|Any CPU.ActiveCfg = DebugTracing|Any CPU 40 | {178417EC-1177-413E-BE85-C83AECD64279}.DebugTracing|Any CPU.Build.0 = DebugTracing|Any CPU 41 | {178417EC-1177-413E-BE85-C83AECD64279}.DebugTracing|x64.ActiveCfg = DebugTracing|Any CPU 42 | {178417EC-1177-413E-BE85-C83AECD64279}.DebugTracing|x64.Build.0 = DebugTracing|Any CPU 43 | {178417EC-1177-413E-BE85-C83AECD64279}.DebugTracing|x86.ActiveCfg = DebugTracing|x86 44 | {178417EC-1177-413E-BE85-C83AECD64279}.DebugTracing|x86.Build.0 = DebugTracing|x86 45 | {178417EC-1177-413E-BE85-C83AECD64279}.DebugVerbose|Any CPU.ActiveCfg = DebugVerbose|Any CPU 46 | {178417EC-1177-413E-BE85-C83AECD64279}.DebugVerbose|Any CPU.Build.0 = DebugVerbose|Any CPU 47 | {178417EC-1177-413E-BE85-C83AECD64279}.DebugVerbose|x64.ActiveCfg = DebugVerbose|Any CPU 48 | {178417EC-1177-413E-BE85-C83AECD64279}.DebugVerbose|x64.Build.0 = DebugVerbose|Any CPU 49 | {178417EC-1177-413E-BE85-C83AECD64279}.DebugVerbose|x86.ActiveCfg = DebugVerbose|x86 50 | {178417EC-1177-413E-BE85-C83AECD64279}.DebugVerbose|x86.Build.0 = DebugVerbose|x86 51 | {178417EC-1177-413E-BE85-C83AECD64279}.Release|Any CPU.ActiveCfg = Release|Any CPU 52 | {178417EC-1177-413E-BE85-C83AECD64279}.Release|Any CPU.Build.0 = Release|Any CPU 53 | {178417EC-1177-413E-BE85-C83AECD64279}.Release|x64.ActiveCfg = Release|Any CPU 54 | {178417EC-1177-413E-BE85-C83AECD64279}.Release|x64.Build.0 = Release|Any CPU 55 | {178417EC-1177-413E-BE85-C83AECD64279}.Release|x86.ActiveCfg = Release|x86 56 | {178417EC-1177-413E-BE85-C83AECD64279}.Release|x86.Build.0 = Release|x86 57 | {178417EC-1177-413E-BE85-C83AECD64279}.ReleaseX|Any CPU.ActiveCfg = Release|Any CPU 58 | {178417EC-1177-413E-BE85-C83AECD64279}.ReleaseX|Any CPU.Build.0 = Release|Any CPU 59 | {178417EC-1177-413E-BE85-C83AECD64279}.ReleaseX|x64.ActiveCfg = Release|Any CPU 60 | {178417EC-1177-413E-BE85-C83AECD64279}.ReleaseX|x64.Build.0 = Release|Any CPU 61 | {178417EC-1177-413E-BE85-C83AECD64279}.ReleaseX|x86.ActiveCfg = Release|x86 62 | {178417EC-1177-413E-BE85-C83AECD64279}.ReleaseX|x86.Build.0 = Release|x86 63 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 64 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.Debug|Any CPU.Build.0 = Debug|Any CPU 65 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.Debug|x64.ActiveCfg = Debug|Any CPU 66 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.Debug|x64.Build.0 = Debug|Any CPU 67 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.Debug|x86.ActiveCfg = Debug|x86 68 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.Debug|x86.Build.0 = Debug|x86 69 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.DebugTracing|Any CPU.ActiveCfg = DebugTracing|Any CPU 70 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.DebugTracing|Any CPU.Build.0 = DebugTracing|Any CPU 71 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.DebugTracing|x64.ActiveCfg = DebugTracing|Any CPU 72 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.DebugTracing|x64.Build.0 = DebugTracing|Any CPU 73 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.DebugTracing|x86.ActiveCfg = DebugTracing|x86 74 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.DebugTracing|x86.Build.0 = DebugTracing|x86 75 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.DebugVerbose|Any CPU.ActiveCfg = DebugVerbose|Any CPU 76 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.DebugVerbose|Any CPU.Build.0 = DebugVerbose|Any CPU 77 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.DebugVerbose|x64.ActiveCfg = DebugVerbose|Any CPU 78 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.DebugVerbose|x64.Build.0 = DebugVerbose|Any CPU 79 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.DebugVerbose|x86.ActiveCfg = DebugVerbose|x86 80 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.DebugVerbose|x86.Build.0 = DebugVerbose|x86 81 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.Release|Any CPU.ActiveCfg = Release|Any CPU 82 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.Release|Any CPU.Build.0 = Release|Any CPU 83 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.Release|x64.ActiveCfg = Release|Any CPU 84 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.Release|x64.Build.0 = Release|Any CPU 85 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.Release|x86.ActiveCfg = Release|x86 86 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.Release|x86.Build.0 = Release|x86 87 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.ReleaseX|Any CPU.ActiveCfg = Release|Any CPU 88 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.ReleaseX|Any CPU.Build.0 = Release|Any CPU 89 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.ReleaseX|x64.ActiveCfg = Release|Any CPU 90 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.ReleaseX|x64.Build.0 = Release|Any CPU 91 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.ReleaseX|x86.ActiveCfg = Release|x86 92 | {CB796120-5EF8-4E9D-BCDB-D2F60A4EFC69}.ReleaseX|x86.Build.0 = Release|x86 93 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 94 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.Debug|Any CPU.Build.0 = Debug|Any CPU 95 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.Debug|x64.ActiveCfg = Debug|Any CPU 96 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.Debug|x64.Build.0 = Debug|Any CPU 97 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.Debug|x86.ActiveCfg = Debug|x86 98 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.Debug|x86.Build.0 = Debug|x86 99 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.DebugTracing|Any CPU.ActiveCfg = DebugTracing|Any CPU 100 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.DebugTracing|Any CPU.Build.0 = DebugTracing|Any CPU 101 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.DebugTracing|x64.ActiveCfg = DebugTracing|Any CPU 102 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.DebugTracing|x64.Build.0 = DebugTracing|Any CPU 103 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.DebugTracing|x86.ActiveCfg = DebugTracing|x86 104 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.DebugTracing|x86.Build.0 = DebugTracing|x86 105 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.DebugVerbose|Any CPU.ActiveCfg = DebugVerbose|Any CPU 106 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.DebugVerbose|Any CPU.Build.0 = DebugVerbose|Any CPU 107 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.DebugVerbose|x64.ActiveCfg = DebugVerbose|Any CPU 108 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.DebugVerbose|x64.Build.0 = DebugVerbose|Any CPU 109 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.DebugVerbose|x86.ActiveCfg = DebugVerbose|x86 110 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.DebugVerbose|x86.Build.0 = DebugVerbose|x86 111 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.Release|Any CPU.ActiveCfg = Release|Any CPU 112 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.Release|Any CPU.Build.0 = Release|Any CPU 113 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.Release|x64.ActiveCfg = Release|Any CPU 114 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.Release|x64.Build.0 = Release|Any CPU 115 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.Release|x86.ActiveCfg = Release|x86 116 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.Release|x86.Build.0 = Release|x86 117 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.ReleaseX|Any CPU.ActiveCfg = ReleaseX|Any CPU 118 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.ReleaseX|Any CPU.Build.0 = ReleaseX|Any CPU 119 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.ReleaseX|x64.ActiveCfg = ReleaseX|Any CPU 120 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.ReleaseX|x64.Build.0 = ReleaseX|Any CPU 121 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.ReleaseX|x86.ActiveCfg = ReleaseX|x86 122 | {88A998F1-C512-416F-ADED-120E50AFE6F3}.ReleaseX|x86.Build.0 = ReleaseX|x86 123 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 124 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.Debug|Any CPU.Build.0 = Debug|Any CPU 125 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.Debug|x64.ActiveCfg = Debug|Any CPU 126 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.Debug|x64.Build.0 = Debug|Any CPU 127 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.Debug|x86.ActiveCfg = Debug|x86 128 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.Debug|x86.Build.0 = Debug|x86 129 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.DebugTracing|Any CPU.ActiveCfg = DebugTracing|Any CPU 130 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.DebugTracing|Any CPU.Build.0 = DebugTracing|Any CPU 131 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.DebugTracing|x64.ActiveCfg = DebugTracing|Any CPU 132 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.DebugTracing|x64.Build.0 = DebugTracing|Any CPU 133 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.DebugTracing|x86.ActiveCfg = DebugTracing|x86 134 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.DebugTracing|x86.Build.0 = DebugTracing|x86 135 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.DebugVerbose|Any CPU.ActiveCfg = DebugVerbose|Any CPU 136 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.DebugVerbose|Any CPU.Build.0 = DebugVerbose|Any CPU 137 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.DebugVerbose|x64.ActiveCfg = DebugVerbose|Any CPU 138 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.DebugVerbose|x64.Build.0 = DebugVerbose|Any CPU 139 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.DebugVerbose|x86.ActiveCfg = DebugVerbose|x86 140 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.DebugVerbose|x86.Build.0 = DebugVerbose|x86 141 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.Release|Any CPU.ActiveCfg = Release|Any CPU 142 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.Release|Any CPU.Build.0 = Release|Any CPU 143 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.Release|x64.ActiveCfg = Release|Any CPU 144 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.Release|x64.Build.0 = Release|Any CPU 145 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.Release|x86.ActiveCfg = Release|x86 146 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.Release|x86.Build.0 = Release|x86 147 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.ReleaseX|Any CPU.ActiveCfg = Release|Any CPU 148 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.ReleaseX|Any CPU.Build.0 = Release|Any CPU 149 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.ReleaseX|x64.ActiveCfg = Release|Any CPU 150 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.ReleaseX|x64.Build.0 = Release|Any CPU 151 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.ReleaseX|x86.ActiveCfg = Release|x86 152 | {A74E7E85-1797-477C-AEC1-583AE7D109D0}.ReleaseX|x86.Build.0 = Release|x86 153 | EndGlobalSection 154 | GlobalSection(SolutionProperties) = preSolution 155 | HideSolutionNode = FALSE 156 | EndGlobalSection 157 | GlobalSection(ExtensibilityGlobals) = postSolution 158 | SolutionGuid = {7A4553E8-6A4B-46A5-B429-7F9128492CAD} 159 | EndGlobalSection 160 | EndGlobal 161 | -------------------------------------------------------------------------------- /UAssetGUI/FindForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text.RegularExpressions; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using System.Windows.Forms; 8 | 9 | namespace UAssetGUI 10 | { 11 | public partial class FindForm : Form 12 | { 13 | public string SearchTerm = string.Empty; 14 | public bool UseRegex = false; 15 | public Regex RegularExpression; 16 | public bool CaseSensitive = false; 17 | public SearchDirection CurrentSearchDirection = SearchDirection.Forward; 18 | 19 | public FindForm() 20 | { 21 | InitializeComponent(); 22 | progressBar1.Visible = false; 23 | searchDirForwardButton.Tag = SearchDirection.Forward; 24 | searchDirBackwardButton.Tag = SearchDirection.Backward; 25 | searchDirForwardButton.Checked = true; 26 | } 27 | 28 | private Form1 BaseForm; 29 | private void FindForm_Load(object sender, EventArgs e) 30 | { 31 | if (this.Owner is Form1) BaseForm = (Form1)this.Owner; 32 | 33 | UAGPalette.RefreshTheme(this); 34 | this.AdjustFormPosition(); 35 | } 36 | 37 | private void SyncSettings() 38 | { 39 | SearchTerm = searchForBox.Text.Trim(); 40 | CaseSensitive = caseSensitiveCheckBox.Checked; 41 | UseRegex = useRegexCheckBox.Checked; 42 | CurrentSearchDirection = (SearchDirection)(searchDirectionGroupBox.Controls.OfType().FirstOrDefault(n => n.Checked).Tag); 43 | 44 | if (UseRegex) 45 | { 46 | RegexOptions ourOptions = RegexOptions.Compiled | RegexOptions.Multiline; 47 | if (!CaseSensitive) ourOptions |= RegexOptions.IgnoreCase; 48 | RegularExpression = new Regex(SearchTerm, ourOptions); 49 | } 50 | } 51 | 52 | private void closeButton_Click(object sender, EventArgs e) 53 | { 54 | if (ts != null) ts.Cancel(); 55 | this.Dispose(); 56 | } 57 | 58 | private bool DoesTextQualify(string txt) 59 | { 60 | if (UseRegex) return RegularExpression.IsMatch(txt); 61 | return CaseSensitive ? txt.Contains(SearchTerm) : (txt.IndexOf(SearchTerm, StringComparison.OrdinalIgnoreCase) >= 0); 62 | } 63 | 64 | private void TraverseToPopulatePreviouslyExpandedNodes(ISet previouslyExpandedNodes, TreeNodeCollection nodes) 65 | { 66 | foreach (TreeNode node in nodes) 67 | { 68 | if (node.IsExpanded) previouslyExpandedNodes.Add(node); 69 | TraverseToPopulatePreviouslyExpandedNodes(previouslyExpandedNodes, node.Nodes); 70 | } 71 | } 72 | 73 | private void PerformSearch(CancellationToken cancelToken) 74 | { 75 | bool foundSomething = false; bool wasCanceled = false; TreeNode originalNode = null; TreeNode examiningNode = null; int minRow = -1; 76 | 77 | ISet previouslyExpandedNodes = new HashSet(); 78 | 79 | UAGUtils.InvokeUI(() => 80 | { 81 | progressBar1.Visible = true; 82 | progressBar1.Value = 0; 83 | progressBar1.Maximum = BaseForm.treeView1.GetNodeCount(true); 84 | BaseForm.dataGridView1.SuspendLayout(); 85 | BaseForm.treeView1.SuspendLayout(); 86 | BaseForm.treeView1.BeginUpdate(); 87 | 88 | originalNode = BaseForm.treeView1.SelectedNode; 89 | examiningNode = BaseForm.treeView1.SelectedNode; 90 | minRow = BaseForm.dataGridView1.SelectedRows.Count > 0 ? BaseForm.dataGridView1.SelectedRows[0].Index : (BaseForm.dataGridView1.SelectedCells.Count > 0 ? BaseForm.dataGridView1.SelectedCells[0].RowIndex : -1); 91 | 92 | // store previously expanded nodes; could take a second 93 | TraverseToPopulatePreviouslyExpandedNodes(previouslyExpandedNodes, BaseForm.treeView1.Nodes); 94 | }); 95 | 96 | try 97 | { 98 | while (examiningNode != null) 99 | { 100 | if (cancelToken.IsCancellationRequested) 101 | { 102 | foundSomething = false; wasCanceled = true; 103 | MessageBox.Show("Operation canceled."); 104 | break; 105 | } 106 | 107 | UAGUtils.InvokeUI(() => 108 | { 109 | // if dynamic tree, expand 110 | if (examiningNode is PointingTreeNode ptn) 111 | { 112 | if (!ptn.ChildrenInitialized) 113 | { 114 | BaseForm.tableEditor.FillOutSubnodes(ptn, false); 115 | } 116 | } 117 | 118 | BaseForm.treeView1.SelectedNode = examiningNode; 119 | BaseForm.UpdateModeFromSelectedNode(examiningNode); 120 | 121 | // check node name 122 | if (DoesTextQualify(examiningNode.Text) && examiningNode != originalNode) 123 | { 124 | foundSomething = true; 125 | return; 126 | } 127 | 128 | // check dgv 129 | if (BaseForm.dataGridView1 != null && BaseForm.dataGridView1.Enabled && BaseForm.dataGridView1.Visible && BaseForm.dataGridView1.Rows.Count > 0) 130 | { 131 | int rowNum = CurrentSearchDirection == SearchDirection.Forward ? 0 : BaseForm.dataGridView1.Rows.Count - 1; 132 | bool isSatisfied = false; 133 | while (!isSatisfied) 134 | { 135 | int oldRowNum = rowNum; 136 | 137 | rowNum += CurrentSearchDirection == SearchDirection.Forward ? 1 : -1; 138 | isSatisfied = CurrentSearchDirection == SearchDirection.Forward ? rowNum >= BaseForm.dataGridView1.Rows.Count : rowNum < 0; 139 | 140 | DataGridViewRow row = BaseForm.dataGridView1.Rows[oldRowNum]; 141 | if (minRow >= 0 && CurrentSearchDirection == SearchDirection.Forward && oldRowNum <= minRow) continue; 142 | if (minRow >= 0 && CurrentSearchDirection == SearchDirection.Backward && oldRowNum >= minRow) continue; 143 | 144 | if (row == null || row.Cells == null) continue; 145 | foreach (DataGridViewCell cell in row.Cells) 146 | { 147 | if (cell == null || cell.Value == null) continue; 148 | 149 | if (DoesTextQualify(cell.Value.ToString())) 150 | { 151 | if (!cell.Displayed) BaseForm.dataGridView1.FirstDisplayedScrollingRowIndex = row.Index; 152 | BaseForm.treeView1.SelectedNode.EnsureVisible(); 153 | row.Selected = true; 154 | cell.Selected = true; 155 | foundSomething = true; 156 | } 157 | 158 | if (foundSomething) return; 159 | } 160 | 161 | if (foundSomething) return; 162 | } 163 | } 164 | 165 | if (foundSomething) return; 166 | minRow = -1; 167 | 168 | if (progressBar1.Value < progressBar1.Maximum) progressBar1.Value++; 169 | examiningNode = UAGFindUtils.GetNextNode(examiningNode, CurrentSearchDirection, previouslyExpandedNodes, BaseForm.tableEditor); 170 | }); 171 | 172 | if (foundSomething) break; 173 | } 174 | } 175 | finally 176 | { 177 | UAGUtils.InvokeUI(() => 178 | { 179 | progressBar1.Value = progressBar1.Maximum; 180 | BaseForm.dataGridView1.ResumeLayout(); 181 | BaseForm.treeView1.ResumeLayout(); 182 | BaseForm.treeView1.EndUpdate(); 183 | 184 | if (!foundSomething) 185 | { 186 | BaseForm.treeView1.SelectedNode = originalNode; 187 | BaseForm.UpdateModeFromSelectedNode(originalNode); 188 | if (!wasCanceled) MessageBox.Show("0 results found."); 189 | } 190 | }); 191 | } 192 | } 193 | 194 | private readonly CancellationTokenSource ts = new CancellationTokenSource(); 195 | private void nextButton_Click(object sender, EventArgs e) 196 | { 197 | SyncSettings(); 198 | if (BaseForm.tableEditor == null || BaseForm.tableEditor.asset == null) return; 199 | 200 | Task.Run(() => 201 | { 202 | PerformSearch(ts.Token); 203 | }); 204 | } 205 | } 206 | 207 | public enum SearchDirection 208 | { 209 | Forward, 210 | Backward 211 | } 212 | 213 | public static class UAGFindUtils 214 | { 215 | public static TreeNode GetLastNode(TreeNode node, TableHandler handler) 216 | { 217 | // if dynamic tree, expand 218 | if (node is PointingTreeNode ptn) 219 | { 220 | if (!ptn.ChildrenInitialized) 221 | { 222 | handler.FillOutSubnodes(ptn, false); 223 | } 224 | } 225 | 226 | if (node.Nodes.Count == 0) return node; 227 | return GetLastNode(node.Nodes[node.Nodes.Count - 1], handler); 228 | } 229 | 230 | public static TreeNode GetNextNode(TreeNode node, SearchDirection dir, ISet previouslyExpandedNodes, TableHandler handler, bool canGoDown = true) 231 | { 232 | if (node == null) return null; 233 | 234 | if (dir == SearchDirection.Forward) 235 | { 236 | if (node.Nodes.Count != 0 && canGoDown) return node.Nodes[0]; // go down one 237 | 238 | // we don't need this node anymore 239 | if (previouslyExpandedNodes.Contains(node)) 240 | { 241 | node.Expand(); 242 | } 243 | else 244 | { 245 | node.Collapse(); 246 | } 247 | 248 | if (node.NextNode != null) return node.NextNode; // go forward one 249 | return GetNextNode(node.Parent, dir, previouslyExpandedNodes, handler, false); // go up one 250 | } 251 | else if (dir == SearchDirection.Backward) 252 | { 253 | // we don't need this node anymore 254 | if (previouslyExpandedNodes.Contains(node)) 255 | { 256 | node.Expand(); 257 | } 258 | else 259 | { 260 | node.Collapse(); 261 | } 262 | 263 | if (node.PrevNode != null && node.PrevNode.Nodes.Count != 0) return GetLastNode(node.PrevNode, handler); // go backwards one (to previous sibling's last descendant) 264 | if (node.PrevNode != null) return node.PrevNode; // go backwards one (to previous sibling directly) 265 | return node.Parent; // go up one (to parent) 266 | } 267 | 268 | return null; 269 | } 270 | } 271 | } 272 | --------------------------------------------------------------------------------