├── .gitattributes ├── .gitignore ├── UnityRefactorHelper ├── Key.snk ├── Resources │ ├── MainIcon.png │ └── CommandIcon.png ├── Model │ ├── FileScanItem.cs │ ├── ProjectSyncItem.cs │ ├── ProjectScanItem.cs │ └── Settings.cs ├── Constants.cs ├── SettingsToolWindow.cs ├── Helpers │ ├── FileIdGenerator.cs │ ├── UnityProjectFileIdReplacer.cs │ └── Md4.cs ├── Cache.cs ├── View │ ├── UnityRefactorHelperSettingsControl.xaml.cs │ ├── SyncProjectControl.xaml.cs │ ├── SyncProjectControl.xaml │ └── UnityRefactorHelperSettingsControl.xaml ├── app.config ├── Properties │ ├── AssemblyInfo.cs │ └── Annotations.cs ├── source.extension.vsixmanifest ├── packages.config ├── Service │ ├── CommonService.cs │ └── ProjectService.cs ├── UnityRefactorHelperSettingsCommand.cs ├── SolutionEvents.cs ├── UnityRefactorHelperSettingsPackage.vsct ├── UnityRefactorHelperSettingsPackage.cs ├── VSPackage.resx ├── ViewModel │ └── ToolWindowViewModel.cs └── UnityRefactorHelper.csproj ├── UnityRefactorHelper.sln ├── License.md └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | packages 2 | *.DotSettings 3 | /**/obj 4 | /**/bin -------------------------------------------------------------------------------- /UnityRefactorHelper/Key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDarkTemplar/UnityRefactorHelper/HEAD/UnityRefactorHelper/Key.snk -------------------------------------------------------------------------------- /UnityRefactorHelper/Resources/MainIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDarkTemplar/UnityRefactorHelper/HEAD/UnityRefactorHelper/Resources/MainIcon.png -------------------------------------------------------------------------------- /UnityRefactorHelper/Resources/CommandIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PDarkTemplar/UnityRefactorHelper/HEAD/UnityRefactorHelper/Resources/CommandIcon.png -------------------------------------------------------------------------------- /UnityRefactorHelper/Model/FileScanItem.cs: -------------------------------------------------------------------------------- 1 | namespace UnityRefactorHelper.Model 2 | { 3 | public class FileScanItem 4 | { 5 | public string ProjectFileId { get; set; } 6 | public int OldId { get; set; } 7 | public int? NewId { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /UnityRefactorHelper/Model/ProjectSyncItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UnityRefactorHelper.Model 4 | { 5 | public class ProjectSyncItem 6 | { 7 | public string ProjectName { get; set; } 8 | public Guid ProjectGuid { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /UnityRefactorHelper/Constants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace UnityRefactorHelper 4 | { 5 | public static class Constants 6 | { 7 | public const int CommandId = 0x0100; 8 | public static readonly Guid CommandSet = new Guid("4043f182-b7f8-4f5f-a41e-2a9b83329ac7"); 9 | } 10 | } -------------------------------------------------------------------------------- /UnityRefactorHelper/Model/ProjectScanItem.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace UnityRefactorHelper.Model 4 | { 5 | public class ProjectScanItem : ProjectSyncItem 6 | { 7 | public ProjectScanItem() 8 | { 9 | Files = new List(); 10 | } 11 | 12 | public List Files { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /UnityRefactorHelper/Model/Settings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | 3 | namespace UnityRefactorHelper.Model 4 | { 5 | public class Settings 6 | { 7 | public Settings() 8 | { 9 | ProjectSyncItems = new ObservableCollection(); 10 | } 11 | 12 | public bool IsEnabled { get; set; } 13 | public string UnityProjectPath { get; set; } 14 | public ObservableCollection ProjectSyncItems { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /UnityRefactorHelper/SettingsToolWindow.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | using Microsoft.VisualStudio.Shell; 3 | using UnityRefactorHelper.View; 4 | 5 | namespace UnityRefactorHelper 6 | { 7 | [Guid("5825C503-1846-4B31-95ED-716E24E5E9E4")] 8 | public sealed class SettingsToolWindow : ToolWindowPane 9 | { 10 | public SettingsToolWindow() : 11 | base(null) 12 | { 13 | Caption = "Unity Refactor Helper"; 14 | 15 | Content = new UnityRefactorHelperSettingsControl(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /UnityRefactorHelper/Helpers/FileIdGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography; 2 | using System.Text; 3 | 4 | namespace UnityRefactorHelper.Helpers 5 | { 6 | public static class FileIdGenerator 7 | { 8 | public static int Compute(string namespaceName, string className) 9 | { 10 | if (string.IsNullOrEmpty(namespaceName)) 11 | namespaceName = string.Empty; 12 | 13 | var toBeHashed = "s\0\0\0" + namespaceName + className; 14 | 15 | using (HashAlgorithm hash = new Md4()) 16 | { 17 | var hashed = hash.ComputeHash(Encoding.UTF8.GetBytes(toBeHashed)); 18 | 19 | var result = 0; 20 | 21 | for (var i = 3; i >= 0; --i) 22 | { 23 | result <<= 8; 24 | result |= hashed[i]; 25 | } 26 | 27 | return result; 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /UnityRefactorHelper.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnityRefactorHelper", "UnityRefactorHelper\UnityRefactorHelper.csproj", "{D7D4741D-E917-4509-A620-ABE6A9573784}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {D7D4741D-E917-4509-A620-ABE6A9573784}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {D7D4741D-E917-4509-A620-ABE6A9573784}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {D7D4741D-E917-4509-A620-ABE6A9573784}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {D7D4741D-E917-4509-A620-ABE6A9573784}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /UnityRefactorHelper/Cache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using EnvDTE; 4 | using Microsoft.VisualStudio.Shell; 5 | using Microsoft.VisualStudio.Shell.Interop; 6 | using UnityRefactorHelper.Model; 7 | 8 | namespace UnityRefactorHelper 9 | { 10 | public class Cache : IDisposable 11 | { 12 | static Cache() 13 | { 14 | Instance = new Cache(); 15 | } 16 | 17 | private Cache() 18 | { 19 | ScanProjects = new List(); 20 | } 21 | 22 | public OleMenuCommandService OleMenuCommandService { get; set; } 23 | public DTE Dte { get; set; } 24 | public IVsSolution SolutionService { get; set; } 25 | 26 | public Settings Settings { get; set; } 27 | public List ScanProjects { get; set; } 28 | 29 | public static Cache Instance { get; private set; } 30 | 31 | public void Dispose() 32 | { 33 | SolutionService = null; 34 | Dte = null; 35 | OleMenuCommandService = null; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 PDarkTemplar 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 | -------------------------------------------------------------------------------- /UnityRefactorHelper/View/UnityRefactorHelperSettingsControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | using System.Windows.Controls; 3 | using UnityRefactorHelper.ViewModel; 4 | 5 | namespace UnityRefactorHelper.View 6 | { 7 | /// 8 | /// Interaction logic for UnityRefactorHelperSettingsControl. 9 | /// 10 | public partial class UnityRefactorHelperSettingsControl : UserControl 11 | { 12 | /// 13 | /// Initializes a new instance of the class. 14 | /// 15 | public UnityRefactorHelperSettingsControl() 16 | { 17 | InitializeComponent(); 18 | } 19 | 20 | public ToolWindowViewModel ViewModel => ToolWindowViewModel.Instance; 21 | 22 | private void selectUnityProjectFolderBtn_Click(object sender, RoutedEventArgs e) 23 | { 24 | ViewModel.OpenUnityFolderDialog(); 25 | } 26 | 27 | private void addBtn_Click(object sender, RoutedEventArgs e) 28 | { 29 | ViewModel.AddNewProjectSync(); 30 | } 31 | 32 | private void saveBtn_Click(object sender, RoutedEventArgs e) 33 | { 34 | ViewModel.Save(); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /UnityRefactorHelper/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /UnityRefactorHelper/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | 8 | [assembly: AssemblyTitle("UnityRefactorHelper")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("UnityRefactorHelper")] 13 | [assembly: AssemblyCopyright("")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | 21 | [assembly: ComVisible(false)] 22 | 23 | // Version information for an assembly consists of the following four values: 24 | // 25 | // Major Version 26 | // Minor Version 27 | // Build Number 28 | // Revision 29 | // 30 | // You can specify all the values or you can default the Build and Revision Numbers 31 | // by using the '*' as shown below: 32 | // [assembly: AssemblyVersion("1.0.*")] 33 | 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /UnityRefactorHelper/source.extension.vsixmanifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Unity Refactor Helper 6 | Helper extension for Unity script refactoring 7 | https://github.com/PDarkTemplar/UnityRefactorHelper 8 | Resources\MainIcon.png 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unity Refactor Helper 2 | Visual Studio 2015, 2017 helper extension for Unity script refactoring. 3 | 4 | Download 5 | 6 | This extension will be helpful if you keep Unity scripts in separate libraries. Extension works only with C#. Scripts references in the scenes and prefabs will be broken after refactoring (changing namespace or class name). This extension monitors changes in project files and update scene and prefab files after assembly build. 7 | 8 | Set the asset serialization to force text and version control to visible Meta files in Unity (Edit -> Project Settings -> Editor). 9 | 10 | Visual Studio extension located at View -> Other Windows -> Unity Refactor Helper. It is become active after solution is open and all projects are loaded. 11 | 12 | #Possible settings 13 |
    14 |
  • Enable – start extension
  • 15 |
  • Unity project folder - path to the Assets folder in Unity project
  • 16 |
  • Projects - select monitored library
  • 17 |
  • Project GUID – Get this GUID from the assembly Meta file in Unity folder
  • 18 |
  • Watch projects - tracked libraries
  • 19 |
20 | 21 | #Additional Information 22 | You can edit project GUID by clicking on the project name in the watch projects. Extension creates two files (configuration and cache) in the *.sln file folder. It tracks file save and synchronize files after build if it is required. Tracking occurs only inside the library, file move tracking between libraries is not supported. 23 | -------------------------------------------------------------------------------- /UnityRefactorHelper/View/SyncProjectControl.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Runtime.CompilerServices; 4 | using System.Windows; 5 | using System.Windows.Controls; 6 | using UnityRefactorHelper.Annotations; 7 | using UnityRefactorHelper.Model; 8 | 9 | namespace UnityRefactorHelper.View 10 | { 11 | /// 12 | /// Interaction logic for SyncProjectControl.xaml 13 | /// 14 | public partial class SyncProjectControl : UserControl, INotifyPropertyChanged 15 | { 16 | private ProjectSyncItem _item; 17 | 18 | public SyncProjectControl(ProjectSyncItem item) 19 | { 20 | Item = item; 21 | InitializeComponent(); 22 | } 23 | 24 | public ProjectSyncItem Item 25 | { 26 | get { return _item; } 27 | set 28 | { 29 | _item = value; 30 | OnPropertyChanged(nameof(LabelText)); 31 | } 32 | } 33 | 34 | public string LabelText => $"{Item.ProjectName} : {Item.ProjectGuid}"; 35 | public event PropertyChangedEventHandler PropertyChanged; 36 | public event EventHandler OnSyncItemDelete; 37 | public event EventHandler OnSyncItemClick; 38 | 39 | private void removeBtn_Click(object sender, RoutedEventArgs e) 40 | { 41 | var messageBoxResult = MessageBox.Show("Are you sure?", "Delete Confirmation", MessageBoxButton.YesNo); 42 | if (messageBoxResult != MessageBoxResult.Yes) return; 43 | OnSyncItemDelete?.Invoke(this, EventArgs.Empty); 44 | } 45 | 46 | private void syncBtn_Click(object sender, RoutedEventArgs e) 47 | { 48 | OnSyncItemClick?.Invoke(Item, EventArgs.Empty); 49 | } 50 | 51 | [NotifyPropertyChangedInvocator] 52 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 53 | { 54 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /UnityRefactorHelper/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /UnityRefactorHelper/Service/CommonService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.Design; 4 | using System.IO; 5 | using Newtonsoft.Json; 6 | using UnityRefactorHelper.Helpers; 7 | using UnityRefactorHelper.Model; 8 | using UnityRefactorHelper.ViewModel; 9 | 10 | namespace UnityRefactorHelper.Service 11 | { 12 | public static class CommonService 13 | { 14 | private const string SettingsFileName = "UnityRefactorSettings.json"; 15 | private const string SettingsCacheFileName = "UnityRefactorSettingsCache.bin"; 16 | 17 | public static void HandleMenuButton(bool enabled) 18 | { 19 | var mc = 20 | Cache.Instance.OleMenuCommandService.FindCommand(new CommandID(Constants.CommandSet, Constants.CommandId)); 21 | if (mc != null) 22 | mc.Enabled = enabled; 23 | ToolWindowViewModel.Instance.SolutionLoaded = enabled; 24 | } 25 | 26 | public static void SaveSettings() 27 | { 28 | var dte = Cache.Instance.Dte; 29 | 30 | var path = Path.Combine(Path.GetDirectoryName(dte.Solution.FullName), SettingsFileName); 31 | File.WriteAllText(path, JsonConvert.SerializeObject(Cache.Instance.Settings)); 32 | } 33 | 34 | public static void LoadSettings() 35 | { 36 | var dte = Cache.Instance.Dte; 37 | 38 | var path = Path.Combine(Path.GetDirectoryName(dte.Solution.FullName), SettingsFileName); 39 | if (File.Exists(path)) 40 | { 41 | var content = File.ReadAllText(path); 42 | Cache.Instance.Settings = JsonConvert.DeserializeObject(content); 43 | } 44 | } 45 | 46 | public static void SaveSyncProjectItemsToCache() 47 | { 48 | var dte = Cache.Instance.Dte; 49 | var scanProjects = Cache.Instance.ScanProjects; 50 | var path = Path.Combine(Path.GetDirectoryName(dte.Solution.FullName), SettingsCacheFileName); 51 | File.WriteAllText(path, JsonConvert.SerializeObject(scanProjects)); 52 | } 53 | 54 | public static void LoadSyncProjectsCache() 55 | { 56 | var dte = Cache.Instance.Dte; 57 | var path = Path.Combine(Path.GetDirectoryName(dte.Solution.FullName), SettingsCacheFileName); 58 | if (File.Exists(path)) 59 | { 60 | var content = File.ReadAllText(path); 61 | Cache.Instance.ScanProjects = JsonConvert.DeserializeObject>(content); 62 | } 63 | } 64 | 65 | public static void UpdateUnityProject(string vsProject) 66 | { 67 | if(!Cache.Instance.Settings.IsEnabled) return; 68 | var projectName = Path.GetFileNameWithoutExtension(vsProject); 69 | var replacer = new UnityProjectFileIdReplacer(projectName); 70 | replacer.Replace(); 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /UnityRefactorHelper/Helpers/UnityProjectFileIdReplacer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Text.RegularExpressions; 5 | using UnityRefactorHelper.Model; 6 | using UnityRefactorHelper.Service; 7 | 8 | namespace UnityRefactorHelper.Helpers 9 | { 10 | public class UnityProjectFileIdReplacer 11 | { 12 | private readonly string _vsProject; 13 | 14 | public UnityProjectFileIdReplacer(string vsProject) 15 | { 16 | _vsProject = vsProject; 17 | } 18 | 19 | public void Replace() 20 | { 21 | var scanProject = Cache.Instance.ScanProjects.FirstOrDefault(x => x.ProjectName == _vsProject); 22 | if (scanProject == null) return; 23 | 24 | ProcessFiles(scanProject); 25 | } 26 | 27 | private void ProcessFiles(ProjectScanItem projectScanItem) 28 | { 29 | var path = Cache.Instance.Settings.UnityProjectPath; 30 | var scenes = GetFilePathes(path, "*.unity"); 31 | var prefabs = GetFilePathes(path, "*.prefab"); 32 | var replaceIn = new List(); 33 | replaceIn.AddRange(scenes); 34 | replaceIn.AddRange(prefabs); 35 | 36 | ProcessReplace(replaceIn, projectScanItem); 37 | ProcessProjectScanItem(projectScanItem); 38 | } 39 | 40 | private IEnumerable GetFilePathes(string parentPath, string mask) 41 | { 42 | var filenames = Directory.GetFiles(parentPath, mask, SearchOption.AllDirectories); 43 | return filenames; 44 | } 45 | 46 | private void ProcessReplace(IEnumerable replacePathes, ProjectScanItem projectScanItem) 47 | { 48 | foreach (var replacePath in replacePathes) 49 | { 50 | var lines = File.ReadAllLines(replacePath); 51 | var newLines = new List(); 52 | foreach (var line in lines) 53 | { 54 | var isFound = false; 55 | foreach (var file in projectScanItem.Files.Where(x => x.NewId.HasValue)) 56 | { 57 | var r = Regex.Match(line, 58 | $" m_Script: {{fileID: {file.OldId}, guid: {projectScanItem.ProjectGuid.ToString("n").ToLower()}, type: 3}}", 59 | RegexOptions.IgnoreCase); 60 | if (r.Success) 61 | { 62 | newLines.Add( 63 | r.Result( 64 | $" m_Script: {{fileID: {file.NewId}, guid: {projectScanItem.ProjectGuid.ToString("n").ToLower()}, type: 3}}")); 65 | isFound = true; 66 | break; 67 | } 68 | } 69 | if (!isFound) 70 | newLines.Add(line); 71 | } 72 | File.WriteAllLines(replacePath, newLines.ToArray()); 73 | } 74 | } 75 | 76 | private void ProcessProjectScanItem(ProjectScanItem projectScanItem) 77 | { 78 | var renamed = projectScanItem.Files.Where(x => x.NewId.HasValue); 79 | foreach (var r in renamed) 80 | { 81 | r.OldId = r.NewId.Value; 82 | r.NewId = null; 83 | } 84 | 85 | CommonService.SaveSyncProjectItemsToCache(); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /UnityRefactorHelper/View/SyncProjectControl.xaml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 32 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /UnityRefactorHelper/UnityRefactorHelperSettingsCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel.Design; 3 | using Microsoft.VisualStudio; 4 | using Microsoft.VisualStudio.Shell; 5 | using Microsoft.VisualStudio.Shell.Interop; 6 | using UnityRefactorHelper.Helpers; 7 | 8 | namespace UnityRefactorHelper 9 | { 10 | /// 11 | /// Command handler 12 | /// 13 | internal sealed class UnityRefactorHelperSettingsCommand 14 | { 15 | /// 16 | /// Command ID. 17 | /// 18 | public const int CommandId = Constants.CommandId; 19 | 20 | /// 21 | /// Command menu group (command set GUID). 22 | /// 23 | public static readonly Guid CommandSet = Constants.CommandSet; 24 | 25 | /// 26 | /// VS Package that provides this command, not null. 27 | /// 28 | private readonly Package package; 29 | 30 | /// 31 | /// Initializes a new instance of the class. 32 | /// Adds our command handlers for menu (commands must exist in the command table file) 33 | /// 34 | /// Owner package, not null. 35 | private UnityRefactorHelperSettingsCommand(Package package) 36 | { 37 | if (package == null) 38 | { 39 | throw new ArgumentNullException("package"); 40 | } 41 | 42 | this.package = package; 43 | 44 | var commandService = ServiceProvider.GetService(typeof (IMenuCommandService)) as OleMenuCommandService; 45 | if (commandService != null) 46 | { 47 | var menuCommandID = new CommandID(CommandSet, CommandId); 48 | var menuItem = new MenuCommand(ShowToolWindow, menuCommandID); 49 | commandService.AddCommand(menuItem); 50 | } 51 | } 52 | 53 | /// 54 | /// Gets the instance of the command. 55 | /// 56 | public static UnityRefactorHelperSettingsCommand Instance { get; private set; } 57 | 58 | /// 59 | /// Gets the service provider from the owner package. 60 | /// 61 | private IServiceProvider ServiceProvider 62 | { 63 | get { return package; } 64 | } 65 | 66 | /// 67 | /// Initializes the singleton instance of the command. 68 | /// 69 | /// Owner package, not null. 70 | public static void Initialize(Package package) 71 | { 72 | Instance = new UnityRefactorHelperSettingsCommand(package); 73 | } 74 | 75 | /// 76 | /// Shows the tool window when the menu item is clicked. 77 | /// 78 | /// The event sender. 79 | /// The event args. 80 | private void ShowToolWindow(object sender, EventArgs e) 81 | { 82 | // Get the instance number 0 of this tool window. This window is single instance so this instance 83 | // is actually the only one. 84 | // The last flag is set to true so that if the tool window does not exists it will be created. 85 | var window = package.FindToolWindow(typeof (SettingsToolWindow), 0, true); 86 | if ((null == window) || (null == window.Frame)) 87 | { 88 | throw new NotSupportedException("Cannot create tool window"); 89 | } 90 | var windowFrame = (IVsWindowFrame) window.Frame; 91 | ErrorHandler.ThrowOnFailure(windowFrame.Show()); 92 | } 93 | } 94 | } -------------------------------------------------------------------------------- /UnityRefactorHelper/SolutionEvents.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Linq; 3 | using EnvDTE; 4 | using Microsoft.VisualStudio; 5 | using Microsoft.VisualStudio.Shell.Interop; 6 | using UnityRefactorHelper.Service; 7 | using UnityRefactorHelper.ViewModel; 8 | 9 | namespace UnityRefactorHelper 10 | { 11 | public class SolutionEvents : IVsSolutionEvents, IVsSolutionLoadEvents 12 | { 13 | public int OnAfterOpenSolution(object pUnkReserved, int fNewSolution) 14 | { 15 | ToolWindowViewModel.Instance.LoadSettings(); 16 | return VSConstants.S_OK; 17 | } 18 | 19 | public int OnAfterCloseSolution(object pUnkReserved) 20 | { 21 | CommonService.HandleMenuButton(false); 22 | return VSConstants.S_OK; 23 | } 24 | 25 | public int OnAfterOpenProject(IVsHierarchy pHierarchy, int fAdded) 26 | { 27 | var project = GetProjectFromHierarchy(pHierarchy); 28 | if (!string.IsNullOrEmpty(project?.FileName)) 29 | { 30 | ToolWindowViewModel.Instance.ProjectNames.Add(Path.GetFileNameWithoutExtension(project.FileName)); 31 | ProjectService.ProcessProject(project); 32 | } 33 | return VSConstants.S_OK; 34 | } 35 | 36 | public int OnBeforeCloseProject(IVsHierarchy pHierarchy, int fRemoved) 37 | { 38 | var project = GetProjectFromHierarchy(pHierarchy); 39 | if (project != null) 40 | { 41 | var name = Path.GetFileNameWithoutExtension(project.FileName); 42 | var item = ToolWindowViewModel.Instance.ProjectNames.FirstOrDefault(x => x == name); 43 | if (item != null) 44 | { 45 | ToolWindowViewModel.Instance.ProjectNames.Remove(item); 46 | } 47 | } 48 | return VSConstants.S_OK; 49 | } 50 | 51 | public int OnAfterBackgroundSolutionLoadComplete() 52 | { 53 | CommonService.HandleMenuButton(true); 54 | return VSConstants.S_OK; 55 | } 56 | 57 | private Project GetProjectFromHierarchy(IVsHierarchy pHierarchy) 58 | { 59 | const uint itemid = VSConstants.VSITEMID_ROOT; 60 | 61 | object objProj; 62 | pHierarchy.GetProperty(itemid, (int) __VSHPROPID.VSHPROPID_ExtObject, out objProj); 63 | var project = objProj as Project; 64 | return project; 65 | } 66 | 67 | #region Not used 68 | 69 | public int OnQueryCloseSolution(object pUnkReserved, ref int pfCancel) 70 | { 71 | return VSConstants.S_OK; 72 | } 73 | 74 | public int OnBeforeCloseSolution(object pUnkReserved) 75 | { 76 | return VSConstants.S_OK; 77 | } 78 | 79 | public int OnBeforeOpenSolution(string pszSolutionFilename) 80 | { 81 | return VSConstants.S_OK; 82 | } 83 | 84 | public int OnBeforeBackgroundSolutionLoadBegins() 85 | { 86 | return VSConstants.S_OK; 87 | } 88 | 89 | public int OnQueryBackgroundLoadProjectBatch(out bool pfShouldDelayLoadToNextIdle) 90 | { 91 | pfShouldDelayLoadToNextIdle = false; 92 | return VSConstants.S_OK; 93 | } 94 | 95 | public int OnBeforeLoadProjectBatch(bool fIsBackgroundIdleBatch) 96 | { 97 | return VSConstants.S_OK; 98 | } 99 | 100 | public int OnAfterLoadProjectBatch(bool fIsBackgroundIdleBatch) 101 | { 102 | return VSConstants.S_OK; 103 | } 104 | 105 | public int OnQueryCloseProject(IVsHierarchy pHierarchy, int fRemoving, ref int pfCancel) 106 | { 107 | return VSConstants.S_OK; 108 | } 109 | 110 | public int OnAfterLoadProject(IVsHierarchy pStubHierarchy, IVsHierarchy pRealHierarchy) 111 | { 112 | return VSConstants.S_OK; 113 | } 114 | 115 | public int OnQueryUnloadProject(IVsHierarchy pRealHierarchy, ref int pfCancel) 116 | { 117 | return VSConstants.S_OK; 118 | } 119 | 120 | public int OnBeforeUnloadProject(IVsHierarchy pRealHierarchy, IVsHierarchy pStubHierarchy) 121 | { 122 | return VSConstants.S_OK; 123 | } 124 | 125 | #endregion 126 | } 127 | } -------------------------------------------------------------------------------- /UnityRefactorHelper/UnityRefactorHelperSettingsPackage.vsct: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 25 | 26 | 33 | 34 | 35 | 37 | 38 | 45 | 53 | 54 | 55 | 56 | 57 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /UnityRefactorHelper/UnityRefactorHelperSettingsPackage.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.Design; 2 | using System.Diagnostics.CodeAnalysis; 3 | using System.Runtime.InteropServices; 4 | using EnvDTE; 5 | using Microsoft.VisualStudio; 6 | using Microsoft.VisualStudio.Shell; 7 | using Microsoft.VisualStudio.Shell.Interop; 8 | using UnityRefactorHelper.Helpers; 9 | using UnityRefactorHelper.Service; 10 | 11 | namespace UnityRefactorHelper 12 | { 13 | /// 14 | /// This is the class that implements the package exposed by this assembly. 15 | /// 16 | /// 17 | /// 18 | /// The minimum requirement for a class to be considered a valid package for Visual Studio 19 | /// is to implement the IVsPackage interface and register itself with the shell. 20 | /// This package uses the helper classes defined inside the Managed Package Framework (MPF) 21 | /// to do it: it derives from the Package class that provides the implementation of the 22 | /// IVsPackage interface and uses the registration attributes defined in the framework to 23 | /// register itself and its components with the shell. These attributes tell the pkgdef creation 24 | /// utility what data to put into .pkgdef file. 25 | /// 26 | /// 27 | /// To get loaded into VS, the package must be referred by <Asset Type="Microsoft.VisualStudio.VsPackage" ...> in .vsixmanifest file. 28 | /// 29 | /// 30 | [PackageRegistration(UseManagedResourcesOnly = true)] 31 | [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] // Info on this package for Help/About 32 | [ProvideMenuResource("Menus.ctmenu", 1)] 33 | [ProvideToolWindow(typeof (SettingsToolWindow))] 34 | [Guid(PackageGuidString)] 35 | [ProvideAutoLoad(VSConstants.UICONTEXT.SolutionExists_string)] 36 | [SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", 37 | Justification = "pkgdef, VS and vsixmanifest are valid VS terms")] 38 | public sealed class UnityRefactorHelperSettingsPackage : Package 39 | { 40 | /// 41 | /// UnityRefactorHelperSettingsPackage GUID string. 42 | /// 43 | public const string PackageGuidString = "704c324b-a17d-45b6-bb8d-3aacff371f0a"; 44 | 45 | private BuildEvents _buildEvents; 46 | private DocumentEvents _documentEvents; 47 | private IVsSolutionEvents _solutionEvents; 48 | private IVsSolution _solution; 49 | private uint _solutionEventsCookie; 50 | 51 | #region Package Members 52 | 53 | /// 54 | /// Initialization of the package; this method is called right after the package is sited, so this is the place 55 | /// where you can put all the initialization code that rely on services provided by VisualStudio. 56 | /// 57 | protected override void Initialize() 58 | { 59 | UnityRefactorHelperSettingsCommand.Initialize(this); 60 | base.Initialize(); 61 | 62 | Cache.Instance.OleMenuCommandService = GetService(typeof (IMenuCommandService)) as OleMenuCommandService; 63 | Cache.Instance.Dte = (DTE) GetService(typeof (SDTE)); 64 | 65 | var events = Cache.Instance.Dte.Events; 66 | _documentEvents = events.DocumentEvents; 67 | _buildEvents = events.BuildEvents; 68 | 69 | Cache.Instance.SolutionService = GetService(typeof (IVsSolution)) as IVsSolution; 70 | 71 | _solutionEvents = new SolutionEvents(); 72 | _solution = GetService(typeof (SVsSolution)) as IVsSolution; 73 | _solution.AdviseSolutionEvents(_solutionEvents, out _solutionEventsCookie); 74 | 75 | _documentEvents.DocumentSaved += DocumentEventsOnDocumentSaved; 76 | _buildEvents.OnBuildProjConfigDone += BuildEventsOnOnBuildProjConfigDone; 77 | } 78 | 79 | private void BuildEventsOnOnBuildProjConfigDone(string project, string projectConfig, string platform, 80 | string solutionConfig, bool success) 81 | { 82 | if (success) 83 | CommonService.UpdateUnityProject(project); 84 | } 85 | 86 | protected override void Dispose(bool disposing) 87 | { 88 | UnadviseSolutionEvents(); 89 | Cache.Instance.Dispose(); 90 | _buildEvents = null; 91 | _documentEvents = null; 92 | _solutionEvents = null; 93 | base.Dispose(disposing); 94 | } 95 | 96 | private void UnadviseSolutionEvents() 97 | { 98 | if (_solution != null) 99 | { 100 | if (_solutionEventsCookie != uint.MaxValue) 101 | { 102 | _solution.UnadviseSolutionEvents(_solutionEventsCookie); 103 | _solutionEventsCookie = uint.MaxValue; 104 | } 105 | 106 | _solution = null; 107 | } 108 | } 109 | 110 | private void DocumentEventsOnDocumentSaved(Document document) 111 | { 112 | ProjectService.DocumentSaved(document); 113 | } 114 | 115 | #endregion 116 | } 117 | } -------------------------------------------------------------------------------- /UnityRefactorHelper/Helpers/Md4.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Security.Cryptography; 4 | 5 | namespace UnityRefactorHelper.Helpers 6 | { 7 | public sealed class Md4 : HashAlgorithm 8 | { 9 | private readonly uint[] _x; 10 | private uint _a; 11 | private uint _b; 12 | private int _bytesProcessed; 13 | private uint _c; 14 | private uint _d; 15 | 16 | public Md4() 17 | { 18 | _x = new uint[16]; 19 | 20 | Initialize(); 21 | } 22 | 23 | public override void Initialize() 24 | { 25 | _a = 0x67452301; 26 | _b = 0xefcdab89; 27 | _c = 0x98badcfe; 28 | _d = 0x10325476; 29 | 30 | _bytesProcessed = 0; 31 | } 32 | 33 | protected override void HashCore(byte[] array, int offset, int length) 34 | { 35 | ProcessMessage(Bytes(array, offset, length)); 36 | } 37 | 38 | protected override byte[] HashFinal() 39 | { 40 | try 41 | { 42 | ProcessMessage(Padding()); 43 | 44 | return new[] {_a, _b, _c, _d}.SelectMany(word => Bytes(word)).ToArray(); 45 | } 46 | finally 47 | { 48 | Initialize(); 49 | } 50 | } 51 | 52 | private void ProcessMessage(IEnumerable bytes) 53 | { 54 | foreach (var b in bytes) 55 | { 56 | var c = _bytesProcessed & 63; 57 | var i = c >> 2; 58 | var s = (c & 3) << 3; 59 | 60 | _x[i] = (_x[i] & ~((uint) 255 << s)) | ((uint) b << s); 61 | 62 | if (c == 63) 63 | { 64 | Process16WordBlock(); 65 | } 66 | 67 | _bytesProcessed++; 68 | } 69 | } 70 | 71 | private static IEnumerable Bytes(byte[] bytes, int offset, int length) 72 | { 73 | for (var i = offset; i < length; i++) 74 | { 75 | yield return bytes[i]; 76 | } 77 | } 78 | 79 | private IEnumerable Bytes(uint word) 80 | { 81 | yield return (byte) (word & 255); 82 | yield return (byte) ((word >> 8) & 255); 83 | yield return (byte) ((word >> 16) & 255); 84 | yield return (byte) ((word >> 24) & 255); 85 | } 86 | 87 | private IEnumerable Repeat(byte value, int count) 88 | { 89 | for (var i = 0; i < count; i++) 90 | { 91 | yield return value; 92 | } 93 | } 94 | 95 | private IEnumerable Padding() 96 | { 97 | return Repeat(128, 1) 98 | .Concat(Repeat(0, ((_bytesProcessed + 8) & 0x7fffffc0) + 55 - _bytesProcessed)) 99 | .Concat(Bytes((uint) _bytesProcessed << 3)) 100 | .Concat(Repeat(0, 4)); 101 | } 102 | 103 | private void Process16WordBlock() 104 | { 105 | var aa = _a; 106 | var bb = _b; 107 | var cc = _c; 108 | var dd = _d; 109 | 110 | foreach (var k in new[] {0, 4, 8, 12}) 111 | { 112 | aa = Round1Operation(aa, bb, cc, dd, _x[k], 3); 113 | dd = Round1Operation(dd, aa, bb, cc, _x[k + 1], 7); 114 | cc = Round1Operation(cc, dd, aa, bb, _x[k + 2], 11); 115 | bb = Round1Operation(bb, cc, dd, aa, _x[k + 3], 19); 116 | } 117 | 118 | foreach (var k in new[] {0, 1, 2, 3}) 119 | { 120 | aa = Round2Operation(aa, bb, cc, dd, _x[k], 3); 121 | dd = Round2Operation(dd, aa, bb, cc, _x[k + 4], 5); 122 | cc = Round2Operation(cc, dd, aa, bb, _x[k + 8], 9); 123 | bb = Round2Operation(bb, cc, dd, aa, _x[k + 12], 13); 124 | } 125 | 126 | foreach (var k in new[] {0, 2, 1, 3}) 127 | { 128 | aa = Round3Operation(aa, bb, cc, dd, _x[k], 3); 129 | dd = Round3Operation(dd, aa, bb, cc, _x[k + 8], 9); 130 | cc = Round3Operation(cc, dd, aa, bb, _x[k + 4], 11); 131 | bb = Round3Operation(bb, cc, dd, aa, _x[k + 12], 15); 132 | } 133 | 134 | unchecked 135 | { 136 | _a += aa; 137 | _b += bb; 138 | _c += cc; 139 | _d += dd; 140 | } 141 | } 142 | 143 | private static uint ROL(uint value, int numberOfBits) 144 | { 145 | return (value << numberOfBits) | (value >> (32 - numberOfBits)); 146 | } 147 | 148 | private static uint Round1Operation(uint a, uint b, uint c, uint d, uint xk, int s) 149 | { 150 | unchecked 151 | { 152 | return ROL(a + ((b & c) | (~b & d)) + xk, s); 153 | } 154 | } 155 | 156 | private static uint Round2Operation(uint a, uint b, uint c, uint d, uint xk, int s) 157 | { 158 | unchecked 159 | { 160 | return ROL(a + ((b & c) | (b & d) | (c & d)) + xk + 0x5a827999, s); 161 | } 162 | } 163 | 164 | private static uint Round3Operation(uint a, uint b, uint c, uint d, uint xk, int s) 165 | { 166 | unchecked 167 | { 168 | return ROL(a + (b ^ c ^ d) + xk + 0x6ed9eba1, s); 169 | } 170 | } 171 | } 172 | } -------------------------------------------------------------------------------- /UnityRefactorHelper/VSPackage.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 | UnityRefactorHelperSettings Extension 122 | 123 | 124 | UnityRefactorHelperSettings Visual Studio Extension Detailed Info 125 | 126 | -------------------------------------------------------------------------------- /UnityRefactorHelper/View/UnityRefactorHelperSettingsControl.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 15 | 19 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |