1+ #if UNITY_EDITOR
2+ using System . IO ;
3+ using UnityEditor ;
4+ using UnityEngine ;
5+
6+ // For Directory, Path
7+
8+ namespace com . kwanjoong . unityuistoryboard . Editor
9+ {
10+ [ CustomEditor ( typeof ( UnityUIStoryboardSettings ) ) ]
11+ public class UnityUIStoryboardSettingsEditor : UnityEditor . Editor
12+ {
13+ #region Dependencies
14+ // External Dependencies
15+ private const string UnityScreenNavigator = "UnityScreenNavigator" ;
16+ private const string ScreenSystem = "ScreenSystem" ;
17+ private const string VContainer = "VContainer" ;
18+ private const string MessagePipe = "MessagePipe" ;
19+ private const string MessagePipeVContainer = "MessagePipe.VContainer" ;
20+ private const string UniTask = "UniTask" ;
21+ private const string UniTaskLinq = "UniTask.Linq" ;
22+ private const string UniTaskTextMeshPro = "UniTask.TextMeshPro" ;
23+
24+ // Engine Dependencies
25+ private const string TextMeshPro = "Unity.TextMeshPro" ;
26+
27+ // Internal Core dependencies
28+ private const string UseCase = "OutGame.Runtime.Core.UseCase" ;
29+ private const string Gateway = "OutGame.Runtime.Core.Gateway" ;
30+ private const string LifetimeScopeCore = "OutGame.Runtime.Core.LifetimeScope" ;
31+ private const string Repository = "OutGame.Runtime.Core.Repository" ;
32+
33+ // Internal UI dependencies
34+ private const string LifetimeScopeUI = "OutGame.Runtime.UI.LifetimeScope" ;
35+ private const string Model = "OutGame.Runtime.UI.Model" ;
36+ private const string Presentation = "OutGame.Runtime.UI.Presentation" ;
37+ private const string View = "OutGame.Runtime.UI.View" ;
38+ #endregion
39+
40+ #region Directories
41+ private const string CoreFolder = "Core" ;
42+ private const string UIFolder = "UI" ;
43+ private const string LifetimeScopeFolder = "LifetimeScope" ;
44+ private const string ModelFolder = "Model" ;
45+ private const string PresentationFolder = "Presentation" ;
46+ private const string ViewFolder = "View" ;
47+ private const string GatewayFolder = "Gateway" ;
48+ private const string RepositoryFolder = "Repository" ;
49+ private const string UseCaseFolder = "UseCase" ;
50+ private const string BuilderFolder = "Builder" ;
51+ private const string PresenterFolder = "Presenter" ;
52+ private const string OutGameFolder = "OutGame" ;
53+ private const string RuntimeFolder = "Runtime" ;
54+ #endregion
55+
56+
57+ public override void OnInspectorGUI ( )
58+ {
59+ base . OnInspectorGUI ( ) ;
60+
61+ UnityUIStoryboardSettings settings = ( UnityUIStoryboardSettings ) target ;
62+
63+ if ( GUILayout . Button ( "프로젝트 초기 설정 (폴더 & asmdef 생성)" ) )
64+ {
65+ CreateProjectStructure ( settings ) ;
66+ }
67+ }
68+
69+ /// <summary>
70+ /// 프로젝트 구조를 생성하는 메인 함수
71+ /// </summary>
72+ private void CreateProjectStructure ( UnityUIStoryboardSettings settings )
73+ {
74+ // 1) 최상위 폴더 생성 (예: Assets/SampleProject)
75+ string rootPath = Path . Combine ( settings . projectRootPath , settings . projectName ) ;
76+ CreateFolderIfNotExist ( rootPath ) ;
77+
78+ // (A) OutGame/Runtime/Core
79+ CreateFolderIfNotExist ( Path . Combine ( rootPath , OutGameFolder ) ) ;
80+ string runtimePath = Path . Combine ( rootPath , OutGameFolder , RuntimeFolder ) ;
81+ CreateFolderIfNotExist ( runtimePath ) ;
82+
83+ // 2) Core 관련 폴더
84+ string corePath = Path . Combine ( runtimePath , CoreFolder ) ;
85+ CreateFolderIfNotExist ( corePath ) ;
86+ CreateFolderIfNotExist ( Path . Combine ( corePath , GatewayFolder ) ) ;
87+ CreateFolderIfNotExist ( Path . Combine ( corePath , LifetimeScopeFolder ) ) ;
88+ CreateFolderIfNotExist ( Path . Combine ( corePath , RepositoryFolder ) ) ;
89+ CreateFolderIfNotExist ( Path . Combine ( corePath , UseCaseFolder ) ) ;
90+
91+ // 3) UI 관련 폴더
92+ string uiPath = Path . Combine ( runtimePath , UIFolder ) ;
93+ CreateFolderIfNotExist ( uiPath ) ;
94+ CreateFolderIfNotExist ( Path . Combine ( uiPath , LifetimeScopeFolder ) ) ;
95+ CreateFolderIfNotExist ( Path . Combine ( uiPath , ModelFolder ) ) ;
96+ CreateFolderIfNotExist ( Path . Combine ( uiPath , ViewFolder ) ) ;
97+
98+ string presentationPath = Path . Combine ( uiPath , PresentationFolder ) ;
99+ CreateFolderIfNotExist ( presentationPath ) ;
100+ CreateFolderIfNotExist ( Path . Combine ( presentationPath , BuilderFolder ) ) ;
101+ CreateFolderIfNotExist ( Path . Combine ( presentationPath , PresenterFolder ) ) ;
102+
103+ // 4) asmdef 생성
104+ CreateAsmdefFiles ( settings , corePath , uiPath ) ;
105+
106+ // 5) Addressable 루트 폴더 (예: Assets/Prefabs)
107+ if ( ! string . IsNullOrEmpty ( settings . addressableRootFolderName ) )
108+ {
109+ string addressableFolder = Path . Combine ( settings . projectRootPath , settings . addressableRootFolderName ) ;
110+ CreateFolderIfNotExist ( addressableFolder ) ;
111+ }
112+
113+ AssetDatabase . Refresh ( ) ;
114+ Debug . Log ( "[UIStoryboard] 프로젝트 초기 설정 완료!" ) ;
115+ }
116+
117+ /// <summary>
118+ /// 폴더가 없으면 생성
119+ /// </summary>
120+ private void CreateFolderIfNotExist ( string path )
121+ {
122+ if ( ! Directory . Exists ( path ) )
123+ {
124+ Directory . CreateDirectory ( path ) ;
125+ Debug . Log ( $ "[UIStoryboard] Created Folder: { path } ") ;
126+ }
127+ }
128+
129+ /// <summary>
130+ /// 필요한 asmdef 파일을 생성
131+ /// </summary>
132+ private void CreateAsmdefFiles ( UnityUIStoryboardSettings settings , string corePath , string uiPath )
133+ {
134+ // (1) UI 쪽 asmdef
135+ // LifetimeScope
136+ CreateAsmdef ( Path . Combine ( uiPath , LifetimeScopeFolder ) ,
137+ LifetimeScopeUI ,
138+ new string [ ]
139+ {
140+ UnityScreenNavigator ,
141+ ScreenSystem ,
142+ VContainer ,
143+ MessagePipe ,
144+ MessagePipeVContainer ,
145+ UseCase ,
146+ View ,
147+ Presentation ,
148+ }
149+ ) ;
150+
151+ // Model
152+ CreateAsmdef ( Path . Combine ( uiPath , ModelFolder ) ,
153+ Model ,
154+ new string [ ]
155+ {
156+ UniTask ,
157+ UniTaskLinq ,
158+ }
159+ ) ;
160+
161+ // Presentation (Builder, Presenter 함께)
162+ CreateAsmdef ( Path . Combine ( uiPath , PresentationFolder ) ,
163+ Presentation ,
164+ new string [ ]
165+ {
166+ UniTask ,
167+ UniTaskLinq ,
168+ UnityScreenNavigator ,
169+ ScreenSystem ,
170+ VContainer ,
171+ View ,
172+ Model ,
173+ UseCase ,
174+ }
175+ ) ;
176+
177+ // View
178+ CreateAsmdef ( Path . Combine ( uiPath , ViewFolder ) ,
179+ View ,
180+ new string [ ]
181+ {
182+ UniTask ,
183+ UniTaskLinq ,
184+ UniTaskTextMeshPro ,
185+ ScreenSystem ,
186+ TextMeshPro ,
187+ UnityScreenNavigator ,
188+ Model ,
189+ }
190+ ) ;
191+
192+ // (2) Core 쪽 asmdef
193+ // Gateway
194+ CreateAsmdef ( Path . Combine ( corePath , GatewayFolder ) ,
195+ Gateway ,
196+ new string [ ]
197+ {
198+ UniTask ,
199+ UniTaskLinq ,
200+ }
201+ ) ;
202+
203+ // LifetimeScope
204+ CreateAsmdef ( Path . Combine ( corePath , LifetimeScopeFolder ) ,
205+ LifetimeScopeCore ,
206+ new string [ ]
207+ {
208+ VContainer ,
209+ MessagePipe ,
210+ MessagePipeVContainer ,
211+ UnityScreenNavigator ,
212+ ScreenSystem ,
213+ Gateway ,
214+ Repository ,
215+ UseCase ,
216+ Presentation ,
217+ }
218+ ) ;
219+
220+ // Repository
221+ CreateAsmdef ( Path . Combine ( corePath , RepositoryFolder ) ,
222+ Repository ,
223+ new string [ ]
224+ {
225+ UniTask ,
226+ UniTaskLinq ,
227+ VContainer ,
228+ Repository ,
229+ }
230+ ) ;
231+
232+ // UseCase
233+ CreateAsmdef ( Path . Combine ( corePath , UseCaseFolder ) ,
234+ UseCase ,
235+ new string [ ]
236+ {
237+ UniTask ,
238+ UniTaskLinq ,
239+ VContainer ,
240+ Repository ,
241+ }
242+ ) ;
243+ }
244+
245+ /// <summary>
246+ /// 실제 .asmdef 파일을 작성
247+ /// </summary>
248+ private void CreateAsmdef ( string folderPath , string assemblyName , string [ ] references = null )
249+ {
250+ // asmdef 파일 경로
251+ string asmdefPath = Path . Combine ( folderPath , assemblyName + ".asmdef" ) ;
252+
253+ if ( File . Exists ( asmdefPath ) )
254+ {
255+ Debug . Log ( $ "[UIStoryboard] Asmdef already exists: { asmdefPath } ") ;
256+ return ;
257+ }
258+
259+ // 간단한 asmdef JSON 템플릿
260+ // 필요 시 "includePlatforms", "excludePlatforms", "allowUnsafeCode", "overrideReferences" 등도 넣을 수 있음
261+ AsmdefData asmdefData = new AsmdefData
262+ {
263+ name = assemblyName ,
264+ references = ( references == null ) ? new string [ ] { } : references ,
265+ autoReferenced = true
266+ } ;
267+
268+ string json = JsonUtility . ToJson ( asmdefData , true ) ;
269+ File . WriteAllText ( asmdefPath , json ) ;
270+ Debug . Log ( $ "[UIStoryboard] Created Asmdef: { asmdefPath } ") ;
271+ }
272+
273+ [ System . Serializable ]
274+ private class AsmdefData
275+ {
276+ public string name ;
277+ public string [ ] references ;
278+ public bool autoReferenced ;
279+ }
280+
281+ }
282+ }
283+ #endif
0 commit comments