Skip to content

Commit

Permalink
* AssetContextMenus: user can now select app location if it is not fo…
Browse files Browse the repository at this point in the history
…und. Also added 3 custom edit menus.
  • Loading branch information
NibbleByte committed Oct 9, 2023
1 parent 175f676 commit 80a2bc9
Showing 1 changed file with 111 additions and 42 deletions.
153 changes: 111 additions & 42 deletions Editor/AssetContextMenus.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ private static void CopySelectedAssetNames()
// Selection.objects my have sub-assets (for example embedded fbx materials).
// All sub assets have the same guid, but different local id.
var objectsNames = Selection.objects.Select(o => o.name).ToList();

// Get by selected guids.
// Selection.assetGUIDs includes selected folders on the left in two-column project view (Selection.objects does not).
// Selected sub-assets will return the main asset guid.
Expand Down Expand Up @@ -125,26 +125,29 @@ private static void CopySelectedAbsolutePaths()

#region Text Editing

private const string PrettyKey_NotepadPlusPlus = "Notepad++";
private const string PrettyKey_Sublime = "Sublime";

[MenuItem("Assets/Edit With/Notepad++", false, EditWith_MenuItemPriorityStart + 0)]
private static void EditWithNotepadPlusPlus()
=> EditWithApp("notepad++.exe", GetPathsOfAssetsJoined(Selection.objects, false), _notepadPaths);
=> EditWithApp(PrettyKey_NotepadPlusPlus, "notepad++.exe", GetPathsOfAssetsJoined(Selection.objects, false), _notepadPaths);

[MenuItem("Assets/Edit With/Notepad++ Metas", false, EditWith_MenuItemPriorityStart + 1)]
private static void EditWithNotepadPlusPlusMetas()
=> EditWithApp("notepad++.exe", GetPathsOfAssetsJoined(Selection.objects, true), _notepadPaths);
=> EditWithApp(PrettyKey_NotepadPlusPlus,"notepad++.exe", GetPathsOfAssetsJoined(Selection.objects, true), _notepadPaths);

[MenuItem("Assets/Edit With/Sublime", false, EditWith_MenuItemPriorityStart + 2)]
private static void EditWithSublime()
=> EditWithApp("subl.exe", GetPathsOfAssetsJoined(Selection.objects, false), _sublimePaths);
=> EditWithApp(PrettyKey_Sublime, "subl.exe", GetPathsOfAssetsJoined(Selection.objects, false), _sublimePaths);

[MenuItem("Assets/Edit With/Sublime Metas", false, EditWith_MenuItemPriorityStart + 3)]
private static void EditWithSublimeMetas()
=> EditWithApp("subl.exe", GetPathsOfAssetsJoined(Selection.objects, true), _sublimePaths);
=> EditWithApp(PrettyKey_Sublime, "subl.exe", GetPathsOfAssetsJoined(Selection.objects, true), _sublimePaths);

[MenuItem("Assets/Edit With/Scripts IDE", false, EditWith_MenuItemPriorityStart + 4)]
private static void EditWithIDE()
=> TryEditWithScriptsIDE(GetPathsOfAssetsJoined(Selection.objects, false));

[MenuItem("Assets/Edit With/Scripts IDE Metas", false, EditWith_MenuItemPriorityStart + 5)]
private static void EditWithIDEMetas()
=> TryEditWithScriptsIDE(GetPathsOfAssetsJoined(Selection.objects, true));
Expand All @@ -160,13 +163,18 @@ private static bool EditWithTextValidate()

#region Textures Editing

private const string PrettyKey_PaintDotNet = "Paint.Net";
private const string PrettyKey_Krita = "Krita";
private const string PrettyKey_Photoshop = "Photoshop";
private const string PrettyKey_Gimp = "Gimp";

[MenuItem("Assets/Edit With/Paint.NET", false, EditWith_MenuItemPriorityStart + 20)]
private static void EditWithPaintDotNet()
{
if (TryEditWithApp("paint.net.1", GetPathsOfAssetsJoined(Selection.objects, false)))
return;

EditWithApp("paintdotnet.exe", GetPathsOfAssetsJoined(Selection.objects, false));
EditWithApp(PrettyKey_PaintDotNet, "paintdotnet.exe", GetPathsOfAssetsJoined(Selection.objects, false));
}

[MenuItem("Assets/Edit With/Krita", false, EditWith_MenuItemPriorityStart + 22)]
Expand All @@ -175,7 +183,7 @@ private static void EditWithKrita()
if (TryEditWithApp("Krita.Document", GetPathsOfAssetsJoined(Selection.objects, false)))
return;

EditWithApp("krita.exe", GetPathsOfAssetsJoined(Selection.objects, false));
EditWithApp(PrettyKey_Krita, "krita.exe", GetPathsOfAssetsJoined(Selection.objects, false));
}

