Skip to content

Commit ed70e05

Browse files
authored
Add files via upload
1 parent bd0e85f commit ed70e05

File tree

4 files changed

+315
-0
lines changed

4 files changed

+315
-0
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
using System;
2+
using UnityEditor;
3+
using UnityEngine;
4+
5+
namespace ScriptableObjectMenu
6+
{
7+
internal sealed class AssetMenu : BaseMenu
8+
{
9+
private static GenericMenu m_AssetPopupMenu;
10+
11+
[MenuItem(EDITOR_ASSET_MENU_PATH + "Asset", true, EDITOR_ASSET_MENU_PRIORITY)]
12+
internal static bool Validate ()
13+
{
14+
// Disabled during domain reload
15+
return !EditorApplication.isCompiling;
16+
}
17+
18+
[MenuItem(EDITOR_ASSET_MENU_PATH + "Asset", false, EDITOR_ASSET_MENU_PRIORITY)]
19+
internal static void Initiate ()
20+
{
21+
// Populate Asset menu
22+
if (m_AssetPopupMenu == null)
23+
{
24+
m_AssetPopupMenu = new GenericMenu();
25+
26+
// Traverse domain assemblies
27+
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
28+
{
29+
// Traverse assembly types
30+
foreach (var type in asm.GetTypes())
31+
{
32+
// Filter by type
33+
if (!type.IsValueType &&
34+
!type.IsInterface &&
35+
!type.IsAbstract)
36+
{
37+
// Filter by namespace
38+
if (type.Namespace != null)
39+
{
40+
var space = type.Namespace.Split('.')[0];
41+
if (space == "UnityEngine" ||
42+
space == "UnityEditor" ||
43+
space == "UnityEditorInternal")
44+
{
45+
continue;
46+
}
47+
}
48+
49+
// Filter by class
50+
if (IsScriptableObject(type))
51+
{
52+
// Convert namespace to path
53+
var path = type.FullName.Replace('.', '/');
54+
55+
// Append type to menu
56+
m_AssetPopupMenu.AddItem(new GUIContent(path), false, () =>
57+
{
58+
CreateAsset(type);
59+
});
60+
}
61+
}
62+
}
63+
}
64+
}
65+
66+
// Display when populated
67+
if (m_AssetPopupMenu.GetItemCount() > 0)
68+
{
69+
var window = CreateInstance<AssetMenu>();
70+
window.position = new Rect(0f, 0f, 2f, 2f);
71+
window.ShowPopup();
72+
}
73+
74+
// Otherwise alert user
75+
else if (EditorUtility.DisplayDialog("Error", "No Scriptable Object Found", "OK"))
76+
{
77+
// And display the Script menu
78+
ScriptMenu.Initiate();
79+
}
80+
}
81+
82+
private static void CreateAsset (Type type)
83+
{
84+
// Create asset instance
85+
var asset = CreateInstance(type);
86+
87+
if (asset != null)
88+
{
89+
// Display save dialog
90+
var path = EditorUtility.SaveFilePanelInProject("Save Asset", type.Name, "asset", string.Empty);
91+
92+
if (path.Length > 0)
93+
{
94+
// Save asset to file
95+
AssetDatabase.CreateAsset(asset, path);
96+
AssetDatabase.SaveAssets();
97+
98+
UpdateAssetDatabase(type, path);
99+
100+
// Log on complete
101+
Debug.Log($"Asset created at \"{path}\"");
102+
}
103+
}
104+
else
105+
{
106+
// Alert on type error
107+
EditorUtility.DisplayDialog("Error", $"Invalid Asset\n\n\"{type.Name}\"", "OK");
108+
}
109+
}
110+
111+
private static bool IsScriptableObject (Type type)
112+
{
113+
// Get base
114+
type = type.BaseType;
115+
116+
// Match type
117+
if (type != null &&
118+
type != typeof(Editor) &&
119+
type != typeof(EditorWindow))
120+
{
121+
if (type == typeof(ScriptableObject))
122+
{
123+
return true;
124+
}
125+
else
126+
{
127+
// Otherwise recurse
128+
return IsScriptableObject(type);
129+
}
130+
}
131+
132+
return false;
133+
}
134+
135+
private void OnGUI ()
136+
{
137+
// Display popup
138+
m_AssetPopupMenu.ShowAsContext();
139+
140+
// Close this Window
141+
Close();
142+
}
143+
}
144+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System;
2+
using UnityEditor;
3+
4+
namespace ScriptableObjectMenu
5+
{
6+
internal abstract class BaseMenu : EditorWindow
7+
{
8+
// The Editor's create asset menu path
9+
protected const string EDITOR_ASSET_MENU_PATH = "Assets/Create/Scriptable Object/";
10+
11+
// The Editor's create asset menu position
12+
protected const int EDITOR_ASSET_MENU_PRIORITY = 82;
13+
14+
protected static void UpdateAssetDatabase (Type type, string path)
15+
{
16+
// Update database
17+
var options = ImportAssetOptions.ForceUpdate | ImportAssetOptions.ForceSynchronousImport;
18+
AssetDatabase.ImportAsset(path, options);
19+
20+
// Focus asset
21+
var asset = AssetDatabase.LoadAssetAtPath(path, type);
22+
ProjectWindowUtil.ShowCreatedAsset(asset);
23+
EditorGUIUtility.PingObject(asset);
24+
}
25+
}
26+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
using System;
2+
using System.IO;
3+
using System.Reflection;
4+
using System.Text;
5+
using System.Text.RegularExpressions;
6+
using UnityEditor;
7+
using UnityEngine;
8+
9+
namespace ScriptableObjectMenu
10+
{
11+
internal sealed class ScriptMenu : BaseMenu
12+
{
13+
// The ScriptableObject template path
14+
private const string TEMPLATE_FILE_PATH = "ScriptTemplate.cs";
15+
16+
// The template's class naming tag
17+
private const string TEMPLATE_CLASS_TAG = "<SCRIPT_CLASS_NAME>";
18+
19+
// The default name for new Scripts
20+
private const string DEFAULT_CLASS_NAME = "NewScriptableObject";
21+
22+
[MenuItem(EDITOR_ASSET_MENU_PATH + "Script", false, EDITOR_ASSET_MENU_PRIORITY + 1)]
23+
internal static void Initiate ()
24+
{
25+
// Display save dialog
26+
var path = EditorUtility.SaveFilePanelInProject("Save Script", DEFAULT_CLASS_NAME, "cs", string.Empty);
27+
28+
if (path.Length > 0)
29+
{
30+
// Get name from path
31+
var name = Path.GetFileNameWithoutExtension(path);
32+
33+
// Validate class name
34+
if (Regex.IsMatch(name, "^[A-Z_][A-Za-z0-9_]*$"))
35+
{
36+
// Find template guid
37+
var guid = AssetDatabase.FindAssets(TEMPLATE_FILE_PATH + " t:TextAsset");
38+
39+
if (guid.Length > 0)
40+
{
41+
// Get path from guid
42+
var file = AssetDatabase.GUIDToAssetPath(guid[0]);
43+
44+
if (File.Exists(file))
45+
{
46+
// Get assembly name
47+
var easm = Assembly.GetExecutingAssembly().FullName;
48+
easm = easm.Replace("-Editor", string.Empty);
49+
50+
// Get qualified name
51+
var qasm = Assembly.CreateQualifiedName(easm, name);
52+
53+
// Get type definition
54+
var type = Type.GetType(qasm, false, true);
55+
56+
// Prevent definition conflict
57+
if (type == null)
58+
{
59+
// Copy template
60+
File.Copy(file, path, true);
61+
62+
if (File.Exists(path))
63+
{
64+
// Get text encoding
65+
var utf8 = new UTF8Encoding(true);
66+
67+
// Set class name
68+
var text = File.ReadAllText(path, utf8);
69+
text = text.Replace(TEMPLATE_CLASS_TAG, name);
70+
71+
// Save template
72+
File.WriteAllText(path, text, utf8);
73+
74+
UpdateAssetDatabase(typeof(MonoScript), path);
75+
76+
// Log on complete
77+
Debug.Log($"Script created at \"{path}\"");
78+
79+
return;
80+
}
81+
}
82+
else
83+
{
84+
// Alert on conflicting type definition error
85+
if (EditorUtility.DisplayDialog("Error", $"Class Name Already Exists\n\n\"{name}\"", "OK"))
86+
{
87+
// And recall
88+
Initiate();
89+
}
90+
91+
return;
92+
}
93+
}
94+
}
95+
}
96+
else
97+
{
98+
// Alert on invalid class name error
99+
if (EditorUtility.DisplayDialog("Error", $"Invalid Class Name\n\n\"{name}\"\n\nThe name must begin with a capital letter and contain only letters, digits or underscores.", "OK"))
100+
{
101+
// And recall
102+
Initiate();
103+
}
104+
105+
return;
106+
}
107+
108+
// Alert on system I/O error
109+
EditorUtility.DisplayDialog("Error", $"Failed To Create Script\n\n\"{path}\"", "OK");
110+
}
111+
}
112+
}
113+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using UnityEngine;
2+
3+
public class <SCRIPT_CLASS_NAME> : ScriptableObject
4+
{
5+
/// <summary>
6+
/// Called when the ScriptableObject is started.
7+
/// </summary>
8+
public void Awake ()
9+
{
10+
}
11+
12+
/// <summary>
13+
/// Called when the ScriptableObject is loaded.
14+
/// </summary>
15+
public void OnEnable ()
16+
{
17+
}
18+
19+
/// <summary>
20+
/// Called when the ScriptableObject goes out of scope.
21+
/// </summary>
22+
public void OnDisable ()
23+
{
24+
}
25+
26+
/// <summary>
27+
/// Called when the ScriptableObject will be destroyed.
28+
/// </summary>
29+
public void OnDestroy ()
30+
{
31+
}
32+
}

0 commit comments

Comments
 (0)