Skip to content

Commit e4bfd59

Browse files
committed
feat: new SceneBuildIndex sample
1 parent f17ad7a commit e4bfd59

File tree

5 files changed

+164
-67
lines changed

5 files changed

+164
-67
lines changed
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
// NOTE: to avoid error until first source generation happens.
2-
public enum ScenesInBuild
2+
public enum SceneBuildIndex
33
{
44
NotInitialized = -9999,
55
_,
66
ToInitializeEnumValues,
77
SeeAlternativeSourceGeneratorSampleFolder,
8+
89
}

Sample/ScenesInBuild.cs.meta renamed to Sample/SceneBuildIndex.cs.meta

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sample/SceneBuildIndexGenerator.cs

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
using System.Collections.Generic;
2+
using System.IO;
3+
using System.Text;
4+
using System.Text.RegularExpressions;
5+
6+
#if UNITY_EDITOR
7+
using UnityEditor;
8+
using UnityEditor.Build;
9+
using UnityEditor.Build.Reporting;
10+
#endif
11+
12+
namespace SatorImaging.UnitySourceGenerator
13+
{
14+
// HOW TO USE: Add the following attribute to *target* class.
15+
// enum, ScenesInBuild will be generated in the target class namespace.
16+
//[UnitySourceGenerator(typeof(SceneBuildIndexEnumGenerator))]
17+
public class SceneBuildIndexGenerator
18+
19+
#if UNITY_EDITOR
20+
// NOTE: class definition is required to avoid build error due to referencing from USG attributes.
21+
// (or exclude [UnitySourceGenerator(typeof(...))] attributes from build)
22+
: IPreprocessBuildWithReport
23+
#endif
24+
25+
{
26+
27+
#if UNITY_EDITOR // USG: class definition is required to avoid build error but methods are not.
28+
#pragma warning disable IDE0051
29+
30+
static string OutputFileName() => "Enum.cs"; // -> Test.<ClassName>.g.cs
31+
32+
33+
const string ENUM_NAME = nameof(SceneBuildIndex);
34+
readonly static Regex RE_REMOVE_INVALID = new Regex(@"[^A-Za-z_0-9]+", RegexOptions.Compiled);
35+
36+
static bool Emit(USGContext context, StringBuilder sb)
37+
{
38+
// code generation
39+
sb.Append($@"
40+
namespace {context.TargetClass.Namespace}
41+
{{
42+
public enum {ENUM_NAME}
43+
{{
44+
");
45+
/* enum ================================================================ */
46+
sb.IndentLevel(2);
47+
48+
var scenePathList = new List<string>();
49+
var sceneNameList = new List<string>();
50+
for (int i = 0; i < UnityEditor.EditorBuildSettings.scenes.Length; i++)
51+
{
52+
var scene = UnityEditor.EditorBuildSettings.scenes[i]; //SceneManager.GetSceneAt(i);
53+
scenePathList.Add(scene.path);
54+
sceneNameList.Add(Path.GetFileNameWithoutExtension(scene.path));
55+
56+
var name = RE_REMOVE_INVALID.Replace(Path.GetFileNameWithoutExtension(scene.path), "_");
57+
sb.IndentLine($"{name} = {i},");
58+
}
59+
60+
//----------------------------------------------------------------------
61+
sb.Append($@"
62+
}}
63+
64+
public static class {ENUM_NAME}Resolver
65+
{{
66+
readonly static string[] Paths = new string[]
67+
{{
68+
");
69+
/* paths ================================================================ */
70+
sb.IndentLevel(3);
71+
foreach (var path in scenePathList)
72+
{
73+
sb.IndentLine($"\"{path}\",");
74+
}
75+
//----------------------------------------------------------------------
76+
sb.Append($@"
77+
}};
78+
79+
readonly static string[] Names = new string[]
80+
{{
81+
");
82+
/* names ================================================================ */
83+
sb.IndentLevel(3);
84+
foreach (var name in sceneNameList)
85+
{
86+
sb.IndentLine($"\"{name}\",");
87+
}
88+
//----------------------------------------------------------------------
89+
sb.Append($@"
90+
}};
91+
92+
public static {ENUM_NAME} GetByName(string name)
93+
{{
94+
int found = -1;
95+
for (int i = 0; i < Names.Length; i++)
96+
{{
97+
if (Names[i] == name)
98+
{{
99+
if (found < 0)
100+
found = i;
101+
else
102+
throw new System.Exception($""multiple scenes are found: '{{name}}'"");
103+
}}
104+
}}
105+
if (found < 0)
106+
throw new System.Exception($""scene file '{{name}}' is not registered in build settings."");
107+
return ({ENUM_NAME})found;
108+
}}
109+
110+
public static System.Collections.Generic.List<{ENUM_NAME}> GetListByPrefix(string fileNamePrefix)
111+
{{
112+
var ret = new System.Collections.Generic.List<{ENUM_NAME}>(capacity: Names.Length);
113+
for (int i = 0; i < Names.Length; i++)
114+
{{
115+
if (Names[i].StartsWith(fileNamePrefix, System.StringComparison.Ordinal))
116+
{{
117+
ret.Add(({ENUM_NAME})i);
118+
}}
119+
}}
120+
return ret;
121+
}}
122+
123+
///<summary>Path must be started with 'Assets/'.</summary>
124+
public static System.Collections.Generic.List<{ENUM_NAME}> GetListByPath(string assetsPath)
125+
{{
126+
var ret = new System.Collections.Generic.List<{ENUM_NAME}>(capacity: Paths.Length);
127+
for (int i = 0; i < Paths.Length; i++)
128+
{{
129+
if (Paths[i].StartsWith(assetsPath, System.StringComparison.Ordinal))
130+
{{
131+
ret.Add(({ENUM_NAME})i);
132+
}}
133+
}}
134+
return ret;
135+
}}
136+
}}
137+
}}
138+
");
139+
return true;
140+
}
141+
142+
143+
/* events ================================================================ */
144+
145+
public int callbackOrder => 0;
146+
public void OnPreprocessBuild(BuildReport report) => ForceUpdate();
147+
148+
static void ForceUpdate() => USGUtility.ForceGenerateByType(typeof(SceneBuildIndexGenerator), false);
149+
150+
[InitializeOnLoadMethod]
151+
static void RegisterEvent()
152+
{
153+
EditorBuildSettings.sceneListChanged -= ForceUpdate;
154+
EditorBuildSettings.sceneListChanged += ForceUpdate;
155+
}
156+
157+
158+
#pragma warning restore IDE0051
159+
#endif
160+
}
161+
}

Sample/ScenesInBuildEnumGenerator.cs

Lines changed: 0 additions & 65 deletions
This file was deleted.

0 commit comments

Comments
 (0)