[MenuItem("Assets/Edit With/Photoshop", false, EditWith_MenuItemPriorityStart + 24)]
Expand All @@ -184,12 +192,12 @@ private static void EditWithPhotoshop()
if (TryEditWithApp("Photoshop.exe", GetPathsOfAssetsJoined(Selection.objects, false)))
return;

EditWithApp("adbps", GetPathsOfAssetsJoined(Selection.objects, false));
EditWithApp(PrettyKey_Photoshop, "adbps", GetPathsOfAssetsJoined(Selection.objects, false));
}

[MenuItem("Assets/Edit With/Gimp", false, EditWith_MenuItemPriorityStart + 26)]
private static void EditWithGimp()
=> EditWithApp("GIMP2.png", GetPathsOfAssetsJoined(Selection.objects, false));
=> EditWithApp(PrettyKey_Gimp, "GIMP2.png", GetPathsOfAssetsJoined(Selection.objects, false));


[MenuItem("Assets/Edit With/Paint.NET", true, EditWith_MenuItemPriorityStart + 20)]
Expand All @@ -203,6 +211,8 @@ private static bool EditWithTextureValidate()

#region Models Editing

private const string PrettyKey_Blender = "Blender";

[MenuItem("Assets/Edit With/Blender", false, EditWith_MenuItemPriorityStart + 40)]
private static void EditWithBlender()
{
Expand All @@ -215,7 +225,7 @@ private static void EditWithBlender()
AssetDatabase.OpenAsset(Selection.objects[0]);
return;
}

// Assume this is fbx or other model file. It can't be opened directly, it needs to be imported.
// Idea by: https://blog.kikicode.com/2018/12/double-click-fbx-files-to-import-to.html
string args = $"--python-expr \"" + // start python expression.
Expand All @@ -229,8 +239,8 @@ private static void EditWithBlender()

if (TryEditWithApp("blendfile", args))
return;
EditWithApp("blender.exe", args);

EditWithApp(PrettyKey_Blender, "blender.exe", args);
}


Expand All @@ -240,6 +250,26 @@ private static bool EditWithModelValidate()

#endregion

#region Custom Editing

private const string PrettyKey_Custom1 = "Custom 1";
private const string PrettyKey_Custom2 = "Custom 2";
private const string PrettyKey_Custom3 = "Custom 3";

[MenuItem("Assets/Edit With/Custom 1", false, EditWith_MenuItemPriorityStart + 60)]
private static void EditWithCustom1()
=> EditWithApp(PrettyKey_Custom1, "", GetPathsOfAssetsJoined(Selection.objects, false));

[MenuItem("Assets/Edit With/Custom 2", false, EditWith_MenuItemPriorityStart + 61)]
private static void EditWithCustom2()
=> EditWithApp(PrettyKey_Custom2, "", GetPathsOfAssetsJoined(Selection.objects, false));

[MenuItem("Assets/Edit With/Custom 3", false, EditWith_MenuItemPriorityStart + 62)]
private static void EditWithCustom3()
=> EditWithApp(PrettyKey_Custom3, "", GetPathsOfAssetsJoined(Selection.objects, false));

#endregion

#region Editing Utils

private static string GetPathsOfAssetsJoined(Object[] objects, bool metas, string separator = " ")
Expand All @@ -255,11 +285,47 @@ private static string GetPathsOfAssetsJoined(Object[] objects, bool metas, strin
return string.Join(separator, paths);
}

private static void EditWithApp(string appRegistryName, string args, params string[] fallbackPaths)
[MenuItem("Assets/Edit With/Clear Saved App Paths", false, EditWith_MenuItemPriorityStart + 80)]
private static void ClearSavedAppPaths()
{
EditorPrefs.DeleteKey($"AssetContextMenus_{PrettyKey_NotepadPlusPlus}");
EditorPrefs.DeleteKey($"AssetContextMenus_{PrettyKey_Sublime}");

EditorPrefs.DeleteKey($"AssetContextMenus_{PrettyKey_PaintDotNet}");
EditorPrefs.DeleteKey($"AssetContextMenus_{PrettyKey_Krita}");
EditorPrefs.DeleteKey($"AssetContextMenus_{PrettyKey_Photoshop}");
EditorPrefs.DeleteKey($"AssetContextMenus_{PrettyKey_Gimp}");

EditorPrefs.DeleteKey($"AssetContextMenus_{PrettyKey_Blender}");

EditorPrefs.DeleteKey($"AssetContextMenus_{PrettyKey_Custom1}");
EditorPrefs.DeleteKey($"AssetContextMenus_{PrettyKey_Custom2}");
EditorPrefs.DeleteKey($"AssetContextMenus_{PrettyKey_Custom3}");
}

