MenuChangeAppLanguage.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. using System.Collections.Generic;
  2. using System.IO;
  3. using System.Text.RegularExpressions;
  4. using UnityEditor;
  5. using UnityEditor.Build;
  6. using UnityEngine;
  7. public class MenuChangeAppLanguage
  8. {
  9. enum LanguageType { CN = 0, EN = 1 }
  10. enum DeviceType { iPhone, iPad }
  11. static void RefreshMenuChecked()
  12. {
  13. int lang = CommonConfig.AppLanguage; //EditorPrefs.GetInt("AppLanguage", 0);
  14. string iosTarget = PlayerSettings.GetApplicationIdentifier(BuildTargetGroup.iOS);
  15. Menu.SetChecked("APP语言版本切换/中文/iPhone", lang == 0 && iosTarget.Contains("BowArrow") && !iosTarget.Contains("Pad"));
  16. Menu.SetChecked("APP语言版本切换/中文/iPad", lang == 0 && iosTarget.Contains("PadBowArrow"));
  17. Menu.SetChecked("APP语言版本切换/海外/iPhone", lang == 1 && iosTarget.Contains("BowArrowEn") && !iosTarget.Contains("Pad"));
  18. Menu.SetChecked("APP语言版本切换/海外/iPad", lang == 1 && iosTarget.Contains("PadBowArrowEn"));
  19. }
  20. [MenuItem("APP语言版本切换/中文/iPhone")]
  21. static void CN_iPhone() => ApplySetting(LanguageType.CN, DeviceType.iPhone);
  22. [MenuItem("APP语言版本切换/中文/iPhone", true)]
  23. static bool CN_iPhone_Validate() { RefreshMenuChecked(); return true; }
  24. [MenuItem("APP语言版本切换/中文/iPad")]
  25. static void CN_iPad() => ApplySetting(LanguageType.CN, DeviceType.iPad);
  26. [MenuItem("APP语言版本切换/中文/iPad", true)]
  27. static bool CN_iPad_Validate() { RefreshMenuChecked(); return true; }
  28. [MenuItem("APP语言版本切换/海外/iPhone")]
  29. static void EN_iPhone() => ApplySetting(LanguageType.EN, DeviceType.iPhone);
  30. [MenuItem("APP语言版本切换/海外/iPhone", true)]
  31. static bool EN_iPhone_Validate() { RefreshMenuChecked(); return true; }
  32. [MenuItem("APP语言版本切换/海外/iPad")]
  33. static void EN_iPad() => ApplySetting(LanguageType.EN, DeviceType.iPad);
  34. [MenuItem("APP语言版本切换/海外/iPad", true)]
  35. static bool EN_iPad_Validate() { RefreshMenuChecked(); return true; }
  36. static void ApplySetting(LanguageType lang, DeviceType device)
  37. {
  38. int langId = (int)lang;
  39. // EditorPrefs.SetInt("AppLanguage", langId);
  40. if (CommonConfig.bInfraredApp)
  41. {
  42. PlayerSettings.productName = CommonConfig.StandaloneModeOrPlatformB
  43. ? CommonConfig.AppNames[2]
  44. : CommonConfig.AppNames[langId];
  45. }
  46. else
  47. {
  48. PlayerSettings.productName = CommonConfig.StandaloneModeOrPlatformB
  49. ? CommonConfig.AppNames[2]
  50. : CommonConfig.AppNames9Axis[langId];
  51. }
  52. #if UNITY_IOS
  53. string bundleId = lang switch
  54. {
  55. LanguageType.CN => device == DeviceType.iPhone ? "com.xmjssvr.BowArrow" : "com.xmjssvr.PadBowArrow",
  56. LanguageType.EN => device == DeviceType.iPhone ? "com.xmjssvr.BowArrowEn" : "com.xmjssvr.PadBowArrowEn",
  57. _ => "com.xmjssvr.BowArrow"
  58. };
  59. PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.iOS, bundleId);
  60. //现在iphone模式需要上传ipad
  61. PlayerSettings.iOS.targetDevice = device == DeviceType.iPhone ? iOSTargetDevice.iPhoneAndiPad : iOSTargetDevice.iPadOnly;
  62. PlayerSettings.iOS.appleDeveloperTeamID = "WR7WD35237";
  63. PlayerSettings.iOS.appleEnableAutomaticSigning = true;
  64. #endif
  65. #if UNITY_ANDROID
  66. string androidId = lang switch
  67. {
  68. LanguageType.CN => CommonConfig.StandaloneModeOrPlatformB
  69. ? "com.xmjssvr.BowArrow.miBClient"
  70. : "com.xmjssvr.BowArrow.mi",
  71. LanguageType.EN => CommonConfig.StandaloneModeOrPlatformB
  72. ? "com.xmjssvr.BowArrowEn.BClient"
  73. : "com.xmjssvr.BowArrowEn",
  74. _ => "com.xmjssvr.BowArrow"
  75. };
  76. PlayerSettings.SetApplicationIdentifier(BuildTargetGroup.Android, androidId);
  77. #endif
  78. SetIosAppIcon(langId, device);
  79. }
  80. static void SetIosAppIcon(int langId, DeviceType device)
  81. {
  82. //string path = langId == 1
  83. // ? "Assets/BowArrow/Textures/Common/AppIconEN.png"
  84. // : "Assets/BowArrow/Textures/Common/AppIcon2.png";
  85. string path;
  86. if (device == DeviceType.iPad)
  87. {
  88. // iPad版,选用 Pad 专用图标
  89. path = langId == 1
  90. ? "Assets/BowArrow/Textures/Common/AppIconPadEN.png"
  91. : "Assets/BowArrow/Textures/Common/AppIconPad.png";
  92. }
  93. else
  94. {
  95. // 普通版
  96. path = langId == 1
  97. ? "Assets/BowArrow/Textures/Common/AppIconEN.png"
  98. : "Assets/BowArrow/Textures/Common/AppIcon2.png";
  99. }
  100. Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>(path);
  101. if (texture == null)
  102. {
  103. Debug.LogWarning("图标文件未找到:" + path);
  104. return;
  105. }
  106. Texture2D[] icons = PlayerSettings.GetIconsForTargetGroup(BuildTargetGroup.Unknown);
  107. for (int i = 0; i < icons.Length; i++) icons[i] = texture;
  108. PlayerSettings.SetIconsForTargetGroup(BuildTargetGroup.Unknown, icons);
  109. AssetDatabase.SaveAssets();
  110. #if UNITY_IOS
  111. if (device == DeviceType.iPhone)
  112. ApplyAllIosIcons(langId);
  113. else
  114. ClearIosIcons();
  115. #endif
  116. }
  117. private static readonly string iconPathCN = "Assets/BowArrow/Textures/Common/AppIconsCN"; // iOS中文图标文件夹
  118. private static readonly string iconPathEN = "Assets/BowArrow/Textures/Common/AppIconsEN"; // iOS英文图标文件夹
  119. /// <summary>
  120. /// 批量导入 iOS 所有图标
  121. /// </summary>
  122. public static void ApplyAllIosIcons(int langId)
  123. {
  124. string iconPath = langId == 1 ? iconPathEN : iconPathCN;
  125. // ✅ 收集文件
  126. string[] files = Directory.GetFiles(iconPath, "*.png", SearchOption.AllDirectories);
  127. if (files.Length == 0)
  128. {
  129. Debug.LogError($"未找到图标文件: {iconPath}");
  130. return;
  131. }
  132. // ✅ 解析像素尺寸
  133. Dictionary<int, Texture2D> pixelMap = new();
  134. foreach (string file in files)
  135. {
  136. Texture2D tex = AssetDatabase.LoadAssetAtPath<Texture2D>(file);
  137. if (tex == null) continue;
  138. if (TryParseIconPixel(file, out int pixels))
  139. {
  140. pixelMap[pixels] = tex;
  141. Debug.Log($"识别图标: {Path.GetFileName(file)} → {pixels}px");
  142. }
  143. }
  144. #if UNITY_2022_1_OR_NEWER
  145. var target = NamedBuildTarget.iOS;
  146. var iconKinds = PlayerSettings.GetSupportedIconKinds(target);
  147. foreach (var kind in iconKinds)
  148. {
  149. var icons = PlayerSettings.GetPlatformIcons(target, kind);
  150. // ✅ 清空旧图标
  151. for (int i = 0; i < icons.Length; i++)
  152. icons[i].SetTexture(null);
  153. for (int i = 0; i < icons.Length; i++)
  154. {
  155. int size = Mathf.RoundToInt(icons[i].width);
  156. if (pixelMap.TryGetValue(size, out var tex))
  157. {
  158. icons[i].SetTexture(tex);
  159. Debug.Log($"✅ [2022+] 设置 {kind} 图标 {size}px");
  160. }
  161. }
  162. PlayerSettings.SetPlatformIcons(target, kind, icons);
  163. }
  164. #else
  165. var group = BuildTargetGroup.iOS;
  166. var iconKinds = PlayerSettings.GetSupportedIconKindsForPlatform(group);
  167. foreach (var kind in iconKinds)
  168. {
  169. var icons = PlayerSettings.GetPlatformIcons(group, kind);
  170. // ✅ 清空旧图标
  171. for (int i = 0; i < icons.Length; i++)
  172. icons[i].SetTexture(null);
  173. for (int i = 0; i < icons.Length; i++)
  174. {
  175. int size = Mathf.RoundToInt(icons[i].width);
  176. if (pixelMap.TryGetValue(size, out var tex))
  177. {
  178. icons[i].SetTexture(tex);
  179. Debug.Log($"✅ [2021] 设置 {kind} 图标 {size}px");
  180. }
  181. }
  182. PlayerSettings.SetPlatformIcons(group, kind, icons);
  183. }
  184. #endif
  185. AssetDatabase.SaveAssets();
  186. Debug.Log("🎯 iOS App Icons 全部导入完成!");
  187. }
  188. public static void ClearIosIcons()
  189. {
  190. #if UNITY_2022_1_OR_NEWER
  191. var target = NamedBuildTarget.iOS;
  192. var iconKinds = PlayerSettings.GetSupportedIconKinds(target);
  193. foreach (var kind in iconKinds)
  194. {
  195. var icons = PlayerSettings.GetPlatformIcons(target, kind);
  196. // ✅ 清空旧图标
  197. for (int i = 0; i < icons.Length; i++)
  198. icons[i].SetTexture(null);
  199. PlayerSettings.SetPlatformIcons(target, kind, icons);
  200. }
  201. #else
  202. var group = BuildTargetGroup.iOS;
  203. var iconKinds = PlayerSettings.GetSupportedIconKindsForPlatform(group);
  204. foreach (var kind in iconKinds)
  205. {
  206. var icons = PlayerSettings.GetPlatformIcons(group, kind);
  207. // ✅ 清空旧图标
  208. for (int i = 0; i < icons.Length; i++)
  209. icons[i].SetTexture(null);
  210. PlayerSettings.SetPlatformIcons(group, kind, icons);
  211. }
  212. #endif
  213. AssetDatabase.SaveAssets();
  214. Debug.Log("🎯 iOS App Icons 全部清空!");
  215. }
  216. /// <summary>
  217. /// 支持多种命名方式的像素解析
  218. /// </summary>
  219. private static bool TryParseIconPixel(string file, out int pixels)
  220. {
  221. pixels = 0;
  222. string name = Path.GetFileNameWithoutExtension(file);
  223. // ① 匹配 iPhoneApp_60pt@3x → 180px
  224. Match m = Regex.Match(name, @"(\d+(?:\.\d+)?)pt@(\d+)x");
  225. if (m.Success)
  226. {
  227. float pt = float.Parse(m.Groups[1].Value);
  228. int scale = int.Parse(m.Groups[2].Value);
  229. pixels = Mathf.RoundToInt(pt * scale);
  230. return true;
  231. }
  232. // ② 匹配 store_1024pt 或 icon_60pt(无倍数,pt=px)
  233. m = Regex.Match(name, @"(\d+)pt");
  234. if (m.Success)
  235. {
  236. pixels = int.Parse(m.Groups[1].Value);
  237. return true;
  238. }
  239. // ③ 匹配直接像素命名 icon_180x180
  240. m = Regex.Match(name, @"(\d+)x\d+");
  241. if (m.Success)
  242. {
  243. pixels = int.Parse(m.Groups[1].Value);
  244. return true;
  245. }
  246. // ④ 特殊情况:AppStore_1024.png
  247. m = Regex.Match(name, @"1024");
  248. if (m.Success)
  249. {
  250. pixels = 1024;
  251. return true;
  252. }
  253. return false;
  254. }
  255. /// <summary>
  256. /// 从文件名中提取像素尺寸,如 "iPhoneApp_60pt@3x" → 180px
  257. /// </summary>
  258. //private static bool TryParseIconPixel(string file, out int pixels)
  259. //{
  260. // pixels = 0;
  261. // string name = Path.GetFileNameWithoutExtension(file);
  262. // Match m = Regex.Match(name, @"(\d+(?:\.\d+)?)pt@(\d+)x");
  263. // if (m.Success)
  264. // {
  265. // float pt = float.Parse(m.Groups[1].Value);
  266. // int scale = int.Parse(m.Groups[2].Value);
  267. // pixels = Mathf.RoundToInt(pt * scale);
  268. // return true;
  269. // }
  270. // // 匹配直接像素命名: Icon_120x120.png
  271. // m = Regex.Match(name, @"(\d+)x\d+");
  272. // if (m.Success)
  273. // {
  274. // pixels = int.Parse(m.Groups[1].Value);
  275. // return true;
  276. // }
  277. // return false;
  278. //}
  279. }