forked from sin365/AxibugEmuOnline
Compare commits
12 Commits
629cd16016
...
1a526b10f6
| Author | SHA1 | Date | |
|---|---|---|---|
| 1a526b10f6 | |||
| a7807194ed | |||
| cd4163d9fe | |||
| c36adccbde | |||
| e1d7ef2d13 | |||
| 0f27fa328c | |||
| 33283a9a34 | |||
| 0a45c4fbbd | |||
| a1db47ab4b | |||
| ebb4cb401c | |||
| 57c4947623 | |||
| 8afcbce6b1 |
@ -0,0 +1,42 @@
|
||||
#if UNITY_EDITOR
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public class AxiProjectTools_AssetsAutoSetting : EditorWindow
|
||||
{
|
||||
[MenuItem("Axibug移植工具/AssetsAutoSetting/自动设置TextureMaxSize为图片大小1倍")]
|
||||
public static void AutoSettTextureSize_1x() { SetTextureSite(1f); }
|
||||
|
||||
[MenuItem("Axibug移植工具/AssetsAutoSetting/自动设置TextureMaxSize为图片大小2分之1倍")]
|
||||
public static void AutoSettTextureSize_1_2x() { SetTextureSite(1f / 2f); }
|
||||
[MenuItem("Axibug移植工具/AssetsAutoSetting/自动设置TextureMaxSize为图片大小4分之1倍")]
|
||||
public static void AutoSettTextureSize_1_4x() { SetTextureSite(1f / 4f); }
|
||||
|
||||
public static void SetTextureSite(float Scale)
|
||||
{
|
||||
Texture2D[] textures = Selection.GetFiltered<Texture2D>(SelectionMode.DeepAssets);
|
||||
if (textures.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("请先选择目录,或者Texture资源");
|
||||
return;
|
||||
}
|
||||
|
||||
AssetDatabase.StartAssetEditing(); // 开启批量编辑模式
|
||||
foreach (var texture in textures)
|
||||
{
|
||||
string path = AssetDatabase.GetAssetPath(texture);
|
||||
TextureImporter importer = AssetImporter.GetAtPath(path) as TextureImporter;
|
||||
if (importer != null)
|
||||
{
|
||||
int size = Mathf.Max(texture.width, texture.height);
|
||||
int maxsize = Mathf.ClosestPowerOfTwo((int)(size * Scale)); // Unity内置方法适配2的幂次方
|
||||
importer.maxTextureSize = maxsize;
|
||||
importer.SaveAndReimport();
|
||||
}
|
||||
}
|
||||
AssetDatabase.StopAssetEditing(); // 结束批量编辑
|
||||
Debug.Log($"Updated {textures.Length} textures.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc0741a79e74f96449a260406f239066
|
||||
@ -0,0 +1,840 @@
|
||||
#if UNITY_EDITOR && UNITY_2020_1_OR_NEWER
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
public class AxiProjectToolsStatistics : EditorWindow
|
||||
{
|
||||
static string cachecfgPath = "Assets/AxiStatisticsDatas.asset";
|
||||
static Dictionary<string, AxiStatisticsDatas> dictTempData = new Dictionary<string, AxiStatisticsDatas>();
|
||||
|
||||
static void ClearTempData()
|
||||
{
|
||||
dictTempData.Clear();
|
||||
}
|
||||
static string GetRootTempKey(int type, string rootName)
|
||||
{
|
||||
return type + "_" + rootName;
|
||||
}
|
||||
|
||||
|
||||
// 添加Hierarchy右键菜单项
|
||||
[MenuItem("GameObject/AxiStatistics/GetAxiNodeHash", false, 10)]
|
||||
public static void GetAxiNodeHash()
|
||||
{
|
||||
// 获取当前右键选中的Transform
|
||||
Transform selectedTransform = Selection.activeTransform;
|
||||
if (selectedTransform != null)
|
||||
{
|
||||
Debug.Log("选中的对象"+selectedTransform.name+",Hash=>"+ GetNodeDataHash(selectedTransform,true));
|
||||
}
|
||||
}
|
||||
|
||||
static int GetNodeDataHash(Transform trans,bool bLog = false)
|
||||
{
|
||||
long hashplus = 0;
|
||||
hashplus += trans.position.GetHashCode();
|
||||
hashplus += trans.localPosition.GetHashCode();
|
||||
|
||||
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
int count = trans.childCount;
|
||||
#else
|
||||
int count = trans.GetChildCount();
|
||||
#endif
|
||||
hashplus += count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
hashplus += trans.GetChild(i).name.GetHashCode();
|
||||
}
|
||||
|
||||
|
||||
if (bLog)
|
||||
{
|
||||
//Debug.Log("trans.position.GetHashCode()=>" + trans.position.GetHashCode());
|
||||
//Debug.Log("trans.localPosition.GetHashCode()=>" + trans.localPosition.GetHashCode());
|
||||
//Debug.Log("childCount =>" + count);
|
||||
//Debug.Log("hashplus =>" + hashplus);
|
||||
//Debug.Log("hashplus.GetHashCode() =>" + hashplus.GetHashCode());
|
||||
}
|
||||
|
||||
return hashplus.GetHashCode();
|
||||
}
|
||||
static int GetNodeLinkListHash(List<AxiStatistics_Node_Link> nodes)
|
||||
{
|
||||
string hashplus = string.Empty;
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
hashplus += node.Name;
|
||||
hashplus += node.Idx.ToString();
|
||||
}
|
||||
|
||||
return hashplus.GetHashCode();
|
||||
}
|
||||
|
||||
static string GetNodeLinkListStr(List<AxiStatistics_Node_Link> nodes)
|
||||
{
|
||||
string linkstr = string.Empty;
|
||||
|
||||
foreach (var node in nodes)
|
||||
{
|
||||
linkstr += "/";
|
||||
linkstr += node.Name;
|
||||
linkstr += "[" + node.Idx + "]";
|
||||
}
|
||||
return linkstr;
|
||||
}
|
||||
|
||||
static void AddComponentData(int _type, string _rootPath, AxiStatistics_Node_Component _comdata, string _nodepath, Component lastcom)
|
||||
{
|
||||
string rootKey = GetRootTempKey(_type, _rootPath);
|
||||
|
||||
if (!dictTempData.ContainsKey(rootKey))
|
||||
{
|
||||
dictTempData[rootKey] = new AxiStatisticsDatas() { type = _type, FullPath = _rootPath, nodes = new List<AxiStatistics_Node>() };
|
||||
}
|
||||
AxiStatisticsDatas rootData = dictTempData[rootKey];
|
||||
|
||||
List<AxiStatistics_Node_Link> link = new List<AxiStatistics_Node_Link>();
|
||||
if (lastcom.transform.parent != null)
|
||||
{
|
||||
Transform currNode = lastcom.transform;
|
||||
while (currNode != null)
|
||||
{
|
||||
//最顶层了
|
||||
if (currNode.parent == null)
|
||||
{
|
||||
link.Insert(0, new AxiStatistics_Node_Link()
|
||||
{
|
||||
NodeHash = GetNodeDataHash(currNode),
|
||||
Idx = 0,
|
||||
OnlyOne = true,
|
||||
Name = currNode.gameObject.name
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
int thisNameAllCount = 0;
|
||||
int thisNodeIdx = -1;
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
int count = currNode.parent.childCount;
|
||||
#else
|
||||
int count = currNode.parent.GetChildCount();
|
||||
#endif
|
||||
bool bFind = false;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
GameObject checkGobj = currNode.parent.GetChild(i).gameObject;
|
||||
if (checkGobj.name == currNode.name)
|
||||
{
|
||||
thisNameAllCount++;
|
||||
if (checkGobj == currNode.gameObject)
|
||||
{
|
||||
thisNodeIdx = thisNameAllCount - 1;
|
||||
bFind = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bFind)
|
||||
{
|
||||
link.Insert(0, new AxiStatistics_Node_Link()
|
||||
{
|
||||
NodeHash = GetNodeDataHash(currNode),
|
||||
Idx = thisNodeIdx,
|
||||
OnlyOne = thisNameAllCount == 1,
|
||||
Name = currNode.gameObject.name
|
||||
});
|
||||
currNode = currNode.parent;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
link.Insert(0, new AxiStatistics_Node_Link()
|
||||
{
|
||||
NodeHash = GetNodeDataHash(lastcom.transform),
|
||||
Idx = 0,
|
||||
OnlyOne = true,
|
||||
Name = lastcom.gameObject.name
|
||||
});
|
||||
}
|
||||
|
||||
int linkhash = GetNodeLinkListHash(link);
|
||||
AxiStatistics_Node nodeData = rootData.nodes.Where(w => w.LinkHash == linkhash).FirstOrDefault();
|
||||
if (nodeData == null)
|
||||
{
|
||||
nodeData = new AxiStatistics_Node();
|
||||
nodeData.Name = Path.GetFileName(_nodepath);
|
||||
//nodeData.NodeFullPath = _nodepath;
|
||||
nodeData.components = new List<AxiStatistics_Node_Component>();
|
||||
//nodeData.NodeIdx = thisNodeIdx;
|
||||
//nodeData.NodeIdxOnlyOne = bNodeIdxOnlyOne;
|
||||
|
||||
nodeData.link = link;
|
||||
nodeData.LinkHash = linkhash;
|
||||
nodeData.LinkFullStr = GetNodeLinkListStr(link);
|
||||
|
||||
rootData.nodes.Add(nodeData);
|
||||
}
|
||||
|
||||
nodeData.components.Add(_comdata);
|
||||
}
|
||||
|
||||
static bool CheckCom(Component[] allcoms, int comRealIdx, int _type, string _rootPath, Component com, string nodepath)
|
||||
{
|
||||
if (com is BoxCollider2D)
|
||||
{
|
||||
BoxCollider2D bc = com as BoxCollider2D;
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
Debug.Log(nodepath + "BoxCollider2D->center=>(" + bc.offset.x + "," + bc.offset.y + ") size=>(" + bc.size.x + "," + bc.size.y + "");
|
||||
#else
|
||||
Debug.Log(nodepath +"BoxCollider2D->center=>("+ bc.center.x+","+bc.center.y+") size=>("+ bc.size.x+","+bc.size.y+"");
|
||||
#endif
|
||||
AxiStatistics_Node_Component _com = new AxiStatistics_Node_Component();
|
||||
_com.type = typeof(BoxCollider2D).ToString();
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
_com.center = bc.offset;
|
||||
#else
|
||||
_com.center = bc.center;
|
||||
#endif
|
||||
_com.size = bc.size;
|
||||
SetCompnentIdxNum<BoxCollider2D>(_com, allcoms, comRealIdx, bc);
|
||||
AddComponentData(_type, _rootPath, _com, nodepath, com);
|
||||
}
|
||||
if (com is Rigidbody2D)
|
||||
{
|
||||
Rigidbody2D rig2d = com as Rigidbody2D;
|
||||
Debug.Log(_rootPath + "Rigidbody2D->simulated=>(" + rig2d.simulated + ")");
|
||||
Debug.Log(_rootPath + "Rigidbody2D->IsSleeping=>(" + rig2d.isKinematic.ToString() + ")");
|
||||
|
||||
AxiStatistics_Node_Component _com = new AxiStatistics_Node_Component();
|
||||
_com.type = typeof(Rigidbody2D).ToString();
|
||||
_com.isKinematic = rig2d.isKinematic;
|
||||
_com.simulated = rig2d.simulated;
|
||||
_com.gravityScale = rig2d.gravityScale;
|
||||
SetCompnentIdxNum<Rigidbody2D>(_com, allcoms, comRealIdx, rig2d);
|
||||
AddComponentData(_type, _rootPath, _com, nodepath, com);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 找出同类Idx
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="allcoms"></param>
|
||||
/// <param name="comRealIdx"></param>
|
||||
/// <param name="com"></param>
|
||||
/// <returns></returns>
|
||||
static void SetCompnentIdxNum<T>(AxiStatistics_Node_Component _comData, Component[] allcoms, int comRealIdx, T com) where T : Component
|
||||
{
|
||||
int ComIdxNum;
|
||||
bool ComTypeIsOnlyOne = false;
|
||||
int TCount = com.transform.GetComponents<T>().Length;
|
||||
if (TCount == 1)
|
||||
{
|
||||
ComIdxNum = 0;
|
||||
ComTypeIsOnlyOne = true;
|
||||
}
|
||||
else if (TCount < 1)
|
||||
{
|
||||
Debug.LogError("找不到,不应该");
|
||||
ComIdxNum = -1;
|
||||
}
|
||||
|
||||
ComIdxNum = -1;
|
||||
for (int i = 0; i < allcoms.Length; i++)
|
||||
{
|
||||
//他自己自然是了
|
||||
if (i == comRealIdx)
|
||||
{
|
||||
ComIdxNum++;
|
||||
break;
|
||||
}
|
||||
if (allcoms[i] is T)
|
||||
ComIdxNum++;
|
||||
}
|
||||
|
||||
_comData.ComIdxNum = ComIdxNum;
|
||||
_comData.ComTypeOnlyOne = ComTypeIsOnlyOne;
|
||||
}
|
||||
|
||||
[MenuItem("Axibug移植工具/Statistics/[1]统计所有预制体和场景下的Collider和RigBody")]
|
||||
|
||||
public static void StatisticsCollider()
|
||||
{
|
||||
ClearTempData();
|
||||
StatisticsCollider<BoxCollider2D>();
|
||||
StatisticsCollider<Rigidbody2D>();
|
||||
|
||||
AxiStatisticsCache cache = ScriptableObject.CreateInstance<AxiStatisticsCache>();
|
||||
foreach (var data in dictTempData)
|
||||
cache.caches.Add(data.Value);
|
||||
AssetDatabase.CreateAsset(cache, cachecfgPath);
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
}
|
||||
|
||||
public static void StatisticsCollider<T>() where T : Component
|
||||
{
|
||||
AxiProjectTools.GoTAxiProjectToolsSence();
|
||||
|
||||
string[] sceneGuids = AssetDatabase.FindAssets("t:scene");
|
||||
foreach (string guid in sceneGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.Contains(AxiProjectTools.toolSenceName))
|
||||
continue;
|
||||
|
||||
#if UNITY_4_6
|
||||
EditorApplication.OpenScene(path);
|
||||
#else
|
||||
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(path);
|
||||
#endif
|
||||
|
||||
// 创建一个列表来存储根节点
|
||||
List<GameObject> rootNodes = new List<GameObject>();
|
||||
|
||||
// 遍历场景中的所有对象
|
||||
GameObject[] allObjects = FindObjectsOfType<GameObject>();
|
||||
foreach (GameObject obj in allObjects)
|
||||
{
|
||||
// 检查对象是否有父对象
|
||||
if (obj.transform.parent == null)
|
||||
{
|
||||
// 如果没有父对象,则它是一个根节点
|
||||
rootNodes.Add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var node in rootNodes)
|
||||
LoopPrefabNode<T>(0, path, path, node, 0);
|
||||
|
||||
}
|
||||
string[] prefabGuids = AssetDatabase.FindAssets("t:Prefab");
|
||||
foreach (string guid in prefabGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
GetPrefab<T>(path);
|
||||
}
|
||||
|
||||
AxiProjectTools.GoTAxiProjectToolsSence();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 统计所有预制体和场景下的" + typeof(T).FullName + "</color>");
|
||||
}
|
||||
|
||||
static void GetPrefab<T>(string path) where T : Component
|
||||
{
|
||||
#if UNITY_4_6
|
||||
GameObject prefab = AssetDatabase.LoadAssetAtPath(path,typeof(GameObject)) as GameObject;
|
||||
#else
|
||||
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
|
||||
#endif
|
||||
|
||||
LoopPrefabNode<T>(1, path, path, prefab.gameObject, 0);
|
||||
}
|
||||
|
||||
static void LoopPrefabNode<T>(int _type, string _rootPath, string noderootPath, GameObject trans, int depth) where T : Component
|
||||
{
|
||||
// #if UNITY_2018_4_OR_NEWER
|
||||
string nodename = noderootPath + "/" + trans.name;
|
||||
GameObject prefabRoot = trans.gameObject;
|
||||
|
||||
Component[] components = prefabRoot.GetComponents<Component>();
|
||||
for (int i = 0; i < components.Length; i++)
|
||||
{
|
||||
var com = components[i];
|
||||
|
||||
if (com == null)
|
||||
continue;
|
||||
|
||||
T comobj = com as T;
|
||||
if (comobj == null)
|
||||
continue;
|
||||
|
||||
if (CheckCom(components, i, _type, _rootPath, comobj, nodename))
|
||||
continue;
|
||||
}
|
||||
|
||||
//遍历
|
||||
foreach (Transform child in trans.transform)
|
||||
LoopPrefabNode<T>(_type, _rootPath, nodename, child.gameObject, depth + 1);
|
||||
//#else
|
||||
// Debug.Log("低版本不要执行本函数");
|
||||
//#endif
|
||||
}
|
||||
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
[MenuItem("Axibug移植工具/Statistics/[2]通过记录,对组件进行修补")]
|
||||
public static void RepairRigBodyByStatistics()
|
||||
{
|
||||
List<string> errLog = new List<string>();
|
||||
List<string> doneLog = new List<string>();
|
||||
List<ValueTuple<string, string>> NeedRepair = new List<ValueTuple<string, string>>();
|
||||
List<ValueTuple<string, string>> FinishRepair = new List<ValueTuple<string, string>>();
|
||||
string CurrScenePath = string.Empty;
|
||||
AxiProjectTools.GoTAxiProjectToolsSence();
|
||||
#if UNITY_4_6
|
||||
AxiStatisticsCache data = AssetDatabase.LoadAssetAtPath(cachecfgPath,typeof(AxiStatisticsCache)) as AxiStatisticsCache;
|
||||
#else
|
||||
AxiStatisticsCache data = AssetDatabase.LoadAssetAtPath<AxiStatisticsCache>(cachecfgPath);
|
||||
#endif
|
||||
string[] sceneGuids = AssetDatabase.FindAssets("t:scene");
|
||||
List<string> ScenePath = new List<string>();
|
||||
List<string> SceneName = new List<string>();
|
||||
foreach (string guid in sceneGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.Contains(AxiProjectTools.toolSenceName))
|
||||
continue;
|
||||
ScenePath.Add(path);
|
||||
SceneName.Add(Path.GetFileName(path));
|
||||
}
|
||||
|
||||
string[] prefabGuids = AssetDatabase.FindAssets("t:prefab");
|
||||
List<string> prefabPath = new List<string>();
|
||||
List<string> prefabName = new List<string>();
|
||||
foreach (string guid in prefabGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
prefabPath.Add(path);
|
||||
prefabName.Add(Path.GetFileName(path));
|
||||
}
|
||||
|
||||
foreach (var cache in data.caches.OrderBy(w => w.type))
|
||||
{
|
||||
//场景
|
||||
if (cache.type == 0)
|
||||
{
|
||||
#region 场景加载
|
||||
string targetName = Path.GetFileName(cache.FullPath);
|
||||
int Idx = SceneName.IndexOf(targetName);
|
||||
if (Idx < 0)
|
||||
{
|
||||
Debug.LogError(targetName + "[Repair]找不到对应资源");
|
||||
continue;
|
||||
}
|
||||
string targetpath = ScenePath[Idx];
|
||||
|
||||
//保证场景切换
|
||||
if (!string.Equals(CurrScenePath, targetpath))
|
||||
{
|
||||
#if UNITY_4_6
|
||||
EditorApplication.OpenScene(targetpath);
|
||||
#else
|
||||
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(targetpath);
|
||||
#endif
|
||||
}
|
||||
CurrScenePath = targetpath;
|
||||
#endregion
|
||||
|
||||
int DirtyCount = 0;
|
||||
foreach (var node in cache.nodes)
|
||||
{
|
||||
GameObject targetNodePathObj = GetNodeByLink(cache.FullPath, node.link, out string errStr);
|
||||
if (targetNodePathObj == null)
|
||||
{
|
||||
errLog.Add(errStr);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
string targetNodePath = node.NodeFullPath.Substring(cache.FullPath.Length, node.NodeFullPath.Length - cache.FullPath.Length);
|
||||
|
||||
//GameObject targetNodePathObj = GameObject.Find(targetNodePath);
|
||||
GameObject targetNodePathObj = GetNodeByIdx(node, targetNodePath);
|
||||
|
||||
if (targetNodePathObj == null)
|
||||
{
|
||||
string err = "[Repair]" + node.NodeFullPath + "找不到对应节点";
|
||||
errLog.Add(err);
|
||||
Debug.LogError(err);
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
foreach (var com in node.components)
|
||||
{
|
||||
if (RepairComponent(node.LinkFullStr, targetNodePathObj, com, out var errlog))
|
||||
{
|
||||
NeedRepair.Add(new ValueTuple<string, string>($"{cache.FullPath}:{node.LinkFullStr}", $"{com.type}[{com.ComIdxNum}]"));
|
||||
DirtyCount++;
|
||||
}
|
||||
errLog.AddRange(errlog);
|
||||
}
|
||||
}
|
||||
if (DirtyCount > 0)
|
||||
{
|
||||
Debug.Log($"[Repair][场景处理]{cache.FullPath}共{DirtyCount}个需要处理");
|
||||
|
||||
|
||||
// 获取当前打开的场景
|
||||
var activeScene = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene();
|
||||
|
||||
// 保存场景
|
||||
UnityEditor.SceneManagement.EditorSceneManager.SaveScene(activeScene);
|
||||
|
||||
Debug.Log("场景已保存: " + activeScene.path);
|
||||
string donestr = $"[Repair][场景处理成功]{targetpath},共{DirtyCount}个";
|
||||
doneLog.Add(donestr);
|
||||
|
||||
}
|
||||
}
|
||||
else if (cache.type == 1)
|
||||
{
|
||||
string targetpath = cache.FullPath;
|
||||
|
||||
//来到空场景
|
||||
if (!string.IsNullOrEmpty(CurrScenePath))
|
||||
{
|
||||
AxiProjectTools.GoTAxiProjectToolsSence();
|
||||
CurrScenePath = string.Empty;
|
||||
}
|
||||
|
||||
|
||||
GameObject prefabInstance = AssetDatabase.LoadAssetAtPath<GameObject>(targetpath);
|
||||
if (prefabInstance == null)
|
||||
{
|
||||
Debug.LogError($"[Repair]Failed to load prefab at path: {prefabPath}");
|
||||
return;
|
||||
}
|
||||
|
||||
var obj = GameObject.Instantiate(prefabInstance, null);
|
||||
|
||||
int DirtyCount = 0;
|
||||
foreach (var node in cache.nodes)
|
||||
{
|
||||
GameObject targetNodePathObj = GetNodeByLink(cache.FullPath, node.link, out string errStr, obj);
|
||||
|
||||
if (targetNodePathObj == null)
|
||||
{
|
||||
errLog.Add(errStr);
|
||||
continue;
|
||||
}
|
||||
//if (node.NodeFullPath == targetpath + "/" + Path.GetFileNameWithoutExtension(targetpath))
|
||||
//{
|
||||
// //预制体自己就是目标
|
||||
// targetNodePathObj = obj;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// string targetNodePath = node.NodeFullPath.Substring(cache.FullPath.Length + prefabInstance.name.Length + 2, node.NodeFullPath.Length - cache.FullPath.Length - prefabInstance.name.Length - 2);
|
||||
// //targetNodePathObj = obj.transform.Find(targetNodePath)?.gameObject;
|
||||
// targetNodePathObj = GetNodeByIdx(node, targetNodePath, obj);
|
||||
|
||||
// if (targetNodePathObj == null)
|
||||
// {
|
||||
// Debug.LogError("[Repair]" + targetNodePath + "找不到对应节点");
|
||||
// continue;
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
foreach (var com in node.components)
|
||||
{
|
||||
if (RepairComponent(node.LinkFullStr, targetNodePathObj, com, out var errlog))
|
||||
{
|
||||
NeedRepair.Add(new ValueTuple<string, string>($"{cache.FullPath}:{node.LinkFullStr}", $"{com.type}[{com.ComIdxNum}]"));
|
||||
DirtyCount++;
|
||||
}
|
||||
|
||||
errLog.AddRange(errlog);
|
||||
}
|
||||
}
|
||||
|
||||
if (DirtyCount > 0)
|
||||
{
|
||||
Debug.Log($"[Repair][预制体处理]{targetpath}共{DirtyCount}个需要处理");
|
||||
PrefabUtility.SaveAsPrefabAsset(obj, targetpath);
|
||||
string donestr = $"[Repair][预制体处理成功]{targetpath},共{DirtyCount}个";
|
||||
doneLog.Add(donestr);
|
||||
}
|
||||
GameObject.DestroyImmediate(obj);
|
||||
}
|
||||
}
|
||||
|
||||
AxiProjectTools.GoTAxiProjectToolsSence();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.AppendLine("[Repair][统计]:");
|
||||
sb.AppendLine("----处理成功----");
|
||||
foreach (var val in doneLog.OrderBy(w => w))
|
||||
{
|
||||
sb.AppendLine(val);
|
||||
}
|
||||
sb.AppendLine("----异常统计----");
|
||||
foreach (var val in errLog.OrderBy(w => w))
|
||||
{
|
||||
sb.AppendLine(val);
|
||||
}
|
||||
sb.AppendLine("----需要处理----");
|
||||
foreach (var val in NeedRepair.OrderBy(w => w.Item1))
|
||||
{
|
||||
sb.AppendLine($"{val.Item1}=>{val.Item2}");
|
||||
}
|
||||
Debug.Log($"{sb}");
|
||||
|
||||
File.WriteAllText("Assets/AxiNeedRepair.txt", sb.ToString());
|
||||
}
|
||||
|
||||
|
||||
// static GameObject GetNodeByIdx(AxiStatistics_Node nodedata, string targetNodePath, GameObject root = null)
|
||||
// {
|
||||
// GameObject targetNodePathObj;
|
||||
|
||||
// if (root == null)
|
||||
// targetNodePathObj = GameObject.Find(targetNodePath);
|
||||
// else
|
||||
// targetNodePathObj = root.transform.Find(targetNodePath)?.gameObject;
|
||||
|
||||
// if (targetNodePathObj == null)
|
||||
// return null;
|
||||
|
||||
// string targetName = targetNodePathObj.name;
|
||||
// int currIdx = -1;
|
||||
// if (!nodedata.NodeIdxOnlyOne)
|
||||
// {
|
||||
// if (targetNodePathObj.transform.parent != null)
|
||||
// {
|
||||
//#if UNITY_2017_1_OR_NEWER
|
||||
// int count = targetNodePathObj.transform.parent.childCount;
|
||||
//#else
|
||||
// int count = targetNodePathObj.transform.parent.GetChildCount();
|
||||
//#endif
|
||||
// for (int i = 0; i < count; i++)
|
||||
// {
|
||||
// GameObject checkGobj = targetNodePathObj.transform.parent.GetChild(i).gameObject;
|
||||
// if (checkGobj.name == targetName)
|
||||
// {
|
||||
// currIdx++;
|
||||
// if (nodedata.NodeIdx == currIdx)
|
||||
// {
|
||||
// targetNodePathObj = checkGobj;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return targetNodePathObj;
|
||||
// }
|
||||
|
||||
|
||||
static GameObject GetNodeByLink(string rootPath, List<AxiStatistics_Node_Link> linklist, out string errStr, GameObject PrefabRoot = null)
|
||||
{
|
||||
List<AxiStatistics_Node_Link> temp_useddlink = new List<AxiStatistics_Node_Link>();
|
||||
if (linklist.Count < 1)
|
||||
{
|
||||
errStr = $"[Repair] Link 为空";
|
||||
Debug.LogError(errStr);
|
||||
return null;
|
||||
}
|
||||
|
||||
temp_useddlink.Add(linklist[0]);
|
||||
GameObject currRoot;
|
||||
|
||||
if (PrefabRoot == null)
|
||||
currRoot = GameObject.Find(linklist[0].Name);
|
||||
else
|
||||
{
|
||||
currRoot = PrefabRoot;
|
||||
//currRoot = PrefabRoot.transform.Find(linklist[0].Name)?.gameObject;
|
||||
}
|
||||
|
||||
if (currRoot == null)
|
||||
{
|
||||
errStr = $"[Repair] 根节点找不到{rootPath}:{GetNodeLinkListStr(linklist)} => null";
|
||||
Debug.LogError(errStr);
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int link_i = 1; link_i < linklist.Count; link_i++)
|
||||
{
|
||||
AxiStatistics_Node_Link targetLink = linklist[link_i];
|
||||
temp_useddlink.Add(targetLink);
|
||||
GameObject findNode = null;
|
||||
#if UNITY_2017_1_OR_NEWER
|
||||
int count = currRoot.transform.childCount;
|
||||
#else
|
||||
int count = currNode.transform.GetChildCount();
|
||||
#endif
|
||||
|
||||
if (targetLink.OnlyOne)
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
GameObject checkGobj = currRoot.transform.GetChild(i).gameObject;
|
||||
if (checkGobj.name == targetLink.Name)
|
||||
{
|
||||
findNode = checkGobj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Dictionary<int, GameObject> tempHash2Node = new Dictionary<int, GameObject>();
|
||||
List<GameObject> tempGobjList = new List<GameObject>();
|
||||
bool HashDrity = false;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
GameObject checkGobj = currRoot.transform.GetChild(i).gameObject;
|
||||
if (checkGobj.name == targetLink.Name)
|
||||
{
|
||||
int temphash = GetNodeDataHash(checkGobj.transform);
|
||||
if (!tempHash2Node.ContainsKey(temphash))
|
||||
{
|
||||
tempHash2Node.Add(GetNodeDataHash(checkGobj.transform), checkGobj);
|
||||
}
|
||||
else
|
||||
{
|
||||
HashDrity = true;
|
||||
}
|
||||
tempGobjList.Add(checkGobj);
|
||||
}
|
||||
}
|
||||
|
||||
//Hash严格模式
|
||||
if (!HashDrity && tempHash2Node.TryGetValue(targetLink.NodeHash, out var val))
|
||||
{
|
||||
findNode = val;
|
||||
}
|
||||
//下标模式
|
||||
else
|
||||
{
|
||||
if (targetLink.Idx < 0 || tempGobjList.Count == 0 || (tempGobjList.Count != 0 && targetLink.Idx >= tempGobjList.Count))
|
||||
{
|
||||
errStr = $"[Repair]link 下标模式 找不到=>{rootPath}:{GetNodeLinkListStr(temp_useddlink)}[{targetLink.Idx}] => 完整链路{rootPath}:{GetNodeLinkListStr(linklist)}";
|
||||
Debug.LogError(errStr);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
findNode = tempGobjList[targetLink.Idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
currRoot = findNode;
|
||||
if (currRoot == null)
|
||||
break;
|
||||
}
|
||||
|
||||
if (currRoot == null)
|
||||
{
|
||||
errStr = $"[Repair]link 找不到[{rootPath}:{GetNodeLinkListStr(temp_useddlink)}] => 完整链路{rootPath}:{GetNodeLinkListStr(linklist)}";
|
||||
Debug.LogError(errStr);
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
errStr = string.Empty;
|
||||
return currRoot;
|
||||
}
|
||||
}
|
||||
|
||||
static bool RepairComponent(string NodePath, GameObject targetNodePathObj, AxiStatistics_Node_Component comdata, out List<string> Errlog)
|
||||
{
|
||||
Errlog = new List<string>();
|
||||
string err;
|
||||
bool Dirty = false;
|
||||
if (comdata.type == typeof(Rigidbody2D).ToString())
|
||||
{
|
||||
Rigidbody2D rg2d = GetCompnentById<Rigidbody2D>(targetNodePathObj, comdata);
|
||||
if (rg2d == null)
|
||||
{
|
||||
err = $"[Repair]{NodePath}=> Rigidbody2D[{comdata.ComIdxNum}] == null";
|
||||
Debug.LogError(err);
|
||||
Errlog.Add(err);
|
||||
Dirty = false;
|
||||
}
|
||||
|
||||
/*
|
||||
与新版Unity的差异
|
||||
无BodyType选项:Unity 4.6.7中所有Rigidbody2D默认等效于新版的Dynamic类型(受重力影响),但无法设置为Static或Kinematic。
|
||||
无Simulated选项:只要物体启用了Rigidbody2D组件且Gravity Scale > 0,就会受重力作用。
|
||||
|
||||
所以,一旦老版本gravityScale > 0,就受重力作用,直接设置新版本这边:simulated = true;bodyType = RigidbodyType2D.Dynamic;
|
||||
*/
|
||||
|
||||
|
||||
if (rg2d.gravityScale != comdata.gravityScale)
|
||||
{
|
||||
Debug.Log($"[Repair]{NodePath}=> Rigidbody2D[{comdata.ComIdxNum}] simulated:{rg2d.gravityScale} != :{comdata.gravityScale} rg2d.bodyType => {rg2d.bodyType} ");
|
||||
|
||||
rg2d.gravityScale = comdata.gravityScale;
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
//if (rg2d.gravityScale > 0 && (!rg2d.simulated || rg2d.bodyType != RigidbodyType2D.Dynamic))
|
||||
if (!rg2d.simulated || rg2d.bodyType != RigidbodyType2D.Dynamic)
|
||||
{
|
||||
Debug.Log($"[Repair]{NodePath}=> Rigidbody2D[{comdata.ComIdxNum}] simulated:{rg2d.simulated} != :{comdata.simulated} rg2d.bodyType => {rg2d.bodyType} ");
|
||||
|
||||
rg2d.simulated = true;
|
||||
rg2d.bodyType = RigidbodyType2D.Dynamic;
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
else if (comdata.type == typeof(BoxCollider2D).ToString())
|
||||
{
|
||||
BoxCollider2D bc = GetCompnentById<BoxCollider2D>(targetNodePathObj, comdata);
|
||||
if (bc == null)
|
||||
{
|
||||
err = $"[Repair]{NodePath}=> BoxCollider2D[{comdata.ComIdxNum}] == null";
|
||||
Debug.LogError(err);
|
||||
Errlog.Add(err);
|
||||
Dirty = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bc.size != comdata.size)
|
||||
{
|
||||
Debug.Log($"[Repair]{NodePath} BoxCollider2D[{comdata.ComIdxNum}] => size:{bc.size} != {comdata.size} ");
|
||||
bc.size = comdata.size;
|
||||
Dirty = true;
|
||||
}
|
||||
if (bc.offset != comdata.center)
|
||||
{
|
||||
Debug.Log($"[Repair]{NodePath} BoxCollider2D[{comdata.ComIdxNum}] => offset:{bc.offset} != center{comdata.center} ");
|
||||
bc.offset = comdata.center;
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
if (Dirty)
|
||||
{
|
||||
bc.size = comdata.size;
|
||||
bc.offset = comdata.center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Dirty;
|
||||
}
|
||||
|
||||
static T GetCompnentById<T>(GameObject gobj, AxiStatistics_Node_Component node) where T : Component
|
||||
{
|
||||
if (node.ComIdxNum == 0)
|
||||
return gobj.GetComponent<T>();
|
||||
else if (node.ComIdxNum > 0)
|
||||
{
|
||||
T[] coms = gobj.GetComponents<T>();
|
||||
if (node.ComIdxNum < coms.Length)
|
||||
return coms[node.ComIdxNum];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 32aabdd304d2c4d47b8ef660f672ead1
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@ -3,19 +3,18 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor;
|
||||
using UnityEditor.SceneManagement;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public class AxiProjectTools : EditorWindow
|
||||
{
|
||||
static string cachecfgPath = "Assets/AxiComToolCache.asset";
|
||||
static string toolSenceName = "AxiProjectTools";
|
||||
static string outCsDir = Application.dataPath + "/AxiCom/";
|
||||
static Dictionary<string, AxiPrefabCache_Com2GUID> ComType2GUID = new Dictionary<string, AxiPrefabCache_Com2GUID>();
|
||||
|
||||
static void GoTAxiProjectToolsSence()
|
||||
public static string toolSenceName = "AxiProjectTools";
|
||||
public static string outCsDir = Application.dataPath + "/AxiCom/";
|
||||
public static Dictionary<string, AxiPrefabCache_Com2GUID> ComType2GUID = new Dictionary<string, AxiPrefabCache_Com2GUID>();
|
||||
|
||||
public static void GoTAxiProjectToolsSence()
|
||||
{
|
||||
string[] sceneGuids = AssetDatabase.FindAssets("t:scene");
|
||||
foreach (string guid in sceneGuids)
|
||||
@ -23,12 +22,16 @@ public class AxiProjectTools : EditorWindow
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.Contains(toolSenceName))
|
||||
{
|
||||
EditorSceneManager.OpenScene(path);
|
||||
#if UNITY_4_6
|
||||
EditorApplication.OpenScene(path);
|
||||
#else
|
||||
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(path);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[1]采集所有预制体和场景下的UGUI组件")]
|
||||
public static void Part1()
|
||||
{
|
||||
@ -40,12 +43,16 @@ public class AxiProjectTools : EditorWindow
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.Contains(toolSenceName))
|
||||
continue;
|
||||
|
||||
EditorSceneManager.OpenScene(path);
|
||||
|
||||
|
||||
#if UNITY_4_6
|
||||
EditorApplication.OpenScene(path);
|
||||
#else
|
||||
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(path);
|
||||
#endif
|
||||
|
||||
// 创建一个列表来存储根节点
|
||||
List<GameObject> rootNodes = new List<GameObject>();
|
||||
|
||||
|
||||
// 遍历场景中的所有对象
|
||||
GameObject[] allObjects = FindObjectsOfType<GameObject>();
|
||||
foreach (GameObject obj in allObjects)
|
||||
@ -57,19 +64,19 @@ public class AxiProjectTools : EditorWindow
|
||||
rootNodes.Add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach (var node in rootNodes)
|
||||
LoopPrefabNode(path, node, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
string[] prefabGuids = AssetDatabase.FindAssets("t:Prefab");
|
||||
foreach (string guid in prefabGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
GetPrefab(path);
|
||||
}
|
||||
|
||||
|
||||
AxiPrefabCache cache = ScriptableObject.CreateInstance<AxiPrefabCache>();
|
||||
foreach (var data in ComType2GUID)
|
||||
cache.caches.Add(data.Value);
|
||||
@ -79,66 +86,88 @@ public class AxiProjectTools : EditorWindow
|
||||
GoTAxiProjectToolsSence();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [1]采集所有预制体和场景下的UGUI组件</color>");
|
||||
}
|
||||
|
||||
|
||||
static void GetPrefab(string path)
|
||||
{
|
||||
{
|
||||
#if UNITY_4_6
|
||||
GameObject prefab = AssetDatabase.LoadAssetAtPath(path,typeof(GameObject)) as GameObject;
|
||||
#else
|
||||
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
|
||||
#endif
|
||||
|
||||
LoopPrefabNode(path, prefab.gameObject, 0);
|
||||
}
|
||||
static void LoopPrefabNode(string rootPath, GameObject trans, int depth)
|
||||
{
|
||||
string nodename = $"{rootPath}>{trans.name}";
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
GameObject prefabRoot = trans.gameObject;
|
||||
int comCount = prefabRoot.GetComponentCount();
|
||||
for (int i = 0; i < comCount; i++)
|
||||
{
|
||||
var com = prefabRoot.GetComponentAtIndex(i);
|
||||
if (com == null)
|
||||
continue;
|
||||
|
||||
MonoBehaviour monoCom = com as MonoBehaviour;
|
||||
if (monoCom == null)
|
||||
continue;
|
||||
Type monoType = monoCom.GetType();
|
||||
if (!monoType.Assembly.FullName.Contains("UnityEngine.UI"))
|
||||
continue;
|
||||
// 获取MonoScript资源
|
||||
MonoScript monoScript = MonoScript.FromMonoBehaviour(monoCom);
|
||||
if (monoScript != null)
|
||||
{
|
||||
// 获取MonoScript资源的GUID
|
||||
string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(monoScript));
|
||||
Debug.Log($"{nodename} | <color=#FFF333>[{monoType.Name}]</color> <color=#FF0000>{guid}</color><color=#00FF00>({monoType.FullName})</color>");
|
||||
ComType2GUID[monoType.FullName] =
|
||||
new AxiPrefabCache_Com2GUID()
|
||||
{
|
||||
SrcFullName = monoType.FullName,
|
||||
SrcName = monoType.Name,
|
||||
GUID = guid,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("!!!! 没得");
|
||||
}
|
||||
}
|
||||
|
||||
//遍历
|
||||
foreach (Transform child in trans.transform)
|
||||
LoopPrefabNode(nodename, child.gameObject, depth + 1);
|
||||
#else
|
||||
Debug.Log("低版本不要执行本函数");
|
||||
#endif
|
||||
// #if UNITY_2018_4_OR_NEWER
|
||||
string nodename = rootPath + trans.name;
|
||||
GameObject prefabRoot = trans.gameObject;
|
||||
|
||||
Component[] components = prefabRoot.GetComponents<Component>();
|
||||
for (int i = 0; i < components.Length; i++)
|
||||
{
|
||||
var com = components[i];
|
||||
|
||||
if (com == null)
|
||||
continue;
|
||||
|
||||
MonoBehaviour monoCom = com as MonoBehaviour;
|
||||
if (monoCom == null)
|
||||
continue;
|
||||
Type monoType = monoCom.GetType();
|
||||
if (!monoType.Assembly.FullName.Contains("UnityEngine.UI"))
|
||||
continue;
|
||||
// 获取MonoScript资源
|
||||
MonoScript monoScript = MonoScript.FromMonoBehaviour(monoCom);
|
||||
if (monoScript != null)
|
||||
{
|
||||
// 获取MonoScript资源的GUID
|
||||
string guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(monoScript));
|
||||
Debug.Log(nodename+" | <color=#FFF333>["+monoType.Name+"]</color> <color=#FF0000>"+guid+"</color><color=#00FF00>("+monoType.FullName+")</color>");
|
||||
ComType2GUID[monoType.FullName] =
|
||||
new AxiPrefabCache_Com2GUID()
|
||||
{
|
||||
SrcFullName = monoType.FullName,
|
||||
SrcName = monoType.Name,
|
||||
GUID = guid,
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("!!!! 没得");
|
||||
}
|
||||
}
|
||||
|
||||
//遍历
|
||||
foreach (Transform child in trans.transform)
|
||||
LoopPrefabNode(nodename, child.gameObject, depth + 1);
|
||||
//#else
|
||||
// Debug.Log("低版本不要执行本函数");
|
||||
//#endif
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[2]生成中间脚本代码")]
|
||||
public static void Part2()
|
||||
{
|
||||
|
||||
#if UNITY_4_6
|
||||
if(System.IO.Directory.Exists(outCsDir))
|
||||
System.IO.Directory.Delete(outCsDir);
|
||||
#else
|
||||
if (UnityEngine.Windows.Directory.Exists(outCsDir))
|
||||
UnityEngine.Windows.Directory.Delete(outCsDir);
|
||||
#endif
|
||||
|
||||
|
||||
Directory.CreateDirectory(outCsDir);
|
||||
|
||||
|
||||
|
||||
#if UNITY_4_6
|
||||
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath(cachecfgPath,typeof(AxiPrefabCache)) as AxiPrefabCache;
|
||||
#else
|
||||
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath<AxiPrefabCache>(cachecfgPath);
|
||||
#endif
|
||||
foreach (var data in cache.caches)
|
||||
{
|
||||
string toName = "Axi" + data.SrcName;
|
||||
@ -160,12 +189,18 @@ public class AxiProjectTools : EditorWindow
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [2]生成中间脚本代码</color>");
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[3]收集生成的脚本")]
|
||||
public static void Part3()
|
||||
{
|
||||
#if UNITY_4_6
|
||||
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath(cachecfgPath,typeof(AxiPrefabCache)) as AxiPrefabCache;
|
||||
MonoScript[] allMonoScripts = (MonoScript[])Resources.FindObjectsOfTypeAll(typeof(MonoScript));
|
||||
#else
|
||||
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath<AxiPrefabCache>(cachecfgPath);
|
||||
List<MonoScript> allMonoScripts = FindAllAssetsOfType<MonoScript>();
|
||||
#endif
|
||||
|
||||
foreach (var data in cache.caches)
|
||||
{
|
||||
MonoScript monoScript = allMonoScripts.FirstOrDefault(w => w.name == data.ToName);
|
||||
@ -183,18 +218,23 @@ public class AxiProjectTools : EditorWindow
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [3]收集生成的脚本</color>");
|
||||
}
|
||||
|
||||
|
||||
static List<T> FindAllAssetsOfType<T>() where T : UnityEngine.Object
|
||||
{
|
||||
List<T> assets = new List<T>();
|
||||
|
||||
|
||||
string[] allGuids = AssetDatabase.FindAssets("");
|
||||
foreach (string guid in allGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.EndsWith(".cs") || path.EndsWith(".js") || path.EndsWith(".boo")) // Unity支持多种脚本语言,但现代Unity主要使用C#
|
||||
{
|
||||
#if UNITY_4_6
|
||||
T asset = AssetDatabase.LoadAssetAtPath(cachecfgPath,typeof(T)) as T;
|
||||
#else
|
||||
T asset = AssetDatabase.LoadAssetAtPath<T>(path);
|
||||
#endif
|
||||
|
||||
if (asset != null)
|
||||
{
|
||||
assets.Add(asset);
|
||||
@ -203,12 +243,18 @@ public class AxiProjectTools : EditorWindow
|
||||
}
|
||||
return assets;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[4]替换所有预制体和场景中的组件")]
|
||||
public static void Part4()
|
||||
{
|
||||
|
||||
#if UNITY_4_6
|
||||
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath(cachecfgPath,typeof(AxiPrefabCache)) as AxiPrefabCache;
|
||||
#else
|
||||
AxiPrefabCache cache = AssetDatabase.LoadAssetAtPath<AxiPrefabCache>(cachecfgPath);
|
||||
#endif
|
||||
|
||||
Dictionary<string, string> tempReplaceDict = new Dictionary<string, string>();
|
||||
foreach (var data in cache.caches)
|
||||
{
|
||||
@ -221,7 +267,7 @@ public class AxiProjectTools : EditorWindow
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [4]替换所有预制体和场景中的组件</color>");
|
||||
}
|
||||
|
||||
|
||||
static void ProcessAllPrefabs(string form, Dictionary<string, string> tempReplaceDict, bool reverse = false)
|
||||
{
|
||||
List<GameObject> prefabs = new List<GameObject>();
|
||||
@ -240,7 +286,7 @@ public class AxiProjectTools : EditorWindow
|
||||
}
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 替换值
|
||||
/// </summary>
|
||||
@ -257,17 +303,17 @@ public class AxiProjectTools : EditorWindow
|
||||
File.WriteAllLines(strFilePath, lines);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[5]UnPack所有嵌套预制体和场景中的预制体")]
|
||||
public static void UnpackPrefabs()
|
||||
{
|
||||
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
GoTAxiProjectToolsSence();
|
||||
string[] allAssetPaths = AssetDatabase.GetAllAssetPaths();
|
||||
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
GoTAxiProjectToolsSence();
|
||||
string[] allAssetPaths = AssetDatabase.GetAllAssetPaths();
|
||||
int prefabCount = 0;
|
||||
|
||||
|
||||
foreach (string path in allAssetPaths)
|
||||
{
|
||||
if (Path.GetExtension(path).Equals(".prefab"))
|
||||
@ -278,59 +324,59 @@ public class AxiProjectTools : EditorWindow
|
||||
}
|
||||
}
|
||||
Debug.Log($"{prefabCount}个预制体Unpack");
|
||||
|
||||
string[] sceneGuids = AssetDatabase.FindAssets("t:scene");
|
||||
foreach (string guid in sceneGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.Contains(toolSenceName))
|
||||
continue;
|
||||
|
||||
EditorSceneManager.OpenScene(path);
|
||||
Scene currentScene = SceneManager.GetActiveScene();
|
||||
GameObject[] rootObjects = currentScene.GetRootGameObjects();
|
||||
|
||||
string[] sceneGuids = AssetDatabase.FindAssets("t:scene");
|
||||
foreach (string guid in sceneGuids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.Contains(toolSenceName))
|
||||
continue;
|
||||
|
||||
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(path);
|
||||
UnityEngine.SceneManagement.Scene currentScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
|
||||
GameObject[] rootObjects = currentScene.GetRootGameObjects();
|
||||
foreach (GameObject rootObj in rootObjects)
|
||||
{
|
||||
// 遍历场景中的所有对象
|
||||
TraverseHierarchy(rootObj);
|
||||
}
|
||||
// Save the scene // 获取当前打开的场景
|
||||
currentScene = EditorSceneManager.GetActiveScene();
|
||||
// 保存场景到文件(默认路径和名称)
|
||||
bool success = EditorSceneManager.SaveScene(currentScene, currentScene.path);
|
||||
|
||||
Debug.Log($"{currentScene.name}场景中 所有物体Unpack");
|
||||
}
|
||||
|
||||
GoTAxiProjectToolsSence();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [5]UnPack所有预制体</color>");
|
||||
#else
|
||||
Debug.Log("低版本不要执行本函数");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void UnpackPrefab(string prefabPath)
|
||||
{
|
||||
// 遍历场景中的所有对象
|
||||
TraverseHierarchy(rootObj);
|
||||
}
|
||||
// Save the scene // 获取当前打开的场景
|
||||
currentScene = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene();
|
||||
// 保存场景到文件(默认路径和名称)
|
||||
bool success = UnityEditor.SceneManagement.EditorSceneManager.SaveScene(currentScene, currentScene.path);
|
||||
|
||||
Debug.Log($"{currentScene.name}场景中 所有物体Unpack");
|
||||
}
|
||||
|
||||
GoTAxiProjectToolsSence();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [5]UnPack所有预制体</color>");
|
||||
#else
|
||||
Debug.Log("低版本不要执行本函数");
|
||||
#endif
|
||||
}
|
||||
|
||||
static void UnpackPrefab(string prefabPath)
|
||||
{
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
GameObject prefabInstance = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
|
||||
if (prefabInstance == null)
|
||||
{
|
||||
Debug.LogError($"Failed to load prefab at path: {prefabPath}");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var obj = GameObject.Instantiate(prefabInstance, null);
|
||||
TraverseHierarchy(obj);
|
||||
PrefabUtility.SaveAsPrefabAsset(obj, prefabPath);
|
||||
GameObject.DestroyImmediate(obj);
|
||||
#else
|
||||
#else
|
||||
Debug.Log("低版本不要执行本函数");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void TraverseHierarchy(GameObject obj)
|
||||
{
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
#if UNITY_2018_4_OR_NEWER
|
||||
// 检查该对象是否是预制体的实例
|
||||
if (PrefabUtility.IsPartOfPrefabInstance(obj))
|
||||
{
|
||||
@ -338,80 +384,123 @@ public class AxiProjectTools : EditorWindow
|
||||
PrefabUtility.UnpackPrefabInstance(obj, PrefabUnpackMode.Completely, InteractionMode.AutomatedAction);
|
||||
Debug.Log("Prefab instance converted to game object: " + obj.name);
|
||||
}
|
||||
|
||||
|
||||
// 递归遍历子对象
|
||||
for (int i = 0; i < obj.transform.childCount; i++)
|
||||
{
|
||||
TraverseHierarchy(obj.transform.GetChild(i).gameObject);
|
||||
}
|
||||
#else
|
||||
#else
|
||||
Debug.Log("低版本不要执行本函数");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[6]修复Sprite")]
|
||||
public static void FixMultipleMaterialSprites()
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("t:sprite");
|
||||
List<Sprite> spritesToFix = new List<Sprite>();
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[6]修复Sprite")]
|
||||
public static void FixMultipleMaterialSprites()
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("t:sprite");
|
||||
List<Sprite> spritesToFix = new List<Sprite>();
|
||||
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(path);
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(path);
|
||||
|
||||
// 检查是否有多个材质
|
||||
if (IsUsingMultipleMaterials(sprite))
|
||||
{
|
||||
spritesToFix.Add(sprite);
|
||||
Debug.Log("Found sprite with multiple materials: " + path);
|
||||
}
|
||||
}
|
||||
// 检查是否有多个材质
|
||||
if (IsUsingMultipleMaterials(sprite))
|
||||
{
|
||||
spritesToFix.Add(sprite);
|
||||
Debug.Log("Found sprite with multiple materials: " + path);
|
||||
}
|
||||
}
|
||||
|
||||
// 修复每个找到的Sprite
|
||||
foreach (var sprite in spritesToFix)
|
||||
{
|
||||
FixSprite(sprite);
|
||||
}
|
||||
// 修复每个找到的Sprite
|
||||
foreach (var sprite in spritesToFix)
|
||||
{
|
||||
FixSprite(sprite);
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [6]修复Sprite</color>");
|
||||
}
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [6]修复Sprite</color>");
|
||||
}
|
||||
|
||||
private static bool IsUsingMultipleMaterials(Sprite sprite)
|
||||
{
|
||||
if (sprite == null) return false;
|
||||
private static bool IsUsingMultipleMaterials(Sprite sprite)
|
||||
{
|
||||
if (sprite == null) return false;
|
||||
|
||||
// 获取精灵的材质
|
||||
var textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(sprite)) as TextureImporter;
|
||||
// 获取精灵的材质
|
||||
var textureImporter = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(sprite)) as TextureImporter;
|
||||
|
||||
return textureImporter != null && textureImporter.spriteImportMode == SpriteImportMode.Multiple;
|
||||
}
|
||||
return textureImporter != null && textureImporter.spriteImportMode == SpriteImportMode.Multiple;
|
||||
}
|
||||
|
||||
private static void FixSprite(Sprite sprite)
|
||||
{
|
||||
// 获取Sprite的路径
|
||||
string path = AssetDatabase.GetAssetPath(sprite);
|
||||
var textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
|
||||
private static void FixSprite(Sprite sprite)
|
||||
{
|
||||
// 获取Sprite的路径
|
||||
string path = AssetDatabase.GetAssetPath(sprite);
|
||||
var textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
|
||||
|
||||
if (textureImporter != null)
|
||||
{
|
||||
// 保存当前切割信息
|
||||
SpriteMetaData[] originalMetaData = textureImporter.spritesheet;
|
||||
if (textureImporter != null)
|
||||
{
|
||||
// 保存当前切割信息
|
||||
SpriteMetaData[] originalMetaData = textureImporter.spritesheet;
|
||||
|
||||
// 临时禁用Sprite导入
|
||||
textureImporter.spriteImportMode = SpriteImportMode.None;
|
||||
textureImporter.SaveAndReimport();
|
||||
// 临时禁用Sprite导入
|
||||
textureImporter.spriteImportMode = SpriteImportMode.None;
|
||||
textureImporter.SaveAndReimport();
|
||||
|
||||
// 重新启用Sprite导入并保持原样切割参数
|
||||
textureImporter.spriteImportMode = SpriteImportMode.Multiple;
|
||||
textureImporter.spritesheet = originalMetaData; // 恢复原来的切割信息
|
||||
// 重新启用Sprite导入并保持原样切割参数
|
||||
textureImporter.spriteImportMode = SpriteImportMode.Multiple;
|
||||
textureImporter.spritesheet = originalMetaData; // 恢复原来的切割信息
|
||||
|
||||
// 重新导入以应用更改
|
||||
textureImporter.SaveAndReimport();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[MenuItem("Axibug移植工具/ToLowVersionUnity/[7]导入后低版本执行:修复组件挂载预制体依赖丢失")]
|
||||
static void FixPrefabRefs()
|
||||
{
|
||||
// 1. 扫描所有预制体
|
||||
string[] prefabPaths = Directory.GetFiles("Assets", "*.prefab", SearchOption.AllDirectories);
|
||||
foreach (var path in prefabPaths) FixRefTypeInFile(path);
|
||||
|
||||
// 2. 处理场景文件
|
||||
string[] scenePaths = Directory.GetFiles("Assets", "*.unity", SearchOption.AllDirectories);
|
||||
foreach (var path in scenePaths) FixRefTypeInFile(path);
|
||||
|
||||
AssetDatabase.Refresh();
|
||||
Debug.Log("<Color=#FFF333>处理完毕 [5]导入低版本后:修复预制体依赖丢失</color>");
|
||||
Debug.Log("修复完成!已处理" + prefabPaths.Length + "个预制体");
|
||||
}
|
||||
|
||||
public static void FixRefTypeInFile(string filePath)
|
||||
{
|
||||
string content = File.ReadAllText(filePath);
|
||||
// 匹配所有 {fileID: X, guid: Y, type: Z} 结构
|
||||
string pattern = @"(\{[^}]*guid:\s*(\w+)[^}]*type:\s*)3(\s*[^}]*\})";
|
||||
string newContent = Regex.Replace(content, pattern, match => {
|
||||
string guid = match.Groups[2].Value;
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
// 仅当资源类型为 GameObject 时修改 type
|
||||
if (AssetDatabase.GetMainAssetTypeAtPath(assetPath) == typeof(GameObject))
|
||||
// if (assetPath.ToLower().EndsWith(".prefab")
|
||||
////&& assetPath.Contains("/sound/")
|
||||
//&& assetPath.Contains("/level")
|
||||
// )
|
||||
{
|
||||
Debug.Log("已处理被引用项=>"+assetPath+" ,引用到=>"+ filePath);
|
||||
Debug.Log("原值=>" + match.Value + " ,处理值=>"+ match.Groups[1].Value + "2" + match.Groups[3].Value);
|
||||
//return match.Value;
|
||||
return match.Groups[1].Value + "2" + match.Groups[3].Value; // type:3→2
|
||||
}
|
||||
return match.Value;
|
||||
});
|
||||
File.WriteAllText(filePath, newContent);
|
||||
}
|
||||
|
||||
// 重新导入以应用更改
|
||||
textureImporter.SaveAndReimport();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,73 @@
|
||||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
public class AxiStatisticsCache : ScriptableObject
|
||||
{
|
||||
public List<AxiStatisticsDatas> caches = new List<AxiStatisticsDatas>();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class AxiStatisticsDatas
|
||||
{
|
||||
/// <summary>
|
||||
/// [0]Sence [1]Prefab
|
||||
/// </summary>
|
||||
public int type;
|
||||
public string FullPath;
|
||||
public List<AxiStatistics_Node> nodes = new List<AxiStatistics_Node>();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class AxiStatistics_Node
|
||||
{
|
||||
public string Name;
|
||||
public List<AxiStatistics_Node_Link> link = new List<AxiStatistics_Node_Link>();
|
||||
public int LinkHash;
|
||||
public string LinkFullStr;
|
||||
//public string NodeFullPath;
|
||||
// /// <summary>
|
||||
// /// 表示相同路径只有一个
|
||||
// /// </summary>
|
||||
// public bool NodeIdxOnlyOne;
|
||||
/// <summary>
|
||||
/// 表示相同路径是第几个下标
|
||||
/// </summary>
|
||||
//public int NodeIdx;
|
||||
public List<AxiStatistics_Node_Component> components = new List<AxiStatistics_Node_Component>();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class AxiStatistics_Node_Link
|
||||
{
|
||||
public string Name;
|
||||
public bool OnlyOne;
|
||||
public int Idx;
|
||||
public int NodeHash;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class AxiStatistics_Node_Component
|
||||
{
|
||||
public string type;
|
||||
/// <summary>
|
||||
/// 表示相同组件只有一个
|
||||
/// </summary>
|
||||
public bool ComTypeOnlyOne;
|
||||
/// <summary>
|
||||
/// 表示相同组件是第几个下标
|
||||
/// </summary>
|
||||
public int ComIdxNum;
|
||||
//Rigboody
|
||||
public bool simulated;
|
||||
public float gravityScale;
|
||||
public bool isKinematic;
|
||||
//BoxCollider2D
|
||||
public Vector2 center;
|
||||
public Vector2 size;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e4cee4feffb506b4c833262e779424f6
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
@ -15,6 +15,11 @@ public class AxiNS
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 延迟提交是否使用多线程
|
||||
/// </summary>
|
||||
public static bool usedmultithreading = false;
|
||||
|
||||
public AxiNSUser user;
|
||||
public AxiNSMount mount;
|
||||
public AxiNSIO io;
|
||||
|
||||
@ -7,20 +7,20 @@ using System.Text.RegularExpressions;
|
||||
|
||||
public class AxiNSIO
|
||||
{
|
||||
string save_name => AxiNS.instance.mount.SaveMountName;
|
||||
public string save_path => $"{save_name}:/";
|
||||
string save_name => AxiNS.instance.mount.SaveMountName;
|
||||
public string save_path => $"{save_name}:/";
|
||||
#if UNITY_SWITCH
|
||||
private FileHandle fileHandle = new nn.fs.FileHandle();
|
||||
#endif
|
||||
|
||||
static object commitLock = new object();
|
||||
static object commitLock = new object();
|
||||
|
||||
static bool bDirty = false;
|
||||
static bool bDirty = false;
|
||||
|
||||
bool CommitSave()
|
||||
{
|
||||
lock (commitLock)
|
||||
{
|
||||
bool CommitSave()
|
||||
{
|
||||
lock (commitLock)
|
||||
{
|
||||
#if UNITY_SWITCH && !UNITY_EDITOR
|
||||
|
||||
// 阻止用户在保存时,退出游戏 Switch 条例 0080
|
||||
@ -39,41 +39,41 @@ public class AxiNSIO
|
||||
bDirty = false;
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void SetCommitDirty()
|
||||
{
|
||||
lock (commitLock)
|
||||
{
|
||||
bDirty = true;
|
||||
}
|
||||
}
|
||||
void SetCommitDirty()
|
||||
{
|
||||
lock (commitLock)
|
||||
{
|
||||
bDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyAutoCommit()
|
||||
{
|
||||
bool temp;
|
||||
lock (commitLock)
|
||||
{
|
||||
temp = bDirty;
|
||||
}
|
||||
public void ApplyAutoCommit()
|
||||
{
|
||||
bool temp;
|
||||
lock (commitLock)
|
||||
{
|
||||
temp = bDirty;
|
||||
}
|
||||
|
||||
if (temp)
|
||||
{
|
||||
CommitSave();
|
||||
}
|
||||
}
|
||||
if (temp)
|
||||
{
|
||||
CommitSave();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查Path是否存在
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
public bool CheckPathExists(string filePath)
|
||||
{
|
||||
/// <summary>
|
||||
/// 检查Path是否存在
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
public bool CheckPathExists(string filePath)
|
||||
{
|
||||
#if !UNITY_SWITCH
|
||||
return false;
|
||||
#else
|
||||
@ -86,14 +86,14 @@ public class AxiNSIO
|
||||
//return nn.fs.FileSystem.ResultPathAlreadyExists.Includes(result);
|
||||
return !nn.fs.FileSystem.ResultPathNotFound.Includes(result);
|
||||
#endif
|
||||
}
|
||||
/// <summary>
|
||||
/// 检查Path是否不存在
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
public bool CheckPathNotFound(string filePath)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// 检查Path是否不存在
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
public bool CheckPathNotFound(string filePath)
|
||||
{
|
||||
#if !UNITY_SWITCH
|
||||
return false;
|
||||
#else
|
||||
@ -102,16 +102,16 @@ public class AxiNSIO
|
||||
//这个异常捕获。真的别扭
|
||||
return nn.fs.FileSystem.ResultPathNotFound.Includes(result);
|
||||
#endif
|
||||
}
|
||||
/// <summary>
|
||||
/// 创建目录,目录存在也会返回true
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
public bool CreateDir(string filePath)
|
||||
{
|
||||
lock (commitLock)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// 创建目录,目录存在也会返回true
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
public bool CreateDir(string filePath)
|
||||
{
|
||||
lock (commitLock)
|
||||
{
|
||||
|
||||
#if !UNITY_SWITCH
|
||||
return false;
|
||||
@ -124,43 +124,43 @@ public class AxiNSIO
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存并创建文件(如果目录不存在回先自动创建目录)
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="bw"></param>
|
||||
/// <returns></returns>
|
||||
public bool FileToSaveWithCreate(string filePath, System.IO.MemoryStream ms)
|
||||
{
|
||||
return FileToSaveWithCreate(filePath, ms.ToArray());
|
||||
}
|
||||
/// <summary>
|
||||
/// 保存并创建文件(如果目录不存在回先自动创建目录)
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public AxiNSWait_FileToSaveByMSWithCreate FileToSaveWithCreateAsync(string filePath, System.IO.MemoryStream ms)
|
||||
{
|
||||
var wait = new AxiNSWait_FileToSaveByMSWithCreate(filePath, ms);
|
||||
AxiNS.instance.wait.AddWait(wait);
|
||||
return wait;
|
||||
}
|
||||
/// <summary>
|
||||
/// 保存并创建文件(如果目录不存在回先自动创建目录)
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="bw"></param>
|
||||
/// <returns></returns>
|
||||
public bool FileToSaveWithCreate(string filePath, System.IO.MemoryStream ms)
|
||||
{
|
||||
return FileToSaveWithCreate(filePath, ms.ToArray());
|
||||
}
|
||||
/// <summary>
|
||||
/// 保存并创建文件(如果目录不存在回先自动创建目录)
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public AxiNSWait_FileToSaveByMSWithCreate FileToSaveWithCreateAsync(string filePath, System.IO.MemoryStream ms)
|
||||
{
|
||||
var wait = new AxiNSWait_FileToSaveByMSWithCreate(filePath, ms);
|
||||
AxiNS.instance.wait.AddWait(wait);
|
||||
return wait;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存并创建文件(如果目录不存在回先自动创建目录)
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="immediatelyCommit">是否立即Commit到物理存储</param>
|
||||
/// <returns></returns>
|
||||
public bool FileToSaveWithCreate(string filePath, byte[] data, bool immediatelyCommit = true)
|
||||
{
|
||||
lock (commitLock)
|
||||
{
|
||||
/// <summary>
|
||||
/// 保存并创建文件(如果目录不存在回先自动创建目录)
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <param name="immediatelyCommit">是否立即Commit到物理存储</param>
|
||||
/// <returns></returns>
|
||||
public bool FileToSaveWithCreate(string filePath, byte[] data, bool immediatelyCommit = true)
|
||||
{
|
||||
lock (commitLock)
|
||||
{
|
||||
#if !UNITY_SWITCH
|
||||
return false;
|
||||
#else
|
||||
@ -293,42 +293,45 @@ public class AxiNSIO
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 保存并创建文件(如果目录不存在回先自动创建目录)
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public AxiNSWait_FileToSaveWithCreate FileToSaveWithCreateAsync(string filePath, byte[] data)
|
||||
{
|
||||
var wait = new AxiNSWait_FileToSaveWithCreate(filePath, data);
|
||||
AxiNS.instance.wait.AddWait(wait);
|
||||
return wait;
|
||||
}
|
||||
public byte[] LoadSwitchDataFile(string filename)
|
||||
{
|
||||
LoadSwitchDataFile(filename, out byte[] outputData);
|
||||
return outputData;
|
||||
}
|
||||
public bool LoadSwitchDataFile(string filename, ref System.IO.MemoryStream ms)
|
||||
{
|
||||
if (LoadSwitchDataFile(filename, out byte[] outputData))
|
||||
{
|
||||
using (System.IO.BinaryWriter writer = new System.IO.BinaryWriter(ms))
|
||||
{
|
||||
writer.Write(outputData);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public bool LoadSwitchDataFile(string filename, out byte[] outputData)
|
||||
{
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 保存并创建文件(如果目录不存在回先自动创建目录)
|
||||
/// </summary>
|
||||
/// <param name="filePath"></param>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
public AxiNSWait_FileToSaveWithCreate FileToSaveWithCreateAsync(string filePath, byte[] data)
|
||||
{
|
||||
var wait = new AxiNSWait_FileToSaveWithCreate(filePath, data);
|
||||
AxiNS.instance.wait.AddWait(wait);
|
||||
return wait;
|
||||
}
|
||||
public byte[] LoadSwitchDataFile(string filename)
|
||||
{
|
||||
byte[] outputData;
|
||||
LoadSwitchDataFile(filename, out outputData);
|
||||
return outputData;
|
||||
}
|
||||
|
||||
public bool LoadSwitchDataFile(string filename, ref System.IO.MemoryStream ms)
|
||||
{
|
||||
byte[] outputData;
|
||||
if (LoadSwitchDataFile(filename, out outputData))
|
||||
{
|
||||
using (System.IO.BinaryWriter writer = new System.IO.BinaryWriter(ms))
|
||||
{
|
||||
writer.Write(outputData);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public bool LoadSwitchDataFile(string filename, out byte[] outputData)
|
||||
{
|
||||
#if !UNITY_SWITCH || UNITY_EDITOR
|
||||
outputData = null;
|
||||
return false;
|
||||
outputData = null;
|
||||
return false;
|
||||
#else
|
||||
outputData = null;
|
||||
if (!AxiNS.instance.mount.SaveIsMount)
|
||||
@ -376,32 +379,34 @@ public class AxiNSIO
|
||||
outputData = loadedData;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
public AxiNSWait_LoadSwitchDataFile LoadSwitchDataFileAsync(string filename)
|
||||
{
|
||||
var wait = new AxiNSWait_LoadSwitchDataFile(filename);
|
||||
AxiNS.instance.wait.AddWait(wait);
|
||||
return wait;
|
||||
}
|
||||
public bool GetDirectoryFiles(string path, out string[] entrys)
|
||||
{
|
||||
}
|
||||
public AxiNSWait_LoadSwitchDataFile LoadSwitchDataFileAsync(string filename)
|
||||
{
|
||||
var wait = new AxiNSWait_LoadSwitchDataFile(filename);
|
||||
AxiNS.instance.wait.AddWait(wait);
|
||||
return wait;
|
||||
}
|
||||
|
||||
public bool GetDirectoryFiles(string path, out string[] entrys)
|
||||
{
|
||||
#if !UNITY_SWITCH || UNITY_EDITOR
|
||||
|
||||
entrys = null;
|
||||
return false;
|
||||
entrys = null;
|
||||
return false;
|
||||
#else
|
||||
return GetDirectoryEntrys(path,nn.fs.OpenDirectoryMode.File,out entrys);
|
||||
#endif
|
||||
}
|
||||
public bool GetDirectoryDirs(string path, out string[] entrys)
|
||||
{
|
||||
}
|
||||
|
||||
public bool GetDirectoryDirs(string path, out string[] entrys)
|
||||
{
|
||||
#if !UNITY_SWITCH || UNITY_EDITOR
|
||||
entrys = null;
|
||||
return false;
|
||||
entrys = null;
|
||||
return false;
|
||||
#else
|
||||
return GetDirectoryEntrys(path, nn.fs.OpenDirectoryMode.Directory, out entrys);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_SWITCH
|
||||
public bool GetDirectoryEntrys(string path, nn.fs.OpenDirectoryMode type, out string[] entrys)
|
||||
@ -430,8 +435,9 @@ public class AxiNSIO
|
||||
}
|
||||
#endif
|
||||
|
||||
public bool GetDirectoryEntrysFullRecursion(string path, out string[] entrys)
|
||||
{
|
||||
|
||||
public bool GetDirectoryEntrysFullRecursion(string path, out string[] entrys)
|
||||
{
|
||||
#if UNITY_SWITCH
|
||||
|
||||
nn.fs.DirectoryHandle eHandle = new nn.fs.DirectoryHandle();
|
||||
@ -462,15 +468,15 @@ public class AxiNSIO
|
||||
entrys = temp.ToArray();
|
||||
return true;
|
||||
#else
|
||||
entrys = default;
|
||||
entrys = null;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> EnumerateFiles(string path, string searchPattern)
|
||||
{
|
||||
public IEnumerable<string> EnumerateFiles(string path, string searchPattern)
|
||||
{
|
||||
#if !UNITY_SWITCH || UNITY_EDITOR
|
||||
yield break;
|
||||
yield break;
|
||||
#else
|
||||
// 将通配符转换为正则表达式(支持*和?)
|
||||
var regexPattern = "^" +
|
||||
@ -494,10 +500,10 @@ public class AxiNSIO
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public bool DeletePathFile(string filename)
|
||||
{
|
||||
public bool DeletePathFile(string filename)
|
||||
{
|
||||
#if !UNITY_SWITCH
|
||||
return false;
|
||||
#else
|
||||
@ -526,15 +532,15 @@ public class AxiNSIO
|
||||
return CommitSave();
|
||||
|
||||
#endif
|
||||
}
|
||||
public AxiNSWait_DeletePathFile DeletePathFileAsync(string filename)
|
||||
{
|
||||
var wait = new AxiNSWait_DeletePathFile(filename);
|
||||
AxiNS.instance.wait.AddWait(wait);
|
||||
return wait;
|
||||
}
|
||||
public bool DeletePathDir(string filename)
|
||||
{
|
||||
}
|
||||
public AxiNSWait_DeletePathFile DeletePathFileAsync(string filename)
|
||||
{
|
||||
var wait = new AxiNSWait_DeletePathFile(filename);
|
||||
AxiNS.instance.wait.AddWait(wait);
|
||||
return wait;
|
||||
}
|
||||
public bool DeletePathDir(string filename)
|
||||
{
|
||||
#if !UNITY_SWITCH
|
||||
return false;
|
||||
#else
|
||||
@ -561,15 +567,15 @@ public class AxiNSIO
|
||||
#endif
|
||||
return CommitSave();
|
||||
#endif
|
||||
}
|
||||
public AxiNSWait_DeletePathDir DeletePathDirAsync(string filename)
|
||||
{
|
||||
var wait = new AxiNSWait_DeletePathDir(filename);
|
||||
AxiNS.instance.wait.AddWait(wait);
|
||||
return wait;
|
||||
}
|
||||
public bool DeletePathDirRecursively(string filename)
|
||||
{
|
||||
}
|
||||
public AxiNSWait_DeletePathDir DeletePathDirAsync(string filename)
|
||||
{
|
||||
var wait = new AxiNSWait_DeletePathDir(filename);
|
||||
AxiNS.instance.wait.AddWait(wait);
|
||||
return wait;
|
||||
}
|
||||
public bool DeletePathDirRecursively(string filename)
|
||||
{
|
||||
#if !UNITY_SWITCH
|
||||
return false;
|
||||
#else
|
||||
@ -596,19 +602,86 @@ public class AxiNSIO
|
||||
#endif
|
||||
return CommitSave();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
public AxiNSWait_DeletePathDirRecursively DeletePathDirRecursivelyAsync(string filename)
|
||||
{
|
||||
var wait = new AxiNSWait_DeletePathDirRecursively(filename);
|
||||
AxiNS.instance.wait.AddWait(wait);
|
||||
return wait;
|
||||
}
|
||||
|
||||
#if UNITY_SWITCH
|
||||
public AxiNSWait_DeletePathDirRecursively DeletePathDirRecursivelyAsync(string filename)
|
||||
{
|
||||
var wait = new AxiNSWait_DeletePathDirRecursively(filename);
|
||||
AxiNS.instance.wait.AddWait(wait);
|
||||
return wait;
|
||||
}
|
||||
/// <summary>
|
||||
/// 递归删除目录
|
||||
/// </summary>
|
||||
/// <param name="filename"></param>
|
||||
/// <returns></returns>
|
||||
public bool DeleteRecursivelyPathDir(string filename)
|
||||
{
|
||||
#if !UNITY_SWITCH
|
||||
return false;
|
||||
#else
|
||||
|
||||
#if UNITY_SWITCH && !UNITY_EDITOR
|
||||
// This next line prevents the user from quitting the game while saving.
|
||||
// This is required for Nintendo Switch Guideline 0080
|
||||
UnityEngine.Switch.Notification.EnterExitRequestHandlingSection();
|
||||
#endif
|
||||
|
||||
public bool RenameDir(string oldpath, string newpath)
|
||||
{
|
||||
if (CheckPathNotFound(filename))
|
||||
return false;
|
||||
nn.Result result;
|
||||
result = nn.fs.Directory.DeleteRecursively(filename);
|
||||
if (result.IsSuccess() == false)
|
||||
{
|
||||
UnityEngine.Debug.LogError($"nn.fs.File.DeleteRecursively 失败 {filename} : result=>{result.GetErrorInfo()}");
|
||||
return false;
|
||||
}
|
||||
|
||||
#if UNITY_SWITCH && !UNITY_EDITOR
|
||||
// End preventing the user from quitting the game while saving.
|
||||
UnityEngine.Switch.Notification.LeaveExitRequestHandlingSection();
|
||||
#endif
|
||||
return CommitSave();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 递归删除情况
|
||||
/// </summary>
|
||||
/// <param name="filename"></param>
|
||||
/// <returns></returns>
|
||||
public bool CleanRecursivelyPathDir(string filename)
|
||||
{
|
||||
#if !UNITY_SWITCH
|
||||
return false;
|
||||
#else
|
||||
|
||||
#if UNITY_SWITCH && !UNITY_EDITOR
|
||||
// This next line prevents the user from quitting the game while saving.
|
||||
// This is required for Nintendo Switch Guideline 0080
|
||||
UnityEngine.Switch.Notification.EnterExitRequestHandlingSection();
|
||||
#endif
|
||||
|
||||
if (CheckPathNotFound(filename))
|
||||
return false;
|
||||
nn.Result result;
|
||||
result = nn.fs.Directory.CleanRecursively(filename);
|
||||
if (result.IsSuccess() == false)
|
||||
{
|
||||
UnityEngine.Debug.LogError($"nn.fs.File.DeleteRecursively 失败 {filename} : result=>{result.GetErrorInfo()}");
|
||||
return false;
|
||||
}
|
||||
|
||||
#if UNITY_SWITCH && !UNITY_EDITOR
|
||||
// End preventing the user from quitting the game while saving.
|
||||
UnityEngine.Switch.Notification.LeaveExitRequestHandlingSection();
|
||||
#endif
|
||||
return CommitSave();
|
||||
#endif
|
||||
}
|
||||
|
||||
public bool RenameDir(string oldpath, string newpath)
|
||||
{
|
||||
#if !UNITY_SWITCH
|
||||
return false;
|
||||
#else
|
||||
@ -637,9 +710,9 @@ public class AxiNSIO
|
||||
return CommitSave();
|
||||
|
||||
#endif
|
||||
}
|
||||
bool EnsureParentDirectory(string filePath, bool bAutoCreateDir = true)
|
||||
{
|
||||
}
|
||||
bool EnsureParentDirectory(string filePath, bool bAutoCreateDir = true)
|
||||
{
|
||||
#if !UNITY_SWITCH
|
||||
return false;
|
||||
#else
|
||||
@ -715,14 +788,14 @@ public class AxiNSIO
|
||||
return true;
|
||||
|
||||
#endif
|
||||
}
|
||||
/// <summary>
|
||||
/// 检查指定挂载点是否可访问
|
||||
/// </summary>
|
||||
/// <param name="pathPrefix">路径前缀,例如 "save:/" 或 "sd:/"</param>
|
||||
/// <returns>挂载点是否可访问</returns>
|
||||
bool IsMountPointAccessible(string pathPrefix)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// 检查指定挂载点是否可访问
|
||||
/// </summary>
|
||||
/// <param name="pathPrefix">路径前缀,例如 "save:/" 或 "sd:/"</param>
|
||||
/// <returns>挂载点是否可访问</returns>
|
||||
bool IsMountPointAccessible(string pathPrefix)
|
||||
{
|
||||
#if !UNITY_SWITCH
|
||||
return false;
|
||||
#else
|
||||
@ -760,5 +833,5 @@ public class AxiNSIO
|
||||
return true; // 其他挂载点需根据实际需求实现
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
41
AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSMono.cs
Normal file
41
AxibugEmuOnline.Client/Assets/Plugins/AxiNSApi/AxiNSMono.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
public class AxiNSMono : MonoBehaviour
|
||||
{
|
||||
Action act;
|
||||
float waittime;
|
||||
float lastinvokeTime;
|
||||
|
||||
public static void SetInvoke(Action _act, int _waitsec)
|
||||
{
|
||||
GameObject gobj = GameObject.Find($"[{nameof(AxiNSMono)}]");
|
||||
if (gobj == null)
|
||||
{
|
||||
gobj = new GameObject();
|
||||
gobj.name = $"[{nameof(AxiNSMono)}]";
|
||||
GameObject.DontDestroyOnLoad(gobj);
|
||||
}
|
||||
AxiNSMono com = gobj.GetComponent<AxiNSMono>();
|
||||
if (com == null)
|
||||
{
|
||||
com = gobj.AddComponent<AxiNSMono>();
|
||||
}
|
||||
com.act = _act;
|
||||
com.waittime = _waitsec;
|
||||
}
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
Debug.Log("AxiNSMono Enable");
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (Time.time - lastinvokeTime < waittime)
|
||||
return;
|
||||
lastinvokeTime = Time.time;
|
||||
if (act != null)
|
||||
act.Invoke();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23d5745b8989af04d8a871b5c7b65d50
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -116,4 +116,19 @@ public class AxiNSWait_DeletePathDir : AxiNSWaitBase
|
||||
{
|
||||
result = AxiNS.instance.io.DeletePathDir(req.filePath);
|
||||
}
|
||||
}
|
||||
|
||||
public class AxiNSWait_DeletePathDirRecursively : AxiNSWaitBase
|
||||
{
|
||||
S_NSWAIT_Path req;
|
||||
public bool result;
|
||||
public AxiNSWait_DeletePathDirRecursively(string filePath)
|
||||
{
|
||||
req = new S_NSWAIT_Path() { filePath = filePath };
|
||||
}
|
||||
|
||||
public override void Invoke()
|
||||
{
|
||||
result = AxiNS.instance.io.DeletePathDirRecursively(req.filePath);
|
||||
}
|
||||
}
|
||||
@ -4,21 +4,30 @@ using System.Threading;
|
||||
|
||||
public class AxiNSWaitHandle
|
||||
{
|
||||
static AutoResetEvent autoEvent = new AutoResetEvent(false);
|
||||
static Thread waitThread = new Thread(Loop);
|
||||
static bool bSingleInit = false;
|
||||
static Queue<AxiNSWaitBase> m_QueueReady = new Queue<AxiNSWaitBase>();
|
||||
static Queue<AxiNSWaitBase> m_QueueWork = new Queue<AxiNSWaitBase>();
|
||||
public void AddWait(AxiNSWaitBase wait)
|
||||
{
|
||||
InitInternalThread();
|
||||
lock (m_QueueReady)
|
||||
{
|
||||
m_QueueReady.Enqueue(wait);
|
||||
}
|
||||
autoEvent.Set();
|
||||
|
||||
if (AxiNS.usedmultithreading)
|
||||
{
|
||||
InitInternalThread();
|
||||
autoEvent.Set();
|
||||
}
|
||||
else
|
||||
{
|
||||
InitMonoInit();
|
||||
}
|
||||
}
|
||||
|
||||
#region 多线程实现
|
||||
static AutoResetEvent autoEvent = new AutoResetEvent(false);
|
||||
static Thread waitThread = new Thread(Loop);
|
||||
static bool bSingleInit = false;
|
||||
static void InitInternalThread()
|
||||
{
|
||||
if (bSingleInit) return;
|
||||
@ -30,27 +39,43 @@ public class AxiNSWaitHandle
|
||||
{
|
||||
while (autoEvent.WaitOne())
|
||||
{
|
||||
lock (m_QueueReady)
|
||||
Do();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 主线程时间间隔实现
|
||||
static bool bMonoInit = false;
|
||||
static void InitMonoInit()
|
||||
{
|
||||
if (bMonoInit) return;
|
||||
AxiNSMono.SetInvoke(Do,15);
|
||||
bMonoInit = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
static void Do()
|
||||
{
|
||||
lock (m_QueueReady)
|
||||
{
|
||||
while (m_QueueReady.Count > 0)
|
||||
{
|
||||
while (m_QueueReady.Count > 0)
|
||||
{
|
||||
m_QueueWork.Enqueue(m_QueueReady.Dequeue());
|
||||
}
|
||||
m_QueueWork.Enqueue(m_QueueReady.Dequeue());
|
||||
}
|
||||
while (m_QueueWork.Count > 0)
|
||||
}
|
||||
while (m_QueueWork.Count > 0)
|
||||
{
|
||||
AxiNSWaitBase wait = m_QueueWork.Dequeue();
|
||||
try
|
||||
{
|
||||
AxiNSWaitBase wait = m_QueueWork.Dequeue();
|
||||
try
|
||||
{
|
||||
wait.Invoke();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
wait.errmsg = ex.ToString();
|
||||
UnityEngine.Debug.Log(ex.ToString());
|
||||
}
|
||||
wait.SetDone();
|
||||
wait.Invoke();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
wait.errmsg = ex.ToString();
|
||||
UnityEngine.Debug.Log(ex.ToString());
|
||||
}
|
||||
wait.SetDone();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 25ea535c006d6544d9b301a2dcde95b9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,5 @@
|
||||
{
|
||||
"timestamp": 1648458313,
|
||||
"signature": "DWppfmRE13R6S+n/9p1BkuJhH8i4OF2aZu3uXd+7pP8L9LaFr+oymbRCxdy+8l1IFlQzQbQL1ewVCMnKQIonn36dYoZpneipJbUa4CBvwiDObtwD1WSasTq8d9smbhOmeBewyLfkHsGmI4z0WvSJFyq11ISeMXe8pCVoq/PNi5gKfxwvOh4Cy49Y65MZOGAI0MOcOyfQjRS7cR5oPEtAQJysVRtcJPcbPSgr5tjbM9dLf7h5/J6AWXCBav4m6h6932umoOv5FsBQhNQquKqbC984E5ku8G45UKX7t7V0pJFBQe0y1++MN8aSVyJ08IV6h206tTOfIyZVRwswMGGyoAvbF5SF0CmL12QbkW7giZJTa23fvOv09sM3nlA2JpyVSvPWgMmv5HGsLvaboXxSVAp6HcN1M83rMPiQaS34YW/f+JgrHumKa/TTwpzml7kG5xdk3dOACLHRlyDag3oHYmC1OpaI1rnlt7r+z3gCYz5dGTavkHHnNRBukliZYft/",
|
||||
"publicKey": "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQm9qQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FZOEFNSUlCaWdLQ0FZRUFzdUhXYUhsZ0I1cVF4ZEJjTlJKSAordHR4SmoxcVY1NTdvMlZaRE1XaXhYRVBkRTBEMVFkT1JIRXNSS1RscmplUXlERU83ZlNQS0ZwZ1A3MU5TTnJCCkFHM2NFSU45aHNQVDhOVmllZmdWem5QTkVMenFkVmdEbFhpb2VpUnV6OERKWFgvblpmU1JWKytwbk9ySTRibG4KS0twelJlNW14OTc1SjhxZ1FvRktKT0NNRlpHdkJMR2MxSzZZaEIzOHJFODZCZzgzbUovWjBEYkVmQjBxZm13cgo2ZDVFUXFsd0E5Y3JZT1YyV1VpWXprSnBLNmJZNzRZNmM1TmpBcEFKeGNiaTFOaDlRVEhUcU44N0ZtMDF0R1ZwCjVNd1pXSWZuYVRUemEvTGZLelR5U0pka0tldEZMVGdkYXpMYlpzUEE2aHBSK0FJRTJhc0tLTi84UUk1N3UzU2cKL2xyMnZKS1IvU2l5eEN1Q20vQWJkYnJMbXk0WjlSdm1jMGdpclA4T0lLQWxBRWZ2TzV5Z2hSKy8vd1RpTFlzUQp1SllDM0V2UE16ZGdKUzdGR2FscnFLZzlPTCsxVzROY05yNWdveVdSUUJ0cktKaWlTZEJVWmVxb0RvSUY5NHpCCndGbzJJT1JFdXFqcU51M3diMWZIM3p1dGdtalFra3IxVjJhd3hmcExLWlROQWdNQkFBRT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg"
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
# Changelog
|
||||
All notable changes to the input system package will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
Due to package verification, the latest version below is the unpublished version and the date is meaningless.
|
||||
however, it has to be formatted properly to pass verification tests.
|
||||
|
||||
## [0.1.0-preview] - 2019-9-2
|
||||
|
||||
First release from develop branch.
|
||||
|
||||
## [0.1.1-preview] - 2019-10-29
|
||||
|
||||
Updated package dependencies to use latest `com.unity.inputsystem` package version 1.0.0-preview.1
|
||||
|
||||
## [0.1.2-preview] - 2021-05-17
|
||||
|
||||
Updated package dependencies to `com.unity.inputsystem` package version 1.1.0-preview.2 and Unity 2019.4
|
||||
|
||||
Overrides added for aButton, bButton, xButton, yButton functions to map to north, south, east, west buttons correctly for Nintendo layout.
|
||||
Fixed incorrect shortDisplayName values inherited from Gamepad.cs
|
||||
Added "Submit" & "Cancel" UI usage tags to A and B buttons.
|
||||
Added Joy-Con attrbutes to NPad.cs as a bit field, with accessors to get connected and wired states.
|
||||
Minium Unity versions for checking m_Attributes functions (IsWired/IsConnected)
|
||||
2021.2.0a10, 2021.1.1f1, 2020.3.4f1, 2019.4.24f1
|
||||
Added code to parse the Unity application version string and test for NPad attributes support (Assert if attempting to use attributes and Unity version is below minimum required).
|
||||
|
||||
## [0.1.3-pre] - 2021-07-06
|
||||
|
||||
Updated package dependencies to use `com.unity.inputsystem` package 1.1.0-pre.5
|
||||
This fixes an issue where earlier 'com.unity.inputsystem' packages (1.1.0-preview.X) were considered more recent than 1.1.0-pre.5 due to the Semantic Versioning spec and that prevented upgrading to 1.1.0-pre.5 or later.
|
||||
Updated the package name to the use the "Pre-release" label following the new package lifecycle naming convention & patch version increased.
|
||||
|
||||
## [0.1.4-pre] - 2021-11-03
|
||||
|
||||
Fixed logic error in minimum version check (IsVersionOrHigher) for checking support for m_Attributes.
|
||||
The Unity version type (alpha, beta, final etc) should be checked ahead of the revision, so 2021.2.0f1 (final 1) is recognised as a later version than 2021.2.0a10 (alpha 10)
|
||||
|
||||
## [0.1.5-pre] - 2021-11-15
|
||||
|
||||
The package is now signed.
|
||||
|
||||
## [0.1.6-pre] - 2022-03-55
|
||||
|
||||
Fixed a bug where ResetHaptics and PauseHaptics functions were not specifying a RumblePosition flag (Was None, should be All) and so had no effect when called.
|
||||
NPadDeviceIOCTLOutputCommand Create function now takes RumblePosition as an argument (defaulting to All)
|
||||
Fixed a bug in NPadRumbleValues.Reset() where frequencyHigh was not being reset.
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2fe913aba0c6c104ca6b05e2a1def256
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3b3482582c1bb9341aacbb0a24c53938
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aaa7ef903a2a1a041b6888d1a259bda3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9177521509a3da24cb1e37e9eb8d7248
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,27 @@
|
||||
#if UNITY_EDITOR || UNITY_SWITCH
|
||||
using UnityEngine.InputSystem.Haptics;
|
||||
|
||||
namespace UnityEngine.InputSystem.Switch
|
||||
{
|
||||
/// <summary>
|
||||
/// Extended dual motor gamepad that adds seperate controls for rumble frequency and amplitude.
|
||||
/// </summary>
|
||||
public interface INPadRumble : IDualMotorRumble
|
||||
{
|
||||
/// <summary>
|
||||
/// Set rumble for all motors
|
||||
/// </summary>
|
||||
void SetMotorSpeeds(float lowAmplitude, float lowFrequency, float highAmplitude, float highFrequency);
|
||||
|
||||
/// <summary>
|
||||
/// Set rumble for left motor
|
||||
/// </summary>
|
||||
void SetMotorSpeedLeft(float lowAmplitude, float lowFrequency, float highAmplitude, float highFrequency);
|
||||
|
||||
/// <summary>
|
||||
/// Set rumble for right motor
|
||||
/// </summary>
|
||||
void SetMotorSpeedRight(float lowAmplitude, float lowFrequency, float highAmplitude, float highFrequency);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7abf5d9c0bddda4cb82a5d0b3525c0b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,746 @@
|
||||
#if UNITY_EDITOR || UNITY_SWITCH || PACKAGE_DOCS_GENERATION
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEngine.InputSystem.Controls;
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.InputSystem.LowLevel;
|
||||
using UnityEngine.InputSystem.Switch.LowLevel;
|
||||
using UnityEngine.InputSystem.Utilities;
|
||||
|
||||
////REVIEW: The Switch controller can be used to point at things; can we somehow help leverage that?
|
||||
|
||||
namespace UnityEngine.InputSystem.Switch.LowLevel
|
||||
{
|
||||
/// <summary>
|
||||
/// Structure of native input reports for Switch NPad controllers.
|
||||
/// </summary>
|
||||
/// <seealso href="http://en-americas-support.nintendo.com/app/answers/detail/a_id/22634/~/joy-con-controller-diagram"/>
|
||||
[StructLayout(LayoutKind.Explicit, Size = 60)]
|
||||
internal struct NPadInputState : IInputStateTypeInfo
|
||||
{
|
||||
public FourCC format
|
||||
{
|
||||
get { return new FourCC('N', 'P', 'A', 'D'); }
|
||||
}
|
||||
|
||||
[InputControl(name = "dpad")]
|
||||
[InputControl(name = "buttonNorth", displayName = "X", shortDisplayName = "X", bit = (uint)Button.North)]
|
||||
[InputControl(name = "buttonSouth", displayName = "B", shortDisplayName = "B", bit = (uint)Button.South, usages = new[] { "Back", "Cancel" })]
|
||||
[InputControl(name = "buttonWest", displayName = "Y", shortDisplayName = "Y", bit = (uint)Button.West, usage = "SecondaryAction")]
|
||||
[InputControl(name = "buttonEast", displayName = "A", shortDisplayName = "A", bit = (uint)Button.East, usages = new[] { "PrimaryAction", "Submit" })]
|
||||
[InputControl(name = "leftStickPress", displayName = "Left Stick", bit = (uint)Button.StickL)]
|
||||
[InputControl(name = "rightStickPress", displayName = "Right Stick", bit = (uint)Button.StickR)]
|
||||
[InputControl(name = "leftShoulder", displayName = "L", shortDisplayName = "L", bit = (uint)Button.L)]
|
||||
[InputControl(name = "rightShoulder", displayName = "R", shortDisplayName = "R", bit = (uint)Button.R)]
|
||||
[InputControl(name = "leftTrigger", displayName = "ZL", shortDisplayName = "ZL", format = "BIT", bit = (uint)Button.ZL)]
|
||||
[InputControl(name = "rightTrigger", displayName = "ZR", shortDisplayName = "ZR", format = "BIT", bit = (uint)Button.ZR)]
|
||||
[InputControl(name = "start", displayName = "Plus", bit = (uint)Button.Plus, usage = "Menu")]
|
||||
[InputControl(name = "select", displayName = "Minus", bit = (uint)Button.Minus)]
|
||||
[InputControl(name = "leftSL", displayName = "SL (Left)", shortDisplayName = "LSL", layout = "Button", bit = (uint)Button.LSL)]
|
||||
[InputControl(name = "leftSR", displayName = "SR (Left)", shortDisplayName = "LSR", layout = "Button", bit = (uint)Button.LSR)]
|
||||
[InputControl(name = "rightSL", displayName = "SL (Right)", shortDisplayName = "RSL", layout = "Button", bit = (uint)Button.RSL)]
|
||||
[InputControl(name = "rightSR", displayName = "SR (Right)", shortDisplayName = "RSR", layout = "Button", bit = (uint)Button.RSR)]
|
||||
[FieldOffset(0)]
|
||||
public uint buttons;
|
||||
|
||||
[FieldOffset(4)]
|
||||
public Vector2 leftStick;
|
||||
|
||||
[FieldOffset(12)]
|
||||
public Vector2 rightStick;
|
||||
|
||||
[InputControl(name = "acceleration", noisy = true)]
|
||||
[FieldOffset(20)]
|
||||
public Vector3 acceleration;
|
||||
|
||||
[InputControl(name = "attitude", noisy = true)]
|
||||
[FieldOffset(32)]
|
||||
public Quaternion attitude;
|
||||
|
||||
[InputControl(name = "angularVelocity", noisy = true)]
|
||||
[FieldOffset(48)]
|
||||
public Vector3 angularVelocity;
|
||||
|
||||
public float leftTrigger => ((buttons & (1 << (int)Button.ZL)) != 0) ? 1f : 0f;
|
||||
|
||||
public float rightTrigger => ((buttons & (1 << (int)Button.ZR)) != 0) ? 1f : 0f;
|
||||
|
||||
public enum Button
|
||||
{
|
||||
// Dpad buttons. Important to be first in the bitfield as we'll
|
||||
// point the DpadControl to it.
|
||||
// IMPORTANT: Order has to match what is expected by DpadControl.
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
|
||||
North,
|
||||
South,
|
||||
West,
|
||||
East,
|
||||
|
||||
StickL,
|
||||
StickR,
|
||||
L,
|
||||
R,
|
||||
|
||||
ZL,
|
||||
ZR,
|
||||
Plus,
|
||||
Minus,
|
||||
|
||||
LSL,
|
||||
LSR,
|
||||
RSL,
|
||||
RSR,
|
||||
|
||||
X = North,
|
||||
B = South,
|
||||
Y = West,
|
||||
A = East,
|
||||
}
|
||||
|
||||
public NPadInputState WithButton(Button button, bool value = true)
|
||||
{
|
||||
var bit = (uint)1 << (int)button;
|
||||
if (value)
|
||||
buttons |= bit;
|
||||
else
|
||||
buttons &= ~bit;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Switch output report sent as command to the backend.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Explicit, Size = kSize)]
|
||||
internal struct NPadStatusReport : IInputDeviceCommandInfo
|
||||
{
|
||||
public static FourCC Type => new FourCC('N', 'P', 'D', 'S');
|
||||
|
||||
internal const int kSize = InputDeviceCommand.BaseCommandSize + 24;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public InputDeviceCommand baseCommand;
|
||||
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 0)]
|
||||
public NPad.NpadId npadId;
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 1)]
|
||||
public NPad.Orientation orientation;
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 2)]
|
||||
public NPad.Attributes attributes;
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 3)]
|
||||
public char padding0;
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 4)]
|
||||
public NPad.NpadStyles styleMask;
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 8)]
|
||||
public int colorLeftMain;
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 12)]
|
||||
public int colorLeftSub;
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 16)]
|
||||
public int colorRightMain;
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 20)]
|
||||
public int colorRightSub;
|
||||
|
||||
public FourCC typeStatic
|
||||
{
|
||||
get { return Type; }
|
||||
}
|
||||
|
||||
public static NPadStatusReport Create()
|
||||
{
|
||||
return new NPadStatusReport
|
||||
{
|
||||
baseCommand = new InputDeviceCommand(Type, kSize),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = kSize)]
|
||||
internal struct NPadControllerSupportCommand : IInputDeviceCommandInfo
|
||||
{
|
||||
public static FourCC Type => new FourCC('N', 'P', 'D', 'U');
|
||||
|
||||
internal const int kSize = InputDeviceCommand.BaseCommandSize + 8;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public InputDeviceCommand baseCommand;
|
||||
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 0)]
|
||||
public int command;
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 4)]
|
||||
public int option;
|
||||
|
||||
public enum Command : int
|
||||
{
|
||||
kShowUI,
|
||||
kSetHorizontalLayout,
|
||||
kStartSixAxisSensor,
|
||||
kStopSixAxisSensor,
|
||||
}
|
||||
|
||||
public FourCC typeStatic
|
||||
{
|
||||
get { return Type; }
|
||||
}
|
||||
|
||||
public static NPadControllerSupportCommand Create(NPadControllerSupportCommand.Command command, int option = 0)
|
||||
{
|
||||
return new NPadControllerSupportCommand
|
||||
{
|
||||
baseCommand = new InputDeviceCommand(Type, kSize),
|
||||
command = (int)command,
|
||||
option = option,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = kSize)]
|
||||
internal struct NpadDeviceIOCTLShowUI : IInputDeviceCommandInfo
|
||||
{
|
||||
public static FourCC Type => new FourCC("NSUI");
|
||||
internal const int kSize = InputDeviceCommand.BaseCommandSize;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public InputDeviceCommand baseCommand;
|
||||
|
||||
public FourCC typeStatic
|
||||
{
|
||||
get { return Type; }
|
||||
}
|
||||
|
||||
public static NpadDeviceIOCTLShowUI Create()
|
||||
{
|
||||
return new NpadDeviceIOCTLShowUI
|
||||
{
|
||||
baseCommand = new InputDeviceCommand(Type, kSize),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = kSize)]
|
||||
internal struct NpadDeviceIOCTLSetOrientation : IInputDeviceCommandInfo
|
||||
{
|
||||
public static FourCC Type => new FourCC("NSOR");
|
||||
internal const int kSize = InputDeviceCommand.BaseCommandSize + 1;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public InputDeviceCommand baseCommand;
|
||||
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 0)]
|
||||
public NPad.Orientation orientation;
|
||||
|
||||
public FourCC typeStatic
|
||||
{
|
||||
get { return Type; }
|
||||
}
|
||||
|
||||
public static NpadDeviceIOCTLSetOrientation Create(NPad.Orientation orientation)
|
||||
{
|
||||
return new NpadDeviceIOCTLSetOrientation
|
||||
{
|
||||
baseCommand = new InputDeviceCommand(Type, kSize),
|
||||
orientation = orientation,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = kSize)]
|
||||
internal struct NpadDeviceIOCTLStartSixAxisSensor : IInputDeviceCommandInfo
|
||||
{
|
||||
public static FourCC Type => new FourCC("SXST");
|
||||
internal const int kSize = InputDeviceCommand.BaseCommandSize;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public InputDeviceCommand baseCommand;
|
||||
|
||||
public FourCC typeStatic
|
||||
{
|
||||
get { return Type; }
|
||||
}
|
||||
|
||||
public static NpadDeviceIOCTLStartSixAxisSensor Create()
|
||||
{
|
||||
return new NpadDeviceIOCTLStartSixAxisSensor
|
||||
{
|
||||
baseCommand = new InputDeviceCommand(Type, kSize),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit, Size = kSize)]
|
||||
internal struct NpadDeviceIOCTLStopSixAxisSensor : IInputDeviceCommandInfo
|
||||
{
|
||||
public static FourCC Type => new FourCC("SXSP");
|
||||
internal const int kSize = InputDeviceCommand.BaseCommandSize;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public InputDeviceCommand baseCommand;
|
||||
|
||||
public FourCC typeStatic
|
||||
{
|
||||
get { return Type; }
|
||||
}
|
||||
|
||||
public static NpadDeviceIOCTLStopSixAxisSensor Create()
|
||||
{
|
||||
return new NpadDeviceIOCTLStopSixAxisSensor
|
||||
{
|
||||
baseCommand = new InputDeviceCommand(Type, kSize),
|
||||
};
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Switch output report sent as command to backend.
|
||||
/// </summary>
|
||||
// IMPORTANT: Struct must match the NpadDeviceIOCTLOutputReport in native
|
||||
[StructLayout(LayoutKind.Explicit, Size = kSize)]
|
||||
internal struct NPadDeviceIOCTLOutputCommand : IInputDeviceCommandInfo
|
||||
{
|
||||
public static FourCC Type { get { return new FourCC('N', 'P', 'G', 'O'); } }
|
||||
|
||||
internal const int kSize = InputDeviceCommand.BaseCommandSize + 20;
|
||||
public const float DefaultFrequencyLow = 160.0f;
|
||||
public const float DefaultFrequencyHigh = 320.0f;
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1028:EnumStorageShouldBeInt32", Justification = "Need to match native struct data size")]
|
||||
public enum NPadRumblePostion : byte
|
||||
{
|
||||
Left = 0x02,
|
||||
Right = 0x04,
|
||||
All = 0xFF,
|
||||
None = 0x00,
|
||||
}
|
||||
|
||||
[FieldOffset(0)] public InputDeviceCommand baseCommand;
|
||||
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 0)]
|
||||
public byte positions;
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 4)]
|
||||
public float amplitudeLow;
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 8)]
|
||||
public float frequencyLow;
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 12)]
|
||||
public float amplitudeHigh;
|
||||
[FieldOffset(InputDeviceCommand.BaseCommandSize + 16)]
|
||||
public float frequencyHigh;
|
||||
|
||||
public FourCC typeStatic
|
||||
{
|
||||
get { return Type; }
|
||||
}
|
||||
|
||||
public static NPadDeviceIOCTLOutputCommand Create(NPadRumblePostion rumblePos = NPadRumblePostion.All)
|
||||
{
|
||||
return new NPadDeviceIOCTLOutputCommand()
|
||||
{
|
||||
baseCommand = new InputDeviceCommand(Type, kSize),
|
||||
positions = (byte)rumblePos,
|
||||
amplitudeLow = 0,
|
||||
frequencyLow = DefaultFrequencyLow,
|
||||
amplitudeHigh = 0,
|
||||
frequencyHigh = DefaultFrequencyHigh
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace UnityEngine.InputSystem.Switch
|
||||
{
|
||||
/// <summary>
|
||||
/// An NPad controller for Switch, which can be a Joy-Con.
|
||||
/// </summary>
|
||||
/// <seealso cref="NPadInputState"/>
|
||||
[InputControlLayout(stateType = typeof(NPadInputState), displayName = "Switch Controller (on Switch)")]
|
||||
[Scripting.Preserve]
|
||||
public class NPad : Gamepad, INPadRumble
|
||||
{
|
||||
public ButtonControl leftSL { get; private set; }
|
||||
public ButtonControl leftSR { get; private set; }
|
||||
public ButtonControl rightSL { get; private set; }
|
||||
public ButtonControl rightSR { get; private set; }
|
||||
|
||||
public Vector3Control acceleration { get; private set; }
|
||||
public QuaternionControl attitude { get; private set; }
|
||||
public Vector3Control angularVelocity { get; private set; }
|
||||
|
||||
// Override inherited a/b/x/y mappings to match the JoyCon layout
|
||||
public new ButtonControl bButton => buttonSouth;
|
||||
public new ButtonControl aButton => buttonEast;
|
||||
public new ButtonControl yButton => buttonWest;
|
||||
public new ButtonControl xButton => buttonNorth;
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1028:EnumStorageShouldBeInt32", Justification = "Need to match native struct data size")]
|
||||
public enum Orientation : byte
|
||||
{
|
||||
Vertical,
|
||||
Horizontal,
|
||||
Default = Vertical,
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1028:EnumStorageShouldBeInt32", Justification = "Need to match native struct data size")]
|
||||
public enum NpadId : byte
|
||||
{
|
||||
No1 = 0x00,
|
||||
No2 = 0x01,
|
||||
No3 = 0x02,
|
||||
No4 = 0x03,
|
||||
No5 = 0x04,
|
||||
No6 = 0x05,
|
||||
No7 = 0x06,
|
||||
No8 = 0x07,
|
||||
Handheld = 0x20,
|
||||
Debug = 0xF0,
|
||||
Invalid = 0xFF,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum Attributes
|
||||
{
|
||||
IsConnected = 0x01,
|
||||
IsWired = 0x02,
|
||||
IsLeftConnected = 0x04,
|
||||
IsLeftWired = 0x08,
|
||||
IsRightConnected = 0x10,
|
||||
IsRightWired = 0x20,
|
||||
}
|
||||
|
||||
//orientation matters for stick axes!!!!
|
||||
|
||||
//there's a touchpad and 90% of games don't support it
|
||||
|
||||
//each person could play with a different style
|
||||
[Flags]
|
||||
public enum NpadStyles
|
||||
{
|
||||
FullKey = 1 << 0,//separate;or pro controller;only one accel
|
||||
Handheld = 1 << 1,//docked to switch
|
||||
JoyDual = 1 << 2,//separate; one accel per joycon
|
||||
JoyLeft = 1 << 3,//just one; orientation matters
|
||||
JoyRight = 1 << 4,//just one; orientation matters
|
||||
}
|
||||
|
||||
public struct JoyConColor
|
||||
{
|
||||
public Color32 Main;
|
||||
public Color32 Sub;
|
||||
}
|
||||
|
||||
public Orientation orientation
|
||||
{
|
||||
get
|
||||
{
|
||||
RefreshConfigurationIfNeeded();
|
||||
return m_Orientation;
|
||||
}
|
||||
}
|
||||
|
||||
public NpadId npadId
|
||||
{
|
||||
get
|
||||
{
|
||||
RefreshConfigurationIfNeeded();
|
||||
return m_NpadId;
|
||||
}
|
||||
}
|
||||
|
||||
public NpadStyles styleMask
|
||||
{
|
||||
get
|
||||
{
|
||||
RefreshConfigurationIfNeeded();
|
||||
return m_StyleMask;
|
||||
}
|
||||
}
|
||||
|
||||
public JoyConColor leftControllerColor
|
||||
{
|
||||
get
|
||||
{
|
||||
RefreshConfigurationIfNeeded();
|
||||
return m_LeftControllerColor;
|
||||
}
|
||||
}
|
||||
|
||||
public JoyConColor rightControllerColor
|
||||
{
|
||||
get
|
||||
{
|
||||
RefreshConfigurationIfNeeded();
|
||||
return m_RightControllerColor;
|
||||
}
|
||||
}
|
||||
|
||||
public bool isConnected
|
||||
{
|
||||
get
|
||||
{
|
||||
Debug.Assert(SwitchConsoleSupport.NpadAttributesSupported(), k_StringAttributesNotSupported);
|
||||
RefreshConfigurationIfNeeded();
|
||||
return (m_Attributes & Attributes.IsConnected) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool isLeftConnected
|
||||
{
|
||||
get
|
||||
{
|
||||
Debug.Assert(SwitchConsoleSupport.NpadAttributesSupported(), k_StringAttributesNotSupported);
|
||||
RefreshConfigurationIfNeeded();
|
||||
return (m_Attributes & Attributes.IsLeftConnected) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool isRightConnected
|
||||
{
|
||||
get
|
||||
{
|
||||
Debug.Assert(SwitchConsoleSupport.NpadAttributesSupported(),k_StringAttributesNotSupported);
|
||||
RefreshConfigurationIfNeeded();
|
||||
return (m_Attributes & Attributes.IsRightConnected) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool isWired
|
||||
{
|
||||
get
|
||||
{
|
||||
Debug.Assert(SwitchConsoleSupport.NpadAttributesSupported(), k_StringAttributesNotSupported);
|
||||
RefreshConfigurationIfNeeded();
|
||||
return (m_Attributes & Attributes.IsWired) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool isLeftWired
|
||||
{
|
||||
get
|
||||
{
|
||||
Debug.Assert(SwitchConsoleSupport.NpadAttributesSupported(), k_StringAttributesNotSupported);
|
||||
RefreshConfigurationIfNeeded();
|
||||
return (m_Attributes & Attributes.IsLeftWired) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public bool isRightWired
|
||||
{
|
||||
get
|
||||
{
|
||||
Debug.Assert(SwitchConsoleSupport.NpadAttributesSupported(), k_StringAttributesNotSupported);
|
||||
RefreshConfigurationIfNeeded();
|
||||
return (m_Attributes & Attributes.IsRightWired) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
private Orientation m_Orientation;
|
||||
private NpadId m_NpadId = NpadId.Invalid;
|
||||
private NpadStyles m_StyleMask;
|
||||
private JoyConColor m_LeftControllerColor;
|
||||
private JoyConColor m_RightControllerColor;
|
||||
private Attributes m_Attributes;
|
||||
|
||||
private const string k_StringAttributesNotSupported = "Attributes not supported in this Unity version! Requires 2021.2.0a10, 2021.1.1f1, 2020.3.4f1, 2019.4.24f1 or higher";
|
||||
|
||||
private struct NPadRumbleValues
|
||||
{
|
||||
public float? amplitudeLow;
|
||||
public float? frequencyLow;
|
||||
public float? amplitudeHigh;
|
||||
public float? frequencyHigh;
|
||||
|
||||
public bool HasValues => amplitudeLow.HasValue && frequencyLow.HasValue && amplitudeHigh.HasValue && frequencyHigh.HasValue;
|
||||
|
||||
public void SetRumbleValues(float lowAmplitude, float lowFrequency, float highAmplitude, float highFrequency)
|
||||
{
|
||||
amplitudeLow = Mathf.Clamp01(lowAmplitude);
|
||||
frequencyLow = lowFrequency;
|
||||
amplitudeHigh = Mathf.Clamp01(highAmplitude);
|
||||
frequencyHigh = highFrequency;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
amplitudeLow = null;
|
||||
frequencyLow = null;
|
||||
amplitudeHigh = null;
|
||||
frequencyHigh = null;
|
||||
}
|
||||
|
||||
public void ApplyRumbleValues(ref NPadDeviceIOCTLOutputCommand cmd)
|
||||
{
|
||||
cmd.amplitudeLow = (float)amplitudeLow;
|
||||
cmd.frequencyLow = (float)frequencyLow;
|
||||
cmd.amplitudeHigh = (float)amplitudeHigh;
|
||||
cmd.frequencyHigh = (float)frequencyHigh;
|
||||
}
|
||||
}
|
||||
|
||||
private NPadRumbleValues m_leftRumbleValues;
|
||||
private NPadRumbleValues m_rightRumbleValues;
|
||||
|
||||
protected override void RefreshConfiguration()
|
||||
{
|
||||
base.RefreshConfiguration();
|
||||
|
||||
var command = NPadStatusReport.Create();
|
||||
|
||||
if (ExecuteCommand(ref command) > 0)
|
||||
{
|
||||
m_NpadId = command.npadId;
|
||||
m_Orientation = command.orientation;
|
||||
m_StyleMask = command.styleMask;
|
||||
m_Attributes = command.attributes;
|
||||
ReadNNColorIntoJoyConColor(ref m_LeftControllerColor, command.colorLeftMain, command.colorLeftSub);
|
||||
ReadNNColorIntoJoyConColor(ref m_RightControllerColor, command.colorRightMain, command.colorRightSub);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: This function should be static
|
||||
public long SetOrientationToSingleJoyCon(Orientation orientation)
|
||||
{
|
||||
var supportCommand = NpadDeviceIOCTLSetOrientation.Create(orientation);
|
||||
|
||||
return ExecuteCommand(ref supportCommand);
|
||||
}
|
||||
|
||||
public long StartSixAxisSensor()
|
||||
{
|
||||
var supportCommand = NpadDeviceIOCTLStartSixAxisSensor.Create();
|
||||
|
||||
return ExecuteCommand(ref supportCommand);
|
||||
}
|
||||
|
||||
public long StopSixAxisSensor()
|
||||
{
|
||||
var supportCommand = NpadDeviceIOCTLStopSixAxisSensor.Create();
|
||||
|
||||
return ExecuteCommand(ref supportCommand);
|
||||
}
|
||||
|
||||
protected override void FinishSetup()
|
||||
{
|
||||
base.FinishSetup();
|
||||
|
||||
leftSL = GetChildControl<ButtonControl>("leftSL");
|
||||
leftSR = GetChildControl<ButtonControl>("leftSR");
|
||||
rightSL = GetChildControl<ButtonControl>("rightSL");
|
||||
rightSR = GetChildControl<ButtonControl>("rightSR");
|
||||
|
||||
acceleration = GetChildControl<Vector3Control>("acceleration");
|
||||
attitude = GetChildControl<QuaternionControl>("attitude");
|
||||
angularVelocity = GetChildControl<Vector3Control>("angularVelocity");
|
||||
}
|
||||
|
||||
private static void ReadNNColorIntoJoyConColor(ref JoyConColor controllerColor, int mainColor, int subColor)
|
||||
{
|
||||
controllerColor.Main = ConvertNNColorToColor32(mainColor);
|
||||
controllerColor.Sub = ConvertNNColorToColor32(subColor);
|
||||
}
|
||||
|
||||
private static Color32 ConvertNNColorToColor32(int color)
|
||||
{
|
||||
return new Color32((byte)(color & 0xFF), (byte)((color >> 8) & 0xFF), (byte)((color >> 16) & 0xFF), (byte)((color >> 24) & 0xFF));
|
||||
}
|
||||
|
||||
public override void PauseHaptics()
|
||||
{
|
||||
var cmd = NPadDeviceIOCTLOutputCommand.Create();
|
||||
ExecuteCommand(ref cmd);
|
||||
}
|
||||
|
||||
public override void ResetHaptics()
|
||||
{
|
||||
var cmd = NPadDeviceIOCTLOutputCommand.Create();
|
||||
ExecuteCommand(ref cmd);
|
||||
m_leftRumbleValues.Reset();
|
||||
m_rightRumbleValues.Reset();
|
||||
}
|
||||
|
||||
public override void ResumeHaptics()
|
||||
{
|
||||
if (m_leftRumbleValues.Equals(m_rightRumbleValues) && m_leftRumbleValues.HasValues)
|
||||
{
|
||||
var cmd = NPadDeviceIOCTLOutputCommand.Create();
|
||||
m_leftRumbleValues.ApplyRumbleValues(ref cmd);
|
||||
ExecuteCommand(ref cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_leftRumbleValues.HasValues)
|
||||
{
|
||||
var cmd = NPadDeviceIOCTLOutputCommand.Create(NPadDeviceIOCTLOutputCommand.NPadRumblePostion.Left);
|
||||
m_leftRumbleValues.ApplyRumbleValues(ref cmd);
|
||||
ExecuteCommand(ref cmd);
|
||||
}
|
||||
|
||||
if (m_rightRumbleValues.HasValues)
|
||||
{
|
||||
var cmd = NPadDeviceIOCTLOutputCommand.Create(NPadDeviceIOCTLOutputCommand.NPadRumblePostion.Right);
|
||||
m_rightRumbleValues.ApplyRumbleValues(ref cmd);
|
||||
ExecuteCommand(ref cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set rummble intensity for all low and high frequency rumble motors
|
||||
/// </summary>
|
||||
/// <param name="lowFrequency">Low frequency motor's vibration intensity, 0..1 range</param>
|
||||
/// <param name="highFrequency">High frequency motor's vibration intensity, 0..1 range</param>
|
||||
public override void SetMotorSpeeds(float lowFrequency, float highFrequency)
|
||||
{
|
||||
SetMotorSpeeds(lowFrequency, NPadDeviceIOCTLOutputCommand.DefaultFrequencyLow, highFrequency, NPadDeviceIOCTLOutputCommand.DefaultFrequencyHigh);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the intensity and vibration frequency for all low and high frequency rumble motors
|
||||
/// </summary>
|
||||
/// <param name="lowAmplitude">Low frequency motor's vibration intensity, 0..1 range</param>
|
||||
/// <param name="lowFrequency">Low frequency motor's vibration frequency in Hz</param>
|
||||
/// <param name="highAmplitude">High frequency motor's vibration intensity, 0..1 range</param>
|
||||
/// <param name="highFrequency">High frequency motor's vibration frequency in Hz</param>
|
||||
public void SetMotorSpeeds(float lowAmplitude, float lowFrequency, float highAmplitude, float highFrequency)
|
||||
{
|
||||
m_leftRumbleValues.SetRumbleValues(lowAmplitude, lowFrequency, highAmplitude, highFrequency);
|
||||
m_rightRumbleValues.SetRumbleValues(lowAmplitude, lowFrequency, highAmplitude, highFrequency);
|
||||
|
||||
var cmd = NPadDeviceIOCTLOutputCommand.Create();
|
||||
m_leftRumbleValues.ApplyRumbleValues(ref cmd);
|
||||
ExecuteCommand(ref cmd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the intensity and vibration frequency for the left low and high frequency rumble motors
|
||||
/// </summary>
|
||||
/// <param name="lowAmplitude">Low frequency motor's vibration intensity, 0..1 range</param>
|
||||
/// <param name="lowFrequency">Low frequency motor's vibration frequency in Hz</param>
|
||||
/// <param name="highAmplitude">High frequency motor's vibration intensity, 0..1 range</param>
|
||||
/// <param name="highFrequency">High frequency motor's vibration frequency in Hz</param>
|
||||
public void SetMotorSpeedLeft(float lowAmplitude, float lowFrequency, float highAmplitude, float highFrequency)
|
||||
{
|
||||
m_leftRumbleValues.SetRumbleValues(lowAmplitude, lowFrequency, highAmplitude, highFrequency);
|
||||
|
||||
var cmd = NPadDeviceIOCTLOutputCommand.Create(NPadDeviceIOCTLOutputCommand.NPadRumblePostion.Left);
|
||||
m_leftRumbleValues.ApplyRumbleValues(ref cmd);
|
||||
ExecuteCommand(ref cmd);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the intensity and vibration frequency for the right low and high frequency rumble motors
|
||||
/// </summary>
|
||||
/// <param name="lowAmplitude">Low frequency motor's vibration intensity, 0..1 range</param>
|
||||
/// <param name="lowFrequency">Low frequency motor's vibration frequency in Hz</param>
|
||||
/// <param name="highAmplitude">High frequency motor's vibration intensity, 0..1 range</param>
|
||||
/// <param name="highFrequency">High frequency motor's vibration frequency in Hz</param>
|
||||
public void SetMotorSpeedRight(float lowAmplitude, float lowFrequency, float highAmplitude, float highFrequency)
|
||||
{
|
||||
m_rightRumbleValues.SetRumbleValues(lowAmplitude, lowFrequency, highAmplitude, highFrequency);
|
||||
|
||||
var cmd = NPadDeviceIOCTLOutputCommand.Create(NPadDeviceIOCTLOutputCommand.NPadRumblePostion.Right);
|
||||
m_rightRumbleValues.ApplyRumbleValues(ref cmd);
|
||||
ExecuteCommand(ref cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // UNITY_EDITOR || UNITY_SWITCH
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 10b79550bec1ec546ac93d5768427df9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,189 @@
|
||||
|
||||
#if UNITY_EDITOR || UNITY_SWITCH
|
||||
using UnityEngine.InputSystem.Layouts;
|
||||
using UnityEngine.Scripting;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
[assembly: AlwaysLinkAssembly]
|
||||
|
||||
namespace UnityEngine.InputSystem.Switch
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds support for Switch NPad controllers.
|
||||
/// </summary>
|
||||
#if UNITY_EDITOR
|
||||
[InitializeOnLoad]
|
||||
#endif
|
||||
#if UNITY_DISABLE_DEFAULT_INPUT_PLUGIN_INITIALIZATION
|
||||
public
|
||||
#else
|
||||
internal
|
||||
#endif
|
||||
static class SwitchConsoleSupport
|
||||
{
|
||||
static SwitchConsoleSupport()
|
||||
{
|
||||
#if UNITY_EDITOR || UNITY_SWITCH
|
||||
InputSystem.RegisterLayout<NPad>(
|
||||
matches: new InputDeviceMatcher()
|
||||
.WithInterface("Switch")
|
||||
.WithManufacturer("Nintendo")
|
||||
.WithProduct("Wireless Controller"));
|
||||
#endif
|
||||
}
|
||||
|
||||
[RuntimeInitializeOnLoadMethod]
|
||||
private static void InitializeInPlayer()
|
||||
{
|
||||
s_UnityVersion.ParseUnityVersion();
|
||||
}
|
||||
|
||||
struct UnityVersion
|
||||
{
|
||||
public enum EType
|
||||
{
|
||||
Unknown,
|
||||
Alpha,
|
||||
Beta,
|
||||
Final,
|
||||
Patch,
|
||||
Experimental
|
||||
}
|
||||
|
||||
// [Version].[Major].[Minor][Type][Revision][Suffix]
|
||||
// Example 2020.3.1f1
|
||||
// Type being one of:
|
||||
// a: alpha
|
||||
// b: beta
|
||||
// f: public ("final") release
|
||||
// p: patch release(after final)
|
||||
// x: experimental
|
||||
private int Version { get; set; } // Main version (2018, 2019, 2020, 2021 etc)
|
||||
private int Major { get; set; } // Tech-stream or LTS, e.g .1, .2, .3, .4
|
||||
private int Minor { get; set; }
|
||||
private int Revision { get; set; }
|
||||
private EType Type{ get; set; }
|
||||
|
||||
// Must match main version
|
||||
public bool IsVersionOrHigher(int versionIn, int majorIn = 0, int minorIn = 0, EType typeIn = EType.Unknown, int revisionIn = 0)
|
||||
{
|
||||
return Version == versionIn && Major >= majorIn && Minor >= minorIn && ((Type > typeIn || Type == typeIn && Revision >= revisionIn) || Type == EType.Unknown);
|
||||
}
|
||||
public bool IsMainVersionOrLater(int versionIn)
|
||||
{
|
||||
return Version >= versionIn;
|
||||
}
|
||||
|
||||
// Package min Unity version compatibility is 2019.4 LTS so we don't expect to parse older version strings
|
||||
public void ParseUnityVersion()
|
||||
{
|
||||
string unityVer = Application.unityVersion;
|
||||
|
||||
// Parse up to first '.' to read Unity version (year)
|
||||
var startIdx = 0;
|
||||
var endIdx = unityVer.IndexOf('.');
|
||||
var verStr = unityVer.Substring(startIdx, endIdx - startIdx);
|
||||
|
||||
if(int.TryParse(verStr, out var version))
|
||||
{
|
||||
Version = version;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("Failed to parse Unity version: " + unityVer);
|
||||
}
|
||||
|
||||
// Parse up to second '.' for major revision
|
||||
startIdx = endIdx + 1;
|
||||
endIdx = unityVer.IndexOf('.', startIdx);
|
||||
var majStr = unityVer.Substring(startIdx, endIdx - startIdx);
|
||||
|
||||
if (int.TryParse(majStr, out var major))
|
||||
{
|
||||
Major = major;
|
||||
}
|
||||
|
||||
// Break down final part of version string, minor revision, type & suffix ([Minor][Type][Revision][Suffix])
|
||||
startIdx = endIdx + 1;
|
||||
|
||||
// Check for -dots suffix and discard.
|
||||
var suffixIdx = unityVer.IndexOf('-', startIdx);
|
||||
string minStr = (suffixIdx != -1) ? unityVer.Substring(startIdx, suffixIdx - startIdx) : unityVer.Substring(startIdx);
|
||||
|
||||
// Check for China suffix ('c') and discard.
|
||||
suffixIdx = minStr.IndexOf('c');
|
||||
if (suffixIdx != -1)
|
||||
{
|
||||
minStr = minStr.Substring(0, suffixIdx);
|
||||
}
|
||||
|
||||
Minor = 0;
|
||||
Revision = 0;
|
||||
Type = EType.Unknown;
|
||||
|
||||
char[] versionTypes = { 'a', 'b', 'f', 'p', 'x' }; // Known version identifiers
|
||||
var typeIdx = minStr.IndexOfAny(versionTypes);
|
||||
|
||||
if (typeIdx != -1)
|
||||
{
|
||||
var type = minStr[typeIdx];
|
||||
switch (type)
|
||||
{
|
||||
case 'a': Type = EType.Alpha; break;
|
||||
case 'b': Type = EType.Beta; break;
|
||||
case 'f': Type = EType.Final; break;
|
||||
case 'p': Type = EType.Patch; break;
|
||||
case 'x': Type = EType.Experimental; break;
|
||||
default:
|
||||
Debug.LogWarningFormat("Unrecognized type identifier ({0}) in Unity version string: {1}", type, unityVer);
|
||||
break;
|
||||
}
|
||||
|
||||
if (int.TryParse(minStr.Substring(0, typeIdx), out var minor))
|
||||
{
|
||||
Minor = minor;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("Failed to parse minor version from Unity version string: " + unityVer);
|
||||
}
|
||||
|
||||
if (int.TryParse(minStr.Substring(typeIdx + 1), out var revision))
|
||||
{
|
||||
Revision = revision;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("Failed to parse revision from Unity version string: " + unityVer);
|
||||
}
|
||||
}
|
||||
|
||||
//Debug.LogFormat("Version: {0} Major: {1} Minor: {2} Type: {3} Revision: {4}\n", Version, Major, Minor, Type, Revision);
|
||||
}
|
||||
}
|
||||
|
||||
static UnityVersion s_UnityVersion;
|
||||
|
||||
// Attributes queries require a fix in the Switch player available in the following versions onwards
|
||||
// (The attributes field is reusing part of the struct that was padding in older versions)
|
||||
// 2021.2.0a10, 2021.1.1f1, 2020.3.4f1, 2019.4.24f1, Not supported in 2018 or older
|
||||
public static bool NpadAttributesSupported()
|
||||
{
|
||||
if (s_UnityVersion.IsMainVersionOrLater(2022) // Will be supported in all versions of 2022 onward
|
||||
|| s_UnityVersion.IsVersionOrHigher(2021, 2, 0, UnityVersion.EType.Alpha, 10)
|
||||
|| s_UnityVersion.IsVersionOrHigher(2020, 3, 4, UnityVersion.EType.Final, 1)
|
||||
|| s_UnityVersion.IsVersionOrHigher(2019, 4, 24, UnityVersion.EType.Final, 1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fc10b23f19793734895f4ef18a67daf7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "Unity.InputSystem.Switch",
|
||||
"references": [
|
||||
"Unity.InputSystem"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor",
|
||||
"Switch"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": true,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": []
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6374799de9bd44442818ee6dd5dbbfc5
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,31 @@
|
||||
**Unity Companion Package License v1.0 ("_License_")**
|
||||
|
||||
Copyright © 2019 Unity Technologies ApS ("**_Unity_**")
|
||||
|
||||
Unity hereby grants to you a worldwide, non-exclusive, no-charge, and royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense, and distribute the software that is made available with this License ("**_Software_**"), subject to the following terms and conditions:
|
||||
|
||||
1. *Unity Companion Use Only*. Exercise of the license granted herein is limited to exercise for the creation, use, and/or distribution of applications, software, or other content pursuant to a valid Unity development engine software license ("**_Engine License_**"). That means while use of the Software is not limited to use in the software licensed under the Engine License, the Software may not be used for any purpose other than the creation, use, and/or distribution of Engine License-dependent applications, software, or other content. No other exercise of the license granted herein is permitted.
|
||||
|
||||
1. *No Modification of Engine License*. Neither this License nor any exercise of the license granted herein modifies the Engine License in any way.
|
||||
|
||||
1. *Ownership & Grant Back to You*.
|
||||
|
||||
3.1. You own your content. In this License, "derivative works" means derivatives of the Software itself--works derived only from the Software by you under this License (for example, modifying the code of the Software itself to improve its efficacy); “derivative works” of the Software do not include, for example, games, apps, or content that you create using the Software. You keep all right, title, and interest to your own content.
|
||||
|
||||
3.2. Unity owns its content. While you keep all right, title, and interest to your own content per the above, as between Unity and you, Unity will own all right, title, and interest to all intellectual property rights (including patent, trademark, and copyright) in the Software and derivative works of the Software, and you hereby assign and agree to assign all such rights in those derivative works to Unity.
|
||||
|
||||
3.3. You have a license to those derivative works. Subject to this License, Unity grants to you the same worldwide, non-exclusive, no-charge, and royalty-free copyright license to derivative works of the Software you create as is granted to you for the Software under this License.
|
||||
|
||||
1. *Trademarks*. You are not granted any right or license under this License to use any trademarks, service marks, trade names, products names, or branding of Unity or its affiliates ("**_Trademarks_**"). Descriptive uses of Trademarks are permitted; see, for example, Unity’s Branding Usage Guidelines at [https://unity3d.com/public-relations/brand](https://unity3d.com/public-relations/brand).
|
||||
|
||||
1. *Notices & Third-Party Rights*. This License, including the copyright notice above, must be provided in all substantial portions of the Software and derivative works thereof (or, if that is impracticable, in any other location where such notices are customarily placed). Further, if the Software is accompanied by a Unity "third-party notices" or similar file, you acknowledge and agree that software identified in that file is governed by those separate license terms.
|
||||
|
||||
1. *DISCLAIMER, LIMITATION OF LIABILITY*. THE SOFTWARE AND ANY DERIVATIVE WORKS THEREOF IS PROVIDED ON AN "AS IS" BASIS, AND IS PROVIDED WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND/OR NONINFRINGEMENT. IN NO EVENT SHALL ANY COPYRIGHT HOLDER OR AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES (WHETHER DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL, INCLUDING PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF USE, DATA, OR PROFITS, AND BUSINESS INTERRUPTION), OR OTHER LIABILITY WHATSOEVER, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM OR OUT OF, OR IN CONNECTION WITH, THE SOFTWARE OR ANY DERIVATIVE WORKS THEREOF OR THE USE OF OR OTHER DEALINGS IN SAME, EVEN WHERE ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
1. *USE IS ACCEPTANCE and License Versions*. Your receipt and use of the Software constitutes your acceptance of this License and its terms and conditions. Software released by Unity under this License may be modified or updated and the License with it; upon any such modification or update, you will comply with the terms of the updated License for any use of any of the Software under the updated License.
|
||||
|
||||
1. *Use in Compliance with Law and Termination*. Your exercise of the license granted herein will at all times be in compliance with applicable law and will not infringe any proprietary rights (including intellectual property rights); this License will terminate immediately on any breach by you of this License.
|
||||
|
||||
1. *Severability*. If any provision of this License is held to be unenforceable or invalid, that provision will be enforced to the maximum extent possible and the other provisions will remain in full force and effect.
|
||||
|
||||
1. *Governing Law and Venue*. This License is governed by and construed in accordance with the laws of Denmark, except for its conflict of laws rules; the United Nations Convention on Contracts for the International Sale of Goods will not apply. If you reside (or your principal place of business is) within the United States, you and Unity agree to submit to the personal and exclusive jurisdiction of and venue in the state and federal courts located in San Francisco County, California concerning any dispute arising out of this License ("**_Dispute_**"). If you reside (or your principal place of business is) outside the United States, you and Unity agree to submit to the personal and exclusive jurisdiction of and venue in the courts located in Copenhagen, Denmark concerning any Dispute.
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0fc53242e6c9fbd4c88f90fb1e7eff9e
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1 @@
|
||||
Switch Devices and extension for new input system.
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d07bdabda6639b447b233e47dca4e09f
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,9 @@
|
||||
{
|
||||
"SuiteConfig":
|
||||
{
|
||||
"Targets":
|
||||
[
|
||||
"+Switch"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe4afccdf24f4148b8719f9a4ba5872a
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "com.unity.inputsystem.switch",
|
||||
"displayName": "Input System Switch",
|
||||
"version": "0.1.6-pre",
|
||||
"unity": "2019.4",
|
||||
"description": "Switch Devices for new Input System",
|
||||
"keywords": [
|
||||
"input",
|
||||
"keyboard",
|
||||
"mouse",
|
||||
"gamepad",
|
||||
"touch"
|
||||
],
|
||||
"dependencies": {
|
||||
"com.unity.inputsystem": "1.1.0-pre.5"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5132f131fbc3d14da629fca5b83a5e7
|
||||
PackageManifestImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
@ -0,0 +1,130 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 562e8ae4167d26b42b4dd08d3f809531
|
||||
TextureImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 13
|
||||
mipmaps:
|
||||
mipMapMode: 0
|
||||
enableMipMap: 0
|
||||
sRGBTexture: 1
|
||||
linearTexture: 0
|
||||
fadeOut: 0
|
||||
borderMipMap: 0
|
||||
mipMapsPreserveCoverage: 0
|
||||
alphaTestReferenceValue: 0.5
|
||||
mipMapFadeDistanceStart: 1
|
||||
mipMapFadeDistanceEnd: 3
|
||||
bumpmap:
|
||||
convertToNormalMap: 0
|
||||
externalNormalMap: 0
|
||||
heightScale: 0.25
|
||||
normalMapFilter: 0
|
||||
flipGreenChannel: 0
|
||||
isReadable: 0
|
||||
streamingMipmaps: 0
|
||||
streamingMipmapsPriority: 0
|
||||
vTOnly: 0
|
||||
ignoreMipmapLimit: 0
|
||||
grayScaleToAlpha: 0
|
||||
generateCubemap: 6
|
||||
cubemapConvolution: 0
|
||||
seamlessCubemap: 0
|
||||
textureFormat: 1
|
||||
maxTextureSize: 2048
|
||||
textureSettings:
|
||||
serializedVersion: 2
|
||||
filterMode: 1
|
||||
aniso: 1
|
||||
mipBias: 0
|
||||
wrapU: 1
|
||||
wrapV: 1
|
||||
wrapW: 0
|
||||
nPOTScale: 0
|
||||
lightmap: 0
|
||||
compressionQuality: 50
|
||||
spriteMode: 1
|
||||
spriteExtrude: 1
|
||||
spriteMeshType: 1
|
||||
alignment: 0
|
||||
spritePivot: {x: 0.5, y: 0.5}
|
||||
spritePixelsToUnits: 100
|
||||
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
|
||||
spriteGenerateFallbackPhysicsShape: 1
|
||||
alphaUsage: 1
|
||||
alphaIsTransparency: 1
|
||||
spriteTessellationDetail: -1
|
||||
textureType: 8
|
||||
textureShape: 1
|
||||
singleChannelComponent: 0
|
||||
flipbookRows: 1
|
||||
flipbookColumns: 1
|
||||
maxTextureSizeSet: 0
|
||||
compressionQualitySet: 0
|
||||
textureFormatSet: 0
|
||||
ignorePngGamma: 0
|
||||
applyGammaDecoding: 0
|
||||
swizzle: 50462976
|
||||
cookieLightType: 0
|
||||
platformSettings:
|
||||
- serializedVersion: 4
|
||||
buildTarget: DefaultTexturePlatform
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Standalone
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
- serializedVersion: 4
|
||||
buildTarget: Android
|
||||
maxTextureSize: 2048
|
||||
resizeAlgorithm: 0
|
||||
textureFormat: -1
|
||||
textureCompression: 1
|
||||
compressionQuality: 50
|
||||
crunchedCompression: 0
|
||||
allowsAlphaSplitting: 0
|
||||
overridden: 0
|
||||
ignorePlatformSupport: 0
|
||||
androidETC2FallbackOverride: 0
|
||||
forceMaximumCompressionQuality_BC6H_BC7: 0
|
||||
spriteSheet:
|
||||
serializedVersion: 2
|
||||
sprites: []
|
||||
outline: []
|
||||
customData:
|
||||
physicsShape: []
|
||||
bones: []
|
||||
spriteID: 5e97eb03825dee720800000000000000
|
||||
internalID: 0
|
||||
vertices: []
|
||||
indices:
|
||||
edges: []
|
||||
weights: []
|
||||
secondaryTextures: []
|
||||
spriteCustomMetadata:
|
||||
entries: []
|
||||
nameFileIdTable: {}
|
||||
mipmapLimitGroupName:
|
||||
pSDRemoveMatte: 0
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -9,7 +9,8 @@
|
||||
"Essgee.Unity",
|
||||
"StoicGooseUnity",
|
||||
"Unity.InputSystem",
|
||||
"AxiNSApi"
|
||||
"AxiNSApi",
|
||||
"Unity.InputSystem.Switch"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
using AxibugEmuOnline.Client.ClientCore;
|
||||
using AxibugEmuOnline.Client.Common;
|
||||
using AxibugEmuOnline.Client.Event;
|
||||
using AxibugEmuOnline.Client.Settings;
|
||||
using NUnit.Framework.Internal;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using VirtualNes.Core;
|
||||
|
||||
namespace AxibugEmuOnline.Client
|
||||
|
||||
@ -1,7 +1,5 @@
|
||||
using Assets.Script.AppMain.Filter;
|
||||
using System.Drawing.Imaging;
|
||||
using UnityEngine;
|
||||
using static Coffee.UIExtensions.UIEffect;
|
||||
|
||||
namespace AxibugEmuOnline.Client.Filters
|
||||
{
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
using AxibugProtobuf;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace AxibugEmuOnline.Client.InputDevices
|
||||
{
|
||||
public class SwitchJoyCon_D : InputDevice_D
|
||||
{
|
||||
public Button_C LeftSL;
|
||||
public Button_C LeftSR;
|
||||
public Button_C RightSL;
|
||||
public Button_C RightSR;
|
||||
|
||||
public Button_C B;
|
||||
public Button_C A;
|
||||
public Button_C Y;
|
||||
public Button_C X;
|
||||
|
||||
public Button_C Up;
|
||||
public Button_C Down;
|
||||
public Button_C Left;
|
||||
public Button_C Right;
|
||||
|
||||
public Button_C Minus;
|
||||
public Button_C Plus;
|
||||
|
||||
public Stick_C LeftStick;
|
||||
public Stick_C RightStick;
|
||||
public Button_C LeftStickPress;
|
||||
public Button_C RightStickPress;
|
||||
|
||||
public SwitchJoyCon_D(InputResolver resolver) : base(resolver) { }
|
||||
|
||||
public override GamePadType PadType => GamePadType.SwitchJoyCon;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 28380f06191bd35458b20113fbd2960b
|
||||
@ -1,9 +1,18 @@
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
|
||||
#if UNITY_EDITOR || UNITY_STANDALONE_OSX || UNITY_STANDALONE_WIN || UNITY_WSA || PACKAGE_DOCS_GENERATION
|
||||
#define DUALSHOCK_SUPPORT
|
||||
#endif
|
||||
|
||||
#if UNITY_EDITOR || UNITY_SWITCH || PACKAGE_DOCS_GENERATION
|
||||
#define JOYCON_SUPPORT
|
||||
#endif
|
||||
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.Android;
|
||||
using UnityEngine.InputSystem.DualShock;
|
||||
using UnityEngine.InputSystem.Switch;
|
||||
using UnityEngine.InputSystem.XInput;
|
||||
|
||||
namespace AxibugEmuOnline.Client.InputDevices.ForInputSystem
|
||||
@ -24,18 +33,26 @@ namespace AxibugEmuOnline.Client.InputDevices.ForInputSystem
|
||||
{
|
||||
InputDevice_D newDevice = null;
|
||||
if (ipdev is Keyboard) newDevice = new Keyboard_D(this);
|
||||
|
||||
#if DUALSHOCK_SUPPORT
|
||||
else if (ipdev is DualShockGamepad)
|
||||
{
|
||||
if (ipdev is DualShock3GamepadHID) newDevice = new DualShockController_D(this, ps3: true);
|
||||
else if (ipdev is DualShock4GamepadHID) newDevice = new DualShockController_D(this, ps4: true);
|
||||
else if (ipdev is DualSenseGamepadHID) newDevice = new DualShockController_D(this, ps5: true);
|
||||
else newDevice = new DualShockController_D(this);
|
||||
|
||||
}
|
||||
#endif
|
||||
else if (ipdev is XInputController)
|
||||
{
|
||||
newDevice = new XboxController_D(this);
|
||||
}
|
||||
#if JOYCON_SUPPORT
|
||||
else if (ipdev is NPad)
|
||||
{
|
||||
newDevice = new SwitchJoyCon_D(this);
|
||||
}
|
||||
#endif
|
||||
else if (ipdev is Gamepad) newDevice = new GamePad_D(this); //注意Gamepad的优先级,因为任何手柄,Inputsystem中的基类都是GamePad
|
||||
|
||||
if (newDevice != null)
|
||||
@ -98,13 +115,13 @@ namespace AxibugEmuOnline.Client.InputDevices.ForInputSystem
|
||||
protected override Vector2 OnGetVector2<CONTROLLER>(CONTROLLER control)
|
||||
{
|
||||
var ipControl = GetInputSystemControl(control);
|
||||
return (ipControl as InputControl<Vector2>).value;
|
||||
return (ipControl as InputControl<Vector2>).ReadValue();
|
||||
}
|
||||
|
||||
protected override float OnGetFloat<CONTROLLER>(CONTROLLER control)
|
||||
{
|
||||
var ipControl = GetInputSystemControl(control);
|
||||
return (ipControl as InputControl<float>).value;
|
||||
return (ipControl as InputControl<float>).ReadValue();
|
||||
}
|
||||
|
||||
InputControl GetInputSystemControl(InputControl_C key)
|
||||
@ -233,6 +250,7 @@ namespace AxibugEmuOnline.Client.InputDevices.ForInputSystem
|
||||
mapper[keyboard_d.Semicolon] = ipKeyboard.semicolonKey;
|
||||
mapper[keyboard_d.Quote] = ipKeyboard.quoteKey;
|
||||
}
|
||||
#if DUALSHOCK_SUPPORT
|
||||
else if (device_d is DualShockController_D ds_d)
|
||||
{
|
||||
var ipDsGamePad = ipdevice as DualShockGamepad;
|
||||
@ -256,6 +274,7 @@ namespace AxibugEmuOnline.Client.InputDevices.ForInputSystem
|
||||
mapper[ds_d.LeftStick] = ipDsGamePad.leftStick;
|
||||
mapper[ds_d.RightStick] = ipDsGamePad.rightStick;
|
||||
}
|
||||
#endif
|
||||
else if (device_d is XboxController_D xbox_d)
|
||||
{
|
||||
var ipXInputGamePad = ipdevice as XInputController;
|
||||
@ -277,8 +296,31 @@ namespace AxibugEmuOnline.Client.InputDevices.ForInputSystem
|
||||
mapper[xbox_d.RightStickPress] = ipXInputGamePad.rightStickButton;
|
||||
mapper[xbox_d.LeftStick] = ipXInputGamePad.leftStick;
|
||||
mapper[xbox_d.RightStick] = ipXInputGamePad.rightStick;
|
||||
|
||||
}
|
||||
#if JOYCON_SUPPORT
|
||||
else if (device_d is SwitchJoyCon_D joycon_d)
|
||||
{
|
||||
var ipdevice_joycon = ipdevice as NPad;
|
||||
mapper[joycon_d.LeftSL] = ipdevice_joycon.leftSL;
|
||||
mapper[joycon_d.LeftSR] = ipdevice_joycon.leftSR;
|
||||
mapper[joycon_d.RightSL] = ipdevice_joycon.rightSL;
|
||||
mapper[joycon_d.RightSR] = ipdevice_joycon.rightSR;
|
||||
mapper[joycon_d.B] = ipdevice_joycon.bButton;
|
||||
mapper[joycon_d.A] = ipdevice_joycon.aButton;
|
||||
mapper[joycon_d.Y] = ipdevice_joycon.yButton;
|
||||
mapper[joycon_d.X] = ipdevice_joycon.xButton;
|
||||
mapper[joycon_d.Up] = ipdevice_joycon.dpad.up;
|
||||
mapper[joycon_d.Down] = ipdevice_joycon.dpad.down;
|
||||
mapper[joycon_d.Left] = ipdevice_joycon.dpad.left;
|
||||
mapper[joycon_d.Right] = ipdevice_joycon.dpad.right;
|
||||
mapper[joycon_d.Minus] = ipdevice_joycon.selectButton;
|
||||
mapper[joycon_d.Plus] = ipdevice_joycon.startButton;
|
||||
mapper[joycon_d.LeftStick] = ipdevice_joycon.leftStick;
|
||||
mapper[joycon_d.RightStick] = ipdevice_joycon.rightStick;
|
||||
mapper[joycon_d.RightStickPress] = ipdevice_joycon.rightStickButton;
|
||||
mapper[joycon_d.LeftStickPress] = ipdevice_joycon.leftStickButton;
|
||||
}
|
||||
#endif
|
||||
else if (device_d is GamePad_D gamepad_d)
|
||||
{
|
||||
var ipGamepad = ipdevice as Gamepad;
|
||||
@ -300,6 +342,7 @@ namespace AxibugEmuOnline.Client.InputDevices.ForInputSystem
|
||||
mapper[gamepad_d.RightStickPress] = ipGamepad.rightStickButton;
|
||||
mapper[gamepad_d.LeftStick] = ipGamepad.leftStick;
|
||||
mapper[gamepad_d.RightStick] = ipGamepad.rightStick;
|
||||
|
||||
}
|
||||
else throw new System.NotImplementedException($"初始化设备失败,未实现的物理按键映射 for {device_d.GetType()}");
|
||||
}
|
||||
@ -308,6 +351,6 @@ namespace AxibugEmuOnline.Client.InputDevices.ForInputSystem
|
||||
m_deviceMapper.Remove(keyboard_d);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -163,7 +163,7 @@ PlayerSettings:
|
||||
androidMaxAspectRatio: 2.1
|
||||
androidMinAspectRatio: 1
|
||||
applicationIdentifier:
|
||||
Android: com.DefaultCompany.AxibugEmuOnline.Client
|
||||
Android: com.AlienTechnology.AxibugEmuOnline.Client
|
||||
Standalone: com.AlienTechnology.AxibugEmuOnline.Client
|
||||
buildNumber:
|
||||
Standalone: 0
|
||||
@ -404,11 +404,13 @@ PlayerSettings:
|
||||
iPhone: 1
|
||||
tvOS: 1
|
||||
m_BuildTargetGroupLightmapEncodingQuality: []
|
||||
m_BuildTargetGroupHDRCubemapEncodingQuality: []
|
||||
m_BuildTargetGroupLightmapSettings: []
|
||||
m_BuildTargetGroupLoadStoreDebugModeSettings: []
|
||||
m_BuildTargetNormalMapEncoding: []
|
||||
m_BuildTargetDefaultTextureCompressionFormat: []
|
||||
m_BuildTargetDefaultTextureCompressionFormat:
|
||||
- serializedVersion: 3
|
||||
m_BuildTarget: Android
|
||||
m_Formats: 01000000
|
||||
playModeTestRunnerEnabled: 0
|
||||
runPlayModeTestAsEditModeTest: 0
|
||||
actionOnDotNetUnhandledException: 1
|
||||
@ -668,12 +670,12 @@ PlayerSettings:
|
||||
webGLMemoryLinearGrowthStep: 16
|
||||
webGLMemoryGeometricGrowthStep: 0.2
|
||||
webGLMemoryGeometricGrowthCap: 96
|
||||
webGLEnableWebGPU: 0
|
||||
webGLPowerPreference: 2
|
||||
webGLWebAssemblyTable: 0
|
||||
webGLWebAssemblyBigInt: 0
|
||||
webGLCloseOnQuit: 0
|
||||
webWasm2023: 0
|
||||
webEnableSubmoduleStrippingCompatibility: 0
|
||||
scriptingDefineSymbols:
|
||||
Android: DOTWEEN;ODIN_INSPECTOR;ODIN_INSPECTOR_3;ODIN_INSPECTOR_3_1;ODIN_INSPECTOR_EDITOR_ONLY;UNITY_POST_PROCESSING_STACK_V2
|
||||
EmbeddedLinux: UNITY_POST_PROCESSING_STACK_V2
|
||||
@ -820,4 +822,3 @@ PlayerSettings:
|
||||
insecureHttpOption: 2
|
||||
androidVulkanDenyFilterList: []
|
||||
androidVulkanAllowFilterList: []
|
||||
androidVulkanDeviceFilterListAsset: {fileID: 0}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user