private static void EditWithApp(string prettyName, string appRegistryName, string args, params string[] fallbackPaths)
{
string prefsPath = EditorPrefs.GetString($"AssetContextMenus_{prettyName}");

if (!string.IsNullOrEmpty(prefsPath) && File.Exists(prefsPath)) {
System.Array.Resize(ref fallbackPaths, fallbackPaths.Length + 1);
fallbackPaths[fallbackPaths.Length - 1] = prefsPath;
}

if (!TryEditWithApp(appRegistryName, args, fallbackPaths)) {
EditorUtility.DisplayDialog("Error", $"Program \"{appRegistryName}\" is not found.", "Sad");
return;

if (string.IsNullOrWhiteSpace(prefsPath) || !File.Exists(prefsPath)) {
prefsPath = EditorUtility.OpenFilePanel($"Locate {prettyName} Executable", "C:\\", "exe");

if (!string.IsNullOrEmpty(prefsPath) && File.Exists(prefsPath)) {
EditorPrefs.SetString($"AssetContextMenus_{prettyName}", prefsPath);

if (TryEditWithApp(appRegistryName, args, prefsPath))
return;
}
}

EditorUtility.DisplayDialog("Error", $"Program \"{prettyName}\" is not found.", "Sad!");
}
}

Expand Down Expand Up @@ -287,36 +353,39 @@ public static bool TryEditWithScriptsIDE(string args)

public static bool TryEditWithApp(string appRegistryName, string args, params string[] fallbackPaths)
{
const string appPaths = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\{0}";
const string shellCommands = @"SOFTWARE\Classes\{0}\shell\open\command";
const string shellCommands2 = @"SOFTWARE\Classes\Applications\{0}\shell\open\command";
if (!string.IsNullOrWhiteSpace(appRegistryName)) {

// https://stackoverflow.com/a/909966/4612666
Microsoft.Win32.RegistryKey fileKey = null
?? Microsoft.Win32.Registry.CurrentUser.OpenSubKey(string.Format(appPaths, appRegistryName))
?? Microsoft.Win32.Registry.LocalMachine.OpenSubKey(string.Format(appPaths, appRegistryName))
const string appPaths = @"SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\{0}";
const string shellCommands = @"SOFTWARE\Classes\{0}\shell\open\command";
const string shellCommands2 = @"SOFTWARE\Classes\Applications\{0}\shell\open\command";

?? Microsoft.Win32.Registry.CurrentUser.OpenSubKey(string.Format(shellCommands, appRegistryName))
?? Microsoft.Win32.Registry.LocalMachine.OpenSubKey(string.Format(shellCommands, appRegistryName))
// https://stackoverflow.com/a/909966/4612666
Microsoft.Win32.RegistryKey fileKey = null
?? Microsoft.Win32.Registry.CurrentUser.OpenSubKey(string.Format(appPaths, appRegistryName))
?? Microsoft.Win32.Registry.LocalMachine.OpenSubKey(string.Format(appPaths, appRegistryName))

?? Microsoft.Win32.Registry.CurrentUser.OpenSubKey(string.Format(shellCommands2, appRegistryName))
?? Microsoft.Win32.Registry.LocalMachine.OpenSubKey(string.Format(shellCommands2, appRegistryName))
;
?? Microsoft.Win32.Registry.CurrentUser.OpenSubKey(string.Format(shellCommands, appRegistryName))
?? Microsoft.Win32.Registry.LocalMachine.OpenSubKey(string.Format(shellCommands, appRegistryName))

if (fileKey != null) {
string executablePath = (string)fileKey.GetValue(string.Empty);
fileKey.Close();
?? Microsoft.Win32.Registry.CurrentUser.OpenSubKey(string.Format(shellCommands2, appRegistryName))
?? Microsoft.Win32.Registry.LocalMachine.OpenSubKey(string.Format(shellCommands2, appRegistryName))
;

// Values coming from the shellCommands are in the format:
// "C:\Programs\Krita\bin\krita.exe" "%1"
if (executablePath.StartsWith('"')) {
executablePath = executablePath.Substring(1, executablePath.IndexOf('"', 1) - 1);
}
if (fileKey != null) {
string executablePath = (string)fileKey.GetValue(string.Empty);
fileKey.Close();

if (File.Exists(executablePath)) {
System.Diagnostics.Process.Start(executablePath, args);
// Values coming from the shellCommands are in the format:
// "C:\Programs\Krita\bin\krita.exe" "%1"
if (executablePath.StartsWith('"')) {
executablePath = executablePath.Substring(1, executablePath.IndexOf('"', 1) - 1);
}

return true;
if (File.Exists(executablePath)) {
System.Diagnostics.Process.Start(executablePath, args);

return true;
}
}
}

Expand Down

0 comments on commit 80a2bc9

Please sign in to comment.