UI系统组件
This commit is contained in:
@@ -313,9 +313,25 @@ namespace BaseGames.Editor
|
||||
// ── 流式加载系统 ──────────────────────────────────────────────────
|
||||
ScaffoldStreamingSystem(services, report);
|
||||
|
||||
// ── 多设备 UI 焦点守护(EventSystem 上挂 UISelectionRestorer)──────────
|
||||
EnsureUISelectionRestorer(report);
|
||||
|
||||
MarkDirtyAndLog("Persistent 场景脚手架", root, report);
|
||||
}
|
||||
|
||||
/// <summary>确保场景中的 EventSystem 挂有 <see cref="BaseGames.UI.UISelectionRestorer"/>(多设备焦点守护,幂等)。</summary>
|
||||
private static void EnsureUISelectionRestorer(List<string> report)
|
||||
{
|
||||
var es = Object.FindObjectOfType<UnityEngine.EventSystems.EventSystem>();
|
||||
if (es == null)
|
||||
{
|
||||
report.Add("未找到 EventSystem,UISelectionRestorer 未挂载(键盘/手柄丢失焦点后无法自动恢复)。请确认 Persistent 场景含 EventSystem + InputSystemUIInputModule。");
|
||||
return;
|
||||
}
|
||||
if (es.GetComponent<BaseGames.UI.UISelectionRestorer>() == null)
|
||||
Undo.AddComponent<BaseGames.UI.UISelectionRestorer>(es.gameObject);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
// Scaffold Main Menu Scene
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
@@ -357,6 +373,7 @@ namespace BaseGames.Editor
|
||||
var subTmp = GetOrAddComponent<TextMeshProUGUI>(subtitleRt.gameObject);
|
||||
subTmp.text = "A 2D Action Adventure"; subTmp.fontSize = 40f; subTmp.alignment = TextAlignmentOptions.Center;
|
||||
subTmp.color = new Color(0.7f, 0.66f, 0.55f, 0.9f); subTmp.raycastTarget = false; subTmp.characterSpacing = 8f;
|
||||
BindLocalizedText(subtitleRt.gameObject, "MENU_SUBTITLE");
|
||||
|
||||
// ── 主菜单控制器 ──────────────────────────────────────────────────
|
||||
MainMenuController menuCtrl = GetOrAddComponent<MainMenuController>(canvasGo);
|
||||
@@ -386,6 +403,11 @@ namespace BaseGames.Editor
|
||||
var le = GetOrAddComponent<LayoutElement>(b);
|
||||
le.preferredHeight = 64f; le.minHeight = 56f;
|
||||
}
|
||||
BindLocalizedButton(btnNewGameGo, "MENU_NEW_GAME");
|
||||
BindLocalizedButton(btnContinueGo, "MENU_CONTINUE");
|
||||
BindLocalizedButton(btnSettingsGo, "MENU_SETTINGS");
|
||||
BindLocalizedButton(btnCreditsGo, "MENU_CREDITS");
|
||||
BindLocalizedButton(btnQuitGo, "MENU_QUIT");
|
||||
|
||||
AssignReference(menuCtrl, "_btnNewGame", btnNewGameGo.GetComponent<Button>());
|
||||
AssignReference(menuCtrl, "_btnContinue", btnContinueGo.GetComponent<Button>());
|
||||
@@ -416,6 +438,7 @@ namespace BaseGames.Editor
|
||||
var slotTitleTmp = GetOrAddComponent<TextMeshProUGUI>(slotTitleRt.gameObject);
|
||||
slotTitleTmp.text = "Select Save"; slotTitleTmp.fontSize = 56f; slotTitleTmp.fontStyle = FontStyles.Bold;
|
||||
slotTitleTmp.alignment = TextAlignmentOptions.Center; slotTitleTmp.color = GoldText; slotTitleTmp.raycastTarget = false;
|
||||
BindLocalizedText(slotTitleRt.gameObject, "SAVESLOT_TITLE");
|
||||
|
||||
// 卡片容器(居中竖排)
|
||||
var slotsContainerRt = GetOrCreateUIChild(saveSlotPanelGo.transform, "SlotsContainer");
|
||||
@@ -450,6 +473,7 @@ namespace BaseGames.Editor
|
||||
SetRect(slotBackRt, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0.5f, 0f),
|
||||
new Vector2(0f, 70f), new Vector2(260f, 64f));
|
||||
StyleAsTextButton(slotBackGo, 30f);
|
||||
BindLocalizedButton(slotBackGo, "BTN_BACK");
|
||||
AssignReference(menuCtrl, "_btnCloseSaveSlot", slotBackGo.GetComponent<Button>());
|
||||
|
||||
// ── ConfirmDialog(覆盖 / 删除确认)─────────────────────
|
||||
@@ -460,15 +484,17 @@ namespace BaseGames.Editor
|
||||
NewGameModeController modeCtrl = BuildNewGameMode(saveSlotPanelGo.transform);
|
||||
AssignReference(saveSlotCtrl, "_modeSelect", modeCtrl);
|
||||
|
||||
// ── SettingsPanel ─────────────────────────────────────────────────
|
||||
// ── SettingsPanel(音量 / 画面 / 可访问性 / 语言)──────────────────
|
||||
var settingsPanelRt = GetOrCreateUIChild(canvasGo.transform, "SettingsPanel");
|
||||
StretchFull(settingsPanelRt);
|
||||
BuildSettingsPanel(settingsPanelRt.gameObject, menuCtrl, report);
|
||||
settingsPanelRt.gameObject.SetActive(false);
|
||||
AssignReference(menuCtrl, "_settingsPanel", settingsPanelRt.gameObject);
|
||||
|
||||
// ── CreditsPanel ──────────────────────────────────────────────────
|
||||
// ── CreditsPanel(制作团队)────────────────────────────────────────
|
||||
var creditsPanelRt = GetOrCreateUIChild(canvasGo.transform, "CreditsPanel");
|
||||
StretchFull(creditsPanelRt);
|
||||
BuildCreditsPanel(creditsPanelRt.gameObject, menuCtrl, report);
|
||||
creditsPanelRt.gameObject.SetActive(false);
|
||||
AssignReference(menuCtrl, "_creditsPanel", creditsPanelRt.gameObject);
|
||||
|
||||
@@ -505,20 +531,38 @@ namespace BaseGames.Editor
|
||||
bgImg.type = Image.Type.Simple; bgImg.preserveAspect = true; bgImg.enabled = false;
|
||||
bgImg.transform.SetSiblingIndex(1);
|
||||
|
||||
// 全覆盖选择按钮(透明,金色高亮;位于信息层之下,靠 raycast 接收点击)
|
||||
// 选中/悬停高亮叠加(基色白不透明;显隐由按钮 ColorBlock 的 alpha 控制 → 可见的选中反馈)
|
||||
var hlImg = GetOrCreateImage(slotGo.transform, "Highlight", Color.white, false);
|
||||
hlImg.transform.SetSiblingIndex(2);
|
||||
|
||||
// 全覆盖选择按钮(透明,靠 raycast 接收点击;着色目标为 Highlight 叠加图)
|
||||
GameObject selectGo = GetOrCreateButtonChild(slotGo.transform, "SelectButton", "");
|
||||
StretchFull((RectTransform)selectGo.transform);
|
||||
var selImg = selectGo.GetComponent<Image>();
|
||||
if (selImg != null) selImg.color = new Color(1f, 1f, 1f, 0f);
|
||||
var selLabel = GetButtonLabel(selectGo);
|
||||
if (selLabel != null) selLabel.gameObject.SetActive(false);
|
||||
var selBtn = selectGo.GetComponent<Button>();
|
||||
if (selBtn != null)
|
||||
{
|
||||
selBtn.targetGraphic = hlImg;
|
||||
var cc = selBtn.colors;
|
||||
cc.normalColor = new Color(1f, 0.85f, 0.45f, 0f); // 静态:透明
|
||||
cc.highlightedColor = new Color(1f, 0.86f, 0.5f, 0.08f); // 悬停:极淡金
|
||||
cc.selectedColor = new Color(1f, 0.86f, 0.5f, 0.13f); // 键盘/手柄选中:淡金叠加
|
||||
cc.pressedColor = new Color(1f, 0.86f, 0.5f, 0.22f);
|
||||
cc.disabledColor = new Color(1f, 1f, 1f, 0f);
|
||||
cc.colorMultiplier = 1f; cc.fadeDuration = 0.1f;
|
||||
selBtn.colors = cc;
|
||||
}
|
||||
|
||||
// 空槽提示
|
||||
var emptyRt = GetOrCreateUIChild(slotGo.transform, "EmptyIndicator");
|
||||
StretchFull(emptyRt);
|
||||
GameObject emptyGo = emptyRt.gameObject;
|
||||
GetOrCreateText(emptyGo.transform, "EmptyText", "Empty Slot · New Game", 34f,
|
||||
var emptyText = GetOrCreateText(emptyGo.transform, "EmptyText", "Empty Slot · New Game", 34f,
|
||||
new Color(0.7f, 0.66f, 0.55f, 0.85f), TextAlignmentOptions.Center);
|
||||
BindLocalizedText(emptyText.gameObject, "SAVESLOT_EMPTY");
|
||||
|
||||
// 有档信息区(左侧竖排:区域 / 时长 / 时间)+ 右侧(灵珠 / 生命 / 钢魂)
|
||||
var dataRt = GetOrCreateUIChild(slotGo.transform, "DataIndicator");
|
||||
@@ -540,7 +584,8 @@ namespace BaseGames.Editor
|
||||
var badgeRt = GetOrCreateUIChild(dataGo.transform, "SteelSoulBadge");
|
||||
SetRect(badgeRt, new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(0f, 4f), new Vector2(120f, 40f));
|
||||
GetOrAddComponent<Image>(badgeRt.gameObject).color = new Color(0.5f, 0.55f, 0.6f, 0.5f);
|
||||
GetOrCreateText(badgeRt.transform, "BadgeText", "STEEL", 22f, new Color(0.85f,0.9f,1f,1f), TextAlignmentOptions.Center);
|
||||
var badgeText = GetOrCreateText(badgeRt.transform, "BadgeText", "STEEL", 22f, new Color(0.85f,0.9f,1f,1f), TextAlignmentOptions.Center);
|
||||
BindLocalizedText(badgeText.gameObject, "BADGE_STEELSOUL");
|
||||
GameObject badgeGo = badgeRt.gameObject;
|
||||
|
||||
// 删除按钮(右上角小 ×)
|
||||
@@ -597,6 +642,8 @@ namespace BaseGames.Editor
|
||||
yesGo.GetComponent<Image>().color = new Color(0.45f, 0.12f, 0.12f, 0.85f);
|
||||
GameObject noGo = GetOrCreateButtonChild(boxRt.transform, "Btn_Cancel", "Cancel");
|
||||
SetRect((RectTransform)noGo.transform, new Vector2(0.5f,0f), new Vector2(0.5f,0f), new Vector2(0.5f,0f), new Vector2(150f,40f), new Vector2(220f,64f));
|
||||
BindLocalizedButton(yesGo, "CONFIRM_YES");
|
||||
BindLocalizedButton(noGo, "CONFIRM_NO");
|
||||
|
||||
AssignReference(confirmCtrl, "_root", confirmGo);
|
||||
AssignReference(confirmCtrl, "_titleText", titleTmp);
|
||||
@@ -638,6 +685,10 @@ namespace BaseGames.Editor
|
||||
GameObject backGo = GetOrCreateButtonChild(boxRt.transform, "Btn_Back", "Back");
|
||||
SetRect((RectTransform)backGo.transform, new Vector2(0.5f,0f), new Vector2(0.5f,0f), new Vector2(0.5f,0f), new Vector2(0f,46f), new Vector2(260f,60f));
|
||||
StyleAsTextButton(backGo, 28f);
|
||||
BindLocalizedText(modeTitle.gameObject, "MODE_SELECT_TITLE");
|
||||
BindLocalizedButton(normalGo, "MODE_NORMAL");
|
||||
BindLocalizedButton(steelGo, "MODE_STEELSOUL");
|
||||
BindLocalizedButton(backGo, "BTN_BACK");
|
||||
|
||||
AssignReference(modeCtrl, "_root", modeGo);
|
||||
AssignReference(modeCtrl, "_btnNormal", normalGo.GetComponent<Button>());
|
||||
@@ -1073,18 +1124,273 @@ namespace BaseGames.Editor
|
||||
return t != null ? t.GetComponent<TextMeshProUGUI>() : null;
|
||||
}
|
||||
|
||||
/// <summary>将按钮改造为"纯文字"风格(透明底,仅金色高亮),用于主菜单主按钮列表。</summary>
|
||||
/// <summary>
|
||||
/// 将按钮改造为"纯文字"风格(透明底)。关键:把 Button 的 targetGraphic 指向文字 Label,
|
||||
/// 这样鼠标悬停(Highlighted)与键盘/手柄选中(Selected)会直接给文字着色 → 导航有可见反馈。
|
||||
/// Label 基色设为白,由 ColorBlock 决定静态/高亮/选中的可见色。
|
||||
/// </summary>
|
||||
private static void StyleAsTextButton(GameObject buttonGo, float fontSize = 34f)
|
||||
{
|
||||
var img = buttonGo.GetComponent<Image>();
|
||||
if (img != null) img.color = new Color(1f, 1f, 1f, 0f); // 透明底,仍可作 raycast target
|
||||
if (img != null) { img.color = new Color(1f, 1f, 1f, 0f); img.raycastTarget = true; } // 透明底仍作 raycast target
|
||||
var label = GetButtonLabel(buttonGo);
|
||||
if (label != null)
|
||||
if (label == null) return;
|
||||
label.fontSize = fontSize;
|
||||
label.fontStyle = FontStyles.Normal;
|
||||
label.color = Color.white; // 基色白,实际可见色由 ColorBlock × 该色得到
|
||||
|
||||
var btn = buttonGo.GetComponent<Button>();
|
||||
if (btn == null) return;
|
||||
btn.targetGraphic = label; // 文字作为着色目标 → 选中/悬停可见
|
||||
var c = btn.colors;
|
||||
c.normalColor = new Color(0.60f, 0.56f, 0.42f, 1f); // 静态:暗金
|
||||
c.highlightedColor = new Color(1f, 0.95f, 0.72f, 1f); // 鼠标悬停:亮金
|
||||
c.selectedColor = new Color(1f, 0.95f, 0.72f, 1f); // 键盘/手柄选中:亮金
|
||||
c.pressedColor = new Color(1f, 0.82f, 0.38f, 1f);
|
||||
c.disabledColor = new Color(0.4f, 0.4f, 0.4f, 0.5f);
|
||||
c.colorMultiplier = 1f; c.fadeDuration = 0.1f;
|
||||
btn.colors = c;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 给含 TMP_Text 的节点挂上 <see cref="BaseGames.Localization.LocalizedText"/> 并绑定本地化 key(UI 表)。
|
||||
/// 自动绑定 FontConfig(语言切换时换 CJK 字体),并立即刷新编辑器预览(显示当前语言文本)。
|
||||
/// </summary>
|
||||
private static void BindLocalizedText(GameObject textGo, string key)
|
||||
{
|
||||
if (textGo == null || textGo.GetComponent<TMP_Text>() == null) return;
|
||||
var loc = GetOrAddComponent<BaseGames.Localization.LocalizedText>(textGo);
|
||||
var so = new SerializedObject(loc);
|
||||
so.FindProperty("_key").stringValue = key;
|
||||
var fontCfg = FindFirstAssetByType<BaseGames.Localization.LanguageFontConfigSO>("FontConfig");
|
||||
if (fontCfg != null) so.FindProperty("_fontConfig").objectReferenceValue = fontCfg;
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
loc.UpdateEditorPreview();
|
||||
}
|
||||
|
||||
/// <summary>给 GetOrCreateButtonChild 生成的按钮的 "Label" 子节点绑定本地化 key。</summary>
|
||||
private static void BindLocalizedButton(GameObject buttonGo, string key)
|
||||
{
|
||||
var label = GetButtonLabel(buttonGo);
|
||||
if (label != null) BindLocalizedText(label.gameObject, key);
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
// 设置控件辅助(复用 Unity DefaultControls / TMP_DefaultControls 标准控件层级)
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
private static UnityEngine.UI.DefaultControls.Resources _uiRes;
|
||||
private static UnityEngine.UI.DefaultControls.Resources UIRes()
|
||||
{
|
||||
if (_uiRes.standard == null)
|
||||
_uiRes = new UnityEngine.UI.DefaultControls.Resources
|
||||
{
|
||||
standard = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/UISprite.psd"),
|
||||
background = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Background.psd"),
|
||||
inputField = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/InputFieldBackground.psd"),
|
||||
knob = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Knob.psd"),
|
||||
checkmark = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Checkmark.psd"),
|
||||
dropdown = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/DropdownArrow.psd"),
|
||||
mask = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/UIMask.psd"),
|
||||
};
|
||||
return _uiRes;
|
||||
}
|
||||
|
||||
private static TMPro.TMP_DefaultControls.Resources _tmpRes;
|
||||
private static TMPro.TMP_DefaultControls.Resources TMPRes()
|
||||
{
|
||||
if (_tmpRes.standard == null)
|
||||
_tmpRes = new TMPro.TMP_DefaultControls.Resources
|
||||
{
|
||||
standard = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/UISprite.psd"),
|
||||
background = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Background.psd"),
|
||||
inputField = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/InputFieldBackground.psd"),
|
||||
knob = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Knob.psd"),
|
||||
checkmark = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/Checkmark.psd"),
|
||||
dropdown = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/DropdownArrow.psd"),
|
||||
mask = AssetDatabase.GetBuiltinExtraResource<Sprite>("UI/Skin/UIMask.psd"),
|
||||
};
|
||||
return _tmpRes;
|
||||
}
|
||||
|
||||
/// <summary>将控件 RectTransform 放到行的右半区(横向拉伸、固定高度、垂直居中)。</summary>
|
||||
private static void PlaceRightHalf(RectTransform rt, float height, float rightInset = 12f)
|
||||
{
|
||||
rt.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
rt.anchorMax = new Vector2(1f, 0.5f);
|
||||
rt.pivot = new Vector2(0.5f, 0.5f);
|
||||
rt.offsetMin = new Vector2(8f, -height / 2f);
|
||||
rt.offsetMax = new Vector2(-rightInset, height / 2f);
|
||||
}
|
||||
|
||||
/// <summary>创建/获取一行设置项(左侧本地化标签 + 右半区控件,由调用方填充),返回行 RectTransform。</summary>
|
||||
private static RectTransform CreateSettingRow(Transform content, string name, string labelKey)
|
||||
{
|
||||
var row = GetOrCreateUIChild(content, name);
|
||||
var le = GetOrAddComponent<LayoutElement>(row.gameObject);
|
||||
le.preferredHeight = 56f; le.minHeight = 50f;
|
||||
var label = GetOrCreateText(row, "Label", labelKey, 26f, GoldText, TextAlignmentOptions.MidlineLeft);
|
||||
SetRect((RectTransform)label.transform, new Vector2(0f, 0f), new Vector2(0.5f, 1f), new Vector2(0f, 0.5f), new Vector2(12f, 0f), Vector2.zero);
|
||||
((RectTransform)label.transform).offsetMin = new Vector2(12f, 0f);
|
||||
((RectTransform)label.transform).offsetMax = new Vector2(0f, 0f);
|
||||
BindLocalizedText(label.gameObject, labelKey);
|
||||
return row;
|
||||
}
|
||||
|
||||
private static Slider GetOrCreateSliderInRow(RectTransform row, float min, float max, float val, float rightInset = 12f)
|
||||
{
|
||||
var existing = row.Find("Slider");
|
||||
GameObject go;
|
||||
if (existing != null && existing.GetComponent<Slider>() != null) go = existing.gameObject;
|
||||
else
|
||||
{
|
||||
label.fontSize = fontSize;
|
||||
label.fontStyle = FontStyles.Normal;
|
||||
label.color = GoldText;
|
||||
if (existing != null) Undo.DestroyObjectImmediate(existing.gameObject);
|
||||
go = UnityEngine.UI.DefaultControls.CreateSlider(UIRes());
|
||||
go.name = "Slider";
|
||||
Undo.RegisterCreatedObjectUndo(go, "Create Slider");
|
||||
go.transform.SetParent(row, false);
|
||||
}
|
||||
PlaceRightHalf((RectTransform)go.transform, 20f, rightInset);
|
||||
var s = go.GetComponent<Slider>();
|
||||
s.minValue = min; s.maxValue = max; s.value = val;
|
||||
return s;
|
||||
}
|
||||
|
||||
private static Toggle GetOrCreateToggleInRow(RectTransform row)
|
||||
{
|
||||
var existing = row.Find("Toggle");
|
||||
GameObject go;
|
||||
if (existing != null && existing.GetComponent<Toggle>() != null) go = existing.gameObject;
|
||||
else
|
||||
{
|
||||
if (existing != null) Undo.DestroyObjectImmediate(existing.gameObject);
|
||||
go = UnityEngine.UI.DefaultControls.CreateToggle(UIRes());
|
||||
go.name = "Toggle";
|
||||
Undo.RegisterCreatedObjectUndo(go, "Create Toggle");
|
||||
go.transform.SetParent(row, false);
|
||||
}
|
||||
// 隐藏勾选框自带的 Label(设置项标签由行左侧统一提供)
|
||||
var lbl = go.transform.Find("Label");
|
||||
if (lbl != null) lbl.gameObject.SetActive(false);
|
||||
PlaceRightHalf((RectTransform)go.transform, 28f);
|
||||
return go.GetComponent<Toggle>();
|
||||
}
|
||||
|
||||
private static TMPro.TMP_Dropdown GetOrCreateDropdownInRow(RectTransform row, string[] options)
|
||||
{
|
||||
var existing = row.Find("Dropdown");
|
||||
GameObject go;
|
||||
if (existing != null && existing.GetComponent<TMPro.TMP_Dropdown>() != null) go = existing.gameObject;
|
||||
else
|
||||
{
|
||||
if (existing != null) Undo.DestroyObjectImmediate(existing.gameObject);
|
||||
go = TMPro.TMP_DefaultControls.CreateDropdown(TMPRes());
|
||||
go.name = "Dropdown";
|
||||
Undo.RegisterCreatedObjectUndo(go, "Create Dropdown");
|
||||
go.transform.SetParent(row, false);
|
||||
}
|
||||
PlaceRightHalf((RectTransform)go.transform, 36f);
|
||||
var dd = go.GetComponent<TMPro.TMP_Dropdown>();
|
||||
dd.options.Clear();
|
||||
foreach (var o in options) dd.options.Add(new TMPro.TMP_Dropdown.OptionData(o));
|
||||
dd.value = 0;
|
||||
dd.RefreshShownValue();
|
||||
return dd;
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
// 设置面板 / 制作团队面板构建器
|
||||
// ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
/// <summary>构建设置面板内容(音量 / 画面 / 可访问性 / 语言)并绑定 SettingsPanelController 全部字段。</summary>
|
||||
private static void BuildSettingsPanel(GameObject panelGo, MainMenuController menuCtrl, List<string> report)
|
||||
{
|
||||
var ctrl = GetOrAddComponent<BaseGames.UI.SettingsPanelController>(panelGo);
|
||||
|
||||
GetOrCreateImage(panelGo.transform, "Overlay", new Color(0.04f, 0.05f, 0.08f, 0.97f), true).transform.SetAsFirstSibling();
|
||||
|
||||
var titleTmp = GetOrCreateText(panelGo.transform, "PanelTitle", "Settings", 56f, GoldText, TextAlignmentOptions.Center);
|
||||
titleTmp.fontStyle = FontStyles.Bold;
|
||||
SetRect((RectTransform)titleTmp.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -70f), new Vector2(900f, 80f));
|
||||
BindLocalizedText(titleTmp.gameObject, "SETTINGS_TITLE");
|
||||
|
||||
var content = GetOrCreateUIChild(panelGo.transform, "Content");
|
||||
SetRect(content, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, -10f), new Vector2(860f, 720f));
|
||||
var vlg = GetOrAddComponent<VerticalLayoutGroup>(content.gameObject);
|
||||
vlg.spacing = 8f; vlg.childAlignment = TextAnchor.UpperCenter;
|
||||
vlg.childControlWidth = true; vlg.childControlHeight = true;
|
||||
vlg.childForceExpandWidth = true; vlg.childForceExpandHeight = false;
|
||||
|
||||
// 音量
|
||||
var rMaster = CreateSettingRow(content, "Row_Master", "SETTINGS_MASTER_VOLUME");
|
||||
var rBgm = CreateSettingRow(content, "Row_BGM", "SETTINGS_BGM_VOLUME");
|
||||
var rSfx = CreateSettingRow(content, "Row_SFX", "SETTINGS_SFX_VOLUME");
|
||||
var rAmbient = CreateSettingRow(content, "Row_Ambient", "SETTINGS_AMBIENT_VOLUME");
|
||||
var sMaster = GetOrCreateSliderInRow(rMaster, 0f, 1f, 1f);
|
||||
var sBgm = GetOrCreateSliderInRow(rBgm, 0f, 1f, 0.8f);
|
||||
var sSfx = GetOrCreateSliderInRow(rSfx, 0f, 1f, 1f);
|
||||
var sAmbient = GetOrCreateSliderInRow(rAmbient, 0f, 1f, 0.8f);
|
||||
|
||||
// 画面
|
||||
var rVsync = CreateSettingRow(content, "Row_VSync", "SETTINGS_VSYNC");
|
||||
var tVsync = GetOrCreateToggleInRow(rVsync);
|
||||
var rFps = CreateSettingRow(content, "Row_FPS", "SETTINGS_FPS");
|
||||
var dFps = GetOrCreateDropdownInRow(rFps, new[] { "30", "60", "120", "∞" });
|
||||
|
||||
// 可访问性
|
||||
var rUiScale = CreateSettingRow(content, "Row_UIScale", "SETTINGS_UI_SCALE");
|
||||
var sUiScale = GetOrCreateSliderInRow(rUiScale, 0.8f, 1.5f, 1f, 76f);
|
||||
var uiScaleVal = GetOrCreateText(rUiScale, "ValueText", "100%", 22f, new Color(0.8f,0.78f,0.7f,1f), TextAlignmentOptions.MidlineRight);
|
||||
SetRect((RectTransform)uiScaleVal.transform, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-12f, 0f), new Vector2(64f, 36f));
|
||||
var rColorblind = CreateSettingRow(content, "Row_Colorblind", "SETTINGS_COLORBLIND");
|
||||
var dColorblind = GetOrCreateDropdownInRow(rColorblind, new[] { "关闭", "红色盲", "绿色盲", "蓝黄色盲" });
|
||||
var rShake = CreateSettingRow(content, "Row_ScreenShake", "SETTINGS_SCREEN_SHAKE");
|
||||
var tShake = GetOrCreateToggleInRow(rShake);
|
||||
|
||||
// 语言
|
||||
var rLang = CreateSettingRow(content, "Row_Language", "SETTINGS_LANGUAGE");
|
||||
var dLang = GetOrCreateDropdownInRow(rLang, new[] { "中文", "English", "日本語", "한국어" });
|
||||
|
||||
// 绑定 SettingsPanelController 字段
|
||||
AssignReference(ctrl, "_masterVolume", sMaster);
|
||||
AssignReference(ctrl, "_bgmVolume", sBgm);
|
||||
AssignReference(ctrl, "_sfxVolume", sSfx);
|
||||
AssignReference(ctrl, "_ambientVolume", sAmbient);
|
||||
AssignReference(ctrl, "_vSyncToggle", tVsync);
|
||||
AssignReference(ctrl, "_fpsDropdown", dFps);
|
||||
AssignReference(ctrl, "_uiScaleSlider", sUiScale);
|
||||
AssignReference(ctrl, "_uiScaleValueText", uiScaleVal);
|
||||
AssignReference(ctrl, "_colorblindDropdown", dColorblind);
|
||||
AssignReference(ctrl, "_screenShakeToggle", tShake);
|
||||
AssignReference(ctrl, "_languageDropdown", dLang);
|
||||
|
||||
// 返回按钮
|
||||
GameObject backGo = GetOrCreateButtonChild(panelGo.transform, "BackButton", "Back");
|
||||
SetRect((RectTransform)backGo.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 60f), new Vector2(260f, 64f));
|
||||
StyleAsTextButton(backGo, 30f);
|
||||
BindLocalizedButton(backGo, "BTN_BACK");
|
||||
AssignReference(menuCtrl, "_btnCloseSettings", backGo.GetComponent<Button>());
|
||||
}
|
||||
|
||||
/// <summary>构建制作团队面板(标题 + 滚动正文 + 返回)。</summary>
|
||||
private static void BuildCreditsPanel(GameObject panelGo, MainMenuController menuCtrl, List<string> report)
|
||||
{
|
||||
GetOrCreateImage(panelGo.transform, "Overlay", new Color(0.04f, 0.05f, 0.08f, 0.97f), true).transform.SetAsFirstSibling();
|
||||
|
||||
var titleTmp = GetOrCreateText(panelGo.transform, "PanelTitle", "Credits", 56f, GoldText, TextAlignmentOptions.Center);
|
||||
titleTmp.fontStyle = FontStyles.Bold;
|
||||
SetRect((RectTransform)titleTmp.transform, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -70f), new Vector2(900f, 80f));
|
||||
BindLocalizedText(titleTmp.gameObject, "CREDITS_TITLE");
|
||||
|
||||
var body = GetOrCreateText(panelGo.transform, "Body", "Credits", 30f, new Color(0.82f, 0.8f, 0.74f, 1f), TextAlignmentOptions.Top);
|
||||
SetRect((RectTransform)body.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), new Vector2(900f, 600f));
|
||||
BindLocalizedText(body.gameObject, "CREDITS_BODY");
|
||||
|
||||
GameObject backGo = GetOrCreateButtonChild(panelGo.transform, "BackButton", "Back");
|
||||
SetRect((RectTransform)backGo.transform, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(0f, 60f), new Vector2(260f, 64f));
|
||||
StyleAsTextButton(backGo, 30f);
|
||||
BindLocalizedButton(backGo, "BTN_BACK");
|
||||
AssignReference(menuCtrl, "_btnCloseCredits", backGo.GetComponent<Button>());
|
||||
}
|
||||
|
||||
private static void AssignReference(Object target, string propertyName, Object value)
|
||||
|
||||
Reference in New Issue
Block a user