ios代码切出,增加新编辑器
This commit is contained in:
parent
6b6ce7473d
commit
5a5b58a37d
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: th1-base
|
||||
description: TH1 project baseline engineering guide for Unity client changes: assembly boundaries, HybridCLR hotfix rules, YooAsset/AssetBundle resource rules, MemoryPack/AOT serialization safety, build packaging flow, and routing to domain skills. Use before broad TH1 Unity code/resource/build changes, especially when touching Scripts, asmdefs, HybridCLR, hotfix DLLs, StreamingAssets, BundleResources, Resources.Load replacement, YooAsset, MemoryPack, generated config, build panels, or package verification.
|
||||
description: TH1 project baseline engineering guide for Unity client changes: assembly boundaries, HybridCLR hotfix rules, YooAsset/AssetBundle resource rules, BundleResources DataAssets -> Export packaging sync, MemoryPack/AOT serialization safety, unified PC/iOS build packaging flow, and routing to domain skills. Use before broad TH1 Unity code/resource/build changes, especially when touching Scripts, asmdefs, HybridCLR, hotfix DLLs, StreamingAssets, BundleResources, Resources.Load replacement, YooAsset, MemoryPack, generated config, build panels, or package verification.
|
||||
---
|
||||
|
||||
# TH1 Base Engineering
|
||||
@ -107,6 +107,7 @@ Rules:
|
||||
Resources are moving to AB-first loading:
|
||||
|
||||
- Use `Assets/BundleResources` as the packaged resource root.
|
||||
- TH1's default YooAsset collector should collect the whole `Assets/BundleResources` root and use `TH1AddressByBundleResourcesPath`, so an asset like `Assets/BundleResources/Export/VersionConfig.asset` is addressed as `Export/VersionConfig.asset`.
|
||||
- Prefer stable logical addresses. Do not make gameplay code depend on platform-specific bundle paths.
|
||||
- Replace `Resources.Load` through `TH1Resource.ResourceLoader`/resource cache wrappers, not scattered direct YooAsset calls.
|
||||
- Editor may run simulate mode; PC/iOS packages should run actual built-in AB package logic.
|
||||
@ -120,18 +121,26 @@ Resources are moving to AB-first loading:
|
||||
|
||||
## Build And Packaging Flow
|
||||
|
||||
For migration-era PC IL2CPP smoke builds, use the project one-click flow where possible:
|
||||
For PC/iOS packages, prefer `Tools/TH1/一体化出包工具` / `TH1UnifiedBuildWindow` where possible.
|
||||
|
||||
Current one-click flow should be visible and stage-based:
|
||||
|
||||
1. Configure target platform/build settings.
|
||||
2. Configure HybridCLR.
|
||||
3. Run HybridCLR `GenerateAll`.
|
||||
4. Build hotfix DLL and copy hotfix/AOT metadata to `StreamingAssets`.
|
||||
5. Build YooAsset built-in `DefaultPackage`.
|
||||
6. Build Windows IL2CPP player.
|
||||
7. Launch player and scan the log for startup red errors.
|
||||
2. Apply selected `VersionConfig` to `Assets/BundleResources/DataAssets/VersionConfig.asset`, `PlayerSettings.bundleVersion`, scripting defines, package type, and OPS obfuscation target.
|
||||
3. Run multilingual export/import when packaging unless the user explicitly disables it. This copies/transforms `Assets/BundleResources/DataAssets/*` into `Assets/BundleResources/Export/*`, updates `Multilingual.asset`, and generates `MatchLevelData/ExportLevelData.bytes`.
|
||||
4. Configure HybridCLR.
|
||||
5. Configure YooAsset collector.
|
||||
6. Run HybridCLR `GenerateAll`.
|
||||
7. Build hotfix DLL and copy hotfix/AOT metadata to `StreamingAssets`.
|
||||
8. Build YooAsset built-in `DefaultPackage`.
|
||||
9. Check migration/build blockers.
|
||||
10. Build the PC or iOS player.
|
||||
|
||||
The window must show each phase and stop on the first phase failure. Do not rely only on a final Unity popup when the flow spans version config, multilingual export, HybridCLR, AB, and player build.
|
||||
|
||||
Manual Unity packaging gotchas:
|
||||
|
||||
- If runtime version/localization/config looks stale, compare `Assets/BundleResources/DataAssets/*` against `Assets/BundleResources/Export/*`; the game usually reads `Export/...`, not raw `DataAssets/...`.
|
||||
- After scene list changes, use full `Build`/`Clean Build`; do not use `Build Scripts Only`.
|
||||
- If the one-click build panel reports success while AOT metadata is missing, trust the artifact check, not the old status text. Required AOT metadata must exist under `Assets/StreamingAssets/HybridCLR/AOTAssemblies`.
|
||||
- If you only need a runnable PC package, keep `Create Visual Studio Solution` off unless explicitly debugging the generated solution.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: th1-ios-migration
|
||||
description: "TH1 project-specific iOS migration guide for same-mainline dual-platform support: HybridCLR hot update foundation, iOS/IL2CPP compile isolation, Steamworks/Steam SDK platform abstraction without Steam regressions, touch input adaptation, YooAsset AssetBundle/resource migration, iOS build settings, and verification that existing online Steam builds and gameplay behavior remain unaffected. Use whenever Codex works on TH1 iOS packaging, mobile porting, HybridCLR, YooAsset AB/resource loading, removing direct Steamworks references for iOS, platform services, touch controls, or build pipeline changes that must preserve the current Steam version."
|
||||
description: "TH1 project-specific iOS migration guide for same-mainline dual-platform support: HybridCLR hot update foundation, iOS/IL2CPP compile isolation, Steamworks/Steam SDK platform abstraction without Steam regressions, touch input adaptation, YooAsset AssetBundle/resource migration, BundleResources DataAssets -> Export packaging sync, iOS build settings, unified PC/iOS build window flow, and verification that existing online Steam builds and gameplay behavior remain unaffected. Use whenever Codex works on TH1 iOS packaging, mobile porting, HybridCLR, YooAsset AB/resource loading, removing direct Steamworks references for iOS, platform services, touch controls, or build pipeline changes that must preserve the current Steam version."
|
||||
---
|
||||
|
||||
# TH1 iOS Migration
|
||||
@ -173,6 +173,14 @@ Goal: move toward AB/resource hot update without destabilizing the Steam build.
|
||||
|
||||
Use the existing YooAsset package and `AssetBundleCollectorSetting.asset` unless there is a clear reason not to.
|
||||
|
||||
Current TH1 built-in resource shape:
|
||||
|
||||
- Packaged resource root is `Assets/BundleResources`.
|
||||
- `TH1YooAssetBuildTools.ConfigureDefaultPackageCollector()` should collect the whole root for the default package.
|
||||
- `TH1AddressByBundleResourcesPath` strips `Assets/BundleResources/`, so `Assets/BundleResources/Export/Multilingual.asset` becomes address `Export/Multilingual.asset`.
|
||||
- `TH1Resource.ResourceLoader.Load<T>("Export/VersionConfig")` and similar calls normalize addresses and try extension candidates. Do not change runtime callers to platform-specific paths when the collector/address rule is the real issue.
|
||||
- Runtime config/localization/table data usually reads `Export/...`; raw `DataAssets/...` is the authoring source copied/transformed by the multilingual export/import flow.
|
||||
|
||||
Recommended sequence:
|
||||
|
||||
1. Finish a real `ResourceManager` wrapper around YooAsset package initialization.
|
||||
@ -185,7 +193,9 @@ Recommended sequence:
|
||||
Resource rules:
|
||||
|
||||
- Keep stable logical addresses. Do not make gameplay code depend on platform-specific paths.
|
||||
- Do not modify export-flow outputs such as `Unity/Assets/Resources/Export/*`, `Tools/Multilingual.xlsx`, or `Tools/MultilingualTxt.txt` unless the user asked for export/import changes.
|
||||
- Do not modify export-flow outputs such as `Unity/Assets/BundleResources/Export/*`, `Tools/Multilingual.xlsx`, or `Tools/MultilingualTxt.txt` unless the user asked for export/import changes.
|
||||
- In the current migration, export-flow outputs live under `Assets/BundleResources/Export/*`. If a package shows the wrong version, stale text, or stale table config, first check whether `DataAssets -> Export` was refreshed before AB build.
|
||||
- Before a release/debug package, run or explicitly skip with confirmation the multilingual export/import flow (`Tools/一键导出导回` or the checkbox in `TH1UnifiedBuildWindow`). It refreshes `Export/*`, `Multilingual.asset`, Excel/TXT intermediate files, and `MatchLevelData/ExportLevelData.bytes`.
|
||||
- Use iOS-specific texture/audio compression settings and bundle output. Do not reuse PC texture assumptions blindly.
|
||||
- Treat generated config/DataAsset loading as compatibility-sensitive; preserve existing table and localization behavior.
|
||||
- For Unity 2021+ / Unity 2022 with YooAsset 2.1.1, prefer SBP (`ScriptableBuildPipeline`) for built-in package builds. YooAsset's BBP path uses Unity's old `BuildPipeline.BuildAssetBundles` call and can trigger the internal assertion `m_InstanceIDToAssetBundleIndex.count(id) > 0`.
|
||||
@ -209,6 +219,20 @@ Maintain one main branch with separate build profiles:
|
||||
- iOS build: iOS, IL2CPP, mobile platform services, no Steamworks compile dependency, touch enabled, iOS bundles.
|
||||
- Hot update build: platform-specific HybridCLR DLL/AOT metadata and YooAsset manifests.
|
||||
|
||||
Prefer `Tools/TH1/一体化出包工具` for manual PC/iOS packaging. The one-click path should be staged and stop on first failure:
|
||||
|
||||
1. Apply version/platform/package defines and OPS obfuscation target.
|
||||
2. Optional but recommended multilingual export/import (`DataAssets -> Export`).
|
||||
3. Configure HybridCLR.
|
||||
4. Configure YooAsset collector.
|
||||
5. HybridCLR `GenerateAll`.
|
||||
6. Build hotfix DLL/AOT metadata.
|
||||
7. Build YooAsset built-in AB.
|
||||
8. Check build blockers.
|
||||
9. Build Player.
|
||||
|
||||
The confirmation dialog should show the selected version and whether the multilingual export/import step is enabled.
|
||||
|
||||
Release branches may exist for stabilization only:
|
||||
|
||||
- `release/steam-*` and `release/ios-*` may freeze and cherry-pick fixes.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "TH1 iOS Migration"
|
||||
short_description: "HybridCLR, iOS isolation, touch, YooAsset"
|
||||
default_prompt: "Use $th1-ios-migration when making TH1 iOS migration changes that must keep the Steam build and existing gameplay behavior intact."
|
||||
short_description: "HybridCLR、iOS隔离、YooAsset与统一出包"
|
||||
default_prompt: "Use $th1-ios-migration when making TH1 iOS migration or PC/iOS packaging changes that must keep the Steam build and existing gameplay behavior intact."
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: th1-multilingual
|
||||
description: TH1 project-specific multilingual/localization guide for Unity editor export/import, Multilingual.asset, Multilingual.xlsx, MultilingualTxt.txt, special-term syntax, ordered embedded references, duplicate ID prevention, active text scanning, Excel round-tripping, and translation data debugging. Use whenever Codex works on TH1 多语言导表/导回, localization Excel issues, duplicated rows/IDs, special-term parsing, ordered marker bugs, MultilingualEditorWindow, MultilingualData, or any bug that may create new localization IDs unexpectedly.
|
||||
description: TH1 project-specific multilingual/localization guide for Unity editor export/import, BundleResources DataAssets -> Export runtime asset sync, Multilingual.asset, Multilingual.xlsx, MultilingualTxt.txt, special-term syntax, ordered embedded references, duplicate ID prevention, active text scanning, Excel round-tripping, and translation data debugging. Use whenever Codex works on TH1 多语言导表/导回, localization Excel issues, duplicated rows/IDs, special-term parsing, ordered marker bugs, MultilingualEditorWindow, MultilingualData, package/export stale version or text issues, or any bug that may create new localization IDs unexpectedly.
|
||||
---
|
||||
|
||||
# TH1 Multilingual
|
||||
@ -26,7 +26,9 @@ Translation length is part of the project quality bar. Keep target-language text
|
||||
- `Tools/ExportStringToExcel.py`
|
||||
- `Tools/Multilingual.xlsx`
|
||||
- `Tools/MultilingualTxt.txt`
|
||||
- `Unity/Assets/Resources/Export/Multilingual.asset`
|
||||
- `Unity/Assets/BundleResources/Export/Multilingual.asset`
|
||||
- `Unity/Assets/BundleResources/DataAssets/*`
|
||||
- `Unity/Assets/BundleResources/Export/*`
|
||||
|
||||
For the full data-flow contract, read `references/pipeline.md`.
|
||||
For duplicate IDs, bad markers, and validation commands, read `references/diagnostics.md`.
|
||||
@ -62,6 +64,14 @@ Asset internal form:
|
||||
7. Only allocate `_idIndex` when the canonical string is genuinely new.
|
||||
8. Write Excel-visible text through `GetMultilingualStrEditor()`, which expands internal IDs back to readable terms.
|
||||
|
||||
In the current BundleResources/YooAsset flow, export is also the authoring-to-runtime sync step:
|
||||
|
||||
- `Assets/BundleResources/DataAssets/*` is the authoring source for many ScriptableObject configs.
|
||||
- `AssetExportToExcelInternal()` instantiates each DataAsset, traverses/transforms multilingual strings, and writes the runtime copy to `Assets/BundleResources/Export/{name}.asset`.
|
||||
- Runtime table/config/localization code usually loads `Export/...` through `TH1Resource.ResourceLoader`, not raw `DataAssets/...`.
|
||||
- `ExportMatchLevelData()` writes `Assets/BundleResources/MatchLevelData/ExportLevelData.bytes`; runtime match config uses this outside editor play mode.
|
||||
- Before PC/iOS packaging, run `Tools/一键导出导回` or enable the `TH1UnifiedBuildWindow` checkbox for multilingual export/import before YooAsset AB build. If this is skipped, the built player can show a new title/bundle version while CrashSight/config/localization still report stale `Export` data.
|
||||
|
||||
## Import Workflow
|
||||
|
||||
1. Convert Excel to `MultilingualTxt.txt` through `Tools/PrintExcelString.py`.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "TH1 Multilingual"
|
||||
short_description: "TH1 Unity 多语言导表导回特殊词和重复ID排查"
|
||||
default_prompt: "Use TH1 multilingual rules to inspect, fix, or explain localization export/import issues."
|
||||
short_description: "TH1 多语言导表导回、DataAssets到Export同步、重复ID排查"
|
||||
default_prompt: "Use TH1 multilingual rules to inspect, fix, or explain localization export/import and DataAssets-to-Export sync issues."
|
||||
|
||||
@ -38,7 +38,7 @@ import sys, io
|
||||
from pathlib import Path
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
|
||||
ids = {'17228', '19977'}
|
||||
text = Path('Unity/Assets/Resources/Export/Multilingual.asset').read_text(encoding='utf-8')
|
||||
text = Path('Unity/Assets/BundleResources/Export/Multilingual.asset').read_text(encoding='utf-8')
|
||||
lines = text.splitlines()
|
||||
for idx, line in enumerate(lines):
|
||||
if line.strip() in [f'- ID: {i}' for i in ids]:
|
||||
@ -59,13 +59,13 @@ Interpretation:
|
||||
Search an ID in exported assets to see who currently references it:
|
||||
|
||||
```powershell
|
||||
rg -n "Desc: 19977|ActionName: 19977|TechDesc: 19977| 19977" Unity/Assets/Resources/Export -S
|
||||
rg -n "Desc: 19977|ActionName: 19977|TechDesc: 19977| 19977" Unity/Assets/BundleResources/Export -S
|
||||
```
|
||||
|
||||
For field-level reference context:
|
||||
|
||||
```powershell
|
||||
rg -n "19977" Unity/Assets/Resources/Export/ActionDataAssets.asset -C 20
|
||||
rg -n "19977" Unity/Assets/BundleResources/Export/ActionDataAssets.asset -C 20
|
||||
```
|
||||
|
||||
If a new duplicate ID is already written into a DataAssets export, rerunning export after fixing canonicalization should normally reassign the source field back to the preserved ID.
|
||||
|
||||
@ -14,8 +14,12 @@
|
||||
- Embedded string resolve/unresolve.
|
||||
- Language fallback.
|
||||
- `MultilingualItem`.
|
||||
- `Unity/Assets/Resources/Export/Multilingual.asset`
|
||||
- `Unity/Assets/BundleResources/Export/Multilingual.asset`
|
||||
- Canonical ScriptableObject data.
|
||||
- `Unity/Assets/BundleResources/DataAssets/*`
|
||||
- Authoring ScriptableObject configs scanned during export.
|
||||
- `Unity/Assets/BundleResources/Export/*`
|
||||
- Runtime ScriptableObject copies produced by export.
|
||||
- `Tools/MultilingualTxt.txt`
|
||||
- Intermediate delimiter file.
|
||||
- `Tools/Multilingual.xlsx`
|
||||
@ -85,8 +89,8 @@ The same row can therefore have different representations at different phases. A
|
||||
- Deduplicate by canonical raw `item.ZH`.
|
||||
2. Initialize `_zhStrDict` from canonical `item.ZH`.
|
||||
3. Scan active `TextMeshProUGUI` from scene `UICanvas`.
|
||||
4. Scan prefabs under `Assets/Resources/Prefab/`.
|
||||
5. Scan ScriptableObjects under `Assets/Resources/DataAssets/`.
|
||||
4. Scan prefabs under `Assets/BundleResources/Prefab/`.
|
||||
5. Scan ScriptableObjects under `Assets/BundleResources/DataAssets/`.
|
||||
6. For each source string:
|
||||
- Trim and normalize newlines.
|
||||
- Optionally `TransformString`.
|
||||
@ -98,6 +102,17 @@ The same row can therefore have different representations at different phases. A
|
||||
8. Write `MultilingualTxt.txt` with `GetMultilingualStrEditor`, which expands IDs for Excel.
|
||||
9. Run `ExportStringToExcel.py`.
|
||||
|
||||
## BundleResources / Packaging Notes
|
||||
|
||||
The multilingual export flow also refreshes runtime config assets for AB builds:
|
||||
|
||||
- `DataAssets/*` is authoring data.
|
||||
- `SaveExportAsset(name, newAsset)` writes transformed runtime assets to `Assets/BundleResources/Export/{name}.asset`.
|
||||
- `ConfigManager`, `Table`, `MultilingualManager`, achievements, AI config, and similar runtime paths generally load `Export/...` through `TH1Resource.ResourceLoader`.
|
||||
- `ExportMatchLevelData()` writes `Assets/BundleResources/MatchLevelData/ExportLevelData.bytes`; runtime match config uses `MatchLevelData/ExportLevelData` outside editor play mode.
|
||||
- `TH1YooAssetBuildTools` collects the whole `Assets/BundleResources` root, and `TH1AddressByBundleResourcesPath` strips that prefix. `Assets/BundleResources/Export/VersionConfig.asset` is therefore addressed as `Export/VersionConfig.asset`.
|
||||
- Before building PC/iOS AB/player packages, run `Tools/一键导出导回` or the `TH1UnifiedBuildWindow` multilingual export/import checkbox. Otherwise a player can contain stale `Export` assets even when `DataAssets` and `PlayerSettings.bundleVersion` were changed.
|
||||
|
||||
## Import Phases
|
||||
|
||||
1. Run `PrintExcelString.py`.
|
||||
|
||||
@ -92,28 +92,15 @@ namespace Logic.Editor
|
||||
[MenuItem("Tools/一键导出导回")]
|
||||
public static void OneClickExportAndImport()
|
||||
{
|
||||
EditorUtility.DisplayProgressBar("一键导出导回", "正在导出到 Excel...", 0.3f);
|
||||
|
||||
try
|
||||
{
|
||||
var window = new MultilingualEditorWindow();
|
||||
window.InitializeAsset();
|
||||
|
||||
// 步骤1: 执行导出
|
||||
window.AssetExportToExcelInternal();
|
||||
Debug.Log("[一键导出导回] 导出 Excel 成功");
|
||||
|
||||
EditorUtility.DisplayProgressBar("一键导出导回", "正在从 Excel 导回...", 0.7f);
|
||||
|
||||
// 步骤2: 执行导回
|
||||
window.ExcelExportToAssetInternal();
|
||||
Debug.Log("[一键导出导回] Excel 导回成功");
|
||||
|
||||
RunOneClickExportAndImportForBuild((message, progress) =>
|
||||
EditorUtility.DisplayProgressBar("一键导出导回", message, progress));
|
||||
EditorUtility.DisplayDialog("成功", "一键导出导回完成!", "确定");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[一键导出导回] 失败: {ex.Message}");
|
||||
Debug.LogError($"[一键导出导回] 失败: {ex}");
|
||||
EditorUtility.DisplayDialog("错误", $"操作失败: {ex.Message}", "确定");
|
||||
}
|
||||
finally
|
||||
@ -122,6 +109,24 @@ namespace Logic.Editor
|
||||
}
|
||||
}
|
||||
|
||||
public static void RunOneClickExportAndImportForBuild(System.Action<string, float> progress = null)
|
||||
{
|
||||
var window = new MultilingualEditorWindow();
|
||||
|
||||
progress?.Invoke("正在初始化多语言资源...", 0.05f);
|
||||
window.InitializeAsset();
|
||||
|
||||
progress?.Invoke("正在导出 DataAssets/UI/Prefab 到 Export 并生成 Excel...", 0.35f);
|
||||
window.AssetExportToExcelInternal();
|
||||
Debug.Log("[一键导出导回] 导出 Excel 成功");
|
||||
|
||||
progress?.Invoke("正在从 Excel 导回 Multilingual.asset...", 0.75f);
|
||||
window.ExcelExportToAssetInternal();
|
||||
Debug.Log("[一键导出导回] Excel 导回成功");
|
||||
|
||||
progress?.Invoke("多语言导出导回完成。", 1f);
|
||||
}
|
||||
|
||||
private void InitializeAsset()
|
||||
{
|
||||
var path = "Assets/BundleResources/Export/Multilingual.asset";
|
||||
|
||||
@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Logic.Config;
|
||||
using TH1_Logic.Editor.HybridCLR;
|
||||
using TH1_Logic.Editor.YooAssetTools;
|
||||
@ -15,8 +16,14 @@ namespace TH1_Logic.Editor
|
||||
public sealed class TH1UnifiedBuildWindow : EditorWindow
|
||||
{
|
||||
private const string VersionConfigPath = "Assets/BundleResources/DataAssets/VersionConfig.asset";
|
||||
private const string OpsObfuscatorSettingsPath = "Assets/OPS/Obfuscator/Settings/Obfuscator_Settings.json";
|
||||
private const string ProductName = "TOHOTOPIA";
|
||||
private const string ExeName = "TOHOTOPIA.exe";
|
||||
private const string OpsObfuscationEnabledLabel = "开启";
|
||||
private const string OpsObfuscationDisabledLabel = "关闭";
|
||||
private static readonly Regex OpsObfuscationRegex = new Regex(
|
||||
"(?<prefix>\"Key\"\\s*:\\s*\"Global_Enable_Obfuscation\"\\s*,\\s*\"Value\"\\s*:\\s*\")(?<value>True|False)(?<suffix>\")",
|
||||
RegexOptions.Multiline);
|
||||
|
||||
private static readonly string[] BaseSharedDefines =
|
||||
{
|
||||
@ -51,10 +58,11 @@ namespace TH1_Logic.Editor
|
||||
private uint _patch;
|
||||
private uint _fourth;
|
||||
private BuildPlatformProfile _platform = BuildPlatformProfile.PC;
|
||||
private PackageProfile _package = PackageProfile.Test;
|
||||
private PackageProfile _package = PackageProfile.Debug;
|
||||
private bool _prepareBeforeBuild = true;
|
||||
private bool _buildPlayer = true;
|
||||
private bool _cleanOutput;
|
||||
private bool _runMultilingualExportImport = true;
|
||||
private bool _showAdvanced;
|
||||
private bool _enableSpeedup;
|
||||
private bool _enableTrain;
|
||||
@ -62,7 +70,11 @@ namespace TH1_Logic.Editor
|
||||
private bool _gameAutoDebug;
|
||||
private bool _checkActionDifference;
|
||||
private bool _steamTest;
|
||||
private bool _actionScheduled;
|
||||
private string _lastAction = "Ready";
|
||||
private string _stageDetail = string.Empty;
|
||||
private string _stageError = string.Empty;
|
||||
private readonly List<BuildStageItem> _stageItems = new List<BuildStageItem>();
|
||||
|
||||
[MenuItem("Tools/TH1/Unified Build Window")]
|
||||
[MenuItem("Tools/TH1/一体化出包工具")]
|
||||
@ -107,7 +119,7 @@ namespace TH1_Logic.Editor
|
||||
}
|
||||
|
||||
EditorGUILayout.HelpBox(
|
||||
"流程:选版本 -> 选平台 -> 选测试/发布 -> 勾特殊功能 -> 一键执行。发布包会关闭所有特殊功能宏;iOS 配置不会写入 STEAM_CHANNEL/STEAMWORKS_NET。",
|
||||
"流程:选版本 -> 选平台 -> 选 Debug/Release -> 勾特殊功能 -> 一键执行。Debug 包会关闭 OPS 混淆;Release 包会关闭特殊功能宏并开启 OPS 混淆;iOS 配置不会写入 STEAM_CHANNEL/STEAMWORKS_NET。",
|
||||
MessageType.Info);
|
||||
}
|
||||
|
||||
@ -177,6 +189,8 @@ namespace TH1_Logic.Editor
|
||||
_prepareBeforeBuild = EditorGUILayout.ToggleLeft("构建前执行 HybridCLR + YooAsset 准备流程", _prepareBeforeBuild);
|
||||
_buildPlayer = EditorGUILayout.ToggleLeft("准备完成后 Build Player", _buildPlayer);
|
||||
_cleanOutput = EditorGUILayout.ToggleLeft("构建前清空本次输出目录", _cleanOutput);
|
||||
EditorGUILayout.HelpBox("建议多语言导表/导回后再打包。勾选后,一键流程会先执行多语言导出导回,把 DataAssets 同步到 Export,再继续构建 AB 和 Player。", MessageType.Warning);
|
||||
_runMultilingualExportImport = EditorGUILayout.ToggleLeft("一键流程中执行多语言导出导回(DataAssets -> Export)", _runMultilingualExportImport);
|
||||
|
||||
var group = GetBuildTargetGroup(_platform);
|
||||
EditorGUILayout.LabelField("目标平台组", group.ToString());
|
||||
@ -201,46 +215,70 @@ namespace TH1_Logic.Editor
|
||||
|
||||
if (_package == PackageProfile.Release)
|
||||
{
|
||||
EditorGUILayout.HelpBox("发布包会强制关闭上面所有特殊功能宏。OPS 混淆设置不会被这个窗口自动修改,需要单独确认后再处理。", MessageType.None);
|
||||
EditorGUILayout.HelpBox("发布包会强制关闭上面所有特殊功能宏,并在应用配置时开启 OPS 混淆。", MessageType.None);
|
||||
}
|
||||
|
||||
DrawOpsObfuscationStatus();
|
||||
}
|
||||
|
||||
private void DrawActions()
|
||||
{
|
||||
EditorGUILayout.LabelField("执行", EditorStyles.boldLabel);
|
||||
using (new EditorGUI.DisabledScope(EditorApplication.isCompiling || EditorApplication.isPlayingOrWillChangePlaymode || GetSelectedVersion() == null))
|
||||
DrawStageProgress();
|
||||
EditorGUILayout.Space(4);
|
||||
|
||||
using (new EditorGUI.DisabledScope(_actionScheduled || EditorApplication.isCompiling || EditorApplication.isPlayingOrWillChangePlaymode || GetSelectedVersion() == null))
|
||||
{
|
||||
if (GUILayout.Button("一键应用配置并出包", GUILayout.Height(42)))
|
||||
{
|
||||
RunAction("Apply And Build", ApplyAndRun);
|
||||
ScheduleAction("Apply And Build", () =>
|
||||
{
|
||||
if (!ConfirmSelectedVersion("一键应用配置并出包")) return false;
|
||||
ApplyAndRun();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("只应用配置", GUILayout.Height(30)))
|
||||
{
|
||||
RunAction("Apply Profile", ApplySelectedProfile);
|
||||
ScheduleAction("Apply Profile", () =>
|
||||
{
|
||||
if (!ConfirmSelectedVersion("只应用配置")) return false;
|
||||
ApplySelectedProfile();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
if (GUILayout.Button("只准备热更/AB", GUILayout.Height(30)))
|
||||
{
|
||||
RunAction("Prepare Assets", () => TH1MigrationCommandLine.PrepareCurrentPlatform(IsDevelopmentBuild()));
|
||||
ScheduleAction("Prepare Assets", PrepareAssetsWithStages);
|
||||
}
|
||||
}
|
||||
|
||||
_showAdvanced = EditorGUILayout.Foldout(_showAdvanced, "高级单项", true);
|
||||
if (_showAdvanced)
|
||||
{
|
||||
if (GUILayout.Button("多语言导出导回(DataAssets -> Export)", GUILayout.Height(30)))
|
||||
{
|
||||
ScheduleAction("Multilingual Export/Import", () =>
|
||||
{
|
||||
ResetBuildStages();
|
||||
RunBuildStage("多语言导出导回", "扫描 DataAssets/UI/Prefab,刷新 Export 和多语言 Excel。", RunMultilingualExportImport);
|
||||
});
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("HybridCLR Generate All"))
|
||||
{
|
||||
RunAction("HybridCLR Generate All", TH1HybridCLRBuildTools.GenerateAll);
|
||||
ScheduleAction("HybridCLR Generate All", TH1HybridCLRBuildTools.GenerateAll);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Build Hotfix DLL"))
|
||||
{
|
||||
RunAction("Build Hotfix DLL", () =>
|
||||
ScheduleAction("Build Hotfix DLL", () =>
|
||||
{
|
||||
if (!TH1HybridCLRBuildTools.BuildAndCopyHotfixArtifacts(IsDevelopmentBuild()))
|
||||
throw new Exception("Build hotfix dll failed. See Console for details.");
|
||||
@ -252,7 +290,7 @@ namespace TH1_Logic.Editor
|
||||
{
|
||||
if (GUILayout.Button("Build YooAsset AB"))
|
||||
{
|
||||
RunAction("Build YooAsset AB", TH1YooAssetBuildTools.BuildBuiltinDefaultPackage);
|
||||
ScheduleAction("Build YooAsset AB", TH1YooAssetBuildTools.BuildBuiltinDefaultPackage);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("打开输出目录"))
|
||||
@ -260,22 +298,273 @@ namespace TH1_Logic.Editor
|
||||
EditorUtility.RevealInFinder(Path.GetDirectoryName(GetOutputPath()));
|
||||
}
|
||||
}
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("按当前包类型设置 OPS 混淆"))
|
||||
{
|
||||
ScheduleAction("Apply OPS Obfuscation", ApplyOpsObfuscationSettings);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("查看 OPS 配置文件"))
|
||||
{
|
||||
EditorUtility.RevealInFinder(GetOpsSettingsFilePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawStageProgress()
|
||||
{
|
||||
if (_stageItems.Count == 0)
|
||||
{
|
||||
EditorGUILayout.HelpBox("一键流程会按阶段执行:应用配置 -> 多语言导出导回 -> HybridCLR/YooAsset 准备 -> Build Player。", MessageType.None);
|
||||
return;
|
||||
}
|
||||
|
||||
EditorGUILayout.LabelField("流程进度", EditorStyles.boldLabel);
|
||||
foreach (var item in _stageItems)
|
||||
{
|
||||
var messageType = item.State == BuildStageState.Failed ? MessageType.Error :
|
||||
item.State == BuildStageState.Running ? MessageType.Info :
|
||||
item.State == BuildStageState.Skipped ? MessageType.Warning :
|
||||
MessageType.None;
|
||||
|
||||
var line = $"{GetStageMarker(item.State)} {item.Title}";
|
||||
if (!string.IsNullOrEmpty(item.Detail))
|
||||
{
|
||||
line += $"\n{item.Detail}";
|
||||
}
|
||||
|
||||
EditorGUILayout.HelpBox(line, messageType);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(_stageError))
|
||||
{
|
||||
EditorGUILayout.HelpBox(_stageError, MessageType.Error);
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(_stageDetail))
|
||||
{
|
||||
EditorGUILayout.HelpBox(_stageDetail, MessageType.None);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyAndRun()
|
||||
{
|
||||
ApplySelectedProfile();
|
||||
ResetBuildStages();
|
||||
var selected = GetSelectedVersion();
|
||||
var version = selected?.FullVersion ?? "NoVersion";
|
||||
|
||||
RunBuildStage("应用配置", $"版本 {version},平台 {_platform},包类型 {_package},同步宏和 OPS 设置。", ApplySelectedProfile);
|
||||
|
||||
if (_runMultilingualExportImport)
|
||||
{
|
||||
RunBuildStage("多语言导出导回", "扫描 DataAssets/UI/Prefab,刷新 Export 和多语言 Excel。", RunMultilingualExportImport);
|
||||
}
|
||||
else
|
||||
{
|
||||
SkipBuildStage("多语言导出导回", "未勾选。请确认 Export 下的多语言和配置资产已经是本次版本。");
|
||||
}
|
||||
|
||||
if (_prepareBeforeBuild)
|
||||
{
|
||||
TH1MigrationCommandLine.PrepareCurrentPlatform(IsDevelopmentBuild());
|
||||
RunHybridClrAndYooAssetStages();
|
||||
}
|
||||
else
|
||||
{
|
||||
SkipPrepareStages("未勾选构建前准备流程。");
|
||||
}
|
||||
|
||||
if (_buildPlayer)
|
||||
{
|
||||
BuildPlayer();
|
||||
RunBuildStage("Build Player", $"输出目录:{GetOutputPathPreview()}", BuildPlayer);
|
||||
}
|
||||
else
|
||||
{
|
||||
SkipBuildStage("Build Player", "未勾选准备完成后 Build Player。");
|
||||
}
|
||||
|
||||
_stageDetail = "一键流程完成。";
|
||||
Repaint();
|
||||
}
|
||||
|
||||
private void PrepareAssetsWithStages()
|
||||
{
|
||||
ResetBuildStages();
|
||||
SkipBuildStage("应用配置", "只准备热更/AB,不修改版本、宏和 PlayerSettings。");
|
||||
SkipBuildStage("多语言导出导回", "只准备热更/AB,不执行多语言导出导回。");
|
||||
RunHybridClrAndYooAssetStages();
|
||||
SkipBuildStage("Build Player", "只准备热更/AB,不执行 Build Player。");
|
||||
_stageDetail = "热更/AB 准备完成。";
|
||||
Repaint();
|
||||
}
|
||||
|
||||
private void RunHybridClrAndYooAssetStages()
|
||||
{
|
||||
RunBuildStage("配置 HybridCLR", "刷新热更程序集、AOT 元数据和 HybridCLR 设置。", TH1HybridCLRBuildTools.ConfigureHotfixSettings);
|
||||
RunBuildStage("配置 YooAsset Collector", "确保 DefaultPackage 收集整个 Assets/BundleResources。", TH1YooAssetBuildTools.ConfigureDefaultPackageCollector);
|
||||
RunBuildStage("HybridCLR Generate All", "生成 HybridCLR 必要代码和裁剪引用。", TH1HybridCLRBuildTools.GenerateAll);
|
||||
RunBuildStage("构建 Hotfix DLL/AOT", "编译热更 DLL 并写入 StreamingAssets。", () =>
|
||||
{
|
||||
if (!TH1HybridCLRBuildTools.BuildAndCopyHotfixArtifacts(IsDevelopmentBuild()))
|
||||
{
|
||||
throw new BuildFailedException("Build hotfix dll failed. See Console for details.");
|
||||
}
|
||||
});
|
||||
RunBuildStage("构建 YooAsset AB", "构建内置 DefaultPackage AssetBundle。", TH1YooAssetBuildTools.BuildBuiltinDefaultPackage);
|
||||
RunBuildStage("检查构建阻断项", "确认热更 DLL、AOT Metadata、YooAsset Manifest 都已就绪。", CheckBuildBlockers);
|
||||
}
|
||||
|
||||
private void SkipPrepareStages(string detail)
|
||||
{
|
||||
SkipBuildStage("配置 HybridCLR", detail);
|
||||
SkipBuildStage("配置 YooAsset Collector", detail);
|
||||
SkipBuildStage("HybridCLR Generate All", detail);
|
||||
SkipBuildStage("构建 Hotfix DLL/AOT", detail);
|
||||
SkipBuildStage("构建 YooAsset AB", detail);
|
||||
SkipBuildStage("检查构建阻断项", detail);
|
||||
}
|
||||
|
||||
private void RunMultilingualExportImport()
|
||||
{
|
||||
Logic.Editor.MultilingualEditorWindow.RunOneClickExportAndImportForBuild((message, progress) =>
|
||||
UpdateRunningStage("多语言导出导回", message, progress));
|
||||
}
|
||||
|
||||
private static void CheckBuildBlockers()
|
||||
{
|
||||
var blockers = TH1MigrationBuildStatus.GetBuildBlockingMessages(EditorUserBuildSettings.activeBuildTarget);
|
||||
if (blockers.Count == 0) return;
|
||||
|
||||
throw new BuildFailedException(
|
||||
"[TH1.UnifiedBuild] Build preparation still has blocking errors:\n" +
|
||||
string.Join("\n", blockers));
|
||||
}
|
||||
|
||||
private void ResetBuildStages()
|
||||
{
|
||||
_stageItems.Clear();
|
||||
_stageError = string.Empty;
|
||||
_stageDetail = "准备开始一键流程。";
|
||||
|
||||
AddBuildStage("应用配置");
|
||||
AddBuildStage("多语言导出导回");
|
||||
AddBuildStage("配置 HybridCLR");
|
||||
AddBuildStage("配置 YooAsset Collector");
|
||||
AddBuildStage("HybridCLR Generate All");
|
||||
AddBuildStage("构建 Hotfix DLL/AOT");
|
||||
AddBuildStage("构建 YooAsset AB");
|
||||
AddBuildStage("检查构建阻断项");
|
||||
AddBuildStage("Build Player");
|
||||
Repaint();
|
||||
}
|
||||
|
||||
private void AddBuildStage(string title)
|
||||
{
|
||||
_stageItems.Add(new BuildStageItem(title));
|
||||
}
|
||||
|
||||
private void RunBuildStage(string title, string detail, System.Action action)
|
||||
{
|
||||
var stage = FindBuildStage(title);
|
||||
stage.State = BuildStageState.Running;
|
||||
stage.Detail = detail;
|
||||
_stageDetail = $"{title}: {detail}";
|
||||
_stageError = string.Empty;
|
||||
_lastAction = $"{title} running...";
|
||||
UpdateProgressBar(stage, 0.05f);
|
||||
Debug.Log($"[TH1.UnifiedBuild] Stage start: {title} - {detail}");
|
||||
Repaint();
|
||||
|
||||
try
|
||||
{
|
||||
AssetDatabase.SaveAssets();
|
||||
action();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
stage.State = BuildStageState.Done;
|
||||
stage.Detail = "完成";
|
||||
_stageDetail = $"{title} 完成。";
|
||||
_lastAction = $"{title} OK";
|
||||
UpdateProgressBar(stage, 1f);
|
||||
Debug.Log($"[TH1.UnifiedBuild] Stage OK: {title}");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
var root = UnwrapException(e);
|
||||
stage.State = BuildStageState.Failed;
|
||||
stage.Detail = root.Message;
|
||||
_stageError = $"{title} 失败:{root.Message}";
|
||||
_lastAction = $"{title} failed: {root.Message}";
|
||||
UpdateProgressBar(stage, 1f);
|
||||
Debug.LogError($"[TH1.UnifiedBuild] Stage failed: {title}\n{root}");
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
Repaint();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateRunningStage(string title, string detail, float localProgress)
|
||||
{
|
||||
var stage = FindBuildStage(title);
|
||||
stage.State = BuildStageState.Running;
|
||||
stage.Detail = detail;
|
||||
_stageDetail = $"{title}: {detail}";
|
||||
UpdateProgressBar(stage, localProgress);
|
||||
Repaint();
|
||||
}
|
||||
|
||||
private void SkipBuildStage(string title, string detail)
|
||||
{
|
||||
var stage = FindBuildStage(title);
|
||||
stage.State = BuildStageState.Skipped;
|
||||
stage.Detail = detail;
|
||||
Debug.Log($"[TH1.UnifiedBuild] Stage skipped: {title} - {detail}");
|
||||
Repaint();
|
||||
}
|
||||
|
||||
private BuildStageItem FindBuildStage(string title)
|
||||
{
|
||||
var item = _stageItems.FirstOrDefault(stage => stage.Title == title);
|
||||
if (item != null) return item;
|
||||
|
||||
item = new BuildStageItem(title);
|
||||
_stageItems.Add(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
private void UpdateProgressBar(BuildStageItem stage, float localProgress)
|
||||
{
|
||||
var index = Mathf.Max(0, _stageItems.IndexOf(stage));
|
||||
var progress = _stageItems.Count == 0
|
||||
? Mathf.Clamp01(localProgress)
|
||||
: Mathf.Clamp01((index + Mathf.Clamp01(localProgress)) / _stageItems.Count);
|
||||
EditorUtility.DisplayProgressBar("TH1 Unified Build", $"{stage.Title}\n{stage.Detail}", progress);
|
||||
}
|
||||
|
||||
private static Exception UnwrapException(Exception e)
|
||||
{
|
||||
return e is System.Reflection.TargetInvocationException && e.InnerException != null ? e.InnerException : e;
|
||||
}
|
||||
|
||||
private static string GetStageMarker(BuildStageState state)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case BuildStageState.Running:
|
||||
return ">";
|
||||
case BuildStageState.Done:
|
||||
return "OK";
|
||||
case BuildStageState.Skipped:
|
||||
return "SKIP";
|
||||
case BuildStageState.Failed:
|
||||
return "FAIL";
|
||||
default:
|
||||
return "...";
|
||||
}
|
||||
}
|
||||
|
||||
@ -288,6 +577,7 @@ namespace TH1_Logic.Editor
|
||||
ApplyVersion(selected);
|
||||
ApplyDefines();
|
||||
ApplyPlayerSettings();
|
||||
ApplyOpsObfuscationSettings();
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
@ -326,7 +616,7 @@ namespace TH1_Logic.Editor
|
||||
defines.Add("TH1_PLATFORM_IOS");
|
||||
}
|
||||
|
||||
if (_package == PackageProfile.Test)
|
||||
if (_package == PackageProfile.Debug)
|
||||
{
|
||||
defines.Add("USE_INPUT");
|
||||
AddSpecialDefines(defines);
|
||||
@ -373,6 +663,73 @@ namespace TH1_Logic.Editor
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawOpsObfuscationStatus()
|
||||
{
|
||||
EditorGUILayout.Space(4);
|
||||
EditorGUILayout.LabelField("OPS 混淆", EditorStyles.boldLabel);
|
||||
var targetEnabled = ShouldEnableOpsObfuscation();
|
||||
EditorGUILayout.LabelField("当前包类型目标", targetEnabled ? $"Release 包:{OpsObfuscationEnabledLabel}" : $"Debug 包:{OpsObfuscationDisabledLabel}");
|
||||
|
||||
if (TryReadOpsObfuscationEnabled(out var currentEnabled))
|
||||
{
|
||||
EditorGUILayout.LabelField("当前配置文件状态", currentEnabled ? OpsObfuscationEnabledLabel : OpsObfuscationDisabledLabel);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.HelpBox($"无法读取 OPS 混淆状态:{OpsObfuscatorSettingsPath}", MessageType.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyOpsObfuscationSettings()
|
||||
{
|
||||
var enabled = ShouldEnableOpsObfuscation();
|
||||
SetOpsObfuscationEnabled(enabled);
|
||||
Debug.Log($"[TH1.UnifiedBuild] OPS obfuscation {(enabled ? "enabled" : "disabled")} for {_package} package.");
|
||||
}
|
||||
|
||||
private bool ShouldEnableOpsObfuscation()
|
||||
{
|
||||
return _package == PackageProfile.Release;
|
||||
}
|
||||
|
||||
private static bool TryReadOpsObfuscationEnabled(out bool enabled)
|
||||
{
|
||||
enabled = false;
|
||||
var path = GetOpsSettingsFilePath();
|
||||
if (!File.Exists(path)) return false;
|
||||
|
||||
var json = File.ReadAllText(path);
|
||||
var matches = OpsObfuscationRegex.Matches(json);
|
||||
if (matches.Count != 1) return false;
|
||||
|
||||
enabled = string.Equals(matches[0].Groups["value"].Value, "True", StringComparison.OrdinalIgnoreCase);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void SetOpsObfuscationEnabled(bool enabled)
|
||||
{
|
||||
var path = GetOpsSettingsFilePath();
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
throw new FileNotFoundException($"OPS obfuscator settings not found: {OpsObfuscatorSettingsPath}", path);
|
||||
}
|
||||
|
||||
var json = File.ReadAllText(path);
|
||||
var matches = OpsObfuscationRegex.Matches(json);
|
||||
if (matches.Count != 1)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot find a unique Global_Enable_Obfuscation entry in {OpsObfuscatorSettingsPath}.");
|
||||
}
|
||||
|
||||
var updated = OpsObfuscationRegex.Replace(json, match =>
|
||||
$"{match.Groups["prefix"].Value}{(enabled ? "True" : "False")}{match.Groups["suffix"].Value}", 1);
|
||||
|
||||
if (updated == json) return;
|
||||
|
||||
File.WriteAllText(path, updated);
|
||||
AssetDatabase.ImportAsset(OpsObfuscatorSettingsPath);
|
||||
}
|
||||
|
||||
private static void SetStackTrace(StackTraceLogType log, StackTraceLogType warning, StackTraceLogType error)
|
||||
{
|
||||
PlayerSettings.SetStackTraceLogType(LogType.Log, log);
|
||||
@ -486,7 +843,7 @@ namespace TH1_Logic.Editor
|
||||
|
||||
private bool IsDevelopmentBuild()
|
||||
{
|
||||
return _package == PackageProfile.Test;
|
||||
return _package == PackageProfile.Debug;
|
||||
}
|
||||
|
||||
private VersionInfo GetSelectedVersion()
|
||||
@ -562,13 +919,75 @@ namespace TH1_Logic.Editor
|
||||
return Directory.GetParent(Application.dataPath)?.FullName ?? Application.dataPath;
|
||||
}
|
||||
|
||||
private void RunAction(string title, Action action)
|
||||
private static string GetOpsSettingsFilePath()
|
||||
{
|
||||
return Path.Combine(GetProjectRoot(), OpsObfuscatorSettingsPath.Replace('/', Path.DirectorySeparatorChar));
|
||||
}
|
||||
|
||||
private void ScheduleAction(string title, System.Action action)
|
||||
{
|
||||
ScheduleAction(title, () =>
|
||||
{
|
||||
action();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void ScheduleAction(string title, System.Func<bool> action)
|
||||
{
|
||||
if (_actionScheduled) return;
|
||||
|
||||
_actionScheduled = true;
|
||||
_lastAction = $"{title} queued...";
|
||||
Repaint();
|
||||
|
||||
EditorApplication.delayCall += () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
RunAction(title, action);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_actionScheduled = false;
|
||||
Repaint();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private bool ConfirmSelectedVersion(string actionName)
|
||||
{
|
||||
var selected = GetSelectedVersion();
|
||||
if (selected == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("确认当前版本", "当前没有选中的打包版本。", "确定");
|
||||
return false;
|
||||
}
|
||||
|
||||
var multilingualLine = actionName.Contains("一键")
|
||||
? $"多语言导出导回:{(_runMultilingualExportImport ? "开启" : "关闭")}"
|
||||
: "多语言导出导回:本操作不执行";
|
||||
|
||||
return EditorUtility.DisplayDialog(
|
||||
"确认当前出包版本",
|
||||
$"将执行:{actionName}\n\n当前版本:{selected.FullVersion}\nVersionId:{selected.VersionId}\n平台:{_platform}\n包类型:{_package}\n{multilingualLine}\n输出目录:{GetOutputPathPreview()}",
|
||||
"继续",
|
||||
"取消");
|
||||
}
|
||||
|
||||
private void RunAction(string title, System.Func<bool> action)
|
||||
{
|
||||
try
|
||||
{
|
||||
_lastAction = $"{title} running...";
|
||||
Repaint();
|
||||
action();
|
||||
if (!action())
|
||||
{
|
||||
_lastAction = $"{title} cancelled";
|
||||
Debug.Log($"[TH1.UnifiedBuild] {title} cancelled");
|
||||
return;
|
||||
}
|
||||
|
||||
_lastAction = $"{title} OK";
|
||||
Debug.Log($"[TH1.UnifiedBuild] {title} OK");
|
||||
}
|
||||
@ -579,9 +998,33 @@ namespace TH1_Logic.Editor
|
||||
}
|
||||
finally
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
Repaint();
|
||||
}
|
||||
}
|
||||
|
||||
private enum BuildStageState
|
||||
{
|
||||
Pending,
|
||||
Running,
|
||||
Done,
|
||||
Skipped,
|
||||
Failed
|
||||
}
|
||||
|
||||
private sealed class BuildStageItem
|
||||
{
|
||||
public readonly string Title;
|
||||
public string Detail;
|
||||
public BuildStageState State;
|
||||
|
||||
public BuildStageItem(string title)
|
||||
{
|
||||
Title = title;
|
||||
Detail = string.Empty;
|
||||
State = BuildStageState.Pending;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public enum BuildPlatformProfile
|
||||
@ -592,7 +1035,7 @@ namespace TH1_Logic.Editor
|
||||
|
||||
public enum PackageProfile
|
||||
{
|
||||
Test,
|
||||
Debug,
|
||||
Release
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user