Skip to content

Commit 225bbb3

Browse files
committed
Add editor window for auto creation of new gameevents
1 parent 952d2e8 commit 225bbb3

File tree

3 files changed

+290
-0
lines changed

3 files changed

+290
-0
lines changed

Packages/SOGameEvents/Editor/Window.meta

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq;
4+
using UnityEditor;
5+
using UnityEngine;
6+
7+
namespace RaCoding.GameEvents
8+
{
9+
public class GameEventWindow : EditorWindow
10+
{
11+
private static readonly string TAB = " ";
12+
private static readonly string PACKAGE_NAMESPACE = "RaCoding.GameEvents";
13+
private static readonly string UNITYEVENT_CLASS_SUFFIX = "UnityEvent";
14+
private static readonly string GAMEEVENT_CLASS_SUFFIX = "GameEvent";
15+
private static readonly string GAMEEVENTLISTENER_CLASS_SUFFIX = "GameEventListener";
16+
private static readonly string COMPONENTGAMEEVENTLISTENER_CLASS_SUFFIX = "ComponentGameEventListener";
17+
private static readonly string GAMEEVENTEDITOR_CLASS_SUFFIX = "GameEventEditor";
18+
19+
private string _newNamespace = "RaCoding.GameEvents";
20+
private string _newType = "Sprite";
21+
private string _newTypeNamespace = "UnityEngine";
22+
23+
private bool _groupEnabled;
24+
private bool _overrideExistingFiles = false;
25+
26+
[MenuItem("Window/RaCoding/SO Game Event Creator")]
27+
static void Init()
28+
{
29+
// Get existing open window or if none, make a new one:
30+
var window = (GameEventWindow)EditorWindow.GetWindow(typeof(GameEventWindow));
31+
window.Show();
32+
}
33+
34+
void OnGUI()
35+
{
36+
GUILayout.Label("Base Settings", EditorStyles.boldLabel);
37+
_newNamespace = EditorGUILayout.TextField("Namespace", _newNamespace);
38+
_newType = EditorGUILayout.TextField("Type", _newType);
39+
_newTypeNamespace = EditorGUILayout.TextField("Type Namespace", _newTypeNamespace);
40+
41+
_groupEnabled = EditorGUILayout.BeginToggleGroup("Optional Settings", _groupEnabled);
42+
_overrideExistingFiles = EditorGUILayout.Toggle("Override existing files", _overrideExistingFiles);
43+
EditorGUILayout.EndToggleGroup();
44+
45+
GUILayout.Space(10);
46+
47+
if (GUILayout.Button("Generate"))
48+
{
49+
GenerateScripts();
50+
}
51+
}
52+
53+
private string GenerateClassNames(string suffix)
54+
{
55+
if (string.IsNullOrEmpty(_newType))
56+
{
57+
throw new ArgumentException("Type can not be null or empty!");
58+
}
59+
return _newType.First().ToString().ToUpper() + _newType[1..] + suffix;
60+
}
61+
62+
private string GenerateVariableNamesPrefix()
63+
{
64+
if (string.IsNullOrEmpty(_newType))
65+
{
66+
throw new ArgumentException("Type can not be null or empty!");
67+
}
68+
return _newType.First().ToString().ToLower() + _newType[1..];
69+
}
70+
71+
private string GenerateClassPath(string className)
72+
{
73+
return "Assets/" + className + ".cs";
74+
}
75+
76+
private void GenerateScripts()
77+
{
78+
Debug.Log("Generating scripts...");
79+
80+
// class names
81+
string unityEventClassName = GenerateClassNames(UNITYEVENT_CLASS_SUFFIX);
82+
string gameeventClassName = GenerateClassNames(GAMEEVENT_CLASS_SUFFIX);
83+
string eventListenerClassName = GenerateClassNames(GAMEEVENTLISTENER_CLASS_SUFFIX);
84+
string componentEventListenerClassName = GenerateClassNames(COMPONENTGAMEEVENTLISTENER_CLASS_SUFFIX);
85+
string gameeventEditorClassName = GenerateClassNames(GAMEEVENTEDITOR_CLASS_SUFFIX);
86+
87+
// class paths
88+
string unityEventClassPath = GenerateClassPath(unityEventClassName);
89+
string gameeventClassPath = GenerateClassPath(gameeventClassName);
90+
string eventListenerClassPath = GenerateClassPath(eventListenerClassName);
91+
string componentEventListenerClassPath = GenerateClassPath(componentEventListenerClassName);
92+
string gameeventEditorClassPath = GenerateClassPath(gameeventEditorClassName);
93+
94+
if (CheckFilesGeneration(new string[] {unityEventClassPath, gameeventClassPath, eventListenerClassPath,
95+
componentEventListenerClassPath, gameeventEditorClassPath}))
96+
{
97+
GenerateUnityEvent(unityEventClassName, unityEventClassPath);
98+
GenerateGameEvent(gameeventClassName, gameeventClassPath);
99+
GenerateGameEventListener(eventListenerClassName, GenerateVariableNamesPrefix(),
100+
unityEventClassName, gameeventClassName, eventListenerClassPath);
101+
GenerateComponentGameEventListener(componentEventListenerClassName,
102+
eventListenerClassName, componentEventListenerClassPath);
103+
GenerateGameEventEditor(gameeventEditorClassName, gameeventEditorClassPath);
104+
}
105+
else
106+
{
107+
Debug.LogError("Could not generate files because they already exist!");
108+
}
109+
110+
AssetDatabase.Refresh();
111+
}
112+
113+
// returns true if files can be generated
114+
private bool CheckFilesGeneration(string[] classPath)
115+
{
116+
bool doesFileExist;
117+
for (int i = 0; i < classPath.Length; i++)
118+
{
119+
doesFileExist = File.Exists(classPath[i]);
120+
if (doesFileExist == true && _overrideExistingFiles == false)
121+
{
122+
return false;
123+
}
124+
}
125+
return true;
126+
}
127+
128+
private void GenerateUnityEvent(string className, string classPath)
129+
{
130+
Debug.Log("Writing UnityEvent classfile...");
131+
132+
using (StreamWriter outfile = new(classPath))
133+
{
134+
outfile.WriteLine("using UnityEngine.Events;");
135+
if (string.IsNullOrEmpty(_newTypeNamespace) == false)
136+
{
137+
outfile.WriteLine("using " + _newTypeNamespace + ";");
138+
}
139+
outfile.WriteLine("");
140+
outfile.WriteLine("namespace " + _newNamespace);
141+
outfile.WriteLine("{");
142+
outfile.WriteLine(TAB + "[System.Serializable]");
143+
outfile.WriteLine(TAB + "public class " + className + " : UnityEvent<" + _newType + "> {}");
144+
outfile.WriteLine("}");
145+
}
146+
}
147+
148+
private void GenerateGameEvent(string className, string classPath)
149+
{
150+
Debug.Log("Writing GameEvent classfile...");
151+
152+
using (StreamWriter outfile = new(classPath))
153+
{
154+
outfile.WriteLine("using UnityEngine;");
155+
if (string.IsNullOrEmpty(_newTypeNamespace) == false
156+
&& _newTypeNamespace != "UnityEngine")
157+
{
158+
outfile.WriteLine("using " + _newTypeNamespace + ";");
159+
}
160+
if (_newNamespace != PACKAGE_NAMESPACE)
161+
{
162+
outfile.WriteLine("using RaCoding.GameEvents;");
163+
}
164+
outfile.WriteLine("");
165+
outfile.WriteLine("namespace " + _newNamespace);
166+
outfile.WriteLine("{");
167+
outfile.WriteLine(TAB + "[CreateAssetMenu(fileName = \"" + className + "\"," +
168+
" menuName = \"RaCoding/GameEvent/Create new " + _newType + " game event\")]");
169+
outfile.WriteLine(TAB + "public class " + className + " : GameEvent<" + _newType + "> {}");
170+
outfile.WriteLine("}");
171+
}
172+
}
173+
174+
private void GenerateGameEventListener(string className, string variableNamePrefix,
175+
string unityeventName, string gameeventName, string classPath)
176+
{
177+
Debug.Log("Writing GameEventListener classfile...");
178+
179+
using (StreamWriter outfile = new(classPath))
180+
{
181+
outfile.WriteLine("using UnityEngine;");
182+
outfile.WriteLine("using UnityEngine.Events;");
183+
if (string.IsNullOrEmpty(_newTypeNamespace) == false
184+
&& _newTypeNamespace != "UnityEngine")
185+
{
186+
outfile.WriteLine("using " + _newTypeNamespace + ";");
187+
}
188+
if (_newNamespace != PACKAGE_NAMESPACE)
189+
{
190+
outfile.WriteLine("using RaCoding.GameEvents;");
191+
}
192+
outfile.WriteLine("");
193+
outfile.WriteLine("namespace " + _newNamespace);
194+
outfile.WriteLine("{");
195+
outfile.WriteLine(TAB + "[System.Serializable]");
196+
outfile.WriteLine(TAB + "public class " + className + " : GameEventListener<" + _newType + ">");
197+
outfile.WriteLine(TAB + "{");
198+
outfile.WriteLine(TAB + TAB + "public " + className + "() : base() {}");
199+
outfile.WriteLine("");
200+
outfile.WriteLine(TAB + TAB + "public " + className + "(IRegisterListener registerListener, GameObject gameObject) : base(registerListener, gameObject) {}");
201+
outfile.WriteLine("");
202+
outfile.WriteLine(TAB + TAB + "[SerializeField] private " + gameeventName + " " + variableNamePrefix + "Event;");
203+
outfile.WriteLine(TAB + TAB + "[SerializeField] private " + unityeventName + " " + variableNamePrefix + "Response;");
204+
outfile.WriteLine("");
205+
outfile.WriteLine(TAB + TAB + "public override GameEvent<" + _newType + "> Event => " + variableNamePrefix + "Event; ");
206+
outfile.WriteLine(TAB + TAB + "public override UnityEvent<" + _newType + "> Response => " + variableNamePrefix + "Response; ");
207+
outfile.WriteLine(TAB + "}");
208+
outfile.WriteLine("}");
209+
}
210+
}
211+
212+
private void GenerateComponentGameEventListener(string className, string eventListenerClassName, string classPath)
213+
{
214+
Debug.Log("Writing ComponentGameEventListener classfile...");
215+
216+
using (StreamWriter outfile = new(classPath))
217+
{
218+
outfile.WriteLine("using UnityEngine;");
219+
if (string.IsNullOrEmpty(_newTypeNamespace) == false
220+
&& _newTypeNamespace != "UnityEngine")
221+
{
222+
outfile.WriteLine("using " + _newTypeNamespace + ";");
223+
}
224+
if (_newNamespace != PACKAGE_NAMESPACE)
225+
{
226+
outfile.WriteLine("using RaCoding.GameEvents;");
227+
}
228+
outfile.WriteLine("");
229+
outfile.WriteLine("namespace " + _newNamespace);
230+
outfile.WriteLine("{");
231+
outfile.WriteLine(TAB + "[AddComponentMenu(\"RaCoding/GameEvents/" + eventListenerClassName + "\")]");
232+
outfile.WriteLine(TAB + "public class " + className + " : ComponentGameEventListener<" + eventListenerClassName + ", " + _newType + "> {}");
233+
outfile.WriteLine("}");
234+
}
235+
}
236+
237+
private void GenerateGameEventEditor(string className, string classPath)
238+
{
239+
Debug.Log("Writing GameEventEditor classfile...");
240+
241+
using (StreamWriter outfile = new(classPath))
242+
{
243+
outfile.WriteLine("using UnityEditor;");
244+
outfile.WriteLine("using UnityEngine;");
245+
if (string.IsNullOrEmpty(_newTypeNamespace) == false
246+
&& _newTypeNamespace != "UnityEngine")
247+
{
248+
outfile.WriteLine("using " + _newTypeNamespace + ";");
249+
}
250+
if (_newNamespace != PACKAGE_NAMESPACE)
251+
{
252+
outfile.WriteLine("using RaCoding.GameEvents;");
253+
}
254+
outfile.WriteLine("");
255+
outfile.WriteLine("namespace " + _newNamespace);
256+
outfile.WriteLine("{");
257+
outfile.WriteLine(TAB + "[CustomEditor(typeof(GameEvent<" + _newType + ">), editorForChildClasses: true)]");
258+
outfile.WriteLine(TAB + "public class " + className + " : GameEventEditor<" + _newType + ">");
259+
outfile.WriteLine(TAB + "{");
260+
outfile.WriteLine(TAB + TAB + "public Object source;");
261+
outfile.WriteLine("");
262+
outfile.WriteLine(TAB + TAB + "protected override " + _newType + " GetValue()");
263+
outfile.WriteLine(TAB + TAB + "{");
264+
outfile.WriteLine(TAB + TAB + TAB + "return EditorGUILayout.ObjectField(source, typeof(Object), true) as " + _newType + ";");
265+
outfile.WriteLine(TAB + TAB + "}");
266+
outfile.WriteLine(TAB + "}");
267+
outfile.WriteLine("}");
268+
}
269+
}
270+
}
271+
}

Packages/SOGameEvents/Editor/Window/GameEventWindow.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)