├── QuickOverTool-WPF ├── extract.ico ├── packages.config ├── UIStrings.xaml ├── App.xaml.cs ├── App.xaml ├── Tabs │ ├── StatusBar.cs │ ├── ConfigurationHandler.cs │ ├── Logging.cs │ ├── ToolVersion.cs │ ├── UpdateChecker.cs │ ├── GameVersion.cs │ ├── ExecutionHandler.cs │ ├── UIStrings.cs │ └── DataToolHandler.cs ├── Logics │ ├── BNetDetector.cs │ ├── DataToolConfig.cs │ ├── ToastManager.cs │ ├── ListAssetsHandler.cs │ ├── ValidationManager.cs │ ├── NetworkingManager.cs │ ├── LoggingManager.cs │ ├── Config.cs │ ├── ExtrAssetsHandler.cs │ ├── VersionManager.cs │ └── CommandLineFabricator.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Settings.settings │ └── Settings.Designer.cs ├── App.config ├── MainWindow.xaml.cs ├── Resources.Designer.cs ├── Resources.resx ├── QuickDataTool.csproj ├── Resources.xaml └── MainWindow.xaml ├── LICENSE ├── README.md ├── QuickDataTool-WPF.sln ├── QuickDataTool.sln ├── .gitattributes └── .gitignore /QuickOverTool-WPF/extract.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyx0826/QuickOverTool-WPF/HEAD/QuickOverTool-WPF/extract.ico -------------------------------------------------------------------------------- /QuickOverTool-WPF/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/UIStrings.xaml: -------------------------------------------------------------------------------- 1 | 4 | MainWindow 5 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | 9 | namespace OWorkbench 10 | { 11 | /// 12 | /// App.xaml 的交互逻辑 13 | /// 14 | public partial class App : Application 15 | { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/App.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Tabs/StatusBar.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace OWorkbench 4 | { 5 | class StatusBar : INotifyPropertyChanged 6 | { 7 | public event PropertyChangedEventHandler PropertyChanged; 8 | 9 | public void Rebind(string name) 10 | { 11 | OnPropertyChanged(name); 12 | } 13 | 14 | protected void OnPropertyChanged(string name) 15 | { 16 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Logics/BNetDetector.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | 3 | namespace OWorkbench.Logics 4 | { 5 | class BNetDetector 6 | { 7 | public static void CheckForBattleNet() 8 | { 9 | Process[] bnets = Process.GetProcessesByName("Battle.net"); 10 | if (!(bnets == null || bnets.Length == 0)) 11 | ToastManager.GetInstance().CreateToast("Battle.net is Running", 12 | "Detected Battle.net client running. Running DataTool without shutting down Battle.net risks corrupting the client.", 2); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Tabs/ConfigurationHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Collections.Generic; 4 | using static OWorkbench.Properties.Settings; 5 | using OWorkbench.Logics; 6 | using System.Windows.Controls; 7 | using System.Windows.Forms; 8 | 9 | namespace OWorkbench 10 | { 11 | public partial class MainWindow : Window 12 | { 13 | /// 14 | /// Select output path. 15 | /// 16 | private void buttonOutputPath_Click(object sender, RoutedEventArgs e) 17 | { 18 | FolderBrowserDialog folderBrowser = new FolderBrowserDialog(); 19 | DialogResult folderBrowserResult = folderBrowser.ShowDialog(); 20 | textBoxOutputPath.Text = (String.IsNullOrEmpty(folderBrowser.SelectedPath) ? textBoxOutputPath.Text : folderBrowser.SelectedPath); 21 | Logging.GetInstance().Increment("Output path: " + textBoxOutputPath.Text); 22 | return; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 xyx0826 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OWorkbench [![Build status](https://ci.appveyor.com/api/projects/status/lcm1habry0xfpgiq?svg=true)](https://ci.appveyor.com/project/xyx0826/quickovertool-wpf-5nemq) 2 | 3 | ## Introduction 4 | OWorkbench (previously named QuickDataTool) is a GUI frontend for DataTool, the CLI app for extracting assets from the game Overwatch. DataTool is built upon OWLib, which could be found [here](https://github.com/overtools/OWLib), 5 | 6 | OWorkbench features graphical implementation of all of DataTool's modes and flags. It has an updater for DataTool and OWorkbench itself. 7 | 8 | ## Support 9 | To download OWorkbench, use the green AppVeyor badge above or go to [this thread](https://forum.facepunch.com/f/fbx/qxgy/Overwatch-Model-Thread-v2/1/). New DataTool/OWorkbench versions are also often published there. 10 | 11 | If you need help using OWorkbench/DataTool or working with Overwatch assets, the thread mentioned above is the best place to go. Most discussions around Overwatch modelling happen there. 12 | 13 | You are also welcome to file Issues in this repo for help regarding OWorkbench. 14 | 15 | ## Contribution 16 | OWorkbench is written in C# with WPF. You are welcome to submit Issues and Pull Requests to this project. 17 | -------------------------------------------------------------------------------- /QuickDataTool-WPF.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.14 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuickDataTool", "QuickOverTool-WPF\QuickDataTool.csproj", "{CBA0F207-3DB9-44D3-9661-C6473277CCAA}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E4691D09-D5A2-4812-874A-08A8E24C2240}" 9 | ProjectSection(SolutionItems) = preProject 10 | appveyor.yml = appveyor.yml 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Any CPU = Debug|Any CPU 16 | Release|Any CPU = Release|Any CPU 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {CBA0F207-3DB9-44D3-9661-C6473277CCAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {CBA0F207-3DB9-44D3-9661-C6473277CCAA}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {CBA0F207-3DB9-44D3-9661-C6473277CCAA}.Release|Any CPU.ActiveCfg = Release|Any CPU 22 | {CBA0F207-3DB9-44D3-9661-C6473277CCAA}.Release|Any CPU.Build.0 = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | EndGlobal 28 | -------------------------------------------------------------------------------- /QuickDataTool.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.14 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuickDataTool", "QuickOverTool-WPF\QuickDataTool.csproj", "{CBA0F207-3DB9-44D3-9661-C6473277CCAA}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E4691D09-D5A2-4812-874A-08A8E24C2240}" 9 | ProjectSection(SolutionItems) = preProject 10 | appveyor.yml = appveyor.yml 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Any CPU = Debug|Any CPU 16 | Release|Any CPU = Release|Any CPU 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {CBA0F207-3DB9-44D3-9661-C6473277CCAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {CBA0F207-3DB9-44D3-9661-C6473277CCAA}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {CBA0F207-3DB9-44D3-9661-C6473277CCAA}.Release|Any CPU.ActiveCfg = Release|Any CPU 22 | {CBA0F207-3DB9-44D3-9661-C6473277CCAA}.Release|Any CPU.Build.0 = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(SolutionProperties) = preSolution 25 | HideSolutionNode = FALSE 26 | EndGlobalSection 27 | GlobalSection(ExtensibilityGlobals) = postSolution 28 | SolutionGuid = {994ED4D5-ABA8-46D7-BB71-9933D85F9676} 29 | EndGlobalSection 30 | EndGlobal 31 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Logics/DataToolConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Windows.Controls; 8 | 9 | using static OWorkbench.Properties.Settings; 10 | 11 | namespace OWorkbench.Logics 12 | { 13 | class DataToolConfig : INotifyPropertyChanged 14 | { 15 | #region Singleton implementation 16 | private static DataToolConfig _uniqueInstance; 17 | 18 | private DataToolConfig() 19 | { 20 | OutputPath = ".\\\\"; 21 | } 22 | 23 | public static DataToolConfig GetInstance() 24 | { 25 | if (_uniqueInstance == null) _uniqueInstance = new DataToolConfig(); 26 | return _uniqueInstance; 27 | } 28 | #endregion 29 | 30 | public int ComboBoxLangIndex 31 | { 32 | get { return Default.TAB_SETTINGS_LangIndex; } 33 | set 34 | { 35 | Default.TAB_SETTINGS_LangIndex = value; 36 | Default.Save(); 37 | } 38 | } 39 | 40 | public ComboBoxItem ComboBoxLanguage { get; set; } 41 | 42 | public string OutputPath 43 | { 44 | get { return Default.TAB_SETTINGS_OutputPath; } 45 | set 46 | { 47 | Default.TAB_SETTINGS_OutputPath = value; 48 | Default.Save(); 49 | } 50 | } 51 | 52 | public event PropertyChangedEventHandler PropertyChanged; 53 | 54 | protected void OnPropertyChanged(string name) 55 | { 56 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Logics/ToastManager.cs: -------------------------------------------------------------------------------- 1 | using Notifications.Wpf; 2 | 3 | namespace OWorkbench 4 | { 5 | class ToastManager 6 | { 7 | private static ToastManager _uniqueInstance; 8 | NotificationManager _manager; 9 | 10 | private ToastManager() 11 | { 12 | _manager = new NotificationManager(); 13 | } 14 | 15 | public static ToastManager GetInstance() 16 | { 17 | if (_uniqueInstance == null) _uniqueInstance = new ToastManager(); 18 | return _uniqueInstance; 19 | } 20 | 21 | /// 22 | /// Creates a system-wide toast with specified parameters. 23 | /// 24 | /// The title of the toast. 25 | /// The message of the toast. 26 | /// The type of the toast. From 0 to 3: Success, Information, Warning, Error. 27 | public void CreateToast(string title, string message, int type) 28 | { 29 | NotificationContent toast = new NotificationContent 30 | { 31 | Title = title, 32 | Message = message, 33 | }; 34 | 35 | switch (type) 36 | { 37 | case 0: 38 | toast.Type = NotificationType.Success; 39 | break; 40 | case 1: 41 | toast.Type = NotificationType.Information; 42 | break; 43 | case 2: 44 | toast.Type = NotificationType.Warning; 45 | break; 46 | case 3: 47 | toast.Type = NotificationType.Error; 48 | break; 49 | } 50 | 51 | _manager.Show(toast); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Tabs/Logging.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.ComponentModel; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using Notifications.Wpf; 7 | 8 | using static OWorkbench.Properties.Settings; 9 | 10 | namespace OWorkbench 11 | { 12 | public partial class MainWindow : Window 13 | { 14 | #region Initialization 15 | public void InitializeLogging() 16 | { 17 | tabLogging.DataContext = Logging.GetInstance(); 18 | if (Default.TAB_QUICKSTART_LoggingOnLaunch) tabControl.SelectedIndex = 5; 19 | Logging.GetInstance().IncrementDebug("Logging: OWorkbench is in debug mode. Logs can only be cleared manually."); 20 | } 21 | #endregion 22 | public void SaveLogs(object sender, RoutedEventArgs e) 23 | { 24 | Logging.GetInstance().SaveLogs(); 25 | } 26 | 27 | public void CopyLogs(object sender, RoutedEventArgs e) 28 | { 29 | if (logBox.SelectedItem == null) return; // Prevent no-selection from crashing the app 30 | Clipboard.SetText(logBox.SelectedItem.ToString()); 31 | } 32 | 33 | public void ClearLogs(object sender, RoutedEventArgs e) 34 | { 35 | Logging.GetInstance().ClearLogs(logBox); 36 | } 37 | 38 | private void buttonTaskkill_Click(object sender, RoutedEventArgs e) 39 | { 40 | try 41 | { 42 | Process proc = Process.GetProcessById(dataToolPID); 43 | proc.Kill(); 44 | Logging.GetInstance().Increment("DataTool is terminated."); 45 | } 46 | catch 47 | { 48 | Logging.GetInstance().Increment("Termination failed; DataTool might not be running."); 49 | return; 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // 有关程序集的一般信息由以下 8 | // 控制。更改这些特性值可修改 9 | // 与程序集关联的信息。 10 | [assembly: AssemblyTitle("OWorkbench")] 11 | [assembly: AssemblyDescription("Graphical interface for DataTool, the Overwatch assets extractor.")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("OWorkbench")] 15 | [assembly: AssemblyCopyright("Copyright © 2017: xyx0826 (GitHub)")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // 将 ComVisible 设置为 false 会使此程序集中的类型 20 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 21 | //请将此类型的 ComVisible 特性设置为 true。 22 | [assembly: ComVisible(false)] 23 | 24 | //若要开始生成可本地化的应用程序,请设置 25 | //.csproj 文件中的 CultureYouAreCodingWith 26 | //例如,如果您在源文件中使用的是美国英语, 27 | //使用的是美国英语,请将 设置为 en-US。 然后取消 28 | //对以下 NeutralResourceLanguage 特性的注释。 更新 29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置 36 | //(未在页面中找到资源时使用, 37 | //或应用程序资源字典中找到时使用) 38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置 39 | //(未在页面中找到资源时使用, 40 | //、应用程序或任何主题专用资源字典中找到时使用) 41 | )] 42 | 43 | 44 | // 程序集的版本信息由下列四个值组成: 45 | // 46 | // 主版本 47 | // 次版本 48 | // 生成号 49 | // 修订号 50 | // 51 | // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 52 | // 方法是按如下所示使用“*”: : 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0")] 56 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Logics/ListAssetsHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using static OWorkbench.Properties.Settings; 4 | 5 | namespace OWorkbench.Logics 6 | { 7 | class ListAssetsHandler : INotifyPropertyChanged 8 | { 9 | private static ListAssetsHandler _uniqueInstance; 10 | 11 | public static ListAssetsHandler GetInstance() 12 | { 13 | if (_uniqueInstance == null) _uniqueInstance = new ListAssetsHandler(); 14 | return _uniqueInstance; 15 | } 16 | 17 | #region ListAssets controls handler 18 | public bool IsTabSelected { get; set; } 19 | 20 | public KeyValuePair comboBoxMode; 21 | 22 | public int ComboBoxIndex // Binded ComboBox index 23 | { 24 | get { return Default.TAB_LIST_ModeIndex; } 25 | set 26 | { 27 | Default.TAB_LIST_ModeIndex = value; 28 | } 29 | } 30 | 31 | public KeyValuePair ComboBoxMode // This KeyValuePair is temporary and is reset every app launch 32 | { 33 | get { return comboBoxMode; } 34 | set { comboBoxMode = value; } 35 | } 36 | 37 | public bool IsJson // Binded JSON checkbox 38 | { 39 | get { return Default.TAB_LIST_OutputJSON; } 40 | set 41 | { 42 | Default.TAB_LIST_OutputJSON = value; 43 | } 44 | } 45 | 46 | public void ResetOptions() 47 | { 48 | Default.TAB_LIST_ModeIndex = 0; 49 | Default.TAB_LIST_OutputJSON = true; 50 | OnPropertyChanged(null); 51 | } 52 | #endregion 53 | 54 | public event PropertyChangedEventHandler PropertyChanged; 55 | 56 | protected void OnPropertyChanged(string name) 57 | { 58 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Logics/ValidationManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | 5 | namespace OWorkbench 6 | { 7 | /// 8 | /// Methods for getting the info on 9 | /// DataTool and Overwatch. 10 | /// 11 | class Validation 12 | { 13 | // Validate Overwatch and return its version and branch 14 | public static string[] Overwatch(string path) 15 | { 16 | string version; 17 | string branch = "Live"; 18 | try 19 | { 20 | string pdbPath = Path.Combine(path, ".product.db"); 21 | StreamReader pdbStream = new StreamReader(pdbPath); 22 | using (var reader = File.OpenText(pdbPath)) 23 | { 24 | Logging.GetInstance().IncrementDebug("Validation: now reading .product.db at installation " + path); 25 | string pdbRead = pdbStream.ReadLine(); 26 | while (pdbStream.Peek() >= 0) 27 | { 28 | pdbRead = pdbStream.ReadLine(); 29 | if (pdbRead.Contains("prometheus_test")) 30 | { 31 | branch = "PTR"; 32 | } 33 | if (pdbRead.EndsWith("B&")) break; 34 | } 35 | version = pdbRead.Substring(pdbRead.IndexOf("1."), 14); 36 | } 37 | return new string[] { version, branch }; 38 | } 39 | catch (Exception e) 40 | { 41 | // If .product.db does not even exist 42 | Logging.GetInstance().IncrementDebug("Validation: error reading .product.db. " + e.Message); 43 | return null; 44 | } 45 | } 46 | // Validate DataTool and ow.keys 47 | public static string DataTool(string path) 48 | { 49 | string version; 50 | try 51 | { 52 | version = FileVersionInfo.GetVersionInfo( 53 | Path.Combine(path, "DataTool.exe")) 54 | .FileVersion; 55 | } 56 | catch 57 | { 58 | version = null; 59 | } 60 | return version; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Tabs/ToolVersion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.IO.Compression; 7 | using System.Linq; 8 | using System.Net; 9 | using System.Text; 10 | using System.Threading.Tasks; 11 | using System.Windows; 12 | using System.Windows.Navigation; 13 | 14 | namespace OWorkbench 15 | { 16 | public partial class MainWindow : Window 17 | { 18 | public string[] DTInfo 19 | { 20 | get 21 | { 22 | return Networking.GetDTInfo(); 23 | } 24 | set { } 25 | } 26 | 27 | private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e) 28 | { 29 | Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri)); 30 | e.Handled = true; 31 | } 32 | 33 | private void DownloadNewDataTool(object sender, RequestNavigateEventArgs e) 34 | { 35 | string zipPath = ".\\datatool_" + Networking.GetDTInfo()[0] + ".zip"; 36 | // Download new build from appveyor 37 | textBlockDownloader.Text = "Downloading..."; 38 | using (WebClient wc = new WebClient()) 39 | { 40 | wc.DownloadProgressChanged += wc_DownloadProgressChanged; 41 | wc.DownloadFileAsync(new Uri(e.Uri.AbsoluteUri), zipPath); 42 | wc.DownloadFileCompleted += new AsyncCompletedEventHandler(Unzip); 43 | } 44 | } 45 | 46 | private void Unzip(object sender, AsyncCompletedEventArgs e) 47 | { 48 | string zipPath = ".\\datatool_" + Networking.GetDTInfo()[0] + ".zip"; 49 | // Read zip content and remove old build 50 | List files = new List(); 51 | ZipArchive zip = ZipFile.OpenRead(zipPath); 52 | foreach (ZipArchiveEntry file in zip.Entries) 53 | { 54 | File.Delete(".\\" + file.Name); 55 | } 56 | try 57 | { 58 | ZipFile.ExtractToDirectory(zipPath, ".\\"); 59 | } 60 | catch { } 61 | UIString.GetInstance().Rebind(null); 62 | textBlockDownloader.Text = "Update successful."; 63 | } 64 | 65 | private void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) 66 | { 67 | UIString.GetInstance().DownloadProgress = e.ProgressPercentage; 68 | UIString.GetInstance().Rebind("DownloadProgress"); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | C:\Program Files (x86)\Overwatch\ 7 | 8 | 9 | 10 | 11 | 12 | .\\ 13 | 14 | 15 | 0 16 | 17 | 18 | False 19 | 20 | 21 | 0 22 | 23 | 24 | 0 25 | 26 | 27 | False 28 | 29 | 30 | 0 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | .\\ 43 | 44 | 45 | 0 46 | 47 | 48 | True 49 | 50 | 51 | False 52 | 53 | 54 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Logics/NetworkingManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using System.Xml; 8 | 9 | namespace OWorkbench 10 | { 11 | class Networking 12 | { 13 | /// 14 | /// Polls AppVeyor API for information regarding a project. 15 | /// 16 | /// Project name, in the format of "[authorname]/[repoName]" 17 | /// Branch name 18 | /// The artifact file name to search for 19 | /// An array of latest build version, message and artifact link. 20 | public static string[] PollAppveyorInfo(string project, string branch, string innerText) 21 | { 22 | // Request XML data from Appveyor API 23 | HttpWebRequest req = WebRequest.Create("https://ci.appveyor.com/api/projects/" + project + "/branch/" + branch) as HttpWebRequest; 24 | req.Accept = "application/xml"; 25 | HttpWebResponse resp = req.GetResponse() as HttpWebResponse; 26 | // Parse XML response 27 | XmlDocument appveyor = new XmlDocument(); 28 | appveyor.Load(resp.GetResponseStream()); 29 | string version = appveyor.GetElementsByTagName("Version")[0].InnerText; 30 | string message = appveyor.GetElementsByTagName("Message")[0].InnerText; 31 | string download = MakeDownloadURL(appveyor.GetElementsByTagName("JobId")[0].InnerText, 32 | innerText); 33 | return new string[] { version, message, download }; 34 | } 35 | 36 | public static string[] GetDTInfo() 37 | { 38 | // Logging.GetInstance().IncrementDebug("Networking: polling AppVeyor API for DataTool."); 39 | return PollAppveyorInfo("yukimono/owlib", "overwatch/1.14", "dist%2Ftoolchain-release.zip"); 40 | } 41 | 42 | public static string[] GetGUIInfo() 43 | { 44 | // Logging.GetInstance().IncrementDebug("Networking: polling AppVeyor API for OWorkbench."); 45 | return PollAppveyorInfo("xyx0826/quickovertool-wpf-5nemq", "experimental", "output%2FOWorkbench.exe"); 46 | } 47 | 48 | public static string GetGUIDependency() 49 | { 50 | return PollAppveyorInfo("xyx0826/quickovertool-wpf-5nemq", "experimental", "output%2FNotifications.Wpf.dll")[2]; 51 | } 52 | 53 | public static string MakeDownloadURL(string jobID, string filename) 54 | { 55 | return "https://ci.appveyor.com/api/buildjobs/" + 56 | jobID + 57 | "/artifacts/" + 58 | filename; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Tabs/UpdateChecker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Net; 4 | using System.Reflection; 5 | using System.Windows; 6 | 7 | namespace OWorkbench 8 | { 9 | public partial class MainWindow : Window 10 | { 11 | BackgroundWorker worker1 = new BackgroundWorker(); 12 | BackgroundWorker worker2 = new BackgroundWorker(); 13 | 14 | private void CheckGUIUpdate() 15 | { 16 | worker1.DoWork += worker_GUI; 17 | worker1.RunWorkerCompleted += worker_GUICompleted; 18 | worker1.WorkerReportsProgress = true; 19 | worker1.RunWorkerAsync(); 20 | } 21 | 22 | private void CheckDTUpdate() 23 | { 24 | worker2.DoWork += worker_DT; 25 | worker2.RunWorkerCompleted += worker_DTCompleted; 26 | worker2.WorkerReportsProgress = true; 27 | worker2.RunWorkerAsync(); 28 | } 29 | 30 | private void worker_GUI(object sender, DoWorkEventArgs e) 31 | { 32 | e.Result = Networking.GetGUIInfo(); 33 | } 34 | 35 | private void worker_DT(object sender, DoWorkEventArgs e) 36 | { 37 | e.Result = Networking.GetDTInfo(); 38 | } 39 | 40 | private void worker_GUICompleted(object sender, RunWorkerCompletedEventArgs e) 41 | { 42 | string[] result = (string[])e.Result; 43 | if (Assembly.GetExecutingAssembly().GetName().Version.CompareTo(new Version(result[0])) < 0) // Remote has a new version 44 | { 45 | Logging.GetInstance().Increment("OWorkbench has an update! Latest version is " + result[0] + "."); 46 | Logging.GetInstance().Increment("Automatic downloading initiated."); 47 | Logging.GetInstance().IncrementDebug("UpdateChecker: found new OWorkbench version at " + result[2]); 48 | using (WebClient wc = new WebClient()) 49 | { 50 | wc.DownloadFileAsync(new Uri(result[2]), ".\\OWorkbench_" + result[0] + ".exe"); 51 | } 52 | UIString.GetInstance().SetNotif("New OWorkbench version will be downloaded to .\\OWorkbench_" + result[0] + ".exe."); 53 | } 54 | } 55 | 56 | private void worker_DTCompleted(object sender, RunWorkerCompletedEventArgs e) 57 | { 58 | string[] result = (string[])e.Result; 59 | if (Validation.DataTool(".\\") == null || 60 | new Version(Validation.DataTool(".\\")).CompareTo(new Version(result[0])) < 0) // Remote has a new version 61 | { 62 | Logging.GetInstance().Increment("DataTool has an update! Latest version is " + result[0] + "."); 63 | Logging.GetInstance().Increment("Download the latest DataTool in \"Tool Version\" tab.\n"); 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | C:\Program Files (x86)\Overwatch\ 19 | 20 | 21 | .\\ 22 | 23 | 24 | 0 25 | 26 | 27 | False 28 | 29 | 30 | 0 31 | 32 | 33 | 0 34 | 35 | 36 | False 37 | 38 | 39 | 0 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | .\\ 52 | 53 | 54 | 0 55 | 56 | 57 | True 58 | 59 | 60 | False 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using OWorkbench.Logics; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Net; 6 | using System.Reflection; 7 | using System.Windows; 8 | using static OWorkbench.Properties.Settings; 9 | 10 | namespace OWorkbench 11 | { 12 | public partial class MainWindow : Window 13 | { 14 | // DataTool path and PID 15 | int dataToolPID = -1; 16 | string sharedPath = Path.GetDirectoryName 17 | (Assembly.GetEntryAssembly().CodeBase).Substring(6); 18 | // Mode parameters dictionary 19 | Dictionary modes = new Dictionary(); 20 | 21 | public MainWindow() 22 | { 23 | AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; 24 | 25 | InitializeComponent(); 26 | Logging.GetInstance().IncrementDebug("MainWindow: OWorkbench is initializing."); 27 | Config.GetInstance().InitConfig(); 28 | InitializeDataToolHandling(); 29 | InitializeLogging(); 30 | 31 | BNetDetector.CheckForBattleNet(); 32 | FlushInst(); 33 | 34 | DataContext = UIString.GetInstance(); 35 | tabStart.DataContext = UIString.GetInstance(); 36 | tabConfig.DataContext = DataToolConfig.GetInstance(); 37 | 38 | CheckGUIUpdate(); 39 | CheckDTUpdate(); 40 | 41 | WindowMain.Title += " | " + UIString.GetInstance().BenchVersion; 42 | } 43 | 44 | // Save config and close application upon MainWindow closure 45 | protected override void OnClosed(EventArgs e) 46 | { 47 | Default.Upgrade(); 48 | Default.Save(); 49 | base.OnClosed(e); 50 | Application.Current.Shutdown(); 51 | } 52 | 53 | protected Assembly ResolveAssembly(object sender, ResolveEventArgs args) 54 | { 55 | if (args.Name.Contains("Notifications.Wpf")) 56 | { 57 | using (WebClient wc = new WebClient()) 58 | { 59 | wc.DownloadFile(new Uri(Networking.GetGUIDependency()), ".\\Notifications.Wpf.dll"); 60 | } 61 | UIString.GetInstance().SetNotif("OWorkbench is downloading a required assembly file. Please restart OWorkbench."); 62 | } 63 | return null; 64 | } 65 | 66 | /* TBD in OWB 67 | private void buttonSaveCmdline_Click(object sender, RoutedEventArgs e) 68 | { 69 | try 70 | { 71 | string[] batFile = {"echo off\n", 72 | ".\\DataTool.exe" + FabricateCmdline(), 73 | "\npause\n"}; 74 | File.WriteAllLines(".\\_" + GetMode() + ".bat", batFile); 75 | Logging.GetInstance().Increment("Written batch file for mode " + GetMode() + 76 | " to _" + GetMode() + ".bat."); 77 | } 78 | catch 79 | { 80 | Logging.GetInstance().Increment("Settings invalid. Please check your mode settings."); 81 | } 82 | } 83 | */ 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Logics/LoggingManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.ObjectModel; 3 | using System.ComponentModel; 4 | using System.IO; 5 | using System.Windows.Controls; 6 | 7 | using static OWorkbench.Properties.Settings; 8 | 9 | namespace OWorkbench 10 | { 11 | class Logging : INotifyPropertyChanged 12 | { 13 | private static Logging _uniqueInstance; 14 | private static readonly object _threadLock = new object(); 15 | 16 | private Logging() 17 | { 18 | 19 | } 20 | 21 | public static Logging GetInstance() // Ensure singleton model 22 | { 23 | if (_uniqueInstance == null) 24 | lock (_threadLock) 25 | _uniqueInstance = new Logging(); 26 | return _uniqueInstance; 27 | } 28 | 29 | public void ClearLogs(ListBox listBox) 30 | { 31 | logCollection = new ObservableCollection(); 32 | Increment("Logs have been cleared."); 33 | IncrementDebug("OWorkbench is in debug mode."); 34 | } 35 | 36 | public void SaveLogs() 37 | { 38 | DateTime timeNow = DateTime.Now; 39 | string logPath = Path.GetFullPath(Default.Path_Output) 40 | + "QDT-Log-" + timeNow.Hour + timeNow.Minute + timeNow.Second + ".log"; 41 | using (StreamWriter logFile = new StreamWriter(@logPath)) 42 | { 43 | foreach (String log in logCollection) logFile.WriteLine(log); 44 | } 45 | if (!UIString.GetInstance().DebugMode) 46 | logCollection = new ObservableCollection(); 47 | Increment("Log written to " + @logPath + "."); 48 | Refresh(); 49 | } 50 | 51 | public event PropertyChangedEventHandler PropertyChanged; 52 | 53 | protected void OnPropertyChanged(string name) 54 | { 55 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 56 | } 57 | 58 | public void Refresh() 59 | { 60 | OnPropertyChanged(null); 61 | } 62 | 63 | private ObservableCollection logCollection = new ObservableCollection(); 64 | 65 | public ObservableCollection LogCollection 66 | { 67 | get { return logCollection; } 68 | } 69 | 70 | public delegate void IncrementDelegate(string log); // Delegated increment 71 | 72 | public void Increment(string log) // Standard increment 73 | { 74 | logCollection.Add(log); 75 | Refresh(); 76 | } 77 | 78 | public void IncrementDebug(string log) // Debug increment 79 | { 80 | if (Default.DebugMode) 81 | { 82 | logCollection.Add("DEBUG - " + DateTime.Now.ToShortTimeString() + " - " + log); 83 | Refresh(); 84 | } 85 | } 86 | 87 | public void IncrementDebug(ListBox box, string log) // Delegated debug increment 88 | { 89 | box.Dispatcher.Invoke(new IncrementDelegate(IncrementDebug), log); 90 | } 91 | 92 | public void Increment(ListBox box, string log) // Dispatched increment 93 | { 94 | box.Dispatcher.Invoke(new IncrementDelegate(Increment), log); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Tabs/GameVersion.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using static OWorkbench.Properties.Settings; 5 | using System; 6 | using OWorkbench.Logics; 7 | using System.Windows.Forms; 8 | 9 | namespace OWorkbench 10 | { 11 | public partial class MainWindow : Window 12 | { 13 | VersionManagement vm = new VersionManagement(); 14 | 15 | public void AddInst(object sender, RoutedEventArgs e) 16 | { 17 | FolderBrowserDialog folderBrowser = new FolderBrowserDialog(); 18 | DialogResult folderBrowserResult = folderBrowser.ShowDialog(); 19 | try 20 | { 21 | Config.GetInstance().AddOWInst(folderBrowser.SelectedPath); 22 | } 23 | catch (ArgumentException f) 24 | { 25 | UIString.GetInstance().SetNotif(lblNotif.Dispatcher, f.Message); 26 | } 27 | FlushInst(); 28 | } 29 | 30 | public void DelInst(object sender, RoutedEventArgs e) 31 | { 32 | if (Config.GetInstance().CountOWInst() == 1) 33 | { 34 | UIString.GetInstance().SetNotif(lblNotif.Dispatcher, "Failed to delete installation record. This is the last one."); 35 | return; 36 | } 37 | try 38 | { 39 | string path = comboOWInsts.SelectedItem.ToString(); 40 | Config.GetInstance().DelOWInst(path); 41 | FlushInst(); 42 | } 43 | catch (NullReferenceException) 44 | { 45 | UIString.GetInstance().SetNotif(lblNotif.Dispatcher, "Failed to remove installation from settings. " + 46 | "Please select an installation first."); 47 | } 48 | } 49 | 50 | public void SetInst(object sender, RoutedEventArgs e) 51 | { 52 | if (comboOWInsts.SelectedIndex != -1) 53 | { 54 | Config.GetInstance().UseOWInst(comboOWInsts.SelectedIndex); 55 | ToastManager.GetInstance().CreateToast("Test", "hello", 0); 56 | UIString.GetInstance().Rebind(null); 57 | } 58 | else UIString.GetInstance().SetNotif(lblNotif.Dispatcher, "Failed to set Overwatch installation. " + 59 | "Please select an installation first."); 60 | } 61 | 62 | public void FlushInst() 63 | { 64 | Dictionary versionDict = new Dictionary(); 65 | foreach (string path in Default.List_OWInsts) // Reads insts from user config 66 | { 67 | string key; 68 | try { key = vm.GetOWVersion(path); } 69 | catch (FileNotFoundException e) 70 | { 71 | UIString.GetInstance().SetNotif(lblNotif.Dispatcher, e.Message); 72 | key = "(Unknown version)"; 73 | } 74 | try { versionDict.Add(path, key); } 75 | catch (ArgumentException) 76 | { 77 | UIString.GetInstance().SetNotif(lblNotif.Dispatcher, "Failed to add this installation. Path duplicate."); 78 | continue; 79 | } 80 | } 81 | // Repopulate ComboBox 82 | comboOWInsts.Items.Clear(); 83 | foreach (KeyValuePair inst in versionDict) 84 | { 85 | comboOWInsts.Items.Add(inst.Key); 86 | comboOWInsts.SelectedIndex = 0; 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Tabs/ExecutionHandler.cs: -------------------------------------------------------------------------------- 1 | using OWorkbench.Logics; 2 | using System; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Text; 6 | using System.Windows; 7 | 8 | namespace OWorkbench 9 | { 10 | public partial class MainWindow : Window 11 | { 12 | public Process PrepareDataTool(string cmdline) 13 | { 14 | Process dataTool = new Process(); 15 | dataTool.StartInfo.FileName = "DataTool.exe"; 16 | dataTool.StartInfo.Arguments = cmdline; 17 | dataTool.StartInfo.UseShellExecute = false; 18 | dataTool.StartInfo.RedirectStandardOutput = true; 19 | dataTool.StartInfo.StandardOutputEncoding = Encoding.UTF8; 20 | dataTool.StartInfo.RedirectStandardError = true; 21 | dataTool.StartInfo.StandardErrorEncoding = Encoding.UTF8; 22 | dataTool.StartInfo.CreateNoWindow = true; 23 | return dataTool; 24 | } 25 | 26 | public void StartDataTool(Process dataTool) 27 | { 28 | using (dataTool) 29 | { 30 | BackgroundWorker aliveChecker = new BackgroundWorker(); 31 | aliveChecker.DoWork += CheckAlive; 32 | aliveChecker.RunWorkerCompleted += OnProcessDead; 33 | 34 | Logging.GetInstance().Increment("List and extract tabs are now temporarily disabled until DataTool terminates or exits."); 35 | 36 | try 37 | { 38 | BNetDetector.CheckForBattleNet(); // Do a final check on Battle.net instances 39 | dataTool.Start(); 40 | dataToolPID = dataTool.Id; 41 | } 42 | catch (Exception e) 43 | { 44 | Logging.GetInstance().IncrementDebug("ExecutionHandler: DataTool launch exception /// " + e.Message); 45 | Logging.GetInstance().Increment("DataTool launch failure. Update your DataTool from \"Tool Version\" tab."); 46 | ToggleRunningState(false); 47 | return; 48 | } 49 | Logging.GetInstance().Increment("Starting DataTool now. PID: " + dataTool.Id); 50 | ToggleRunningState(true); 51 | aliveChecker.RunWorkerAsync(dataTool); 52 | 53 | dataTool.BeginOutputReadLine(); 54 | dataTool.BeginErrorReadLine(); 55 | dataTool.OutputDataReceived += new DataReceivedEventHandler(DataTool_DataReceived); 56 | dataTool.ErrorDataReceived += new DataReceivedEventHandler(DataTool_DataReceived); 57 | } 58 | } 59 | 60 | /// 61 | /// Toggle the display of lower right corner icons. 62 | /// 63 | /// Whether DataTool is running or not. 64 | public void ToggleRunningState(bool state) 65 | { 66 | if (state) 67 | { 68 | // Certain tabs have to be disabled to prevent multi-launch 69 | tabListAssets.IsEnabled = false; 70 | tabExtrAssets.IsEnabled = false; 71 | lblInactive.Visibility = Visibility.Collapsed; 72 | lblRunning.Visibility = Visibility.Visible; 73 | } 74 | else 75 | { 76 | tabListAssets.IsEnabled = true; 77 | tabExtrAssets.IsEnabled = true; 78 | lblInactive.Visibility = Visibility.Visible; 79 | lblRunning.Visibility = Visibility.Collapsed; 80 | } 81 | } 82 | 83 | public void DataTool_DataReceived(object sender, DataReceivedEventArgs e) 84 | { 85 | if (e.Data != null) Logging.GetInstance().Increment(logBox, e.Data); 86 | } 87 | 88 | private void CheckAlive(object sender, DoWorkEventArgs e) 89 | { 90 | ((Process)e.Argument).WaitForExit(); 91 | } 92 | 93 | private void OnProcessDead(object sender, RunWorkerCompletedEventArgs e) 94 | { 95 | ToastManager.GetInstance().CreateToast("DataTool Termination", "DataTool has finished working.", 1); 96 | Logging.GetInstance().Increment("DataTool has exited."); 97 | ToggleRunningState(false); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Logics/Config.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Configuration; 5 | using System.IO; 6 | using System.Linq; 7 | 8 | using static OWorkbench.Properties.Settings; 9 | 10 | namespace OWorkbench.Logics 11 | { 12 | class Config 13 | { 14 | private static Config _uniqueInstance; 15 | 16 | private Config() 17 | { 18 | 19 | } 20 | 21 | public static Config GetInstance() 22 | { 23 | if (_uniqueInstance == null) _uniqueInstance = new Config(); 24 | return _uniqueInstance; 25 | } 26 | 27 | /// 28 | /// Initialize the configurations on first run. 29 | /// 30 | public void InitConfig() 31 | { 32 | if (String.IsNullOrWhiteSpace(Default.Path_CurrentOW)) // Default Overwatch path 33 | { 34 | Logging.GetInstance().IncrementDebug("Config: resetting Path_CurrentOW"); 35 | Default.Path_CurrentOW = "C:\\Program Files (x86)\\Overwatch"; 36 | } 37 | if (String.IsNullOrWhiteSpace(Default.Path_Output)) // Default output path 38 | { 39 | Logging.GetInstance().IncrementDebug("Config: resetting Path_Output"); 40 | Default.Path_Output = ".\\"; 41 | } 42 | if (Default.List_OWInsts == null || Default.List_OWInsts.Count == 0) // Default Overwatch path in selector 43 | { 44 | Logging.GetInstance().IncrementDebug("Config: resetting List_OWInsts"); 45 | Default.List_OWInsts = new List 46 | { 47 | "C:\\Program Files (x86)\\Overwatch" 48 | }; 49 | } 50 | } 51 | #region Overwatch installation management 52 | public void AddOWInst(string path) 53 | { 54 | if (String.IsNullOrEmpty(path)) 55 | throw new ArgumentException("Please select a path to add to installation library."); 56 | if (Default.List_OWInsts.IndexOf(path) == -1) 57 | { 58 | Default.List_OWInsts.Add(path); 59 | Default.Save(); 60 | Logging.GetInstance().IncrementDebug("Config: added Overwatch installation " + path); 61 | } 62 | else 63 | throw new ArgumentException("Failed to add " + path + " to installation library. " + 64 | "Path already exists."); 65 | } 66 | 67 | public void DelOWInst(string path) 68 | { 69 | Default.List_OWInsts.Remove(path); 70 | Logging.GetInstance().IncrementDebug("Config: removed Overwatch installation " + path); 71 | } 72 | 73 | public void UseOWInst(int index) 74 | { 75 | Default.Path_CurrentOW = Default.List_OWInsts[index]; 76 | Default.Save(); 77 | Logging.GetInstance().IncrementDebug("Config: using Overwatch installation #" + index); 78 | 79 | BackgroundWorker sizeWorker = new BackgroundWorker(); 80 | sizeWorker.DoWork += GetOWInstSize; 81 | sizeWorker.RunWorkerCompleted += GetOWInstSizeCompleted; 82 | sizeWorker.RunWorkerAsync(Default.Path_CurrentOW); 83 | 84 | } 85 | 86 | public int CountOWInst() 87 | { 88 | int count = Default.List_OWInsts.Count(); 89 | Logging.GetInstance().Increment("Config: returned Overwatch installations is " + count); 90 | return count; 91 | } 92 | 93 | public void GetOWInstSize(object sender, DoWorkEventArgs e) 94 | { 95 | long size = 0; 96 | double sizeInGb; 97 | string[] files; 98 | try 99 | { 100 | files = Directory.GetFiles((string)e.Argument, "*", SearchOption.AllDirectories); 101 | } 102 | catch (Exception ex) 103 | { 104 | return; 105 | } 106 | foreach (string file in files) size += new FileInfo(file).Length; 107 | sizeInGb = size / 1073741824.0; // 1024 ^ 3 108 | e.Result = sizeInGb; 109 | } 110 | 111 | public void GetOWInstSizeCompleted(object sender, RunWorkerCompletedEventArgs e) 112 | { 113 | if (e.Result != null) 114 | UIString.GetInstance().CurrentOWSize = ((double)e.Result).ToString("0.000"); 115 | } 116 | #endregion 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Logics/ExtrAssetsHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using System.Windows; 4 | using System.Windows.Controls; 5 | using static OWorkbench.Properties.Settings; 6 | 7 | namespace OWorkbench.Logics 8 | { 9 | class ExtrAssetsHandler : INotifyPropertyChanged 10 | { 11 | #region Singleton implementation 12 | private static ExtrAssetsHandler _uniqueInstance; 13 | 14 | private ExtrAssetsHandler() 15 | { 16 | noExtRefpose = true; 17 | isLosslessTexture = true; 18 | } 19 | 20 | public static ExtrAssetsHandler GetInstance() 21 | { 22 | if (_uniqueInstance == null) _uniqueInstance = new ExtrAssetsHandler(); 23 | return _uniqueInstance; 24 | } 25 | #endregion 26 | 27 | #region ExtractAssets controls handler: global options 28 | // Variables binding to UI controls 29 | public bool IsTabSelected { get; set; } 30 | 31 | public KeyValuePair ComboBoxMode { get; set; } 32 | public ComboBoxItem comboBoxFormat { get; set; } 33 | public int modelLOD { get; set; } 34 | public bool isLosslessTexture { get; set; } 35 | public bool noExtTextures { get; set; } 36 | public bool noExtSound { get; set; } 37 | public bool noExtModels { get; set; } 38 | public bool noExtAnimation { get; set; } 39 | public bool noExtRefpose { get; set; } 40 | public bool noConAnything { get; set; } 41 | public bool noConTextures { get; set; } 42 | public bool noConSound { get; set; } 43 | public bool noConModels { get; set; } 44 | public bool noConAnimation { get; set; } 45 | public bool noEnvSound { get; set; } 46 | public bool noEnvEntity { get; set; } 47 | public bool noEnvLUT { get; set; } 48 | public bool noEnvSkybox { get; set; } 49 | public bool noEnvBlend { get; set; } 50 | public bool noEnvCubeMap { get; set; } 51 | public bool noEnvGround { get; set; } 52 | public bool noEnvSky { get; set; } 53 | 54 | /* 55 | public int ComboBoxModeIndex // Adapter: Mode ComboBox index <-> AppSettings 56 | { 57 | get { return Default.TAB3_ModeIndex; } 58 | set { Default.TAB3_ModeIndex = value; } 59 | } 60 | */ 61 | 62 | public void ResetOptions() // Resets options - NYI 63 | { 64 | OnPropertyChanged(null); 65 | } 66 | #endregion 67 | #region ExtractAssets controls handler: query parameters 68 | // Visibility binding for 4 query editors 69 | public Visibility queryGeneralVisb { get; set; } = Visibility.Collapsed; 70 | public Visibility queryVoiceVisb { get; set; } = Visibility.Collapsed; 71 | public Visibility queryNpcVisb { get; set; } = Visibility.Collapsed; 72 | public Visibility queryMapVisb { get; set; } = Visibility.Collapsed; 73 | 74 | public void UpdateVisibility() 75 | { 76 | queryGeneralVisb = queryVoiceVisb = queryNpcVisb = queryMapVisb = Visibility.Collapsed; 77 | 78 | switch (ComboBoxMode.Value) 79 | { 80 | case "extract-unlocks": 81 | queryGeneralVisb = Visibility.Visible; 82 | break; 83 | case "extract-hero-voice": 84 | queryVoiceVisb = Visibility.Visible; 85 | break; 86 | case "extract-npcs": 87 | queryNpcVisb = Visibility.Visible; 88 | break; 89 | case "extract-maps": 90 | queryMapVisb = Visibility.Visible; 91 | break; 92 | } 93 | 94 | OnPropertyChanged(null); 95 | } 96 | 97 | // Unlockable queries 98 | public string queryUnlockable_Name { get; set; } 99 | public string queryUnlockable_Param { get; set; } 100 | public KeyValuePair queryUnlockable_Type { get; set; } 101 | public KeyValuePair queryUnlockable_Tag { get; set; } 102 | // Voice queries 103 | public string queryVoice_Name { get; set; } 104 | public KeyValuePair queryVoice_Type { get; set; } 105 | public string queryVoice_Param { get; set; } 106 | // NPC queries 107 | public string queryNpc_Name { get; set; } 108 | // Map queries 109 | public string queryMap_Name { get; set; } 110 | 111 | #endregion 112 | 113 | public event PropertyChangedEventHandler PropertyChanged; 114 | 115 | protected void OnPropertyChanged(string name) 116 | { 117 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Logics/VersionManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Text.RegularExpressions; 6 | 7 | namespace OWorkbench 8 | { 9 | class VersionManagement 10 | { 11 | private bool _isOWValid; 12 | public string GetOWVersion(string owPath) 13 | { 14 | string[] buildInfo; 15 | _isOWValid = true; 16 | List versions = new List(); 17 | string latestVersion = "0.00.0.0.00000"; 18 | try 19 | { 20 | buildInfo = File.ReadAllLines(owPath + "\\.build.info"); 21 | } 22 | catch 23 | { 24 | _isOWValid = false; 25 | return "(Version unknown)"; 26 | // throw new FileNotFoundException("Failed to read version info for " + owPath + ": .build.info not found."); 27 | } 28 | Regex pattern = new Regex(@"^\d.\d{2}.\d.\d.\d{5}"); 29 | foreach (string buildEntry in buildInfo) 30 | { 31 | string[] keys = buildEntry.Split('|'); 32 | foreach (string key in keys) 33 | { 34 | if (pattern.IsMatch(key)) versions.Add(key); 35 | } 36 | } 37 | foreach (string version in versions) 38 | { 39 | if (Int32.Parse(version.Substring(version.Length - 5)) > 40 | Int32.Parse(latestVersion.Substring(latestVersion.Length - 5))) 41 | { 42 | latestVersion = version; 43 | } 44 | } 45 | if (latestVersion != "0.00.0.0.00000") return latestVersion; 46 | else 47 | { 48 | _isOWValid = false; 49 | throw new FileNotFoundException("Failed to read version info for " + owPath + 50 | ": .build.info invalid."); 51 | } 52 | } 53 | 54 | public bool IsOWPtr(string owPath) 55 | { 56 | try 57 | { 58 | string pdbPath = Path.Combine(owPath, ".product.db"); 59 | StreamReader pdbStream = new StreamReader(pdbPath); 60 | using (var reader = File.OpenText(pdbPath)) 61 | { 62 | string pdbRead = pdbStream.ReadLine(); 63 | while (pdbStream.Peek() >= 0) 64 | { 65 | pdbRead = pdbStream.ReadLine(); 66 | if (pdbRead.Contains("prometheus_test")) return true; 67 | } 68 | } 69 | return false; 70 | } 71 | catch 72 | { 73 | return false; 74 | } 75 | } 76 | 77 | public List CheckDTIntegerity(string dtPath) 78 | { 79 | string[] files = {"\\CascLib.dll", 80 | "\\DataTool.exe", 81 | "\\DynamicExpresso.Core.dll", 82 | "\\librevorb.dll", 83 | "\\Newtonsoft.Json.dll", 84 | "\\OpenTK.dll", 85 | "\\ow.events", 86 | "\\ow.keys", 87 | "\\OWlib.dll", 88 | "\\OWReplayLib.dll", 89 | "\\RevorbStd.dll", 90 | "\\STULib.dll", 91 | "\\System.Data.HashFunction.Core.dll", 92 | "\\System.Data.HashFunction.CRC.dll", 93 | "\\System.Data.HashFunction.Interfaces.dll", 94 | "\\ZstdNet.dll", 95 | "\\Third Party\\packed_codebooks_aoTuV_603.bin", 96 | "\\Third Party\\texconv.exe", 97 | "\\x64\\libzstd.dll", 98 | "\\x86\\libzstd.dll"}; 99 | List missingFiles = new List(); 100 | foreach (string file in files) 101 | { 102 | if (!File.Exists(dtPath + file)) missingFiles.Add(file); 103 | } 104 | return missingFiles; 105 | } 106 | 107 | public string GetDTVersion(string dtPath) 108 | { 109 | string version; 110 | try 111 | { 112 | version = FileVersionInfo.GetVersionInfo( 113 | Path.Combine(dtPath, "DataTool.exe")) 114 | .FileVersion; 115 | } 116 | catch 117 | { 118 | return null; 119 | } 120 | return version; 121 | } 122 | 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | */[Dd]ebug/ 15 | */[Dd]ebugPublic/ 16 | */[Rr]elease/ 17 | */[Rr]eleases/ 18 | */x64/ 19 | */x86/ 20 | */bld/ 21 | */[Bb]in/ 22 | */[Oo]bj/ 23 | */[Ll]og/ 24 | [Oo]utput/ 25 | */[Oo]utput/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # DNX 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | 50 | *_i.c 51 | *_p.c 52 | *_i.h 53 | *.ilk 54 | *.meta 55 | *.obj 56 | *.pch 57 | *.pdb 58 | *.pgc 59 | *.pgd 60 | *.rsp 61 | *.sbr 62 | *.tlb 63 | *.tli 64 | *.tlh 65 | *.tmp 66 | *.tmp_proj 67 | *.log 68 | *.vspscc 69 | *.vssscc 70 | .builds 71 | *.pidb 72 | *.svclog 73 | *.scc 74 | 75 | # Chutzpah Test files 76 | _Chutzpah* 77 | 78 | # Visual C++ cache files 79 | ipch/ 80 | *.aps 81 | *.ncb 82 | *.opendb 83 | *.opensdf 84 | *.sdf 85 | *.cachefile 86 | *.VC.db 87 | *.VC.VC.opendb 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | *.sap 94 | 95 | # TFS 2012 Local Workspace 96 | $tf/ 97 | 98 | # Guidance Automation Toolkit 99 | *.gpState 100 | 101 | # ReSharper is a .NET coding add-in 102 | _ReSharper*/ 103 | *.[Rr]e[Ss]harper 104 | *.DotSettings.user 105 | 106 | # JustCode is a .NET coding add-in 107 | .JustCode 108 | 109 | # TeamCity is a build add-in 110 | _TeamCity* 111 | 112 | # DotCover is a Code Coverage Tool 113 | *.dotCover 114 | 115 | # NCrunch 116 | _NCrunch_* 117 | .*crunch*.local.xml 118 | nCrunchTemp_* 119 | 120 | # MightyMoose 121 | *.mm.* 122 | AutoTest.Net/ 123 | 124 | # Web workbench (sass) 125 | .sass-cache/ 126 | 127 | # Installshield output folder 128 | [Ee]xpress/ 129 | 130 | # DocProject is a documentation generator add-in 131 | DocProject/buildhelp/ 132 | DocProject/Help/*.HxT 133 | DocProject/Help/*.HxC 134 | DocProject/Help/*.hhc 135 | DocProject/Help/*.hhk 136 | DocProject/Help/*.hhp 137 | DocProject/Help/Html2 138 | DocProject/Help/html 139 | 140 | # Click-Once directory 141 | publish/ 142 | 143 | # Publish Web Output 144 | *.[Pp]ublish.xml 145 | *.azurePubxml 146 | # TODO: Comment the next line if you want to checkin your web deploy settings 147 | # but database connection strings (with potential passwords) will be unencrypted 148 | #*.pubxml 149 | *.publishproj 150 | 151 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 152 | # checkin your Azure Web App publish settings, but sensitive information contained 153 | # in these scripts will be unencrypted 154 | PublishScripts/ 155 | 156 | # NuGet Packages 157 | *.nupkg 158 | # The packages folder can be ignored because of Package Restore 159 | **/packages/* 160 | # except build/, which is used as an MSBuild target. 161 | !**/packages/build/ 162 | # Uncomment if necessary however generally it will be regenerated when needed 163 | #!**/packages/repositories.config 164 | # NuGet v3's project.json files produces more ignoreable files 165 | *.nuget.props 166 | *.nuget.targets 167 | 168 | # Microsoft Azure Build Output 169 | csx/ 170 | *.build.csdef 171 | 172 | # Microsoft Azure Emulator 173 | ecf/ 174 | rcf/ 175 | 176 | # Windows Store app package directories and files 177 | AppPackages/ 178 | BundleArtifacts/ 179 | Package.StoreAssociation.xml 180 | _pkginfo.txt 181 | 182 | # Visual Studio cache files 183 | # files ending in .cache can be ignored 184 | *.[Cc]ache 185 | # but keep track of directories ending in .cache 186 | !*.[Cc]ache/ 187 | 188 | # Others 189 | ClientBin/ 190 | ~$* 191 | *~ 192 | *.dbmdl 193 | *.dbproj.schemaview 194 | *.jfm 195 | *.pfx 196 | *.publishsettings 197 | node_modules/ 198 | orleans.codegen.cs 199 | 200 | # Since there are multiple workflows, uncomment next line to ignore bower_components 201 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 202 | #bower_components/ 203 | 204 | # RIA/Silverlight projects 205 | Generated_Code/ 206 | 207 | # Backup & report files from converting an old project file 208 | # to a newer Visual Studio version. Backup files are not needed, 209 | # because we have git ;-) 210 | _UpgradeReport_Files/ 211 | Backup*/ 212 | UpgradeLog*.XML 213 | UpgradeLog*.htm 214 | 215 | # SQL Server files 216 | *.mdf 217 | *.ldf 218 | 219 | # Business Intelligence projects 220 | *.rdl.data 221 | *.bim.layout 222 | *.bim_*.settings 223 | 224 | # Microsoft Fakes 225 | FakesAssemblies/ 226 | 227 | # GhostDoc plugin setting file 228 | *.GhostDoc.xml 229 | 230 | # Node.js Tools for Visual Studio 231 | .ntvs_analysis.dat 232 | 233 | # Visual Studio 6 build log 234 | *.plg 235 | 236 | # Visual Studio 6 workspace options file 237 | *.opt 238 | 239 | # Visual Studio LightSwitch build output 240 | **/*.HTMLClient/GeneratedArtifacts 241 | **/*.DesktopClient/GeneratedArtifacts 242 | **/*.DesktopClient/ModelManifest.xml 243 | **/*.Server/GeneratedArtifacts 244 | **/*.Server/ModelManifest.xml 245 | _Pvt_Extensions 246 | 247 | # Paket dependency manager 248 | .paket/paket.exe 249 | paket-files/ 250 | 251 | # FAKE - F# Make 252 | .fake/ 253 | 254 | # JetBrains Rider 255 | .idea/ 256 | *.sln.iml 257 | 258 | # CodeRush 259 | .cr/ 260 | 261 | # Python Tools for Visual Studio (PTVS) 262 | __pycache__/ 263 | *.pyc 264 | /output 265 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace OWorkbench { 12 | using System; 13 | 14 | 15 | /// 16 | /// 一个强类型的资源类,用于查找本地化的字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | public 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 | /// 返回此类使用的缓存的 ResourceManager 实例。 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | public 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("OWorkbench.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// 使用此强类型资源类,为所有资源查找 51 | /// 重写当前线程的 CurrentUICulture 属性。 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | public static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// 查找类似 Using DataTool to list Overwatch contents. 的本地化字符串。 65 | /// 66 | public static string TAB_LIST_SUMMARY { 67 | get { 68 | return ResourceManager.GetString("TAB_LIST_SUMMARY", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// 查找类似 Configuring basic DataTool settings. 的本地化字符串。 74 | /// 75 | public static string TAB_SETTINGS_SUMMARY { 76 | get { 77 | return ResourceManager.GetString("TAB_SETTINGS_SUMMARY", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// 查找类似 Simplifying Overwatch asset extraction and management. 的本地化字符串。 83 | /// 84 | public static string TAB0_DESC1 { 85 | get { 86 | return ResourceManager.GetString("TAB0_DESC1", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// 查找类似 Choose something to do from the menu on the left. 的本地化字符串。 92 | /// 93 | public static string TAB0_DESC2 { 94 | get { 95 | return ResourceManager.GetString("TAB0_DESC2", resourceCulture); 96 | } 97 | } 98 | 99 | /// 100 | /// 查找类似 OWorkbench 的本地化字符串。 101 | /// 102 | public static string TAB0_TITLE1 { 103 | get { 104 | return ResourceManager.GetString("TAB0_TITLE1", resourceCulture); 105 | } 106 | } 107 | 108 | /// 109 | /// 查找类似 Getting Started 的本地化字符串。 110 | /// 111 | public static string TAB0_TITLE2 { 112 | get { 113 | return ResourceManager.GetString("TAB0_TITLE2", resourceCulture); 114 | } 115 | } 116 | 117 | /// 118 | /// 查找类似 Using DataTool to extract Overwatch contents. 的本地化字符串。 119 | /// 120 | public static string TAB3_SUMMARY { 121 | get { 122 | return ResourceManager.GetString("TAB3_SUMMARY", resourceCulture); 123 | } 124 | } 125 | 126 | /// 127 | /// 查找类似 Choosing/managing the Overwatch version used in OWorkbench. 的本地化字符串。 128 | /// 129 | public static string TAB6_SUMMARY { 130 | get { 131 | return ResourceManager.GetString("TAB6_SUMMARY", resourceCulture); 132 | } 133 | } 134 | 135 | /// 136 | /// 查找类似 Updating the DataTool version used in OWorkbench. 的本地化字符串。 137 | /// 138 | public static string TAB7_SUMMARY { 139 | get { 140 | return ResourceManager.GetString("TAB7_SUMMARY", resourceCulture); 141 | } 142 | } 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/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 | Simplifying Overwatch asset extraction and management. 122 | 123 | 124 | Choose something to do from the menu on the left. 125 | 126 | 127 | OWorkbench 128 | 129 | 130 | Getting Started 131 | 132 | 133 | Using DataTool to extract Overwatch contents. 134 | 135 | 136 | Choosing/managing the Overwatch version used in OWorkbench. 137 | 138 | 139 | Updating the DataTool version used in OWorkbench. 140 | 141 | 142 | Using DataTool to list Overwatch contents. 143 | 144 | 145 | Configuring basic DataTool settings. 146 | 147 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Tabs/UIStrings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel; 3 | using System.IO; 4 | using System.Reflection; 5 | using System.Windows.Controls; 6 | using System.Windows.Media; 7 | using System.Windows.Threading; 8 | using static OWorkbench.Properties.Settings; 9 | 10 | namespace OWorkbench 11 | { 12 | class UIString : INotifyPropertyChanged 13 | { 14 | #region Singleton implementation 15 | private static UIString _uniqueInstance; 16 | private static readonly object _threadLock = new object(); 17 | 18 | private UIString() 19 | { 20 | currentOWSize = "?"; 21 | } 22 | 23 | public static UIString GetInstance() // Ensure singleton model 24 | { 25 | if (_uniqueInstance == null) 26 | lock (_threadLock) 27 | _uniqueInstance = new UIString(); 28 | return _uniqueInstance; 29 | } 30 | #endregion 31 | 32 | #region Binding implementation 33 | public event PropertyChangedEventHandler PropertyChanged; 34 | 35 | public void Rebind(string name) 36 | { 37 | OnPropertyChanged(name); 38 | } 39 | 40 | protected void OnPropertyChanged(string name) 41 | { 42 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); 43 | } 44 | #endregion 45 | #region Header strings 46 | public string BenchDir 47 | { 48 | get 49 | { 50 | return Path.GetDirectoryName( 51 | Assembly.GetEntryAssembly(). 52 | CodeBase).Substring(6); 53 | } 54 | } // OWorkbench working directory 55 | public string BenchVersion 56 | { 57 | get 58 | { 59 | return "v. " + 60 | Assembly.GetExecutingAssembly() 61 | .GetName().Version.ToString(); 62 | } 63 | } // OWorkbench version 64 | public string CurrentOWVersion 65 | { 66 | get 67 | { 68 | VersionManagement vm = new VersionManagement(); 69 | string s = vm.GetOWVersion(Default.Path_CurrentOW); 70 | if (s != null) return s; 71 | else return "Unknown"; 72 | } 73 | } // Current Overwatch version 74 | public string CurrentOWServer 75 | { 76 | get 77 | { 78 | VersionManagement vm = new VersionManagement(); 79 | if (vm.IsOWPtr(Default.Path_CurrentOW)) 80 | { 81 | ToastManager.GetInstance().CreateToast("PTR Incompatibility", 82 | "Overwatch PTR build detected. While you can still run DataTool with it, note that PTR builds are incompatible with DataTool.", 2); 83 | return "PTR"; 84 | } 85 | 86 | else return "Live"; 87 | } 88 | } // Current Overwatch server 89 | public string CurrentOWPath 90 | { 91 | get { return Path.GetFullPath(Default.Path_CurrentOW); } 92 | } // Current Overwatch path 93 | 94 | private string currentOWSize; 95 | 96 | public string CurrentOWSize 97 | { 98 | get { return "(" + currentOWSize + " GB)"; } 99 | set 100 | { 101 | currentOWSize = value; 102 | OnPropertyChanged(null); 103 | } 104 | } 105 | public string DTVersion 106 | { 107 | get 108 | { 109 | VersionManagement vm = new VersionManagement(); 110 | string s = vm.GetDTVersion(BenchDir); 111 | if (s != null) return s; 112 | else return "Unknown"; 113 | } 114 | } // DataTool version 115 | public string DTIntegrity 116 | { 117 | get 118 | { 119 | VersionManagement vm = new VersionManagement(); 120 | List list = vm.CheckDTIntegerity(BenchDir); 121 | if (list.Count == 0) return "Complete"; 122 | else 123 | { 124 | // output missing files to log 125 | ToastManager.GetInstance().CreateToast("DataTool File Incomplete", 126 | "Some files required by DataTool could not be found. See the log for details. Try updating DataTool to resolve this issue.", 3); 127 | Logging.GetInstance().Increment("At least " + list.Count + " DataTool dependency files are missing."); 128 | foreach (string file in list) 129 | { 130 | Logging.GetInstance().Increment(" " + file); 131 | } 132 | return "Incomplete"; 133 | } 134 | } 135 | } // Datatool file integrity 136 | #endregion 137 | #region Notif banner string and highlight 138 | // Notif banner itself 139 | private string notif; 140 | 141 | public string Notif 142 | { 143 | get { return notif; } 144 | set 145 | { 146 | notif = value; 147 | OnPropertyChanged(null); 148 | } 149 | } 150 | // Notif banner color 151 | private Brush notifBrush = Brushes.Black; 152 | 153 | public Brush NotifBrush 154 | { 155 | get { return notifBrush; } 156 | set 157 | { 158 | notifBrush = value; 159 | OnPropertyChanged(null); 160 | } 161 | } 162 | // Only set notif message, or also apply a highlight effect 163 | public void SetNotif(string s) 164 | { 165 | Notif = s; 166 | } 167 | 168 | public void SetNotif(Dispatcher dispatcher, string s) 169 | { 170 | Notif = s; 171 | BackgroundWorker colorWorker = new BackgroundWorker(); 172 | colorWorker.DoWork += ColorWorker; 173 | colorWorker.RunWorkerAsync(dispatcher); 174 | } 175 | // Highlight the banner for 2 seconds in red 176 | public void ColorWorker(object sender, DoWorkEventArgs e) 177 | { 178 | ((Dispatcher)e.Argument).Invoke(new System.Action(() => { NotifBrush = Brushes.Red; })); 179 | System.Threading.Thread.Sleep(2000); 180 | ((Dispatcher)e.Argument).Invoke(new System.Action(() => { NotifBrush = Brushes.Black; })); 181 | } 182 | #endregion 183 | 184 | public int DownloadProgress { get; set; } 185 | 186 | public bool LoggingOnLaunch 187 | { 188 | get { return Default.TAB_QUICKSTART_LoggingOnLaunch; } 189 | set 190 | { 191 | Default.TAB_QUICKSTART_LoggingOnLaunch = value; 192 | Default.Save(); 193 | } 194 | } 195 | 196 | public bool DebugMode 197 | { 198 | get { return Default.DebugMode; } 199 | set 200 | { 201 | Default.DebugMode = value; 202 | Default.Save(); 203 | } 204 | } 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Tabs/DataToolHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows; 3 | using System.Collections.Generic; 4 | using static OWorkbench.Properties.Settings; 5 | using OWorkbench.Logics; 6 | using System.Windows.Controls; 7 | using System.Text; 8 | 9 | namespace OWorkbench 10 | { 11 | public partial class MainWindow : Window 12 | { 13 | #region Initialization 14 | public void InitializeDataToolHandling() 15 | { 16 | tabListAssets.DataContext = ListAssetsHandler.GetInstance(); 17 | tabExtrAssets.DataContext = ExtrAssetsHandler.GetInstance(); 18 | PopulateModes(); 19 | } 20 | #endregion 21 | #region Populate modes 22 | private void PopulateModes() 23 | { 24 | // Populate list modes 25 | List> listModes = new List> 26 | { 27 | CreateMode("(Please select a mode...)", null), 28 | CreateMode("List achievements", "list-achievements"), 29 | CreateMode("List chat replacements", "list-chat-replacements"), 30 | CreateMode("List general unlocks", "list-general-unlocks"), 31 | CreateMode("List heroes", "list-heroes"), 32 | CreateMode("List user highlights", "list-highlights"), 33 | CreateMode("List encryption keys", "list-keys"), 34 | CreateMode("List lootboxes", "list-lootbox"), 35 | CreateMode("List maps", "list-maps"), 36 | CreateMode("List subtitles", "list-subtitles"), 37 | CreateMode("List subtitles (from audio data)", "list-subtitles-real"), 38 | CreateMode("List unlocks", "list-hero-unlocks") 39 | }; 40 | comboListAssets.ItemsSource = listModes; 41 | comboListAssets.SelectedValuePath = "Value"; 42 | comboListAssets.DisplayMemberPath = "Key"; 43 | // Populate extraction modes 44 | List> extrModes = new List> 45 | { 46 | CreateMode("(Please select a mode...)", null), 47 | CreateMode("Dump strings", "dump-strings"), 48 | CreateMode("Extract abilities", "extract-abilities"), 49 | CreateMode("Extract general", "extract-general"), 50 | CreateMode("Extract unlocks", "extract-unlocks"), 51 | CreateMode("Extract hero voice", "extract-hero-voice"), 52 | CreateMode("Extract lootbox", "extract-lootbox"), 53 | CreateMode("Extract maps", "extract-maps"), 54 | CreateMode("Extract map environment data", "extract-map-envs"), 55 | CreateMode("Extract NPCs", "extract-npcs") 56 | }; 57 | comboExtrAssets.ItemsSource = extrModes; 58 | comboExtrAssets.SelectedValuePath = "Value"; 59 | comboExtrAssets.DisplayMemberPath = "Key"; 60 | // Populate query editor types 61 | List> queryTypes = new List> 62 | { 63 | CreateMode("Skin", "skin"), 64 | CreateMode("Icon", "icon"), 65 | CreateMode("Spray", "spray"), 66 | CreateMode("Emote", "emote"), 67 | CreateMode("Voice line", "voiceline"), 68 | CreateMode("Victory pose", "victory pose"), 69 | CreateMode("Highlight intro", "highlightintro") 70 | }; 71 | comboBoxQueryType.ItemsSource = queryTypes; 72 | comboBoxQueryType.SelectedValuePath = "Value"; 73 | comboBoxQueryType.DisplayMemberPath = "Key"; 74 | // Populate query editor tags 75 | List> queryTags = new List> 76 | { 77 | CreateMode("Rarity", "rarity"), 78 | CreateMode("Event", "event"), 79 | CreateMode("OWL Team", "leagueTeam") 80 | }; 81 | comboBoxQueryTag.ItemsSource = queryTags; 82 | comboBoxQueryTag.SelectedValuePath = "Value"; 83 | comboBoxQueryTag.DisplayMemberPath = "Key"; 84 | // Populate query editor sound modes 85 | List> querySoundModes = new List> 86 | { 87 | CreateMode("Sound Restriction", "soundRestriction"), 88 | CreateMode("Group Restriction", "groupRestriction") 89 | }; 90 | comboBoxQuerySound.ItemsSource = querySoundModes; 91 | comboBoxQuerySound.SelectedValuePath = "Value"; 92 | comboBoxQuerySound.DisplayMemberPath = "Key"; 93 | } 94 | 95 | private static KeyValuePair CreateMode(string displayName, string command) 96 | { 97 | return new KeyValuePair(displayName, command); 98 | } 99 | #endregion 100 | #region Global interaction 101 | 102 | /// 103 | /// Hides and shows certain parts of the UI according to the extrmode combobox selection. 104 | /// 105 | private void comboExtrAssets_SelectionChanged(object sender, SelectionChangedEventArgs e) 106 | { 107 | ExtrAssetsHandler.GetInstance().UpdateVisibility(); 108 | } 109 | 110 | public void ResetOptions(object sender, RoutedEventArgs e) // Fire corresponding ResetOptions() 111 | { 112 | if (((Button)sender).Name.Contains("List")) ListAssetsHandler.GetInstance().ResetOptions(); 113 | else if (((Button)sender).Name.Contains("Extr")) ExtrAssetsHandler.GetInstance().ResetOptions(); 114 | } 115 | 116 | /// 117 | /// Fire corresponding launch logics according to the pressed button. 118 | /// 119 | public void Launch(object sender, RoutedEventArgs e) 120 | { 121 | // Once again, refresh OW path to prevent weird config glitches 122 | Config.GetInstance().UseOWInst(comboOWInsts.SelectedIndex); 123 | 124 | // Start fabricating the command line 125 | StringBuilder cmdLine = CommandLineFabricator.CreateBaseCommand(); 126 | if (ExtrAssetsHandler.GetInstance().IsTabSelected) 127 | cmdLine = CommandLineFabricator.AppendExtractFlags(cmdLine); 128 | 129 | cmdLine = CommandLineFabricator.AppendPathAndMode(cmdLine); 130 | if (ExtrAssetsHandler.GetInstance().IsTabSelected) 131 | try { cmdLine = CommandLineFabricator.AppendExtractQueries(cmdLine); } 132 | catch (Exception ex) 133 | { 134 | Logging.GetInstance().Increment(ex.Message); 135 | ToastManager.GetInstance().CreateToast("Query Error", "The query supplied for this extraction mode is invalid. See log for details.", 3); 136 | return; 137 | } 138 | 139 | // Launch 140 | tabControl.SelectedIndex = 5; // Go to logging tab 141 | if (!Default.DebugMode) 142 | Logging.GetInstance().ClearLogs(logBox); // Debug mode will not clear logs 143 | 144 | Logging.GetInstance().Increment(logBox, DateTime.Now.ToString() + " - Starting DataTool now.\nCmdline: DataTool.exe " + cmdLine.ToString()); 145 | StartDataTool(PrepareDataTool(cmdLine.ToString())); 146 | } 147 | #endregion 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/QuickDataTool.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {CBA0F207-3DB9-44D3-9661-C6473277CCAA} 8 | WinExe 9 | OWorkbench 10 | OWorkbench 11 | v4.6.1 12 | 512 13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 4 15 | true 16 | 17 | publish\ 18 | true 19 | Disk 20 | false 21 | Foreground 22 | 7 23 | Days 24 | false 25 | false 26 | true 27 | 0 28 | 1.0.0.%2a 29 | false 30 | false 31 | true 32 | 33 | 34 | 35 | 36 | AnyCPU 37 | true 38 | full 39 | false 40 | ..\output\ 41 | DEBUG;TRACE 42 | prompt 43 | 4 44 | 45 | 46 | AnyCPU 47 | pdbonly 48 | true 49 | ..\output\ 50 | TRACE 51 | prompt 52 | 4 53 | 54 | 55 | extract.ico 56 | 57 | 58 | 59 | ..\packages\Notifications.Wpf.0.1.1\lib\net461\Notifications.Wpf.dll 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 4.0 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | MSBuild:Compile 85 | Designer 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | True 98 | True 99 | Resources.resx 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | MSBuild:Compile 114 | Designer 115 | 116 | 117 | App.xaml 118 | Code 119 | 120 | 121 | MainWindow.xaml 122 | Code 123 | 124 | 125 | Designer 126 | MSBuild:Compile 127 | 128 | 129 | 130 | 131 | Code 132 | 133 | 134 | True 135 | Settings.settings 136 | True 137 | 138 | 139 | 140 | PublicSettingsSingleFileGenerator 141 | Settings.Designer.cs 142 | Designer 143 | 144 | 145 | 146 | 147 | Designer 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | False 156 | Microsoft .NET Framework 4.6 %28x86 和 x64%29 157 | true 158 | 159 | 160 | False 161 | .NET Framework 3.5 SP1 162 | false 163 | 164 | 165 | 166 | 167 | PublicResXFileCodeGenerator 168 | Resources.Designer.cs 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace OWorkbench.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.6.0.0")] 16 | public sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("C:\\Program Files (x86)\\Overwatch\\")] 29 | public string Path_CurrentOW { 30 | get { 31 | return ((string)(this["Path_CurrentOW"])); 32 | } 33 | set { 34 | this["Path_CurrentOW"] = value; 35 | } 36 | } 37 | 38 | [global::System.Configuration.UserScopedSettingAttribute()] 39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 40 | public global::System.Collections.Generic.List List_OWInsts { 41 | get { 42 | return ((global::System.Collections.Generic.List)(this["List_OWInsts"])); 43 | } 44 | set { 45 | this["List_OWInsts"] = value; 46 | } 47 | } 48 | 49 | [global::System.Configuration.UserScopedSettingAttribute()] 50 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 51 | [global::System.Configuration.DefaultSettingValueAttribute(".\\\\")] 52 | public string Path_Output { 53 | get { 54 | return ((string)(this["Path_Output"])); 55 | } 56 | set { 57 | this["Path_Output"] = value; 58 | } 59 | } 60 | 61 | [global::System.Configuration.UserScopedSettingAttribute()] 62 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 63 | [global::System.Configuration.DefaultSettingValueAttribute("0")] 64 | public int TAB_LIST_ModeIndex { 65 | get { 66 | return ((int)(this["TAB_LIST_ModeIndex"])); 67 | } 68 | set { 69 | this["TAB_LIST_ModeIndex"] = value; 70 | } 71 | } 72 | 73 | [global::System.Configuration.UserScopedSettingAttribute()] 74 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 75 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 76 | public bool TAB_LIST_OutputJSON { 77 | get { 78 | return ((bool)(this["TAB_LIST_OutputJSON"])); 79 | } 80 | set { 81 | this["TAB_LIST_OutputJSON"] = value; 82 | } 83 | } 84 | 85 | [global::System.Configuration.UserScopedSettingAttribute()] 86 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 87 | [global::System.Configuration.DefaultSettingValueAttribute("0")] 88 | public int TAB3_ModeIndex { 89 | get { 90 | return ((int)(this["TAB3_ModeIndex"])); 91 | } 92 | set { 93 | this["TAB3_ModeIndex"] = value; 94 | } 95 | } 96 | 97 | [global::System.Configuration.UserScopedSettingAttribute()] 98 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 99 | [global::System.Configuration.DefaultSettingValueAttribute("0")] 100 | public int TAB3_FormatIndex { 101 | get { 102 | return ((int)(this["TAB3_FormatIndex"])); 103 | } 104 | set { 105 | this["TAB3_FormatIndex"] = value; 106 | } 107 | } 108 | 109 | [global::System.Configuration.UserScopedSettingAttribute()] 110 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 111 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 112 | public bool TAB3_LosslessTexture { 113 | get { 114 | return ((bool)(this["TAB3_LosslessTexture"])); 115 | } 116 | set { 117 | this["TAB3_LosslessTexture"] = value; 118 | } 119 | } 120 | 121 | [global::System.Configuration.UserScopedSettingAttribute()] 122 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 123 | [global::System.Configuration.DefaultSettingValueAttribute("0")] 124 | public int TAB3_LOD { 125 | get { 126 | return ((int)(this["TAB3_LOD"])); 127 | } 128 | set { 129 | this["TAB3_LOD"] = value; 130 | } 131 | } 132 | 133 | [global::System.Configuration.UserScopedSettingAttribute()] 134 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 135 | [global::System.Configuration.DefaultSettingValueAttribute("")] 136 | public string TAB3_NoExtract { 137 | get { 138 | return ((string)(this["TAB3_NoExtract"])); 139 | } 140 | set { 141 | this["TAB3_NoExtract"] = value; 142 | } 143 | } 144 | 145 | [global::System.Configuration.UserScopedSettingAttribute()] 146 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 147 | [global::System.Configuration.DefaultSettingValueAttribute("")] 148 | public string TAB3_NoConvert { 149 | get { 150 | return ((string)(this["TAB3_NoConvert"])); 151 | } 152 | set { 153 | this["TAB3_NoConvert"] = value; 154 | } 155 | } 156 | 157 | [global::System.Configuration.UserScopedSettingAttribute()] 158 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 159 | [global::System.Configuration.DefaultSettingValueAttribute("")] 160 | public string TAB3_NoEnvExtract { 161 | get { 162 | return ((string)(this["TAB3_NoEnvExtract"])); 163 | } 164 | set { 165 | this["TAB3_NoEnvExtract"] = value; 166 | } 167 | } 168 | 169 | [global::System.Configuration.UserScopedSettingAttribute()] 170 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 171 | [global::System.Configuration.DefaultSettingValueAttribute(".\\\\")] 172 | public string TAB_SETTINGS_OutputPath { 173 | get { 174 | return ((string)(this["TAB_SETTINGS_OutputPath"])); 175 | } 176 | set { 177 | this["TAB_SETTINGS_OutputPath"] = value; 178 | } 179 | } 180 | 181 | [global::System.Configuration.UserScopedSettingAttribute()] 182 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 183 | [global::System.Configuration.DefaultSettingValueAttribute("0")] 184 | public int TAB_SETTINGS_LangIndex { 185 | get { 186 | return ((int)(this["TAB_SETTINGS_LangIndex"])); 187 | } 188 | set { 189 | this["TAB_SETTINGS_LangIndex"] = value; 190 | } 191 | } 192 | 193 | [global::System.Configuration.UserScopedSettingAttribute()] 194 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 195 | [global::System.Configuration.DefaultSettingValueAttribute("True")] 196 | public bool TAB_QUICKSTART_LoggingOnLaunch { 197 | get { 198 | return ((bool)(this["TAB_QUICKSTART_LoggingOnLaunch"])); 199 | } 200 | set { 201 | this["TAB_QUICKSTART_LoggingOnLaunch"] = value; 202 | } 203 | } 204 | 205 | [global::System.Configuration.UserScopedSettingAttribute()] 206 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 207 | [global::System.Configuration.DefaultSettingValueAttribute("False")] 208 | public bool DebugMode { 209 | get { 210 | return ((bool)(this["DebugMode"])); 211 | } 212 | set { 213 | this["DebugMode"] = value; 214 | } 215 | } 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Logics/CommandLineFabricator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using static OWorkbench.Properties.Settings; 8 | 9 | namespace OWorkbench.Logics 10 | { 11 | /// 12 | /// The class that handles the creation of command line parameters. 13 | /// 14 | class CommandLineFabricator 15 | { 16 | /// 17 | /// Creates a base command line containing working mode, language selection and other shared parameters 18 | /// 19 | /// A StringBuilder containing the base command. 20 | public static StringBuilder CreateBaseCommand() 21 | { 22 | StringBuilder builder = new StringBuilder(); 23 | 24 | if (String.IsNullOrEmpty(ListAssetsHandler.GetInstance().IsTabSelected // Determine which ComboBoxMode to **check** 25 | ? ListAssetsHandler.GetInstance().ComboBoxMode.Value // with an inline if-else (not actually appending yet) 26 | : ExtrAssetsHandler.GetInstance().ComboBoxMode.Value)) 27 | throw new ArgumentException("Please select an Extract Assets mode to continue."); 28 | 29 | builder.Append("--language=" + DataToolConfig.GetInstance().ComboBoxLanguage.Content + " "); // Language 30 | 31 | return builder; 32 | } 33 | 34 | /// 35 | /// Appends flags used by extract mode. 36 | /// 37 | /// A StringBuilder, typically returned from previous command line fabricator methods. 38 | /// 39 | public static StringBuilder AppendExtractFlags(StringBuilder builder) 40 | { 41 | ExtrAssetsHandler handler = ExtrAssetsHandler.GetInstance(); 42 | 43 | if (!handler.noExtTextures) // if texture will be extracted 44 | { 45 | if (!handler.noConTextures) // if texture will be converted 46 | { 47 | if (!handler.isLosslessTexture) builder.Append("--convert-lossless-textures=false "); // texture lossless 48 | builder.Append("--convert-textures-type=" + handler.comboBoxFormat.Content + " "); // texture format 49 | } 50 | else builder.Append("--convert-textures=false "); 51 | } 52 | else builder.Append("--skip-textures=true "); 53 | 54 | if (!handler.noExtSound) // if sound will be extracted 55 | { 56 | if (handler.noConSound) builder.Append("--convert-sound=false "); 57 | } 58 | else builder.Append("--skip-sound=true "); 59 | 60 | if (!handler.noExtModels) // if models will be extracted 61 | { 62 | builder.Append("--lod=" + handler.modelLOD + " "); // model LOD 63 | if (handler.noConModels) builder.Append("--convert-models=false "); 64 | } 65 | else builder.Append("--skip-models=true "); 66 | 67 | if (!handler.noExtAnimation) // if models will be extracted 68 | { 69 | if (handler.noConAnimation) builder.Append("--convert-animations=false "); 70 | } 71 | else builder.Append("--skip-animations=true "); 72 | 73 | if (!handler.noExtRefpose) // if refposes will be extracted 74 | builder.Append("--extract-refpose=true "); 75 | 76 | if (handler.noConAnything) builder.Append("--raw "); // convert nothing 77 | 78 | if (handler.ComboBoxMode.Value == "extract-map-envs") // if map env extraction is active 79 | { 80 | if (handler.noEnvSound) builder.Append("--skip-map-env-sound=true "); 81 | if (handler.noEnvLUT) builder.Append("--skip-map-env-lut=true "); 82 | if (handler.noEnvBlend) builder.Append("--skip-map-env-blend=true "); 83 | if (handler.noEnvCubeMap) builder.Append("--skip-map-env-cubemap=true "); 84 | if (handler.noEnvGround) builder.Append("--skip-map-env-ground=true "); 85 | if (handler.noEnvSky) builder.Append("--skip-map-env-sky=true "); 86 | if (handler.noEnvSkybox) builder.Append("--skip-map-env-skybox=true "); 87 | if (handler.noEnvEntity) builder.Append("--skip-map-env-entity=true "); 88 | } 89 | 90 | return builder; 91 | } 92 | 93 | /// 94 | /// Validate and append extract queries based on mode selection. 95 | /// 96 | /// A StringBuilder, typically returned from previous command line fabricator methods. 97 | /// 98 | public static StringBuilder AppendExtractQueries(StringBuilder builder) 99 | { 100 | ExtrAssetsHandler handler = ExtrAssetsHandler.GetInstance(); 101 | if (!handler.IsTabSelected) return builder; // Query is not needed in that case 102 | 103 | switch (handler.ComboBoxMode.Value) // Mode-specified queries 104 | { 105 | // Leading and trailing quotes shall only be added when there is query, so they had to be in individual switches 106 | case "extract-unlocks": 107 | builder.Append("\""); 108 | if (!(String.IsNullOrEmpty(handler.queryUnlockable_Name) // Verify hero name and type 109 | || String.IsNullOrEmpty(handler.queryUnlockable_Type.Value))) 110 | { 111 | builder.Append(handler.queryUnlockable_Name); 112 | builder.Append("|"); 113 | builder.Append(handler.queryUnlockable_Type.Value); 114 | } 115 | else throw new ArgumentException("Extract-unlocks mode: invalid queries. Please fill in hero name and type."); 116 | 117 | if (!String.IsNullOrEmpty(handler.queryUnlockable_Tag.Value)) // Tag is specified 118 | { 119 | if (String.IsNullOrEmpty(handler.queryUnlockable_Param)) 120 | throw new ArgumentException("Extract-unlocks mode: invalid queries. Either specify a parameter or unspecify the tag."); 121 | 122 | builder.Append("=("); 123 | builder.Append(handler.queryUnlockable_Tag.Value); 124 | builder.Append("="); 125 | builder.Append(handler.queryUnlockable_Param); 126 | builder.Append(")"); 127 | } 128 | builder.Append("\""); 129 | break; 130 | 131 | case "extract-hero-voice": 132 | if (!String.IsNullOrEmpty(handler.queryVoice_Name)) // Hero name is specified 133 | { 134 | builder.Append("\""); 135 | builder.Append(handler.queryVoice_Name); 136 | 137 | if (!String.IsNullOrEmpty(handler.queryVoice_Type.Value)) // Type is specified 138 | { 139 | if (String.IsNullOrEmpty(handler.queryVoice_Param)) 140 | throw new ArgumentException("Extract-hero-voice mode: invalid queries. Either specify a parameter or unspecify the type."); 141 | 142 | builder.Append("|"); 143 | builder.Append(handler.queryVoice_Type.Value); 144 | builder.Append(handler.queryVoice_Param); 145 | } 146 | builder.Append("\""); 147 | } 148 | else throw new ArgumentException("Extract-hero-voice mode: invalid queries. Specify a hero name."); 149 | break; 150 | 151 | case "extract-npcs": 152 | if (!String.IsNullOrEmpty(handler.queryNpc_Name)) 153 | { 154 | builder.Append("\""); 155 | builder.Append(handler.queryNpc_Name); 156 | builder.Append("\""); 157 | } 158 | break; 159 | 160 | case "extract-maps": 161 | if (!String.IsNullOrEmpty(handler.queryMap_Name)) 162 | { 163 | builder.Append("\""); 164 | builder.Append(handler.queryMap_Name); 165 | builder.Append("\""); 166 | } 167 | else throw new ArgumentException("Extract-maps mode: invalid queries. Specify a map name."); 168 | break; 169 | } 170 | return builder; 171 | } 172 | 173 | /// 174 | /// Appends the paths as the last part of the command line. 175 | /// 176 | /// A StringBuilder, typically returned from previous command line fabricator methods. 177 | /// 178 | 179 | public static StringBuilder AppendPathAndMode(StringBuilder builder) 180 | { 181 | if (ListAssetsHandler.GetInstance().IsTabSelected // ListAssets JSON output 182 | && Default.TAB_LIST_OutputJSON) 183 | builder.Append(" --json"); 184 | 185 | builder.Append(" \"" + UIString.GetInstance().CurrentOWPath + "\" "); 186 | 187 | builder.Append((ExtrAssetsHandler.GetInstance().IsTabSelected // Determine which ComboBoxMode to **use** 188 | ? ExtrAssetsHandler.GetInstance().ComboBoxMode.Value // with an inline if-else 189 | : ListAssetsHandler.GetInstance().ComboBoxMode.Value)); // Value should already be ensured non-null 190 | 191 | if (ExtrAssetsHandler.GetInstance().IsTabSelected) // Extract mode requires a global output path 192 | builder.Append(" \"" + Default.TAB_SETTINGS_OutputPath + "\" "); 193 | return builder; 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/Resources.xaml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 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 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /QuickOverTool-WPF/MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 38 | 39 | 40 | 41 | 42 | 43 | 70 | 71 | 75 | 76 | 80 | 81 | 82 | 83 | 84 | 85 | 88 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 |