464 lines
23 KiB
C#
464 lines
23 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using UnityEditor;
|
|
using UnityEditor.AddressableAssets;
|
|
using UnityEditor.AddressableAssets.Settings;
|
|
using UnityEditor.Build;
|
|
using UnityEditor.Build.Reporting;
|
|
using UnityEditor.Callbacks;
|
|
#if UNITY_IOS
|
|
using UnityEditor.iOS.Xcode;
|
|
using UnityEditor.iOS.Xcode.Extensions;
|
|
#endif
|
|
using UnityEngine;
|
|
|
|
/// <summary>
|
|
/// WL(What's your level?) 자동 빌드 메뉴 — 수상한 잡화점 AutoBuild 구조를 WL 에 맞게 이식 (2026-10-11 #836 · PD 지시).
|
|
///
|
|
/// 메뉴 (Unity 상단 AutoBuild/)
|
|
/// · Build APK with KeyStore = 테스트 APK. bundleVersion 은 현재값(9.9.9 = dev PlayFab · TitleInfo 분기) 유지 · FGB_LIVE 기본 OFF
|
|
/// · Build Test AAB = 테스트 AAB(Play 내부 테스트 트랙용). 버전·심볼은 다이얼로그
|
|
/// · Build Live AAB = 출시 AAB. 버전·버전코드 다이얼로그(기본 = 마지막+1) · FGB_LIVE 기본 ON · 네이티브 symbols.zip 생성
|
|
/// · Addressables Build Only = 플레이어 빌드 없이 Addressables 콘텐츠만 빌드(WL_Local 프로필)
|
|
/// · Set_AndroidKeyStore / Open Build Folder
|
|
///
|
|
/// 공통 절차 = 키스토어 지정 → 심볼(FGB_LIVE 만 관리 · 기존 UNITY_PIPELINE_URP 등 보존) → VersionCode.txt → Addressables 콘텐츠 빌드 → BuildPlayer → 심볼·프로필 복원.
|
|
/// Addressables: 활성 프로필은 CCD(이전 개발자 버킷 · 그룹 20 개가 Remote 경로)라 그대로 빌드하면 기기에서 원격 로드가 실패한다.
|
|
/// → 빌드 시에만 「WL_Local」 프로필(Remote.* = Local.* 경로 · 없으면 자동 생성)로 바꿔 전 그룹을 APK/AAB 안(StreamingAssets)에 넣고, 끝나면 원래 프로필로 복원.
|
|
/// 버전 권위 = Assets/Editor/BuildVersionBackup.txt (잡화점과 동일 · ProjectSettings 가 다른 커밋으로 덮여도 마지막 빌드값 복원).
|
|
/// CLI(대화 상자 없이) = AutoBuild.Build_TestAPK_NoDialog() · AutoBuild.Build_LiveAAB_NoDialog("1.0.0", 3)
|
|
/// </summary>
|
|
public static class AutoBuild
|
|
{
|
|
// ── 산출물 경로 (프로젝트 루트 기준 · AndroidData/ 는 git 추적, *.apk·*.aab 는 .gitignore) ──
|
|
const string OutDir = "AndroidData";
|
|
const string PathTestApk = OutDir + "/WL_Test_";
|
|
const string PathTestAab = OutDir + "/WL_TestAAB_";
|
|
const string PathLiveAab = OutDir + "/WL_Live_";
|
|
const string VersionCodeTxt = "Assets/Resources/VersionCode.txt"; // 런타임 ServerInfo.VersionCode (TitleInfo 가 읽음)
|
|
const string BuildVersionBackupPath = "Assets/Editor/BuildVersionBackup.txt"; // 마지막 빌드 버전/버전코드 권위(팀 공유)
|
|
const string AddrLocalProfile = "WL_Local";
|
|
|
|
// 이 클래스가 관리하는 심볼만 넣고 뺀다. 나머지(UNITY_PIPELINE_URP·MOREMOUNTAINS_* 등)는 그대로 보존.
|
|
const string SymLive = "FGB_LIVE";
|
|
|
|
static int s_ManualVersionCode = -1; // 다이얼로그 입력 버전코드 (-1 = 미입력 → 현재값 유지)
|
|
static bool s_Live; // FGB_LIVE 주입 여부
|
|
static bool s_DevBuild; // BuildOptions.Development
|
|
static string s_SavedDefines; // 빌드 전 Scripting Define 원문 (복원용)
|
|
static string s_SavedAddrProfile; // 빌드 전 Addressables 활성 프로필 id (복원용)
|
|
static string s_SavedBundleVersion; // 빌드 전 bundleVersion (복원용)
|
|
|
|
// ───────────────────────── 버전 백업 (잡화점 동일) ─────────────────────────
|
|
static void Load_VersionBackup(ref string ver, ref int code)
|
|
{
|
|
if (!File.Exists(BuildVersionBackupPath)) return;
|
|
foreach (var raw in File.ReadAllLines(BuildVersionBackupPath))
|
|
{
|
|
var line = raw.Trim();
|
|
if (line.StartsWith("version=")) { var v = line.Substring("version=".Length).Trim(); if (!string.IsNullOrEmpty(v)) ver = v; }
|
|
else if (line.StartsWith("versionCode=") && int.TryParse(line.Substring("versionCode=".Length).Trim(), out var c)) code = c;
|
|
}
|
|
}
|
|
static void Save_VersionBackup(string ver, int code)
|
|
{
|
|
File.WriteAllText(BuildVersionBackupPath, $"version={ver}\nversionCode={code}\n");
|
|
AssetDatabase.ImportAsset(BuildVersionBackupPath);
|
|
}
|
|
/// <summary> 마지막 빌드 버전/코드 — 백업 txt 가 권위. 백업이 없을 때(최초 1회)만 PlayerSettings. </summary>
|
|
static void Get_LastVersion(out string ver, out int code)
|
|
{
|
|
ver = PlayerSettings.bundleVersion;
|
|
code = PlayerSettings.Android.bundleVersionCode;
|
|
Load_VersionBackup(ref ver, ref code);
|
|
}
|
|
static void Apply_ManualVersionCode_And_Backup()
|
|
{
|
|
if (s_ManualVersionCode < 0) return;
|
|
PlayerSettings.Android.bundleVersionCode = s_ManualVersionCode;
|
|
Save_VersionBackup(PlayerSettings.bundleVersion, s_ManualVersionCode);
|
|
s_ManualVersionCode = -1;
|
|
}
|
|
|
|
// ───────────────────────── 공통 ─────────────────────────
|
|
[MenuItem("AutoBuild/Set_AndroidKeyStore")]
|
|
static void Set_AndroidKeyStore()
|
|
{
|
|
PlayerSettings.Android.useCustomKeystore = true;
|
|
PlayerSettings.Android.keystoreName = OutDir + "/himminji.keystore";
|
|
PlayerSettings.Android.keyaliasName = "nerdnavis";
|
|
PlayerSettings.Android.keystorePass = PlayerSettings.Android.keyaliasPass = "himminji3#";
|
|
}
|
|
|
|
/// <summary> FGB_LIVE 만 넣고/빼고 나머지 심볼은 보존. 원문은 s_SavedDefines 에 보관 → Common_End 에서 복원. </summary>
|
|
static void Set_LiveSymbol(bool live)
|
|
{
|
|
var nbt = NamedBuildTarget.Android;
|
|
s_SavedDefines = PlayerSettings.GetScriptingDefineSymbols(nbt);
|
|
var list = s_SavedDefines.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()).Where(s => s != SymLive).ToList();
|
|
if (live) list.Add(SymLive);
|
|
PlayerSettings.SetScriptingDefineSymbols(nbt, string.Join(";", list));
|
|
}
|
|
static void Restore_Symbols()
|
|
{
|
|
if (s_SavedDefines == null) return;
|
|
PlayerSettings.SetScriptingDefineSymbols(NamedBuildTarget.Android, s_SavedDefines);
|
|
s_SavedDefines = null;
|
|
}
|
|
|
|
static void Common()
|
|
{
|
|
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android, BuildTarget.Android);
|
|
PlayerSettings.Android.splitApplicationBinary = false;
|
|
PlayerSettings.Android.targetArchitectures = AndroidArchitecture.ARMv7 | AndroidArchitecture.ARM64;
|
|
Set_AndroidKeyStore();
|
|
Set_LiveSymbol(s_Live);
|
|
Apply_ManualVersionCode_And_Backup();
|
|
File.WriteAllText(VersionCodeTxt, PlayerSettings.Android.bundleVersionCode.ToString());
|
|
AssetDatabase.ImportAsset(VersionCodeTxt);
|
|
}
|
|
/// <summary> 빌드 버전 지정. 원래 값은 s_SavedBundleVersion 에 보관 → Common_End 에서 복원 (에디터는 9.9.9 = dev 서버 유지 · 1.0.0 등이 남으면 Play 시 업데이트 팝업). </summary>
|
|
static void Set_BuildVersion(string ver)
|
|
{
|
|
s_SavedBundleVersion = PlayerSettings.bundleVersion;
|
|
PlayerSettings.bundleVersion = ver;
|
|
}
|
|
static void Restore_BuildVersion()
|
|
{
|
|
if (s_SavedBundleVersion == null) return;
|
|
PlayerSettings.bundleVersion = s_SavedBundleVersion;
|
|
s_SavedBundleVersion = null;
|
|
}
|
|
|
|
static void Common_End()
|
|
{
|
|
Restore_BuildVersion();
|
|
Restore_Symbols();
|
|
Restore_AddressablesProfile();
|
|
AssetDatabase.SaveAssets();
|
|
}
|
|
|
|
/// <summary> 네이티브 디버그 심볼(symbols.zip) — 라이브 AAB 만 ON (Play Console·Cloud Diagnostics 역심볼화). IL2CPP 스택은 파일·라인까지 상시. </summary>
|
|
static void Set_AndroidSymbols(bool on)
|
|
{
|
|
UnityEditor.Android.UserBuildSettings.DebugSymbols.level = on ? Unity.Android.Types.DebugSymbolLevel.Full : Unity.Android.Types.DebugSymbolLevel.None;
|
|
UnityEditor.Android.UserBuildSettings.DebugSymbols.format = Unity.Android.Types.DebugSymbolFormat.Zip;
|
|
PlayerSettings.SetIl2CppStacktraceInformation(NamedBuildTarget.Android, Il2CppStacktraceInformation.MethodFileLineNumber);
|
|
}
|
|
|
|
// ───────────────────────── Addressables ─────────────────────────
|
|
/// <summary> WL_Local 프로필(Remote.* 를 Local.* 경로로) 활성화 → 전 그룹이 StreamingAssets 로 들어간다. 없으면 Default 복제로 생성. </summary>
|
|
static bool Activate_AddressablesLocalProfile()
|
|
{
|
|
var settings = AddressableAssetSettingsDefaultObject.Settings;
|
|
if (settings == null) { Debug.LogError("[AutoBuild] AddressableAssetSettings 없음"); return false; }
|
|
var ps = settings.profileSettings;
|
|
string id = ps.GetProfileId(AddrLocalProfile);
|
|
if (string.IsNullOrEmpty(id))
|
|
{
|
|
id = ps.AddProfile(AddrLocalProfile, ps.GetProfileId("Default"));
|
|
ps.SetValue(id, AddressableAssetSettings.kRemoteBuildPath, ps.GetValueByName(id, AddressableAssetSettings.kLocalBuildPath));
|
|
ps.SetValue(id, AddressableAssetSettings.kRemoteLoadPath, ps.GetValueByName(id, AddressableAssetSettings.kLocalLoadPath));
|
|
EditorUtility.SetDirty(settings);
|
|
Debug.Log($"[AutoBuild] Addressables 프로필 '{AddrLocalProfile}' 생성 (Remote = Local 경로)");
|
|
}
|
|
s_SavedAddrProfile = settings.activeProfileId;
|
|
settings.activeProfileId = id;
|
|
return true;
|
|
}
|
|
static void Restore_AddressablesProfile()
|
|
{
|
|
if (string.IsNullOrEmpty(s_SavedAddrProfile)) return;
|
|
var settings = AddressableAssetSettingsDefaultObject.Settings;
|
|
if (settings != null) settings.activeProfileId = s_SavedAddrProfile;
|
|
s_SavedAddrProfile = null;
|
|
}
|
|
|
|
/// <summary> 앱 빌드 직전 Addressables 콘텐츠 빌드(WL_Local). SBP 캐시 비우고 풀빌드 → stale 번들 차단. 실패 시 false. </summary>
|
|
static bool Build_Addressables_BeforePlayer()
|
|
{
|
|
if (!Activate_AddressablesLocalProfile()) return false;
|
|
UnityEditor.Build.Pipeline.Utilities.BuildCache.PurgeCache(false);
|
|
AddressableAssetSettings.BuildPlayerContent(out var result);
|
|
if (result != null && !string.IsNullOrEmpty(result.Error))
|
|
{
|
|
Debug.LogError($"[AutoBuild] Addressables 콘텐츠 빌드 실패 — 앱 빌드 중단: {result.Error}");
|
|
return false;
|
|
}
|
|
Debug.Log($"[AutoBuild] Addressables 콘텐츠 빌드 완료 ({AddrLocalProfile} · {result?.Duration:F0}s · {result?.OutputPath})");
|
|
return true;
|
|
}
|
|
|
|
[MenuItem("AutoBuild/Addressables Build Only (WL_Local)")]
|
|
static void Build_AddressablesOnly()
|
|
{
|
|
try { Build_Addressables_BeforePlayer(); }
|
|
finally { Restore_AddressablesProfile(); AssetDatabase.SaveAssets(); }
|
|
}
|
|
|
|
// ───────────────────────── 플레이어 빌드 ─────────────────────────
|
|
static string[] EnabledScenes() => EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray();
|
|
|
|
static bool BuildStart(string path, bool appBundle)
|
|
{
|
|
Directory.CreateDirectory(OutDir);
|
|
EditorUserBuildSettings.buildAppBundle = appBundle;
|
|
var opts = new BuildPlayerOptions
|
|
{
|
|
scenes = EnabledScenes(),
|
|
locationPathName = path,
|
|
target = BuildTarget.Android,
|
|
targetGroup = BuildTargetGroup.Android,
|
|
options = s_DevBuild ? (BuildOptions.Development | BuildOptions.AllowDebugging) : BuildOptions.None,
|
|
};
|
|
var report = BuildPipeline.BuildPlayer(opts);
|
|
var s = report.summary;
|
|
if (s.result == BuildResult.Succeeded)
|
|
{
|
|
Debug.Log($"[AutoBuild] 빌드 성공 {path} · {s.totalSize / 1048576f:F1} MB · {s.totalTime.TotalMinutes:F1} 분 · 경고 {s.totalWarnings}");
|
|
if (!Application.isBatchMode) Show_BuildFolder();
|
|
return true;
|
|
}
|
|
Debug.LogError($"[AutoBuild] 빌드 실패 {path} · result={s.result} · errors={s.totalErrors}");
|
|
return false;
|
|
}
|
|
|
|
[MenuItem("AutoBuild/Open Build Folder")]
|
|
static void Show_BuildFolder()
|
|
{
|
|
Directory.CreateDirectory(OutDir);
|
|
System.Diagnostics.Process.Start(Path.GetFullPath(OutDir));
|
|
}
|
|
|
|
static string OutName(string prefix, string ext) => $"{prefix}{PlayerSettings.bundleVersion}_({PlayerSettings.Android.bundleVersionCode}){ext}";
|
|
|
|
/// <summary> 빌드 파이프라인 1회 실행. 다이얼로그 뒤 호출 — s_Live/s_DevBuild/s_ManualVersionCode 가 이미 정해진 상태. </summary>
|
|
static bool Run(string prefix, string ext, bool appBundle, bool symbols)
|
|
{
|
|
try
|
|
{
|
|
Common();
|
|
Set_AndroidSymbols(symbols);
|
|
if (!Build_Addressables_BeforePlayer()) return false;
|
|
return BuildStart(OutName(prefix, ext), appBundle);
|
|
}
|
|
finally
|
|
{
|
|
Common_End();
|
|
}
|
|
}
|
|
|
|
// ── 테스트 APK: bundleVersion 은 그대로(9.9.9 = dev 서버) · 버전코드 기본 = 마지막+1 ──
|
|
[MenuItem("AutoBuild/Build APK with KeyStore")]
|
|
static void Build_APK_with_KeyStore()
|
|
{
|
|
Get_LastVersion(out string ver, out int code);
|
|
code += 1;
|
|
if (!Application.isBatchMode)
|
|
{
|
|
if (!BuildVersionDialog.Show($"Test APK 빌드 (마지막 v{ver} / code {code - 1}).\n9.9.9 = dev PlayFab(TitleInfo 분기) · versionCode 기본 = 마지막+1.",
|
|
ref ver, ref code, live: false, out s_Live, out s_DevBuild))
|
|
return;
|
|
}
|
|
else { s_Live = false; s_DevBuild = false; }
|
|
Set_BuildVersion(ver);
|
|
s_ManualVersionCode = code;
|
|
Run(PathTestApk, ".apk", appBundle: false, symbols: false);
|
|
}
|
|
|
|
// ── 테스트 AAB: Play 내부 테스트 트랙용 (서명·버전은 라이브와 같은 흐름 · symbols 생성) ──
|
|
[MenuItem("AutoBuild/Build Test AAB")]
|
|
static void Build_Test_AAB()
|
|
{
|
|
Get_LastVersion(out string ver, out int code);
|
|
code += 1;
|
|
if (!Application.isBatchMode)
|
|
{
|
|
if (!BuildVersionDialog.Show($"Test AAB 빌드 (마지막 v{ver} / code {code - 1}).\nPlay 내부 테스트 트랙용 · versionCode 기본 = 마지막+1.",
|
|
ref ver, ref code, live: false, out s_Live, out s_DevBuild))
|
|
return;
|
|
}
|
|
else { s_Live = false; s_DevBuild = false; }
|
|
Set_BuildVersion(ver);
|
|
s_ManualVersionCode = code;
|
|
Run(PathTestAab, ".aab", appBundle: true, symbols: true);
|
|
}
|
|
|
|
// ── 라이브 AAB: 출시. 버전은 9.9.9 가 아니어야 라이브 서버(TitleInfo) · FGB_LIVE 기본 ON ──
|
|
[MenuItem("AutoBuild/Build Live AAB")]
|
|
static void Build_AAB()
|
|
{
|
|
Get_LastVersion(out string ver, out int code);
|
|
code += 1;
|
|
if (!Application.isBatchMode)
|
|
{
|
|
if (!BuildVersionDialog.Show($"Live AAB 빌드 (마지막 v{ver} / code {code - 1}).\n출시 버전은 9.9.9 가 아니어야 라이브 서버로 붙습니다 · versionCode 기본 = 마지막+1.",
|
|
ref ver, ref code, live: true, out s_Live, out s_DevBuild))
|
|
return;
|
|
}
|
|
else { s_Live = true; s_DevBuild = false; }
|
|
if (ver == "9.9.9" && !Application.isBatchMode
|
|
&& !EditorUtility.DisplayDialog("버전 확인", "bundleVersion 이 9.9.9(dev 서버)입니다. 출시 AAB 로 계속할까요?", "계속", "중단"))
|
|
return;
|
|
Set_BuildVersion(ver);
|
|
s_ManualVersionCode = code;
|
|
Run(PathLiveAab, ".aab", appBundle: true, symbols: true);
|
|
}
|
|
|
|
// ───────────────────────── CLI 진입점 (대화 상자 없음 · unity command eval 에서 호출) ─────────────────────────
|
|
public static bool Build_TestAPK_NoDialog(bool devBuild = false)
|
|
{
|
|
Get_LastVersion(out string ver, out int code);
|
|
s_Live = false; s_DevBuild = devBuild;
|
|
Set_BuildVersion(ver);
|
|
s_ManualVersionCode = code + 1;
|
|
return Run(PathTestApk, ".apk", appBundle: false, symbols: false);
|
|
}
|
|
public static bool Build_LiveAAB_NoDialog(string version, int versionCode)
|
|
{
|
|
s_Live = true; s_DevBuild = false;
|
|
Set_BuildVersion(version);
|
|
s_ManualVersionCode = versionCode;
|
|
return Run(PathLiveAab, ".aab", appBundle: true, symbols: true);
|
|
}
|
|
|
|
#if UNITY_IOS
|
|
// iOS 는 론칭 단계에서 PD 지시로 정비 (Facebook SDK 참조 제거 · 최소 유지)
|
|
[MenuItem("AutoBuild/IOS Xcode")]
|
|
static void Build_IOS_Xcode()
|
|
{
|
|
PlayerSettings.iOS.buildNumber = (int.Parse(PlayerSettings.iOS.buildNumber) + 1).ToString();
|
|
File.WriteAllText(VersionCodeTxt, PlayerSettings.iOS.buildNumber);
|
|
PlayerSettings.iOS.appleEnableAutomaticSigning = true;
|
|
PlayerSettings.iOS.sdkVersion = iOSSdkVersion.DeviceSDK;
|
|
EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.iOS, BuildTarget.iOS);
|
|
var opts = new BuildPlayerOptions { scenes = EnabledScenes(), locationPathName = "IOSData/IOSXcode_" + PlayerSettings.bundleVersion + "_" + PlayerSettings.iOS.buildNumber, target = BuildTarget.iOS, targetGroup = BuildTargetGroup.iOS };
|
|
BuildPipeline.BuildPlayer(opts);
|
|
}
|
|
|
|
[PostProcessBuild(1)]
|
|
static void OnPostProcessBuild(BuildTarget buildTarget, string path)
|
|
{
|
|
if (buildTarget != BuildTarget.iOS) return;
|
|
var plistPath = Path.Combine(path, "Info.plist");
|
|
var plist = new PlistDocument();
|
|
plist.ReadFromFile(plistPath);
|
|
plist.root.SetBoolean("ITSAppUsesNonExemptEncryption", false);
|
|
plist.WriteToFile(plistPath);
|
|
|
|
string pbxPath = PBXProject.GetPBXProjectPath(path);
|
|
var proj = new PBXProject();
|
|
proj.ReadFromFile(pbxPath);
|
|
var guid = proj.GetUnityMainTargetGuid();
|
|
var unityframework = proj.GetUnityFrameworkTargetGuid();
|
|
proj.SetBuildProperty(guid, "ENABLE_BITCODE", "NO");
|
|
proj.SetBuildProperty(unityframework, "ENABLE_BITCODE", "NO");
|
|
proj.WriteToFile(pbxPath);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/// <summary> 빌드 메뉴 모달 — bundleVersion(↑↓ 스피너 3단) + versionCode(←→) + FGB_LIVE 체크 + Development Build 체크. 잡화점 BuildVersionDialog 이식(CDN 버튼 제거). </summary>
|
|
class BuildVersionDialog : EditorWindow
|
|
{
|
|
int[] _verParts = new int[3];
|
|
int _codeNum;
|
|
bool _ok, _live, _dev;
|
|
string _msg;
|
|
|
|
static int[] ParseVer(string v)
|
|
{
|
|
var parts = (v ?? "").Split('.');
|
|
var r = new int[3];
|
|
for (int i = 0; i < 3; i++)
|
|
r[i] = (i < parts.Length && int.TryParse(parts[i].Trim(), out var n) && n >= 0) ? n : 0;
|
|
return r;
|
|
}
|
|
|
|
public static bool Show(string message, ref string version, ref int versionCode, bool live, out bool liveOut, out bool devOut)
|
|
{
|
|
var w = ScriptableObject.CreateInstance<BuildVersionDialog>();
|
|
w.titleContent = new GUIContent("WL 빌드 버전 / 심볼");
|
|
w._msg = message;
|
|
w._verParts = ParseVer(version);
|
|
w._codeNum = versionCode;
|
|
w._live = live;
|
|
w._dev = false;
|
|
const float W = 470, H = 360;
|
|
w.minSize = w.maxSize = new Vector2(W, H);
|
|
var main = EditorGUIUtility.GetMainWindowPosition();
|
|
w.position = new Rect(main.x + (main.width - W) / 2f, main.y + (main.height - H) / 2f, W, H);
|
|
w.ShowModal();
|
|
bool ok = w._ok;
|
|
liveOut = w._live; devOut = w._dev;
|
|
if (ok)
|
|
{
|
|
version = $"{w._verParts[0]}.{w._verParts[1]}.{w._verParts[2]}";
|
|
versionCode = w._codeNum;
|
|
}
|
|
UnityEngine.Object.DestroyImmediate(w);
|
|
return ok;
|
|
}
|
|
|
|
void OnGUI()
|
|
{
|
|
EditorGUILayout.Space(8);
|
|
EditorGUILayout.LabelField(_msg, EditorStyles.wordWrappedLabel);
|
|
EditorGUILayout.Space(6);
|
|
var bigNum = new GUIStyle(EditorStyles.boldLabel) { alignment = TextAnchor.MiddleCenter, fontSize = 18 };
|
|
|
|
EditorGUILayout.LabelField($"bundleVersion = {_verParts[0]}.{_verParts[1]}.{_verParts[2]}", EditorStyles.boldLabel);
|
|
using (new EditorGUILayout.HorizontalScope())
|
|
{
|
|
GUILayout.Space(12);
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
using (new EditorGUILayout.VerticalScope(GUILayout.Width(56)))
|
|
{
|
|
if (GUILayout.Button("↑", GUILayout.Width(56), GUILayout.Height(22))) _verParts[i]++;
|
|
GUILayout.Label(_verParts[i].ToString(), bigNum, GUILayout.Width(56), GUILayout.Height(26));
|
|
if (GUILayout.Button("↓", GUILayout.Width(56), GUILayout.Height(22))) _verParts[i] = Mathf.Max(0, _verParts[i] - 1);
|
|
}
|
|
if (i < 2) GUILayout.Label(".", bigNum, GUILayout.Width(12), GUILayout.Height(70));
|
|
}
|
|
GUILayout.FlexibleSpace();
|
|
}
|
|
|
|
EditorGUILayout.Space(10);
|
|
EditorGUILayout.LabelField("versionCode", EditorStyles.boldLabel);
|
|
using (new EditorGUILayout.HorizontalScope())
|
|
{
|
|
GUILayout.Space(12);
|
|
if (GUILayout.Button("←", GUILayout.Width(44), GUILayout.Height(26))) _codeNum = Mathf.Max(0, _codeNum - 1);
|
|
GUILayout.Label(_codeNum.ToString(), bigNum, GUILayout.Width(90), GUILayout.Height(26));
|
|
if (GUILayout.Button("→", GUILayout.Width(44), GUILayout.Height(26))) _codeNum++;
|
|
GUILayout.FlexibleSpace();
|
|
}
|
|
|
|
EditorGUILayout.Space(10);
|
|
EditorGUILayout.LabelField("옵션", EditorStyles.boldLabel);
|
|
_live = EditorGUILayout.ToggleLeft("FGB_LIVE", _live);
|
|
EditorGUILayout.LabelField(" 라이브 심볼. ON 이면 ErrorLogHook 팝업 등 개발용 로직 제외 — 출시 빌드는 ON.", EditorStyles.miniLabel);
|
|
_dev = EditorGUILayout.ToggleLeft("Development Build", _dev);
|
|
EditorGUILayout.LabelField(" 프로파일러·스크립트 디버깅 연결 허용 — 테스트 APK 에서만.", EditorStyles.miniLabel);
|
|
|
|
GUILayout.FlexibleSpace();
|
|
using (new EditorGUILayout.HorizontalScope())
|
|
{
|
|
GUILayout.FlexibleSpace();
|
|
if (GUILayout.Button("취소", GUILayout.Width(80))) { _ok = false; Close(); }
|
|
if (GUILayout.Button("빌드", GUILayout.Width(80))) { _ok = true; Close(); }
|
|
}
|
|
EditorGUILayout.Space(8);
|
|
|
|
var e = Event.current;
|
|
if (e.type == EventType.KeyDown)
|
|
{
|
|
if (e.keyCode == KeyCode.Return || e.keyCode == KeyCode.KeypadEnter) { _ok = true; Close(); }
|
|
else if (e.keyCode == KeyCode.Escape) { _ok = false; Close(); }
|
|
}
|
|
}
|
|
}
|