bingo 项目提交
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
using UnityEditor;
|
||||
using UnityEditor.Callbacks;
|
||||
using UnityEditor.iOS.Xcode;
|
||||
using System.IO;
|
||||
using UnityEditor.Build;
|
||||
using UnityEngine;
|
||||
|
||||
public class PostProcessBuild : IPostprocessBuildWithReport
|
||||
{
|
||||
public int callbackOrder => 1;
|
||||
|
||||
public void OnPostprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
|
||||
{
|
||||
// 检查是否为 iOS 平台构建
|
||||
if (report.summary.platform == BuildTarget.iOS)
|
||||
{
|
||||
string projectPath = report.summary.outputPath;
|
||||
string customControllerPath = "Assets/Editor/UnityAppController.mm"; // 自定义文件的路径
|
||||
string destinationPath = Path.Combine(projectPath, "Classes/UnityAppController.mm");
|
||||
|
||||
if (File.Exists(customControllerPath))
|
||||
{
|
||||
// 复制文件到 Xcode 项目中
|
||||
File.Copy(customControllerPath, destinationPath, overwrite: true);
|
||||
Debug.Log("Custom UnityAppController.mm has been copied to Xcode project.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Custom UnityAppController.mm file not found at " + customControllerPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c63f69f4234bbc4dba0591f050d264f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,50 @@
|
||||
using UnityEditor;
|
||||
using UnityEditor.Callbacks;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
public class PostProcessBuild_AddPod
|
||||
{
|
||||
[PostProcessBuild]
|
||||
public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject)
|
||||
{
|
||||
if (target == BuildTarget.iOS)
|
||||
{
|
||||
// 定位到 Podfile 文件路径
|
||||
string podfilePath = Path.Combine(pathToBuiltProject, "Podfile");
|
||||
|
||||
// 确保文件存在
|
||||
if (File.Exists(podfilePath))
|
||||
{
|
||||
// 读取 Podfile 文件内容
|
||||
string podfileContent = File.ReadAllText(podfilePath);
|
||||
|
||||
// 检查是否已经包含 DataEyeSDK,避免重复添加
|
||||
if (!podfileContent.Contains("pod 'DataEyeSDK'"))
|
||||
{
|
||||
// 在 `target 'UnityFramework'` 中增加 pod 指令
|
||||
string targetPattern = "target 'UnityFramework' do";
|
||||
if (podfileContent.Contains(targetPattern))
|
||||
{
|
||||
int insertIndex = podfileContent.IndexOf(targetPattern) + targetPattern.Length;
|
||||
string customPod = "\n pod 'DataEyeSDK'";
|
||||
podfileContent = podfileContent.Insert(insertIndex, customPod);
|
||||
|
||||
// 写回 Podfile 文件
|
||||
File.WriteAllText(podfilePath, podfileContent);
|
||||
|
||||
Debug.Log("Successfully added 'pod DataEyeSDK' to Podfile.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("'DataEyeSDK' is already included in the Podfile.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Podfile not found in the Xcode project.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0017801dce894dd7ba10c85d6f5560f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 067f6e53cf452c346a71ba54b7fc6b8f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,22 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b9eba1ecab4c43c41869985e270bbe09, type: 3}
|
||||
m_Name: QSettingsObjectAsset
|
||||
m_EditorClassIdentifier:
|
||||
settingStringNames: []
|
||||
settingStringValues: []
|
||||
settingFloatNames: []
|
||||
settingFloatValues: []
|
||||
settingIntNames: []
|
||||
settingIntValues:
|
||||
settingBoolNames: []
|
||||
settingBoolValues:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d639541d7e9b9184db2daba1c91c466d
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,28 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b29e98153ec2fbd44b8f7da1b41194e8, type: 3}
|
||||
m_Name: SpineSettings
|
||||
m_EditorClassIdentifier:
|
||||
defaultScale: 0.01
|
||||
defaultMix: 0.2
|
||||
defaultShader: Spine/Skeleton
|
||||
defaultZSpacing: 0
|
||||
defaultInstantiateLoop: 1
|
||||
showHierarchyIcons: 1
|
||||
setTextureImporterSettings: 1
|
||||
textureSettingsReference: Assets/Jarvis/Plugins/Spine/Editor/spine-unity/Editor/ImporterPresets/PMATexturePreset.preset
|
||||
atlasTxtImportWarning: 1
|
||||
textureImporterWarning: 1
|
||||
autoReloadSceneSkeletons: 1
|
||||
handleScale: 1
|
||||
mecanimEventIncludeFolderName: 1
|
||||
timelineUseBlendDuration: 1
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ae20d9a08b1fc44cad457d1f036e36d
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6f68f433665e402f9035b6aa0a343d30
|
||||
timeCreated: 1705568778
|
||||
@@ -0,0 +1,90 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BingoBrain.Editor
|
||||
{
|
||||
public class AssetBundleBuildKit
|
||||
{
|
||||
public const string AssetBundleRootPath = "Assets/AssetHotFix/";
|
||||
public const string AssetBundleSuffix = ".assetbundle";
|
||||
static void SetABName(string assetPath)
|
||||
{
|
||||
var importerPath = $"Assets{assetPath[Application.dataPath.Length..]}";
|
||||
importerPath = importerPath.Replace("\\", "/");
|
||||
const string assetBundleRootPath = AssetBundleRootPath;
|
||||
|
||||
if (importerPath.StartsWith(assetBundleRootPath))
|
||||
{
|
||||
var bundleName = importerPath.Replace(assetBundleRootPath, "");
|
||||
|
||||
var endIndex = bundleName.LastIndexOf("/", StringComparison.Ordinal);
|
||||
|
||||
if (endIndex <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var fileInfo = new FileInfo(importerPath);
|
||||
|
||||
if ((fileInfo.Attributes & FileAttributes.Directory) == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
bundleName = bundleName.ToLower().Substring(0, endIndex).Replace("/", ".");
|
||||
|
||||
var importer = AssetImporter.GetAtPath(importerPath);
|
||||
if (importer != null)
|
||||
{
|
||||
importer.assetBundleName = $"{bundleName}{AssetBundleSuffix}";
|
||||
if (importer.assetBundleName != null)
|
||||
{
|
||||
importer.assetBundleVariant = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError(importerPath);
|
||||
Debug.LogError(endIndex);
|
||||
Debug.LogError(e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void SetAssetBundlesName(string _assetsPath)
|
||||
{
|
||||
var dir = new DirectoryInfo(_assetsPath);
|
||||
|
||||
var files = dir.GetFileSystemInfos();
|
||||
|
||||
for (var i = 0; i < files.Length; i++)
|
||||
{
|
||||
if (files[i] is DirectoryInfo)
|
||||
{
|
||||
SetAssetBundlesName(files[i].FullName);
|
||||
}
|
||||
else if (!files[i].Name.EndsWith(".meta"))
|
||||
{
|
||||
SetABName(files[i].FullName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void ClearAssetBundlesName()
|
||||
{
|
||||
var abNames = AssetDatabase.GetAllAssetBundleNames();
|
||||
|
||||
|
||||
for (var i = 0; i < abNames.Length; i++)
|
||||
{
|
||||
AssetDatabase.RemoveAssetBundleName(abNames[i], true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0d705bde2444bc7800da81344efcfa2
|
||||
timeCreated: 1705384501
|
||||
@@ -0,0 +1,148 @@
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Comgreate;
|
||||
|
||||
namespace BingoBrain.Editor
|
||||
{
|
||||
public class BuildSome
|
||||
{
|
||||
public const string AssetBundleRootPath = "Assets/AssetHotFix/";
|
||||
public static readonly string AssetBundleBuildOutputPath =
|
||||
$"{Application.dataPath}/../AssetBundle/{AssetBundlesName}";
|
||||
public const string AssetBundlesName = "AssetBundles";
|
||||
public const string AssetBundleSuffix = ".assetbundle";
|
||||
public const string AssetBundlePassword = "4s2f6ac15sa6ds45";
|
||||
|
||||
[MenuItem("Tools/Build")]
|
||||
public static void BuildAssetBundle()
|
||||
{
|
||||
AssetBundleBuildKit.ClearAssetBundlesName();
|
||||
|
||||
AssetBundleBuildKit.SetAssetBundlesName(AssetBundleRootPath);
|
||||
|
||||
EditorApplication.isPlaying = false;
|
||||
|
||||
var dir = AssetBundleBuildOutputPath;
|
||||
|
||||
if (!Directory.Exists(dir))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
Directory.Delete(dir, true);
|
||||
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
|
||||
|
||||
var buildTarget = EditorUserBuildSettings.activeBuildTarget;
|
||||
|
||||
var manifest = BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.ChunkBasedCompression,
|
||||
buildTarget);
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
EncryptAssetBundle();
|
||||
|
||||
BuildAssetBundleFileIndex(manifest);
|
||||
|
||||
Debug.Log($"[ Jarvis ] [ AssetBundle构建 ] 平台: {buildTarget.ToString()} 打包完成");
|
||||
|
||||
Application.OpenURL(dir + "/..");
|
||||
}
|
||||
|
||||
|
||||
private static void EncryptAssetBundle()
|
||||
{
|
||||
var dir = AssetBundleBuildOutputPath;
|
||||
|
||||
var filePaths = Directory.GetFiles(dir, $"*{AssetBundleSuffix}",
|
||||
SearchOption.TopDirectoryOnly);
|
||||
|
||||
|
||||
var encryptPath = $"{Application.dataPath}/../AssetBundlesEncrypt";
|
||||
|
||||
if (!Directory.Exists(encryptPath))
|
||||
{
|
||||
Directory.CreateDirectory(encryptPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
Directory.Delete(encryptPath, true);
|
||||
|
||||
Directory.CreateDirectory(encryptPath);
|
||||
}
|
||||
|
||||
foreach (var assetBundleFile in filePaths)
|
||||
{
|
||||
if (!assetBundleFile.EndsWith(".meta") && !assetBundleFile.Contains(".DS_Store"))
|
||||
{
|
||||
var assetBundleName = assetBundleFile.Replace(dir, string.Empty).Replace("\\", "");
|
||||
var encryptFilePath = Path.Combine(encryptPath, assetBundleName);
|
||||
AESForFileKit.EncryptFile(assetBundleFile, encryptFilePath,
|
||||
AssetBundlePassword);
|
||||
|
||||
File.Copy(encryptFilePath, Path.Combine(dir, assetBundleName), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Directory.Delete(encryptPath, true);
|
||||
}
|
||||
public const string AssetHotFixFileName = "AssetHotFixFile.txt";
|
||||
|
||||
private static void BuildAssetBundleFileIndex(AssetBundleManifest manifest)
|
||||
{
|
||||
var dir = AssetBundleBuildOutputPath;
|
||||
var dirFile = $"{AssetBundleBuildOutputPath}/../";
|
||||
|
||||
var filePath = Path.Combine(dirFile, AssetHotFixFileName);
|
||||
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
File.Delete(filePath);
|
||||
}
|
||||
|
||||
|
||||
var filePaths = Directory.GetFiles(dir, $"*{AssetBundleSuffix}",
|
||||
SearchOption.TopDirectoryOnly);
|
||||
|
||||
using var fileStream = new FileStream(filePath, FileMode.CreateNew);
|
||||
|
||||
using var streamWriter = new StreamWriter(fileStream);
|
||||
|
||||
var totalAssetBundlePath = $"{dir}/{AssetBundlesName}";
|
||||
|
||||
var totalAssetBundleManifestPath = $"{dir}/{AssetBundlesManifestName}";
|
||||
|
||||
var totalMD5 = MD5Kit.GetFileMD5(totalAssetBundlePath);
|
||||
streamWriter.WriteLine(GetAssetBundleFileIndex(AssetBundlesName, totalMD5));
|
||||
|
||||
var manifestMD5 = MD5Kit.GetFileMD5(totalAssetBundleManifestPath);
|
||||
streamWriter.WriteLine(GetAssetBundleFileIndex(AssetBundlesManifestName,
|
||||
manifestMD5));
|
||||
foreach (var assetBundleFile in filePaths)
|
||||
{
|
||||
if (!assetBundleFile.EndsWith(".meta") && !assetBundleFile.Contains(".DS_Store"))
|
||||
{
|
||||
var fileMD5 = MD5Kit.GetFileMD5(assetBundleFile);
|
||||
|
||||
var assetBundleName = assetBundleFile.Replace(dir, string.Empty).Replace("\\", "");
|
||||
|
||||
streamWriter.WriteLine(GetAssetBundleFileIndex(assetBundleName, fileMD5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static string GetAssetBundleFileIndex(string assetBundleName, string assetBundleFileMD5)
|
||||
{
|
||||
return $"{assetBundleName}{AssetBundleSplitChar}{assetBundleFileMD5}";
|
||||
}
|
||||
|
||||
public const string ManifestSuffix = ".manifest";
|
||||
public static readonly string AssetBundlesManifestName = $"{AssetBundlesName}{ManifestSuffix}";
|
||||
public static readonly string AssetBundleSplitChar = "|";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 737ea17132a549b08f03ba4d45d7bc56
|
||||
timeCreated: 1705384441
|
||||
@@ -0,0 +1,241 @@
|
||||
using FairyGUI;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BingoBrain.Editor
|
||||
{
|
||||
public static class FGUIContollerConstantKit
|
||||
{
|
||||
private const string content =
|
||||
@"
|
||||
|
||||
/// <summary>
|
||||
/// FGUI控制器自动生成
|
||||
/// </summary>
|
||||
namespace FGUI.{0}
|
||||
{
|
||||
public partial class className
|
||||
{
|
||||
{1} }
|
||||
}";
|
||||
|
||||
private static Dictionary<string, string> classDic = new();
|
||||
private static Dictionary<string, string> constClassDic = new();
|
||||
|
||||
private static string C_DestFolderPath =
|
||||
Application.dataPath + "/Comgreate/Logic/FGUI/ControlDefine/Common/";
|
||||
|
||||
private static string DestFolderPath =
|
||||
Application.dataPath + "/Comgreate/Logic/FGUI/ControlDefine/Project/";
|
||||
|
||||
[MenuItem("Tools/CreateCtrl")]
|
||||
public static void CreateAllControllerScripts()
|
||||
{
|
||||
UIPackage.RemoveAllPackages();
|
||||
|
||||
CreateControllerScripts(true);
|
||||
CreateControllerScripts(false);
|
||||
|
||||
UIPackage.RemoveAllPackages();
|
||||
var stage = GameObject.Find("Stage");
|
||||
if (stage != null)
|
||||
{
|
||||
Object.DestroyImmediate(stage);
|
||||
}
|
||||
|
||||
var stageCamera = GameObject.Find("Stage Camera");
|
||||
if (stageCamera != null)
|
||||
{
|
||||
Object.DestroyImmediate(stageCamera);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void CreateController_ScriptsCommon()
|
||||
{
|
||||
UIPackage.RemoveAllPackages();
|
||||
|
||||
CreateControllerScripts(true);
|
||||
|
||||
UIPackage.RemoveAllPackages();
|
||||
}
|
||||
|
||||
|
||||
public static void CreateController_ScriptsProject()
|
||||
{
|
||||
UIPackage.RemoveAllPackages();
|
||||
|
||||
CreateControllerScripts(false);
|
||||
|
||||
UIPackage.RemoveAllPackages();
|
||||
}
|
||||
|
||||
private static void CreateControllerScripts(bool isCreateCommon)
|
||||
{
|
||||
classDic.Clear();
|
||||
constClassDic.Clear();
|
||||
|
||||
string[] ids = AssetDatabase.FindAssets("_fui t:textAsset");
|
||||
foreach (var item in ids)
|
||||
{
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(item);
|
||||
int pos = assetPath.LastIndexOf("_fui");
|
||||
if (pos == -1)
|
||||
continue;
|
||||
|
||||
assetPath = assetPath.Substring(0, pos);
|
||||
LoadOneUI(assetPath, isCreateCommon);
|
||||
}
|
||||
|
||||
CreateScripts(isCreateCommon);
|
||||
}
|
||||
|
||||
private static void CreateScripts(bool isCreateCommon)
|
||||
{
|
||||
if (isCreateCommon)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Directory.Exists(DestFolderPath))
|
||||
{
|
||||
Directory.Delete(DestFolderPath, true);
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(DestFolderPath);
|
||||
}
|
||||
|
||||
string startPre = isCreateCommon ? C_DestFolderPath : DestFolderPath;
|
||||
foreach (var item in classDic)
|
||||
{
|
||||
if (item.Key.StartsWith(startPre))
|
||||
FileKit.CreateTxt(item.Key, item.Value, true);
|
||||
}
|
||||
|
||||
foreach (var item in constClassDic)
|
||||
{
|
||||
if (item.Key.StartsWith(startPre))
|
||||
FileKit.CreateTxt(item.Key, item.Value, true);
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
private static void LoadOneUI(string resPath, bool isCreateCommon)
|
||||
{
|
||||
string objName = new FileInfo(Path.GetFullPath(resPath)).Name;
|
||||
UIPackage pkg = UIPackage.GetByName(objName);
|
||||
if (pkg == null)
|
||||
{
|
||||
pkg = UIPackage.AddPackage(resPath);
|
||||
}
|
||||
|
||||
foreach (var item in pkg.GetItems())
|
||||
{
|
||||
if (item.type == PackageItemType.Component)
|
||||
{
|
||||
GComponent gComponent = null;
|
||||
|
||||
var tmpGomponent = pkg.CreateObject(item.name);
|
||||
gComponent = tmpGomponent as GComponent;
|
||||
|
||||
if (gComponent == null)
|
||||
{
|
||||
DisposeGObject(tmpGomponent);
|
||||
continue;
|
||||
}
|
||||
|
||||
string tmpPropertyStr = "";
|
||||
string constPropertyStr = "";
|
||||
List<string> nameList = new List<string>();
|
||||
foreach (var tmp in gComponent.Controllers)
|
||||
{
|
||||
nameList.Clear();
|
||||
for (int i = 0; i < tmp.pageCount; i++)
|
||||
{
|
||||
string name = tmp.GetPageName(i).Replace(" ", "");
|
||||
if (nameList.Contains(name))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
nameList.Add(name);
|
||||
|
||||
string summary = @" /// <summary>
|
||||
/// {0}:{1}
|
||||
/// </summary>
|
||||
";
|
||||
summary = string.Format(summary, i, tmp.GetPageName(i));
|
||||
|
||||
tmpPropertyStr += summary;
|
||||
constPropertyStr += summary;
|
||||
string contName = tmp.name.Replace("cont_", "");
|
||||
contName = FirstLetterToUpper(contName);
|
||||
tmpPropertyStr += string.Format("public int _{0}_{1} = {2};\r\n", contName, name, i);
|
||||
constPropertyStr += string.Format("public const int {0}_{1} = {2};\r\n", contName, name, i);
|
||||
}
|
||||
}
|
||||
|
||||
List<Controller> controllers = gComponent.Controllers;
|
||||
DisposeGObject(gComponent);
|
||||
if (controllers.Count != 0)
|
||||
{
|
||||
if (isCreateCommon)
|
||||
{
|
||||
if (!pkg.name.StartsWith("C"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pkg.name.StartsWith("C"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
string objClassContent = content.Replace("{0}", pkg.name).Replace("{1}", tmpPropertyStr)
|
||||
.Replace("className", item.name);
|
||||
string constClassContent = content.Replace("{0}", pkg.name).Replace("{1}", constPropertyStr)
|
||||
.Replace("className", item.name);
|
||||
string prePath = pkg.name.StartsWith("C") ? C_DestFolderPath : DestFolderPath;
|
||||
string path = prePath + pkg.name + "/" + item.name + "_AutoCreator.cs";
|
||||
string constPath = prePath + pkg.name + "/" + item.name + "_Const.cs";
|
||||
if (!classDic.ContainsKey(path))
|
||||
{
|
||||
classDic.Add(path, objClassContent);
|
||||
constClassDic.Add(constPath, constClassContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DisposeGObject(GObject gObject)
|
||||
{
|
||||
gObject.Dispose();
|
||||
if (gObject.displayObject != null)
|
||||
{
|
||||
if (gObject.displayObject.gameObject)
|
||||
{
|
||||
Object.Destroy(gObject.displayObject.gameObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string FirstLetterToUpper(string str)
|
||||
{
|
||||
if (str == null)
|
||||
return null;
|
||||
|
||||
if (str.Length > 1)
|
||||
return char.ToUpper(str[0]) + str.Substring(1);
|
||||
|
||||
return str.ToUpper();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4b4c038f692d4d7f9790562beb637d71
|
||||
timeCreated: 1705385121
|
||||
@@ -0,0 +1,40 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BingoBrain.Editor
|
||||
{
|
||||
public static class FileKit
|
||||
{
|
||||
public static void CreateTxt(string path, string Txt, bool IsCover = false, bool IsAssetPath = false)
|
||||
{
|
||||
if (IsAssetPath)
|
||||
{
|
||||
path = Application.dataPath.Replace("Assets", string.Empty) + path;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(GetFullDiretoryPath(path)))
|
||||
{
|
||||
Directory.CreateDirectory(GetFullDiretoryPath(path));
|
||||
}
|
||||
|
||||
if (File.Exists(path))
|
||||
{
|
||||
if (!IsCover)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
File.Delete(path);
|
||||
}
|
||||
|
||||
File.WriteAllText(path, Txt, new UTF8Encoding(false));
|
||||
}
|
||||
|
||||
public static string GetFullDiretoryPath(string filePath)
|
||||
{
|
||||
string fileName = Path.GetFileName(filePath);
|
||||
return filePath.Replace(fileName, string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fee6df4c57174846a073a8c9de464651
|
||||
timeCreated: 1705385221
|
||||
@@ -0,0 +1,746 @@
|
||||
#import "UnityAppController.h"
|
||||
#import "UnityAppController+ViewHandling.h"
|
||||
#import "UnityAppController+Rendering.h"
|
||||
#import "iPhone_Sensors.h"
|
||||
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
#import <QuartzCore/CADisplayLink.h>
|
||||
#import <Availability.h>
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
||||
#include <mach/mach_time.h>
|
||||
|
||||
// MSAA_DEFAULT_SAMPLE_COUNT was removed
|
||||
// ENABLE_INTERNAL_PROFILER and related defines were moved to iPhone_Profiler.h
|
||||
// kFPS define for removed: you can use Application.targetFrameRate (30 fps by default)
|
||||
// DisplayLink is the only run loop mode now - all others were removed
|
||||
|
||||
#include "CrashReporter.h"
|
||||
|
||||
#include "UI/OrientationSupport.h"
|
||||
#include "UI/UnityView.h"
|
||||
#include "UI/Keyboard.h"
|
||||
#include "UI/UnityViewControllerBase.h"
|
||||
#include "Unity/InternalProfiler.h"
|
||||
#include "Unity/DisplayManager.h"
|
||||
#include "Unity/ObjCRuntime.h"
|
||||
#include "PluginBase/AppDelegateListener.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
|
||||
#import <CoreTelephony/CTCarrier.h>
|
||||
#import "CustomAppController.h"
|
||||
#import "H5View.h"
|
||||
#import "EventMark.h"
|
||||
#import <DataEyeSDK.h>
|
||||
|
||||
// we assume that app delegate is never changed and we can cache it, instead of re-query UIApplication every time
|
||||
UnityAppController* _UnityAppController = nil;
|
||||
UnityAppController* GetAppController()
|
||||
{
|
||||
return _UnityAppController;
|
||||
}
|
||||
|
||||
// we keep old bools around to support "old" code that might have used them
|
||||
bool _ios81orNewer = false, _ios82orNewer = false, _ios83orNewer = false, _ios90orNewer = false, _ios91orNewer = false;
|
||||
bool _ios100orNewer = false, _ios101orNewer = false, _ios102orNewer = false, _ios103orNewer = false;
|
||||
bool _ios110orNewer = false, _ios111orNewer = false, _ios112orNewer = false;
|
||||
bool _ios130orNewer = false, _ios140orNewer = false, _ios150orNewer = false, _ios160orNewer = false;
|
||||
|
||||
// was core of Unity loaded (non-graphics part prior to loading first scene)
|
||||
bool _unityEngineInitialized = false;
|
||||
// was unity rendering already inited: we should not touch rendering while this is false
|
||||
bool _renderingInited = false;
|
||||
// was unity inited: we should not touch unity api while this is false
|
||||
bool _unityAppReady = false;
|
||||
// see if there's a need to do internal player pause/resume handling
|
||||
//
|
||||
// Typically the trampoline code should manage this internally, but
|
||||
// there are use cases, videoplayer, plugin code, etc where the player
|
||||
// is paused before the internal handling comes relevant. Avoid
|
||||
// overriding externally managed player pause/resume handling by
|
||||
// caching the state
|
||||
bool _wasPausedExternal = false;
|
||||
// should we skip present on next draw: used in corner cases (like rotation) to fill both draw-buffers with some content
|
||||
bool _skipPresent = false;
|
||||
// was app "resigned active": some operations do not make sense while app is in background
|
||||
bool _didResignActive = false;
|
||||
|
||||
#if UNITY_SUPPORT_ROTATION
|
||||
// Required to enable specific orientation for some presentation controllers: see supportedInterfaceOrientationsForWindow below for details
|
||||
NSInteger _forceInterfaceOrientationMask = 0;
|
||||
#endif
|
||||
|
||||
@implementation UnityAppController
|
||||
|
||||
@synthesize unityView = _unityView;
|
||||
@synthesize unityDisplayLink = _displayLink;
|
||||
|
||||
@synthesize rootView = _rootView;
|
||||
@synthesize rootViewController = _rootController;
|
||||
@synthesize mainDisplay = _mainDisplay;
|
||||
@synthesize renderDelegate = _renderDelegate;
|
||||
@synthesize quitHandler = _quitHandler;
|
||||
|
||||
#if UNITY_SUPPORT_ROTATION
|
||||
@synthesize interfaceOrientation = _curOrientation;
|
||||
#endif
|
||||
|
||||
- (id)init
|
||||
{
|
||||
if ((self = _UnityAppController = [super init]))
|
||||
{
|
||||
// due to clang issues with generating warning for overriding deprecated methods
|
||||
// we will simply assert if deprecated methods are present
|
||||
// NB: methods table is initied at load (before this call), so it is ok to check for override
|
||||
NSAssert(![self respondsToSelector: @selector(createUnityViewImpl)],
|
||||
@"createUnityViewImpl is deprecated and will not be called. Override createUnityView"
|
||||
);
|
||||
NSAssert(![self respondsToSelector: @selector(createViewHierarchyImpl)],
|
||||
@"createViewHierarchyImpl is deprecated and will not be called. Override willStartWithViewController"
|
||||
);
|
||||
NSAssert(![self respondsToSelector: @selector(createViewHierarchy)],
|
||||
@"createViewHierarchy is deprecated and will not be implemented. Use createUI"
|
||||
);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setWindow:(id)object {}
|
||||
- (UIWindow*)window { return _window; }
|
||||
|
||||
|
||||
- (void)shouldAttachRenderDelegate {}
|
||||
- (void)preStartUnity {}
|
||||
|
||||
|
||||
- (void)startUnity:(UIApplication*)application
|
||||
{
|
||||
NSAssert(_unityAppReady == NO, @"[UnityAppController startUnity:] called after Unity has been initialized");
|
||||
|
||||
UnityInitApplicationGraphics();
|
||||
|
||||
#if !PLATFORM_VISIONOS
|
||||
// we make sure that first level gets correct display list and orientation
|
||||
[[DisplayManager Instance] updateDisplayListCacheInUnity];
|
||||
#endif
|
||||
|
||||
UnityLoadApplication();
|
||||
Profiler_InitProfiler();
|
||||
|
||||
[self showGameUI];
|
||||
[self createDisplayLink];
|
||||
|
||||
UnitySetPlayerFocus(1);
|
||||
|
||||
AVAudioSession* audioSession = [AVAudioSession sharedInstance];
|
||||
// If Unity audio is disabled, we set the category to ambient to make sure we don't mute other app's audio. We set the audio session
|
||||
// to active so we can get outputVolume callbacks. If Unity audio is enabled, FMOD should have already handled all of this AVAudioSession init.
|
||||
if (!UnityIsAudioManagerAvailableAndEnabled())
|
||||
{
|
||||
[audioSession setCategory: AVAudioSessionCategoryAmbient error: nil];
|
||||
[audioSession setActive: YES error: nil];
|
||||
}
|
||||
[audioSession addObserver: self forKeyPath: @"outputVolume" options: 0 context: nil];
|
||||
UnityUpdateMuteState([audioSession outputVolume] < 0.01f ? 1 : 0);
|
||||
|
||||
#if UNITY_REPLAY_KIT_AVAILABLE
|
||||
void InitUnityReplayKit(); // Classes/Unity/UnityReplayKit.mm
|
||||
|
||||
InitUnityReplayKit();
|
||||
#endif
|
||||
|
||||
//自己加的部分
|
||||
[UIApplication sharedApplication].statusBarHidden = YES;
|
||||
|
||||
|
||||
UIView* unityView = UnityGetGLView();
|
||||
|
||||
UIViewController *vc = [UIViewController new];
|
||||
vc.modalPresentationStyle = UIModalPresentationFullScreen;
|
||||
//[vc.view setFrame:self.window.bounds];
|
||||
//[vc.view setBackgroundColor:[UIColor orangeColor]];
|
||||
[self.window setRootViewController:vc];
|
||||
|
||||
[vc.view addSubview:unityView];
|
||||
H5View *hview;
|
||||
hview = [H5View shared];
|
||||
[vc.view addSubview:hview];
|
||||
|
||||
|
||||
[hview setFrame:self.window.bounds];
|
||||
[hview initView];
|
||||
CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init];
|
||||
|
||||
if (@available(iOS 12.0, *)) {
|
||||
NSDictionary *ctDict = networkInfo.serviceSubscriberCellularProviders;
|
||||
if ([ctDict allKeys].count > 1) {
|
||||
NSArray *keys = [ctDict allKeys];
|
||||
CTCarrier *carrier1 = [ctDict objectForKey:[keys firstObject]];
|
||||
CTCarrier *carrier2 = [ctDict objectForKey:[keys lastObject]];
|
||||
if (carrier1.mobileCountryCode.length && carrier2.mobileCountryCode.length) {
|
||||
UnitySendMessage("WebviewManager", "diaoyongtest", "TRUE");
|
||||
|
||||
}else if (!carrier1.mobileCountryCode.length && !carrier2.mobileCountryCode.length) {
|
||||
UnitySendMessage("WebviewManager", "diaoyongtest", "FALSE");
|
||||
|
||||
}else {
|
||||
UnitySendMessage("WebviewManager", "diaoyongtest", "TRUE");
|
||||
}
|
||||
}else if ([ctDict allKeys].count == 1) {
|
||||
NSArray *keys = [ctDict allKeys];
|
||||
CTCarrier *carrier1 = [ctDict objectForKey:[keys firstObject]];
|
||||
if (carrier1.mobileCountryCode.length) {
|
||||
UnitySendMessage("WebviewManager", "diaoyongtest", "TRUE");
|
||||
}else {
|
||||
UnitySendMessage("WebviewManager", "diaoyongtest", "FALSE");
|
||||
}
|
||||
}else {
|
||||
UnitySendMessage("WebviewManager", "diaoyongtest", "FALSE");
|
||||
}
|
||||
}
|
||||
NSArray *preferredLanguages = [NSLocale preferredLanguages];
|
||||
NSString *firstLanguage = preferredLanguages.firstObject;
|
||||
}
|
||||
|
||||
extern "C" void UnityDestroyDisplayLink()
|
||||
{
|
||||
[GetAppController() destroyDisplayLink];
|
||||
}
|
||||
|
||||
extern "C" void UnityRequestQuit()
|
||||
{
|
||||
_didResignActive = true;
|
||||
if (GetAppController().quitHandler)
|
||||
GetAppController().quitHandler();
|
||||
else
|
||||
exit(0);
|
||||
}
|
||||
|
||||
extern void SensorsCleanup();
|
||||
extern "C" void UnityCleanupTrampoline()
|
||||
{
|
||||
// Unity view and viewController will not necessary be destroyed right after this function execution.
|
||||
// We need to ensure that these objects will not receive any callbacks from system during that time.
|
||||
[_UnityAppController window].rootViewController = nil;
|
||||
[[_UnityAppController unityView] removeFromSuperview];
|
||||
|
||||
// Prevent multiple cleanups
|
||||
if (_UnityAppController == nil)
|
||||
return;
|
||||
|
||||
[KeyboardDelegate Destroy];
|
||||
|
||||
SensorsCleanup();
|
||||
|
||||
Profiler_UninitProfiler();
|
||||
|
||||
[DisplayManager Destroy];
|
||||
|
||||
UnityDestroyDisplayLink();
|
||||
|
||||
_UnityAppController = nil;
|
||||
}
|
||||
|
||||
#if UNITY_SUPPORT_ROTATION
|
||||
|
||||
- (NSUInteger)application:(UIApplication*)application supportedInterfaceOrientationsForWindow:(UIWindow*)window
|
||||
{
|
||||
return UIInterfaceOrientationMaskPortrait;
|
||||
// No rootViewController is set because we are switching from one view controller to another, all orientations should be enabled
|
||||
if ([window rootViewController] == nil)
|
||||
return UIInterfaceOrientationMaskAll;
|
||||
|
||||
// During splash screen show phase no forced orientations should be allowed.
|
||||
// This will prevent unwanted rotation while splash screen is on and application is not yet ready to present (Ex. Fogbugz cases: 1190428, 1269547).
|
||||
if (!_unityAppReady)
|
||||
return [_rootController supportedInterfaceOrientations];
|
||||
|
||||
// Some presentation controllers (e.g. UIImagePickerController) require portrait orientation and will throw exception if it is not supported.
|
||||
// At the same time enabling all orientations by returning UIInterfaceOrientationMaskAll might cause unwanted orientation change
|
||||
// (e.g. when using UIActivityViewController to "share to" another application, iOS will use supportedInterfaceOrientations to possibly reorient).
|
||||
// So to avoid exception we are returning combination of constraints for root view controller and orientation requested by iOS.
|
||||
// _forceInterfaceOrientationMask is updated in willChangeStatusBarOrientation, which is called if some presentation controller insists on orientation change.
|
||||
return [[window rootViewController] supportedInterfaceOrientations] | _forceInterfaceOrientationMask;
|
||||
}
|
||||
|
||||
- (void)application:(UIApplication*)application willChangeStatusBarOrientation:(UIInterfaceOrientation)newStatusBarOrientation duration:(NSTimeInterval)duration
|
||||
{
|
||||
// Setting orientation mask which is requested by iOS: see supportedInterfaceOrientationsForWindow above for details
|
||||
_forceInterfaceOrientationMask = 1 << newStatusBarOrientation;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if UNITY_USES_REMOTE_NOTIFICATIONS
|
||||
|
||||
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
|
||||
{
|
||||
AppController_SendNotificationWithArg(kUnityDidRegisterForRemoteNotificationsWithDeviceToken, deviceToken);
|
||||
}
|
||||
|
||||
#if !PLATFORM_TVOS
|
||||
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
|
||||
{
|
||||
AppController_SendNotificationWithArg(kUnityDidReceiveRemoteNotification, userInfo);
|
||||
|
||||
if (handler)
|
||||
{
|
||||
handler(UIBackgroundFetchResultNoData);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
- (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error
|
||||
{
|
||||
AppController_SendNotificationWithArg(kUnityDidFailToRegisterForRemoteNotificationsWithError, error);
|
||||
|
||||
// alas people do not check remote notification error through api (which is clunky, i agree) so log here to have at least some visibility
|
||||
::printf("\nFailed to register for remote notifications:\n%s\n\n", [[error localizedDescription] UTF8String]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// UIApplicationOpenURLOptionsKey was added only in ios10 sdk, while we still support ios9 sdk
|
||||
- (BOOL)application:(UIApplication*)app openURL:(NSURL*)url options:(NSDictionary<NSString*, id>*)options
|
||||
{
|
||||
id sourceApplication = options[UIApplicationOpenURLOptionsSourceApplicationKey], annotation = options[UIApplicationOpenURLOptionsAnnotationKey];
|
||||
|
||||
NSMutableDictionary<NSString*, id>* notifData = [NSMutableDictionary dictionaryWithCapacity: 3];
|
||||
if (url)
|
||||
{
|
||||
notifData[@"url"] = url;
|
||||
UnitySetAbsoluteURL(url.absoluteString.UTF8String);
|
||||
}
|
||||
if (sourceApplication) notifData[@"sourceApplication"] = sourceApplication;
|
||||
if (annotation) notifData[@"annotation"] = annotation;
|
||||
|
||||
AppController_SendNotificationWithArg(kUnityOnOpenURL, notifData);
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray<id<UIUserActivityRestoring> > * _Nullable restorableObjects))restorationHandler
|
||||
{
|
||||
NSURL* url = userActivity.webpageURL;
|
||||
if (url)
|
||||
UnitySetAbsoluteURL(url.absoluteString.UTF8String);
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication*)application willFinishLaunchingWithOptions:(NSDictionary*)launchOptions
|
||||
{
|
||||
AppController_SendNotificationWithArg(kUnityWillFinishLaunchingWithOptions, launchOptions);
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (UIWindowScene*)pickStartupWindowScene:(NSSet<UIScene*>*)scenes API_AVAILABLE(ios(13.0), tvos(13.0))
|
||||
{
|
||||
// if we have scene with UISceneActivationStateForegroundActive - pick it
|
||||
// otherwise UISceneActivationStateForegroundInactive will work
|
||||
// it will be the scene going into active state
|
||||
// if there were no active/inactive scenes (only background) we should allow background scene
|
||||
// this might happen in some cases with native plugins doing "things"
|
||||
UIWindowScene *foregroundScene = nil, *backgroundScene = nil;
|
||||
for (UIScene* scene in scenes)
|
||||
{
|
||||
if (![scene isKindOfClass: [UIWindowScene class]])
|
||||
continue;
|
||||
UIWindowScene* windowScene = (UIWindowScene*)scene;
|
||||
|
||||
if (scene.activationState == UISceneActivationStateForegroundActive)
|
||||
return windowScene;
|
||||
if (scene.activationState == UISceneActivationStateForegroundInactive)
|
||||
foregroundScene = windowScene;
|
||||
else if (scene.activationState == UISceneActivationStateBackground)
|
||||
backgroundScene = windowScene;
|
||||
}
|
||||
|
||||
return foregroundScene ? foregroundScene : backgroundScene;
|
||||
}
|
||||
|
||||
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
|
||||
{
|
||||
::printf("-> applicationDidFinishLaunching()\n");
|
||||
|
||||
// send notfications
|
||||
#if !PLATFORM_TVOS && !PLATFORM_VISIONOS
|
||||
if ([UIDevice currentDevice].generatesDeviceOrientationNotifications == NO)
|
||||
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
|
||||
#endif
|
||||
|
||||
|
||||
EventMark *eventMark;
|
||||
eventMark = [EventMark sharedEventMark];
|
||||
[eventMark initDataEyeSDK];
|
||||
|
||||
|
||||
if ([self isBackgroundLaunchOptions: launchOptions])
|
||||
return YES;
|
||||
|
||||
[self initUnityWithApplication: application];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)isBackgroundLaunchOptions:(NSDictionary*)launchOptions
|
||||
{
|
||||
if (launchOptions.count == 0)
|
||||
return NO;
|
||||
|
||||
// launch due to location event, the app likely will stay in background
|
||||
BOOL locationLaunch = [[launchOptions valueForKey: UIApplicationLaunchOptionsLocationKey] boolValue];
|
||||
if (locationLaunch)
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)initUnityWithApplication:(UIApplication*)application
|
||||
{
|
||||
if (_unityEngineInitialized)
|
||||
return;
|
||||
_unityEngineInitialized = true;
|
||||
|
||||
// basic unity init
|
||||
UnityInitApplicationNoGraphics(UnityDataBundleDir());
|
||||
|
||||
[self selectRenderingAPI];
|
||||
[UnityRenderingView InitializeForAPI: self.renderingAPI];
|
||||
|
||||
#if !PLATFORM_VISIONOS
|
||||
if (@available(iOS 13, tvOS 13, *))
|
||||
_window = [[UIWindow alloc] initWithWindowScene: [self pickStartupWindowScene: application.connectedScenes]];
|
||||
else
|
||||
_window = [[UIWindow alloc] initWithFrame: [UIScreen mainScreen].bounds];
|
||||
#else
|
||||
_window = [[UIWindow alloc] init];
|
||||
#endif
|
||||
|
||||
_unityView = [self createUnityView];
|
||||
|
||||
|
||||
[DisplayManager Initialize];
|
||||
_mainDisplay = [DisplayManager Instance].mainDisplay;
|
||||
[_mainDisplay createWithWindow: _window andView: _unityView];
|
||||
|
||||
[self createUI];
|
||||
[self preStartUnity];
|
||||
|
||||
// if you wont use keyboard you may comment it out at save some memory
|
||||
[KeyboardDelegate Initialize];
|
||||
|
||||
#if UNITY_DEVELOPER_BUILD
|
||||
// Causes a black screen after splash screen, but would deadlock if waiting for manged debugger otherwise
|
||||
[self performSelector: @selector(startUnity:) withObject: application afterDelay: 0];
|
||||
#else
|
||||
[self startUnity: application];
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey, id> *)change context:(void *)context
|
||||
{
|
||||
if ([keyPath isEqual: @"outputVolume"])
|
||||
{
|
||||
UnityUpdateMuteState([[AVAudioSession sharedInstance] outputVolume] < 0.01f ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication*)application
|
||||
{
|
||||
::printf("-> applicationDidEnterBackground()\n");
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication*)application
|
||||
{
|
||||
::printf("-> applicationWillEnterForeground()\n");
|
||||
|
||||
// applicationWillEnterForeground: might sometimes arrive *before* actually initing unity (e.g. locking on startup)
|
||||
if (_unityAppReady)
|
||||
{
|
||||
// if we were showing video before going to background - the view size may be changed while we are in background
|
||||
[GetAppController().unityView recreateRenderingSurfaceIfNeeded];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applicationDidBecomeActive:(UIApplication*)application
|
||||
{
|
||||
::printf("-> applicationDidBecomeActive()\n");
|
||||
|
||||
[self removeSnapshotViewController];
|
||||
|
||||
if (_unityAppReady)
|
||||
{
|
||||
if (UnityIsPaused() && _wasPausedExternal == false)
|
||||
{
|
||||
UnityWillResume();
|
||||
UnityPause(0);
|
||||
}
|
||||
if (_wasPausedExternal)
|
||||
{
|
||||
if (UnityIsFullScreenPlaying())
|
||||
TryResumeFullScreenVideo();
|
||||
}
|
||||
// need to do this with delay because FMOD restarts audio in AVAudioSessionInterruptionNotification handler
|
||||
[self performSelector: @selector(updateUnityAudioOutput) withObject: nil afterDelay: 0.1];
|
||||
UnitySetPlayerFocus(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
[self initUnityWithApplication: application];
|
||||
}
|
||||
|
||||
_didResignActive = false;
|
||||
}
|
||||
|
||||
- (void)updateUnityAudioOutput
|
||||
{
|
||||
UnityUpdateMuteState([[AVAudioSession sharedInstance] outputVolume] < 0.01f ? 1 : 0);
|
||||
}
|
||||
|
||||
- (void)addSnapshotViewController
|
||||
{
|
||||
if (!_didResignActive || self->_snapshotViewController)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UIView* snapshotView = [self createSnapshotView];
|
||||
|
||||
if (snapshotView != nil)
|
||||
{
|
||||
UIViewController* snapshotViewController = [AllocUnityViewController() init];
|
||||
snapshotViewController.modalPresentationStyle = UIModalPresentationFullScreen;
|
||||
snapshotViewController.view = snapshotView;
|
||||
|
||||
[self->_rootController presentViewController: snapshotViewController animated: false completion: nil];
|
||||
self->_snapshotViewController = snapshotViewController;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)removeSnapshotViewController
|
||||
{
|
||||
// do this on the main queue async so that if we try to create one
|
||||
// and remove in the same frame, this always happens after in the same queue
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self->_snapshotViewController)
|
||||
{
|
||||
// we've got a view on top of the snapshot view (3rd party plugin/social media login etc).
|
||||
if (self->_snapshotViewController.presentedViewController)
|
||||
{
|
||||
[self performSelector: @selector(removeSnapshotViewController) withObject: nil afterDelay: 0.05];
|
||||
return;
|
||||
}
|
||||
|
||||
[self->_snapshotViewController dismissViewControllerAnimated: NO completion: nil];
|
||||
self->_snapshotViewController = nil;
|
||||
|
||||
// Make sure that the keyboard input field regains focus after the application becomes active.
|
||||
[[KeyboardDelegate Instance] becomeFirstResponder];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication*)application
|
||||
{
|
||||
::printf("-> applicationWillResignActive()\n");
|
||||
|
||||
if (_unityAppReady)
|
||||
{
|
||||
UnitySetPlayerFocus(0);
|
||||
|
||||
// signal unity that the frame rendering have ended
|
||||
// as we will not get the callback from the display link current frame
|
||||
UnityDisplayLinkCallback(0);
|
||||
|
||||
_wasPausedExternal = UnityIsPaused();
|
||||
if (_wasPausedExternal == false)
|
||||
{
|
||||
// Pause Unity only if we don't need special background processing
|
||||
// otherwise batched player loop can be called to run user scripts.
|
||||
if (!UnityGetUseCustomAppBackgroundBehavior())
|
||||
{
|
||||
#if UNITY_SNAPSHOT_VIEW_ON_APPLICATION_PAUSE
|
||||
// Force player to do one more frame, so scripts get a chance to render custom screen for minimized app in task manager.
|
||||
// NB: UnityWillPause will schedule OnApplicationPause message, which will be sent normally inside repaint (unity player loop)
|
||||
// NB: We will actually pause after the loop (when calling UnityPause).
|
||||
UnityWillPause();
|
||||
[self repaint];
|
||||
UnityWaitForFrame();
|
||||
[self addSnapshotViewController];
|
||||
#endif
|
||||
UnityPause(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_didResignActive = true;
|
||||
}
|
||||
|
||||
- (void)applicationDidReceiveMemoryWarning:(UIApplication*)application
|
||||
{
|
||||
UnityLowMemory();
|
||||
}
|
||||
|
||||
- (void)applicationWillTerminate:(UIApplication*)application
|
||||
{
|
||||
::printf("-> applicationWillTerminate()\n");
|
||||
|
||||
// Only clean up if Unity has finished initializing, else the clean up process will crash,
|
||||
// this happens if the app is force closed immediately after opening it.
|
||||
if (_unityAppReady)
|
||||
{
|
||||
UnityCleanup();
|
||||
UnityCleanupTrampoline();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)application:(UIApplication*)application handleEventsForBackgroundURLSession:(nonnull NSString *)identifier completionHandler:(nonnull void (^)())completionHandler
|
||||
{
|
||||
NSDictionary* arg = @{identifier: completionHandler};
|
||||
AppController_SendNotificationWithArg(kUnityHandleEventsForBackgroundURLSession, arg);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
void AppController_SendNotification(NSString* name)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName: name object: GetAppController()];
|
||||
}
|
||||
|
||||
void AppController_SendNotificationWithArg(NSString* name, id arg)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName: name object: GetAppController() userInfo: arg];
|
||||
}
|
||||
|
||||
void AppController_SendUnityViewControllerNotification(NSString* name)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName: name object: UnityGetGLViewController()];
|
||||
}
|
||||
|
||||
extern "C" UIWindow* UnityGetMainWindow()
|
||||
{
|
||||
return GetAppController().mainDisplay.window;
|
||||
}
|
||||
|
||||
extern "C" UIViewController* UnityGetGLViewController()
|
||||
{
|
||||
return GetAppController().rootViewController;
|
||||
}
|
||||
|
||||
extern "C" UIView* UnityGetGLView()
|
||||
{
|
||||
return GetAppController().unityView;
|
||||
}
|
||||
|
||||
extern "C" ScreenOrientation UnityCurrentOrientation() { return GetAppController().unityView.contentOrientation; }
|
||||
|
||||
|
||||
bool LogToNSLogHandler(LogType logType, const char* log, va_list list)
|
||||
{
|
||||
NSLogv([NSString stringWithUTF8String: log], list);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void AddNewAPIImplIfNeeded();
|
||||
|
||||
// From https://stackoverflow.com/questions/4744826/detecting-if-ios-app-is-run-in-debugger
|
||||
static bool isDebuggerAttachedToConsole(void)
|
||||
// Returns true if the current process is being debugged (either
|
||||
// running under the debugger or has a debugger attached post facto).
|
||||
{
|
||||
int junk;
|
||||
int mib[4];
|
||||
struct kinfo_proc info;
|
||||
size_t size;
|
||||
|
||||
// Initialize the flags so that, if sysctl fails for some bizarre
|
||||
// reason, we get a predictable result.
|
||||
|
||||
info.kp_proc.p_flag = 0;
|
||||
|
||||
// Initialize mib, which tells sysctl the info we want, in this case
|
||||
// we're looking for information about a specific process ID.
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
mib[2] = KERN_PROC_PID;
|
||||
mib[3] = getpid();
|
||||
|
||||
// Call sysctl.
|
||||
|
||||
size = sizeof(info);
|
||||
junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
|
||||
assert(junk == 0);
|
||||
|
||||
// We're being debugged if the P_TRACED flag is set.
|
||||
|
||||
return ((info.kp_proc.p_flag & P_TRACED) != 0);
|
||||
}
|
||||
|
||||
void UnityInitTrampoline()
|
||||
{
|
||||
InitCrashHandling();
|
||||
|
||||
NSString* version = [[UIDevice currentDevice] systemVersion];
|
||||
#define CHECK_VER(s) [version compare: s options: NSNumericSearch] != NSOrderedAscending
|
||||
_ios81orNewer = CHECK_VER(@"8.1"); _ios82orNewer = CHECK_VER(@"8.2"); _ios83orNewer = CHECK_VER(@"8.3");
|
||||
_ios90orNewer = CHECK_VER(@"9.0"); _ios91orNewer = CHECK_VER(@"9.1");
|
||||
_ios100orNewer = CHECK_VER(@"10.0"); _ios101orNewer = CHECK_VER(@"10.1"); _ios102orNewer = CHECK_VER(@"10.2"); _ios103orNewer = CHECK_VER(@"10.3");
|
||||
_ios110orNewer = CHECK_VER(@"11.0"); _ios111orNewer = CHECK_VER(@"11.1"); _ios112orNewer = CHECK_VER(@"11.2");
|
||||
_ios130orNewer = CHECK_VER(@"13.0"); _ios140orNewer = CHECK_VER(@"14.0"); _ios150orNewer = CHECK_VER(@"15.0");
|
||||
_ios160orNewer = CHECK_VER(@"16.0");
|
||||
#undef CHECK_VER
|
||||
|
||||
AddNewAPIImplIfNeeded();
|
||||
|
||||
#if !TARGET_IPHONE_SIMULATOR
|
||||
// Use NSLog logging if a debugger is not attached, otherwise we write to stdout.
|
||||
if (!isDebuggerAttachedToConsole())
|
||||
UnitySetLogEntryHandler(LogToNSLogHandler);
|
||||
#endif
|
||||
}
|
||||
|
||||
extern "C" bool UnityiOS81orNewer() { return _ios81orNewer; }
|
||||
extern "C" bool UnityiOS82orNewer() { return _ios82orNewer; }
|
||||
extern "C" bool UnityiOS90orNewer() { return _ios90orNewer; }
|
||||
extern "C" bool UnityiOS91orNewer() { return _ios91orNewer; }
|
||||
extern "C" bool UnityiOS100orNewer() { return _ios100orNewer; }
|
||||
extern "C" bool UnityiOS101orNewer() { return _ios101orNewer; }
|
||||
extern "C" bool UnityiOS102orNewer() { return _ios102orNewer; }
|
||||
extern "C" bool UnityiOS103orNewer() { return _ios103orNewer; }
|
||||
extern "C" bool UnityiOS110orNewer() { return _ios110orNewer; }
|
||||
extern "C" bool UnityiOS111orNewer() { return _ios111orNewer; }
|
||||
extern "C" bool UnityiOS112orNewer() { return _ios112orNewer; }
|
||||
extern "C" bool UnityiOS130orNewer() { return _ios130orNewer; }
|
||||
extern "C" bool UnityiOS140orNewer() { return _ios140orNewer; }
|
||||
extern "C" bool UnityiOS150orNewer() { return _ios150orNewer; }
|
||||
extern "C" bool UnityiOS160orNewer() { return _ios160orNewer; }
|
||||
|
||||
// sometimes apple adds new api with obvious fallback on older ios.
|
||||
// in that case we simply add these functions ourselves to simplify code
|
||||
static void AddNewAPIImplIfNeeded()
|
||||
{
|
||||
#if !PLATFORM_VISIONOS
|
||||
if (![[UIScreen class] instancesRespondToSelector: @selector(maximumFramesPerSecond)])
|
||||
{
|
||||
IMP UIScreen_MaximumFramesPerSecond_IMP = imp_implementationWithBlock(^NSInteger(id _self) {
|
||||
return 60;
|
||||
});
|
||||
class_replaceMethod([UIScreen class], @selector(maximumFramesPerSecond), UIScreen_MaximumFramesPerSecond_IMP, UIScreen_maximumFramesPerSecond_Enc);
|
||||
}
|
||||
|
||||
if (![[UIView class] instancesRespondToSelector: @selector(safeAreaInsets)])
|
||||
{
|
||||
IMP UIView_SafeAreaInsets_IMP = imp_implementationWithBlock(^UIEdgeInsets(id _self) {
|
||||
return UIEdgeInsetsZero;
|
||||
});
|
||||
class_replaceMethod([UIView class], @selector(safeAreaInsets), UIView_SafeAreaInsets_IMP, UIView_safeAreaInsets_Enc);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2d92f054ee7b0c4c92893f828a339b0
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 0
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 1
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d94ea3741ad8d344a76cca0aa62f67e
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,42 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 0863bf92b4fcc45b0b9267325249bf0f, type: 3}
|
||||
m_Name: NotificationSettings
|
||||
m_EditorClassIdentifier:
|
||||
toolbarInt: 0
|
||||
iOSNotificationEditorSettingsValues:
|
||||
keys:
|
||||
- UnityNotificationRequestAuthorizationOnAppLaunch
|
||||
- UnityNotificationDefaultAuthorizationOptions
|
||||
- UnityAddRemoteNotificationCapability
|
||||
- UnityNotificationRequestAuthorizationForRemoteNotificationsOnAppLaunch
|
||||
- UnityRemoteNotificationForegroundPresentationOptions
|
||||
- UnityUseAPSReleaseEnvironment
|
||||
- UnityUseLocationNotificationTrigger
|
||||
values:
|
||||
- True
|
||||
- 7
|
||||
- False
|
||||
- False
|
||||
- -1
|
||||
- False
|
||||
- False
|
||||
AndroidNotificationEditorSettingsValues:
|
||||
keys:
|
||||
- UnityNotificationAndroidRescheduleOnDeviceRestart
|
||||
- UnityNotificationAndroidUseCustomActivity
|
||||
- UnityNotificationAndroidCustomActivityString
|
||||
values:
|
||||
- False
|
||||
- False
|
||||
- com.unity3d.player.UnityPlayerActivity
|
||||
TrackedResourceAssets: []
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4cee8bca36f2ab74b8feb832747fa6f4
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user