Compare commits
20 Commits
e432177af8
...
main
Author | SHA1 | Date | |
---|---|---|---|
64e0bf2282 | |||
41d502b239 | |||
6271171ab4 | |||
7906203f84 | |||
dfa00340f5 | |||
9b9264a6cc | |||
3c962267ab | |||
344260266c | |||
040f167b6d | |||
7887695a67 | |||
073dd25857 | |||
ce56cca782 | |||
f8aea1c383 | |||
249836d1ec | |||
6de8b3ebc5 | |||
427b916dd2 | |||
f6384a4a8c | |||
f9f80aa559 | |||
5365ab6441 | |||
2c784ff343 |
58
Convention/Editor/File.cs
Normal file
58
Convention/Editor/File.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Convention
|
||||
{
|
||||
public class FileEditor : AbstractCustomEditor
|
||||
{
|
||||
[MenuItem("Convention/AssetBundle/Create for Android")]
|
||||
static void CreatAssetBundle()
|
||||
{
|
||||
string path = Path.Combine(Application.dataPath, "../", "AssetBundle", "Android");
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
BuildPipeline.BuildAssetBundles(path, BuildAssetBundleOptions.None, BuildTarget.Android);
|
||||
UnityEngine.Debug.Log("Android Finish!");
|
||||
}
|
||||
|
||||
[MenuItem("Convention/AssetBundle/Create for IOS")]
|
||||
static void BuildAllAssetBundlesForIOS()
|
||||
{
|
||||
string dirName = "AssetBundles/IOS/";
|
||||
if (!Directory.Exists(dirName))
|
||||
{
|
||||
Directory.CreateDirectory(dirName);
|
||||
}
|
||||
BuildPipeline.BuildAssetBundles(dirName, BuildAssetBundleOptions.None, BuildTarget.iOS);
|
||||
UnityEngine.Debug.Log("IOS Finish!");
|
||||
|
||||
}
|
||||
|
||||
[MenuItem("Convention/AssetBundle/Create for Windows")]
|
||||
static void CreatPCAssetBundleForwINDOWS()
|
||||
{
|
||||
string path = Path.Combine(Application.dataPath, "../", "AssetBundle", "Windows");
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
BuildPipeline.BuildAssetBundles(path, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
|
||||
UnityEngine.Debug.Log("Windows Finish!");
|
||||
}
|
||||
|
||||
[MenuItem("Convention/AssetBundle/Create for Mac")]
|
||||
static void CreatPCAssetBundleForMac()
|
||||
{
|
||||
string path = Path.Combine(Application.dataPath, "../", "AssetBundle", "Mac");
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
Directory.CreateDirectory(path);
|
||||
}
|
||||
BuildPipeline.BuildAssetBundles(path, BuildAssetBundleOptions.None, BuildTarget.StandaloneOSX);
|
||||
UnityEngine.Debug.Log("Mac Finish!");
|
||||
}
|
||||
}
|
||||
}
|
11
Convention/Editor/File.cs.meta
Normal file
11
Convention/Editor/File.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0fde7509f09639547adff8534a7d9698
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Convention/Editor/UI.meta
Normal file
8
Convention/Editor/UI.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c35ac0f81d1249a46909cd5f6156b761
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
12
Convention/Editor/UI/Button.cs
Normal file
12
Convention/Editor/UI/Button.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Convention;
|
||||
using UnityEditor;
|
||||
using Convention.WindowsUI;
|
||||
|
||||
[CustomEditor(typeof(ModernUIButton))]
|
||||
public class ModernUIButtonEditor : AbstractCustomEditor
|
||||
{
|
||||
|
||||
}
|
11
Convention/Editor/UI/Button.cs.meta
Normal file
11
Convention/Editor/UI/Button.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b297501dc7cdd2149ab976e2fb8f88f0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
97
Convention/Resources/Master.mixer
Normal file
97
Convention/Resources/Master.mixer
Normal file
@@ -0,0 +1,97 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!244 &-6002849048023987392
|
||||
AudioMixerEffectController:
|
||||
m_ObjectHideFlags: 3
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_EffectID: ceab011db4879ba41ad52c5eeea147e4
|
||||
m_EffectName: Pitch Shifter
|
||||
m_MixLevel: cd15d53e9c8be5142b26dca79aa9887e
|
||||
m_Parameters:
|
||||
- m_ParameterName: Pitch
|
||||
m_GUID: a397a80ee8dae584d8bf0cca5579369b
|
||||
- m_ParameterName: FFT size
|
||||
m_GUID: a4a905f7c52f4b94e99ba9e6040d409e
|
||||
- m_ParameterName: Overlap
|
||||
m_GUID: 7671900607ffbac4ca75e8a96523d3a2
|
||||
- m_ParameterName: Max channels
|
||||
m_GUID: 088381d8f17bda842aa440a34123a808
|
||||
m_SendTarget: {fileID: 0}
|
||||
m_EnableWetMix: 0
|
||||
m_Bypass: 0
|
||||
--- !u!241 &24100000
|
||||
AudioMixerController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Master
|
||||
m_OutputGroup: {fileID: 0}
|
||||
m_MasterGroup: {fileID: 24300002}
|
||||
m_Snapshots:
|
||||
- {fileID: 24500006}
|
||||
m_StartSnapshot: {fileID: 24500006}
|
||||
m_SuspendThreshold: -80
|
||||
m_EnableSuspend: 1
|
||||
m_UpdateMode: 0
|
||||
m_ExposedParameters:
|
||||
- guid: b0ebf2901c1aeb344b2a87ae242df1b5
|
||||
name: MasterPitch
|
||||
- guid: a397a80ee8dae584d8bf0cca5579369b
|
||||
name: PitchShifterPitch
|
||||
m_AudioMixerGroupViews:
|
||||
- guids:
|
||||
- a3c32b9d162f19a419568f094319d0c7
|
||||
name: View
|
||||
m_CurrentViewIndex: 0
|
||||
m_TargetSnapshot: {fileID: 24500006}
|
||||
--- !u!243 &24300002
|
||||
AudioMixerGroupController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Master
|
||||
m_AudioMixer: {fileID: 24100000}
|
||||
m_GroupID: a3c32b9d162f19a419568f094319d0c7
|
||||
m_Children: []
|
||||
m_Volume: 068965e8a514a9a44863437ee299ef13
|
||||
m_Pitch: b0ebf2901c1aeb344b2a87ae242df1b5
|
||||
m_Send: 00000000000000000000000000000000
|
||||
m_Effects:
|
||||
- {fileID: 24400004}
|
||||
- {fileID: -6002849048023987392}
|
||||
m_UserColorIndex: 0
|
||||
m_Mute: 0
|
||||
m_Solo: 0
|
||||
m_BypassEffects: 0
|
||||
--- !u!244 &24400004
|
||||
AudioMixerEffectController:
|
||||
m_ObjectHideFlags: 3
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name:
|
||||
m_EffectID: a8d7e4c02308ae44f9fc51dc9de13a3e
|
||||
m_EffectName: Attenuation
|
||||
m_MixLevel: 529a1bce94cdf3b43af8d5ba16028c5c
|
||||
m_Parameters: []
|
||||
m_SendTarget: {fileID: 0}
|
||||
m_EnableWetMix: 0
|
||||
m_Bypass: 0
|
||||
--- !u!245 &24500006
|
||||
AudioMixerSnapshotController:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: Snapshot
|
||||
m_AudioMixer: {fileID: 24100000}
|
||||
m_SnapshotID: 92ac84973c010d04fbc3a98fc121b6ce
|
||||
m_FloatValues:
|
||||
b0ebf2901c1aeb344b2a87ae242df1b5: 1
|
||||
a397a80ee8dae584d8bf0cca5579369b: 1
|
||||
m_TransitionOverrides: {}
|
8
Convention/Resources/Master.mixer.meta
Normal file
8
Convention/Resources/Master.mixer.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d8c64a4848e9d849a8e2eddaae1c049
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 24100000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -18,7 +18,7 @@ GameObject:
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 0
|
||||
m_IsActive: 1
|
||||
--- !u!224 &6739692666707570911
|
||||
RectTransform:
|
||||
m_ObjectHideFlags: 0
|
||||
|
@@ -96,8 +96,10 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_CurrentContextKey: 0
|
||||
m_AllContextPlane: []
|
||||
WindowPlane: {fileID: 6262932319296346077}
|
||||
m_AllContextPlane:
|
||||
- plane: {fileID: 1743752460056994028}
|
||||
root: {fileID: 6898088878883608404}
|
||||
WindowPlane: {fileID: 2851218872878303137}
|
||||
WindowBar: {fileID: 5431686027440357681}
|
||||
--- !u!114 &8120993653923732271
|
||||
MonoBehaviour:
|
||||
@@ -350,6 +352,7 @@ MonoBehaviour:
|
||||
anchorMin: {x: 0, y: 0}
|
||||
pivot: {x: 0, y: 0}
|
||||
BeforeMaximizeWindowBackgroundColorA: 1
|
||||
IsMaximizeWindowMode: 0
|
||||
AdjustSizeToContainsRect: {fileID: 0}
|
||||
--- !u!114 &6852005934204649840
|
||||
MonoBehaviour:
|
||||
@@ -707,6 +710,17 @@ PrefabInstance:
|
||||
addedObject: {fileID: 1225826108170619254}
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 9f83398a7d855e44493acb9b240c01ca, type: 3}
|
||||
--- !u!114 &2851218872878303137 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 6525725186002079832, guid: 9f83398a7d855e44493acb9b240c01ca, type: 3}
|
||||
m_PrefabInstance: {fileID: 9007647915676817401}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 999be728ad5e8324baf45ccaf0f9c3d2, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!224 &6898088878883608404 stripped
|
||||
RectTransform:
|
||||
m_CorrespondingSourceObject: {fileID: 2502725167534981293, guid: 9f83398a7d855e44493acb9b240c01ca, type: 3}
|
||||
|
@@ -482,7 +482,7 @@ MonoBehaviour:
|
||||
m_Calls: []
|
||||
m_text: Assets
|
||||
m_isRightToLeft: 0
|
||||
m_fontAsset: {fileID: 11400000, guid: 3994fc09180bdb54484d538bb5d127b4, type: 2}
|
||||
m_fontAsset: {fileID: 0}
|
||||
m_sharedMaterial: {fileID: -8493678639131513909, guid: 3994fc09180bdb54484d538bb5d127b4, type: 2}
|
||||
m_fontSharedMaterials: []
|
||||
m_fontMaterial: {fileID: 0}
|
||||
|
@@ -1085,6 +1085,7 @@ MonoBehaviour:
|
||||
anchorMin: {x: 0, y: 0}
|
||||
pivot: {x: 0, y: 0}
|
||||
BeforeMaximizeWindowBackgroundColorA: 1
|
||||
IsMaximizeWindowMode: 0
|
||||
AdjustSizeToContainsRect: {fileID: 0}
|
||||
--- !u!114 &3897188892033144510
|
||||
MonoBehaviour:
|
||||
@@ -1106,7 +1107,7 @@ MonoBehaviour:
|
||||
m_ChildAlignment: 0
|
||||
m_Spacing: 2
|
||||
m_ChildForceExpandWidth: 1
|
||||
m_ChildForceExpandHeight: 1
|
||||
m_ChildForceExpandHeight: 0
|
||||
m_ChildControlWidth: 0
|
||||
m_ChildControlHeight: 0
|
||||
m_ChildScaleWidth: 0
|
||||
|
@@ -58,11 +58,11 @@ MonoBehaviour:
|
||||
m_ChildAlignment: 0
|
||||
m_Spacing: 0
|
||||
m_ChildForceExpandWidth: 1
|
||||
m_ChildForceExpandHeight: 1
|
||||
m_ChildForceExpandHeight: 0
|
||||
m_ChildControlWidth: 0
|
||||
m_ChildControlHeight: 0
|
||||
m_ChildScaleWidth: 0
|
||||
m_ChildScaleHeight: 0
|
||||
m_ChildScaleHeight: 1
|
||||
m_ReverseArrangement: 0
|
||||
--- !u!114 &2447206846939804910
|
||||
MonoBehaviour:
|
||||
@@ -77,6 +77,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_rawButton: {fileID: 6792858692426831327}
|
||||
m_modernButton: {fileID: 0}
|
||||
layerTab: 7.5
|
||||
layerHeight: 15
|
||||
dropdownImage: {fileID: 7630776060629663467}
|
||||
@@ -327,6 +328,18 @@ PrefabInstance:
|
||||
serializedVersion: 3
|
||||
m_TransformParent: {fileID: 0}
|
||||
m_Modifications:
|
||||
- target: {fileID: 860861549860063477, guid: 14851ab435cb18448974bf76e92d8952, type: 3}
|
||||
propertyPath: m_AllContextPlane.Array.size
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 860861549860063477, guid: 14851ab435cb18448974bf76e92d8952, type: 3}
|
||||
propertyPath: m_AllContextPlane.Array.data[0].root
|
||||
value:
|
||||
objectReference: {fileID: 8975345697986449064}
|
||||
- target: {fileID: 860861549860063477, guid: 14851ab435cb18448974bf76e92d8952, type: 3}
|
||||
propertyPath: m_AllContextPlane.Array.data[0].plane
|
||||
value:
|
||||
objectReference: {fileID: 8975345697986449064}
|
||||
- target: {fileID: 2372686227554923148, guid: 14851ab435cb18448974bf76e92d8952, type: 3}
|
||||
propertyPath: m_AnchorMax.y
|
||||
value: 0
|
||||
|
@@ -439,6 +439,7 @@ MonoBehaviour:
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
m_rawButton: {fileID: 3558458297121154720}
|
||||
m_modernButton: {fileID: 0}
|
||||
layerTab: 7.5
|
||||
layerHeight: 15
|
||||
dropdownImage: {fileID: 240697464900702333}
|
||||
@@ -1127,7 +1128,7 @@ PrefabInstance:
|
||||
- target: {fileID: 3241788778710343315, guid: 37924db2d27cd6e49bf8002531a08095, type: 3}
|
||||
propertyPath: m_fontAsset
|
||||
value:
|
||||
objectReference: {fileID: 11400000, guid: 3994fc09180bdb54484d538bb5d127b4, type: 2}
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 3241788778710343315, guid: 37924db2d27cd6e49bf8002531a08095, type: 3}
|
||||
propertyPath: m_fontSizeMax
|
||||
value: 12
|
||||
@@ -1458,6 +1459,7 @@ MonoBehaviour:
|
||||
anchorMin: {x: 0, y: 0}
|
||||
pivot: {x: 0, y: 0}
|
||||
BeforeMaximizeWindowBackgroundColorA: 1
|
||||
IsMaximizeWindowMode: 0
|
||||
AdjustSizeToContainsRect: {fileID: 0}
|
||||
--- !u!114 &682559958368963457
|
||||
MonoBehaviour:
|
||||
|
@@ -141,7 +141,7 @@ Material:
|
||||
- _Anisotropy: 0
|
||||
- _BlendMode: 0
|
||||
- _CoatMask: 0
|
||||
- _ColorLevel: 1
|
||||
- _ColorLevel: 0.1
|
||||
- _CullMode: 2
|
||||
- _CullModeForward: 2
|
||||
- _Cutoff: 0.5
|
||||
|
@@ -6,7 +6,7 @@ using UnityEngine;
|
||||
|
||||
namespace Convention.VFX
|
||||
{
|
||||
public class DreamTeckSplinePointBuilder : MonoAnyBehaviour, ILoadedInHierarchy
|
||||
public class DreamTeckSplinePointBuilder : MonoBehaviour, ILoadedInHierarchy
|
||||
{
|
||||
public enum InjectType
|
||||
{
|
||||
@@ -15,7 +15,6 @@ namespace Convention.VFX
|
||||
Broken = SplinePoint.Type.Broken,
|
||||
SmoothFree = SplinePoint.Type.SmoothFree
|
||||
};
|
||||
[Setting, InspectorDraw] public PerformanceIndicator.PerformanceMode performanceMode = PerformanceIndicator.PerformanceMode.Speed;
|
||||
[Content] public List<LinePoint> childPoints = new();
|
||||
|
||||
[Resources, SerializeField, HopeNotNull, InspectorDraw] private SplineComputer m_splineComputer;
|
||||
@@ -100,23 +99,6 @@ namespace Convention.VFX
|
||||
m_splineRenderer = GetComponent<SplineRenderer>();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if ((int)performanceMode >= (int)PerformanceIndicator.PerformanceMode.L6)
|
||||
{
|
||||
RebuildAll();
|
||||
m_splineRenderer.Rebuild();
|
||||
}
|
||||
else if ((int)performanceMode >= (int)PerformanceIndicator.PerformanceMode.L6)
|
||||
{
|
||||
if (childPoints.Count != knots.Count)
|
||||
RebuildAll();
|
||||
else
|
||||
ResetPoints();
|
||||
m_splineRenderer.Rebuild();
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetKnot([In, ArgPackage] ref SplinePoint point, [In, ArgPackage] LinePoint linePoint)
|
||||
{
|
||||
point.position = linePoint.transform.localPosition;
|
||||
|
File diff suppressed because one or more lines are too long
@@ -34,7 +34,14 @@ MonoBehaviour:
|
||||
- Assembly-CSharp-firstpass
|
||||
- Cinemachine
|
||||
- CW.Common
|
||||
- Dreamteck.Splines
|
||||
- Dreamteck.Utilities
|
||||
- EasySave3
|
||||
- glTFast
|
||||
- glTFast.Documentation.Examples
|
||||
- glTFast.dots
|
||||
- glTFast.Export
|
||||
- glTFast.Newtonsoft
|
||||
- LeanCommon
|
||||
- LeanGUI
|
||||
- LeanTransition
|
||||
|
@@ -22,7 +22,7 @@ namespace ES3Internal
|
||||
|
||||
public StreamReader baseReader;
|
||||
|
||||
internal ES3JSONReader(Stream stream, ES3Settings settings, bool readHeaderAndFooter = true) : base(settings, readHeaderAndFooter)
|
||||
public ES3JSONReader(Stream stream, ES3Settings settings, bool readHeaderAndFooter = true) : base(settings, readHeaderAndFooter)
|
||||
{
|
||||
this.baseReader = new StreamReader(stream);
|
||||
|
||||
|
8
Convention/[IL2CPP].meta
Normal file
8
Convention/[IL2CPP].meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f28191148868da4eb919b1b1d5c2399
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
254
Convention/[IL2CPP]/ProcessLauncher.cs
Normal file
254
Convention/[IL2CPP]/ProcessLauncher.cs
Normal file
@@ -0,0 +1,254 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using Debug = UnityEngine.Debug;
|
||||
|
||||
// ReSharper disable InconsistentNaming
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
|
||||
namespace Convention.IL2CPP
|
||||
{
|
||||
/// <summary>
|
||||
/// <para>rainwl/CreateAndTerminateProcessWithIL2CPP: In Unity,if we use IL2CPP as scripting backend,System.Diagnotics.Process could not be supported (github.com)
|
||||
/// </para>
|
||||
/// <para>When developing with Unity, if you choose IL2CPP as the scripting backend, it brings along several challenges.
|
||||
/// First, code that relies on C# reflection is not supported. Common libraries like Protocol Buffers and log4net, which use reflection, require modifications.
|
||||
/// </para>
|
||||
/// <para>Secondly, the System.Diagnostics.Process namespace is also unsupported.If you need to launch an external application, an alternative approach is necessary.Unfortunately, Unity lacks sufficient resources to modify IL2CPP to support Process. The solutions available online are quite scarce, with only one GitHub repository providing a potential workaround.However, this solution is not readily usable due to various issues.
|
||||
/// Given this situation, I've developed a method utilizing kernel32 API calls to achieve launching and closing external processes, as well as terminating processes with specific names.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public static class ProcessLauncher
|
||||
{
|
||||
#region DLL Import
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
private static extern bool CreateProcessW(
|
||||
string lpApplicationName,
|
||||
string lpCommandLine,
|
||||
IntPtr lpProcessAttributes,
|
||||
IntPtr lpThreadAttributes,
|
||||
bool bInheritHandles,
|
||||
uint dwCreationFlags,
|
||||
IntPtr lpEnvironment,
|
||||
string lpCurrentDirectory,
|
||||
[In] ref StartUpInfo lpStartupInfo,
|
||||
out ProcessInformation lpProcessInformation
|
||||
);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
// ReSharper disable once IdentifierTypo
|
||||
public static extern IntPtr CreateToolhelp32Snapshot(uint dwFlags, uint th32ProcessID);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern bool Process32First(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern bool Process32Next(IntPtr hSnapshot, ref PROCESSENTRY32 lppe);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool CloseHandle(IntPtr hObject);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, uint dwProcessId);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct PROCESSENTRY32
|
||||
{
|
||||
public uint dwSize;
|
||||
public uint cntUsage;
|
||||
public uint th32ProcessID;
|
||||
public IntPtr th32DefaultHeapID;
|
||||
public uint th32ModuleID;
|
||||
public uint cntThreads;
|
||||
public uint th32ParentProcessID;
|
||||
public int pcPriClassBase;
|
||||
public uint dwFlags;
|
||||
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
|
||||
public string szExeFile;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
private struct StartUpInfo
|
||||
{
|
||||
public int cb;
|
||||
public string lpReserved;
|
||||
public string lpDesktop;
|
||||
public string lpTitle;
|
||||
public int dwX;
|
||||
public int dwY;
|
||||
public int dwXSize;
|
||||
public int dwYSize;
|
||||
public int dwXCountChars;
|
||||
public int dwYCountChars;
|
||||
public int dwFillAttribute;
|
||||
public int dwFlags;
|
||||
public short wShowWindow;
|
||||
public short cbReserved2;
|
||||
public IntPtr lpReserved2;
|
||||
public IntPtr hStdInput;
|
||||
public IntPtr hStdOutput;
|
||||
public IntPtr hStdError;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct ProcessInformation
|
||||
{
|
||||
public IntPtr hProcess;
|
||||
public IntPtr hThread;
|
||||
public int dwProcessId;
|
||||
public int dwThreadId;
|
||||
}
|
||||
|
||||
// ReSharper disable once FieldCanBeMadeReadOnly.Local
|
||||
public static List<ProcessInformation> processList = new List<ProcessInformation>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Process Methods
|
||||
|
||||
public static ProcessInformation StartExternalProcess(string programPath, string arguments, string currentDirectory)
|
||||
{
|
||||
// const string programPath = @"E:\FleX-1.2.0\NvFlexDemoReleaseCUDA_x64.exe";
|
||||
// const string arguments = "-surgeryType=0";
|
||||
|
||||
var startupInfo = new StartUpInfo();
|
||||
startupInfo.cb = Marshal.SizeOf(startupInfo);
|
||||
|
||||
var success = CreateProcessW(
|
||||
programPath,
|
||||
arguments,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
false,
|
||||
0,
|
||||
IntPtr.Zero,
|
||||
currentDirectory,
|
||||
ref startupInfo,
|
||||
out var processInfo
|
||||
);
|
||||
|
||||
if (success)
|
||||
{
|
||||
processList.Add(processInfo);
|
||||
return processInfo;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Unable to start process, error code: " + Marshal.GetLastWin32Error());
|
||||
}
|
||||
}
|
||||
|
||||
public static void TerminateExternalProcess(ProcessInformation processInfo)
|
||||
{
|
||||
// ReSharper disable once InvertIf
|
||||
if (processInfo.hProcess != IntPtr.Zero)
|
||||
{
|
||||
var success = TerminateProcess(processInfo.hProcess, 0);
|
||||
if (success)
|
||||
{
|
||||
Debug.Log("The external process is shut down");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Unable to shut down external process, error code:" + Marshal.GetLastWin32Error());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void CloseProcessByName(string processName, IntPtr snapShot)
|
||||
{
|
||||
var processEntry = new PROCESSENTRY32
|
||||
{
|
||||
dwSize = (uint)Marshal.SizeOf(typeof(PROCESSENTRY32))
|
||||
};
|
||||
|
||||
// ReSharper disable once InvertIf
|
||||
if (Process32First(snapShot, ref processEntry))
|
||||
{
|
||||
do
|
||||
{
|
||||
// ReSharper disable once InvertIf
|
||||
if (processEntry.szExeFile.Equals(processName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var processHandle = OpenProcess(processEntry.th32ProcessID);
|
||||
// ReSharper disable once InvertIf
|
||||
if (processHandle != IntPtr.Zero)
|
||||
{
|
||||
TerminateProcess(processHandle, 0); // Terminate the process
|
||||
CloseHandle(processHandle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (Process32Next(snapShot, ref processEntry));
|
||||
}
|
||||
}
|
||||
|
||||
private static IntPtr OpenProcess(uint processId)
|
||||
{
|
||||
const uint processTerminate = 0x0001;
|
||||
return OpenProcess(processTerminate, false, processId);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Test Methods
|
||||
|
||||
//private ProcessInformation _processInfo1;
|
||||
//private ProcessInformation _processInfo2;
|
||||
|
||||
//private void Update()
|
||||
//{
|
||||
// if (Input.GetKeyDown(KeyCode.A))
|
||||
// {
|
||||
// _processInfo1 =
|
||||
// StartExternalProcess(@"D:\Projects\Log[]\LogInsights\src\LogInsights\bin\x64\Release\LogInsights.exe",
|
||||
// null, null);
|
||||
// _processInfo2 = StartExternalProcess(@"C:\Windows\System32\cmd.exe", null, null);
|
||||
// }
|
||||
|
||||
// if (Input.GetKeyDown(KeyCode.B))
|
||||
// {
|
||||
// TerminateExternalProcess(_processInfo1);
|
||||
// }
|
||||
|
||||
// if (Input.GetKeyDown(KeyCode.C))
|
||||
// {
|
||||
// TerminateExternalProcess(_processInfo2);
|
||||
// }
|
||||
|
||||
// // ReSharper disable once InvertIf
|
||||
// if (Input.GetKeyDown(KeyCode.D))
|
||||
// {
|
||||
// var snapshot = CreateToolhelp32Snapshot(2, 0);
|
||||
// CloseProcessByName("cmd.exe", snapshot);
|
||||
// CloseProcessByName("LogInsights.exe", snapshot);
|
||||
// CloseHandle(snapshot);
|
||||
// }
|
||||
//}
|
||||
|
||||
//private void OnDestroy()
|
||||
//{
|
||||
// foreach (var processInfo in processList)
|
||||
// {
|
||||
// TerminateProcess(processInfo.hProcess, 0);
|
||||
// Debug.Log("The external process is shut down,error code: " + processInfo.dwProcessId);
|
||||
// }
|
||||
//}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
11
Convention/[IL2CPP]/ProcessLauncher.cs.meta
Normal file
11
Convention/[IL2CPP]/ProcessLauncher.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c723354975719bd4abffd154b6d1fa3d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -14,13 +14,18 @@ namespace Convention
|
||||
public abstract void LoadAudioClip(AudioClip clip);
|
||||
public abstract AudioClip GetAudioClip();
|
||||
public abstract float GetClockTime();
|
||||
public abstract void SetClockTime(float value);
|
||||
|
||||
public AudioClip CurrentClip
|
||||
{
|
||||
get => GetAudioClip();
|
||||
set => LoadAudioClip(value);
|
||||
}
|
||||
public float CurrentTime => GetClockTime();
|
||||
public float CurrentTime
|
||||
{
|
||||
get => GetClockTime();
|
||||
set => SetClockTime(value);
|
||||
}
|
||||
|
||||
public abstract bool IsPlaying();
|
||||
|
||||
@@ -187,9 +192,7 @@ namespace Convention
|
||||
get
|
||||
{
|
||||
if (source == null)
|
||||
source = this.SeekComponent<AudioSource>();
|
||||
if (source == null)
|
||||
source = this.gameObject.AddComponent<AudioSource>();
|
||||
source = this.GetOrAddComponent<AudioSource>();
|
||||
return source;
|
||||
}
|
||||
set
|
||||
@@ -207,9 +210,16 @@ namespace Convention
|
||||
}
|
||||
public override float GetClockTime()
|
||||
{
|
||||
if (Source.clip == null)
|
||||
return 0;
|
||||
return (float)Source.timeSamples / (float)Source.clip.frequency;
|
||||
}
|
||||
|
||||
public override void SetClockTime(float value)
|
||||
{
|
||||
Source.time = value;
|
||||
}
|
||||
|
||||
public override bool IsPlaying()
|
||||
{
|
||||
return Source.isPlaying;
|
||||
@@ -239,7 +249,7 @@ namespace Convention
|
||||
}
|
||||
public override void SetSpeed(float speed)
|
||||
{
|
||||
SetSpeed(speed, 1.0f, "Master", "MasterPitch", "PitchShifterPitch", true);
|
||||
SetSpeed(speed, "Master", "MasterPitch", "PitchShifterPitch", true);
|
||||
}
|
||||
public override void SetVolume(float volume)
|
||||
{
|
||||
@@ -247,7 +257,6 @@ namespace Convention
|
||||
}
|
||||
|
||||
public void SetSpeed(float speed,
|
||||
float TargetPitchValue,
|
||||
string TargetGroupName,
|
||||
string TargetPitch_Attribute_Name,
|
||||
string TargetPitchshifterPitch_Attribute_Name,
|
||||
@@ -255,19 +264,19 @@ namespace Convention
|
||||
{
|
||||
if (Mixer != null)
|
||||
{
|
||||
if (TargetPitchValue > 0)
|
||||
if (speed > 0)
|
||||
{
|
||||
Source.pitch = 1;
|
||||
Mixer.SetFloat(TargetPitch_Attribute_Name, TargetPitchValue);
|
||||
float TargetPitchshifterPitchValue = 1.0f / TargetPitchValue;
|
||||
Mixer.SetFloat(TargetPitch_Attribute_Name, speed);
|
||||
float TargetPitchshifterPitchValue = 1.0f / speed;
|
||||
Mixer.SetFloat(TargetPitchshifterPitch_Attribute_Name, TargetPitchshifterPitchValue);
|
||||
Source.outputAudioMixerGroup = Mixer.FindMatchingGroups(TargetGroupName)[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
Source.pitch = -1;
|
||||
Mixer.SetFloat(TargetPitch_Attribute_Name, -TargetPitchValue);
|
||||
float TargetPitchshifterPitchValue = -1.0f / TargetPitchValue;
|
||||
Mixer.SetFloat(TargetPitch_Attribute_Name, -speed);
|
||||
float TargetPitchshifterPitchValue = -1.0f / speed;
|
||||
Mixer.SetFloat(TargetPitchshifterPitch_Attribute_Name, TargetPitchshifterPitchValue);
|
||||
Source.outputAudioMixerGroup = Mixer.FindMatchingGroups(TargetGroupName)[0];
|
||||
}
|
||||
@@ -412,18 +421,19 @@ namespace Convention
|
||||
BandNegativeCheck();
|
||||
|
||||
}
|
||||
void Update()
|
||||
{
|
||||
float[] spectrum = new float[256];
|
||||
AudioListener.GetSpectrumData(spectrum, 0, FFTWindow.Rectangular);
|
||||
for (int i = 1; i < spectrum.Length - 1; i++)
|
||||
{
|
||||
Debug.DrawLine(new Vector3(i - 1, spectrum[i] + 10, 0), new Vector3(i, spectrum[i + 1] + 10, 0), Color.red);
|
||||
Debug.DrawLine(new Vector3(i - 1, Mathf.Log(spectrum[i - 1]) + 10, 2), new Vector3(i, Mathf.Log(spectrum[i]) + 10, 2), Color.cyan);
|
||||
Debug.DrawLine(new Vector3(Mathf.Log(i - 1), spectrum[i - 1] - 10, 1), new Vector3(Mathf.Log(i), spectrum[i] - 10, 1), Color.green);
|
||||
Debug.DrawLine(new Vector3(Mathf.Log(i - 1), Mathf.Log(spectrum[i - 1]), 3), new Vector3(Mathf.Log(i), Mathf.Log(spectrum[i]), 3), Color.blue);
|
||||
}
|
||||
}
|
||||
|
||||
//void Update()
|
||||
//{
|
||||
// float[] spectrum = new float[256];
|
||||
// AudioListener.GetSpectrumData(spectrum, 0, FFTWindow.Rectangular);
|
||||
// for (int i = 1; i < spectrum.Length - 1; i++)
|
||||
// {
|
||||
// Debug.DrawLine(new Vector3(i - 1, spectrum[i] + 10, 0), new Vector3(i, spectrum[i + 1] + 10, 0), Color.red);
|
||||
// Debug.DrawLine(new Vector3(i - 1, Mathf.Log(spectrum[i - 1]) + 10, 2), new Vector3(i, Mathf.Log(spectrum[i]) + 10, 2), Color.cyan);
|
||||
// Debug.DrawLine(new Vector3(Mathf.Log(i - 1), spectrum[i - 1] - 10, 1), new Vector3(Mathf.Log(i), spectrum[i] - 10, 1), Color.green);
|
||||
// Debug.DrawLine(new Vector3(Mathf.Log(i - 1), Mathf.Log(spectrum[i - 1]), 3), new Vector3(Mathf.Log(i), Mathf.Log(spectrum[i]), 3), Color.blue);
|
||||
// }
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,3 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Cinemachine;
|
||||
using Convention.WindowsUI.Variant;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
@@ -29,30 +26,61 @@ namespace Convention
|
||||
}
|
||||
}
|
||||
|
||||
public void SetMoveSpeed(float value)
|
||||
{
|
||||
moveSpeed = value;
|
||||
}
|
||||
|
||||
public void SetRotationSpeed(float value)
|
||||
{
|
||||
rotationSpeed = value;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
m_IsFocus = false;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (isFocus)
|
||||
{
|
||||
Vector3 dxyz = Vector3.zero;
|
||||
Vector3 rxyz = Vector3.zero;
|
||||
//Vector3 rxyz = Vector3.zero;
|
||||
if (Keyboard.current[Key.W].isPressed || Keyboard.current[Key.UpArrow].isPressed)
|
||||
dxyz += TargetFollow.forward;
|
||||
{
|
||||
var temp = TargetFollow.forward;
|
||||
//temp.y = 0;
|
||||
dxyz += temp.normalized;
|
||||
}
|
||||
if (Keyboard.current[Key.A].isPressed || Keyboard.current[Key.LeftArrow].isPressed)
|
||||
dxyz += -TargetFollow.right;
|
||||
{
|
||||
var temp = TargetFollow.right;
|
||||
temp.y = 0;
|
||||
dxyz -= temp.normalized;
|
||||
}
|
||||
if (Keyboard.current[Key.D].isPressed || Keyboard.current[Key.RightArrow].isPressed)
|
||||
dxyz += TargetFollow.right;
|
||||
{
|
||||
var temp = TargetFollow.right;
|
||||
temp.y = 0;
|
||||
dxyz += temp.normalized;
|
||||
}
|
||||
if (Keyboard.current[Key.S].isPressed || Keyboard.current[Key.DownArrow].isPressed)
|
||||
dxyz += -TargetFollow.forward;
|
||||
{
|
||||
var temp = TargetFollow.forward;
|
||||
//temp.y = 0;
|
||||
dxyz -= temp.normalized;
|
||||
}
|
||||
if (Keyboard.current[Key.Space].isPressed)
|
||||
dxyz += TargetFollow.up;
|
||||
dxyz += Vector3.up;
|
||||
#if !UNITY_EDITOR
|
||||
if (Keyboard.current[Key.LeftShift].isPressed)
|
||||
dxyz += -TargetFollow.up;
|
||||
#else
|
||||
if (Keyboard.current[Key.Q].isPressed)
|
||||
#endif
|
||||
dxyz -= Vector3.up;
|
||||
|
||||
var drotation = Vector3.zero;
|
||||
if (isFocus)
|
||||
{
|
||||
var temp = Mouse.current.delta.ReadValue();
|
||||
drotation = new(-temp.y, temp.x, 0);
|
||||
@@ -60,13 +88,25 @@ namespace Convention
|
||||
|
||||
//
|
||||
|
||||
TargetFollow.Translate(dxyz * moveSpeed, Space.Self);
|
||||
TargetFollow.Translate(dxyz * moveSpeed, Space.World);
|
||||
TargetFollow.Rotate(drotation * rotationSpeed, Space.Self);
|
||||
|
||||
//
|
||||
|
||||
if (Keyboard.current[Key.Escape].isPressed)
|
||||
isFocus = false;
|
||||
if (Keyboard.current[Key.LeftCtrl].isPressed && Keyboard.current[Key.LeftShift].isPressed)
|
||||
{
|
||||
if(Keyboard.current[Key.Z].isPressed)
|
||||
{
|
||||
TargetFollow.localPosition = Vector3.zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
TargetFollow.localEulerAngles = new(0, TargetFollow.eulerAngles.y, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
@@ -12,6 +13,7 @@ using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.Scripting;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace UnityEditor
|
||||
@@ -55,6 +57,19 @@ namespace Convention
|
||||
public static string PersistentDataPath => Application.persistentDataPath;
|
||||
|
||||
public static string DataPath => Application.dataPath;
|
||||
|
||||
public static string CurrentWorkPath => Environment.CurrentDirectory;
|
||||
|
||||
public static string Combine(string a, string b) => Path.Combine(a, b);
|
||||
public static string CombineAsDir(string a, string b)
|
||||
{
|
||||
string name = b.Replace("\\", "/");
|
||||
if (name.EndsWith("/") == false)
|
||||
{
|
||||
name += "/";
|
||||
}
|
||||
return Path.Combine(a, name);
|
||||
}
|
||||
}
|
||||
|
||||
public static partial class Utility
|
||||
@@ -424,7 +439,7 @@ namespace Convention
|
||||
public static _T convert_xvalue<_T>([In] string str)
|
||||
{
|
||||
Type type = typeof(_T);
|
||||
var parse_method = type.GetMethod("Parse");
|
||||
var parse_method = type.GetMethod(nameof(int.Parse), BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(string) }, null);
|
||||
if (parse_method != null &&
|
||||
(parse_method.ReturnType.IsSubclassOf(type) || parse_method.ReturnType == type) &&
|
||||
parse_method.GetParameters().Length == 1 &&
|
||||
@@ -435,6 +450,21 @@ namespace Convention
|
||||
|
||||
throw new InvalidCastException($"\"{str}\" is cannt convert to type<{type}>");
|
||||
}
|
||||
|
||||
public static object ConventValue([In] Type type, [In] string str)
|
||||
{
|
||||
var parse_method = type.GetMethod("Parse");
|
||||
if (parse_method != null &&
|
||||
(parse_method.ReturnType.IsSubclassOf(type) || parse_method.ReturnType == type) &&
|
||||
parse_method.GetParameters().Length == 1 &&
|
||||
parse_method.GetParameters()[0].ParameterType == typeof(string))
|
||||
{
|
||||
return parse_method.Invoke(null, new object[] { str });
|
||||
}
|
||||
|
||||
throw new InvalidCastException($"\"{str}\" is cannt convert to type<{type}>");
|
||||
}
|
||||
|
||||
public static string Combine([In] params object[] args)
|
||||
{
|
||||
if (args.Length == 0)
|
||||
@@ -1048,33 +1078,62 @@ namespace Convention
|
||||
|
||||
public class ActionStepCoroutineWrapper
|
||||
{
|
||||
private List<KeyValuePair<YieldInstruction, Action>> steps = new();
|
||||
private class YieldInstructionWrapper
|
||||
{
|
||||
public YieldInstruction UnityYieldInstruction;
|
||||
public CustomYieldInstruction CustomYieldInstruction;
|
||||
|
||||
public YieldInstructionWrapper()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public YieldInstructionWrapper(YieldInstruction unityYieldInstruction)
|
||||
{
|
||||
this.UnityYieldInstruction = unityYieldInstruction;
|
||||
}
|
||||
|
||||
public YieldInstructionWrapper(CustomYieldInstruction customYieldInstruction)
|
||||
{
|
||||
this.CustomYieldInstruction = customYieldInstruction;
|
||||
}
|
||||
}
|
||||
|
||||
private List<KeyValuePair<YieldInstructionWrapper, Action>> steps = new();
|
||||
public ActionStepCoroutineWrapper Update(Action action)
|
||||
{
|
||||
steps.Add(new(null, action));
|
||||
steps.Add(new(new(), action));
|
||||
return this;
|
||||
}
|
||||
public ActionStepCoroutineWrapper Wait(float time, Action action)
|
||||
{
|
||||
steps.Add(new(new WaitForSeconds(time), action));
|
||||
steps.Add(new(new(new WaitForSeconds(time)), action));
|
||||
return this;
|
||||
}
|
||||
public ActionStepCoroutineWrapper FixedUpdate(Action action)
|
||||
{
|
||||
steps.Add(new(new WaitForFixedUpdate(), action));
|
||||
steps.Add(new(new (new WaitForFixedUpdate()), action));
|
||||
return this;
|
||||
}
|
||||
public ActionStepCoroutineWrapper Next(Action action)
|
||||
{
|
||||
steps.Add(new(new WaitForEndOfFrame(), action));
|
||||
steps.Add(new(new(new WaitForEndOfFrame()), action));
|
||||
return this;
|
||||
}
|
||||
private static IEnumerator Execute(List<KeyValuePair<YieldInstruction, Action>> steps)
|
||||
public ActionStepCoroutineWrapper Until(Func<bool> pr, Action action)
|
||||
{
|
||||
steps.Add(new(new(new WaitUntil(pr)), action));
|
||||
return this;
|
||||
}
|
||||
private static IEnumerator Execute(List<KeyValuePair<YieldInstructionWrapper, Action>> steps)
|
||||
{
|
||||
foreach (var (waiting, action) in steps)
|
||||
{
|
||||
action();
|
||||
yield return waiting;
|
||||
if (waiting.UnityYieldInstruction != null)
|
||||
yield return waiting.UnityYieldInstruction;
|
||||
else
|
||||
yield return waiting.CustomYieldInstruction;
|
||||
}
|
||||
}
|
||||
~ActionStepCoroutineWrapper()
|
||||
@@ -1083,7 +1142,7 @@ namespace Convention
|
||||
}
|
||||
public void Invoke()
|
||||
{
|
||||
StartCoroutine(Execute(new List<KeyValuePair<YieldInstruction, Action>>(steps)));
|
||||
StartCoroutine(Execute(new List<KeyValuePair<YieldInstructionWrapper, Action>>(steps)));
|
||||
steps.Clear();
|
||||
}
|
||||
}
|
||||
@@ -1252,35 +1311,47 @@ namespace Convention
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<MemberInfo> SeekMemberInfoFromType(
|
||||
[In] Type targetType,
|
||||
[In, Opt] IEnumerable<Type> attrs, [In, Opt] IEnumerable<Type> types,
|
||||
[In, Opt] Type untilBase = null
|
||||
)
|
||||
{
|
||||
List<MemberInfo> result = new();
|
||||
result.AddRange(targetType.GetMembers(BindingFlags.Public | BindingFlags.Instance));
|
||||
while (targetType != null && targetType != typeof(object) && targetType != untilBase)
|
||||
{
|
||||
result.AddRange(
|
||||
from info in targetType.GetMembers(BindingFlags.NonPublic | BindingFlags.Instance)
|
||||
where attrs == null || HasCustomAttribute(info, attrs)
|
||||
where types == null || (GetMemberValueType(info, out var type) && types.Contains(type))
|
||||
select info
|
||||
);
|
||||
targetType = targetType.BaseType;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static List<MemberInfo> SeekMemberInfo(
|
||||
[In] object target,
|
||||
[In, Opt] IEnumerable<Type> attrs, [In, Opt] IEnumerable<Type> types,
|
||||
[In, Opt] Type untilBase = null
|
||||
)
|
||||
{
|
||||
Type _CurType = target.GetType();
|
||||
List<MemberInfo> result = new();
|
||||
result.AddRange(_CurType.GetMembers(BindingFlags.Public | BindingFlags.Instance));
|
||||
while (_CurType != null && _CurType != typeof(object) && _CurType != untilBase)
|
||||
{
|
||||
result.AddRange(
|
||||
from info in _CurType.GetMembers(BindingFlags.NonPublic | BindingFlags.Instance)
|
||||
where attrs == null || HasCustomAttribute(info, attrs)
|
||||
where types == null || (GetMemberValueType(info, out var type) && types.Contains(type))
|
||||
select info
|
||||
);
|
||||
_CurType = _CurType.BaseType;
|
||||
return SeekMemberInfoFromType(target.GetType(), attrs, types, untilBase);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
public static List<MemberInfo> SeekMemberInfo([In] object target, IEnumerable<string> names, BindingFlags flags = BindingFlags.Public | BindingFlags.Instance)
|
||||
public static List<MemberInfo> SeekMemberInfoFromType([In] Type target, IEnumerable<string> names,
|
||||
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance)
|
||||
{
|
||||
Type _CurType = target.GetType();
|
||||
List<MemberInfo> result = _CurType.GetMembers(flags).ToList();
|
||||
List<MemberInfo> result = target.GetMembers(flags).ToList();
|
||||
HashSet<string> nameSet = names.ToHashSet();
|
||||
result.RemoveAll(x => nameSet.Contains(x.Name) == false);
|
||||
return result;
|
||||
}
|
||||
public static List<MemberInfo> SeekMemberInfo([In] object target, IEnumerable<string> names,
|
||||
BindingFlags flags = BindingFlags.Public | BindingFlags.Instance)
|
||||
{
|
||||
return SeekMemberInfoFromType(target.GetType(), names, flags);
|
||||
}
|
||||
public static object InvokeMember([In] MemberInfo member, [In] object target, params object[] parameters)
|
||||
{
|
||||
if (member is MethodInfo method)
|
||||
@@ -2117,5 +2188,47 @@ namespace Convention
|
||||
return Activator.CreateInstance(type);
|
||||
}
|
||||
}
|
||||
|
||||
public static partial class ConventionUtility
|
||||
{
|
||||
public static byte[] ReadAllBytes(this BinaryReader reader)
|
||||
{
|
||||
const int bufferSize = 4096;
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
int count;
|
||||
while ((count = reader.Read(buffer, 0, buffer.Length)) != 0)
|
||||
ms.Write(buffer, 0, count);
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace Convention
|
||||
{
|
||||
public static partial class ConventionUtility
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Unity engine function to disable the GC
|
||||
/// </summary>
|
||||
public static void GC_disable()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
GarbageCollector.GCMode = GarbageCollector.Mode.Disabled;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unity engine function to enable the GC
|
||||
/// </summary>
|
||||
public static void GC_enable()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
GarbageCollector.GCMode = GarbageCollector.Mode.Enabled;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
@@ -58,70 +57,81 @@ namespace Convention
|
||||
};
|
||||
}
|
||||
|
||||
private string FullPath;
|
||||
private string OriginPath;
|
||||
private FileSystemInfo OriginInfo;
|
||||
public ToolFile(string path)
|
||||
{
|
||||
FullPath = Path.GetFullPath(path);
|
||||
OriginPath = Environment.ExpandEnvironmentVariables(path).Replace('\\', '/');
|
||||
Refresh();
|
||||
}
|
||||
public override string ToString()
|
||||
{
|
||||
return this.FullPath;
|
||||
return this.OriginPath;
|
||||
}
|
||||
|
||||
#region Path
|
||||
|
||||
public static implicit operator string(ToolFile data) => data.FullPath;
|
||||
public static implicit operator string(ToolFile data) => data.OriginPath;
|
||||
public string GetAbsPath()
|
||||
{
|
||||
return Path.GetFullPath(OriginPath);
|
||||
}
|
||||
public string GetFullPath()
|
||||
{
|
||||
return this.FullPath;
|
||||
return this.OriginPath;
|
||||
}
|
||||
public string GetName(bool is_ignore_extension = false)
|
||||
{
|
||||
var result = this.FullPath[..(
|
||||
(this.FullPath.Contains('.') && is_ignore_extension)
|
||||
? this.FullPath.LastIndexOf('.')
|
||||
if (OriginInfo != null)
|
||||
{
|
||||
if (OriginInfo is FileInfo finfo)
|
||||
return is_ignore_extension ? Path.GetFileNameWithoutExtension(finfo.FullName) : finfo.Name;
|
||||
else if (OriginInfo is DirectoryInfo dinfo)
|
||||
return dinfo.Name;
|
||||
}
|
||||
var result = this.OriginPath[..(
|
||||
(this.OriginPath.Contains('.') && is_ignore_extension)
|
||||
? this.OriginPath.LastIndexOf('.')
|
||||
: ^0
|
||||
)]
|
||||
[..(
|
||||
(this.FullPath[^1] == '/' || this.FullPath[^1] == '\\')
|
||||
(this.OriginPath[^1] == '/' || this.OriginPath[^1] == '\\')
|
||||
? ^1
|
||||
: ^0
|
||||
)];
|
||||
return result[(Mathf.Max(result.Contains('/') ? result.LastIndexOf('/') : -1,
|
||||
result.Contains('\\') ? result.LastIndexOf('\\') : -1) + 1)..];
|
||||
//result.LastIndexOf('\\') return -1 when '\\' was not been contained
|
||||
return result[(Mathf.Max(result.LastIndexOf('/'), result.LastIndexOf('\\')) + 1)..];
|
||||
}
|
||||
public string GetExtension()
|
||||
{
|
||||
if (IsDir())
|
||||
return "";
|
||||
return this.FullPath[(
|
||||
(this.FullPath.Contains('.'))
|
||||
? this.FullPath.LastIndexOf('.')
|
||||
return this.OriginPath[(
|
||||
(this.OriginPath.Contains('.'))
|
||||
? this.OriginPath.LastIndexOf('.')
|
||||
: ^0
|
||||
)..];
|
||||
}
|
||||
|
||||
public string GetFilename(bool is_without_extension = false)
|
||||
{
|
||||
if (is_without_extension && Path.HasExtension(FullPath))
|
||||
if (is_without_extension && Path.HasExtension(OriginPath))
|
||||
{
|
||||
return Path.GetFileNameWithoutExtension(FullPath);
|
||||
return Path.GetFileNameWithoutExtension(OriginPath);
|
||||
}
|
||||
else if (FullPath.EndsWith(Path.DirectorySeparatorChar.ToString()) || FullPath.EndsWith(Path.AltDirectorySeparatorChar.ToString()))
|
||||
else if (OriginPath.EndsWith(Path.DirectorySeparatorChar.ToString()) || OriginPath.EndsWith(Path.AltDirectorySeparatorChar.ToString()))
|
||||
{
|
||||
return Path.GetFileName(FullPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
|
||||
return Path.GetFileName(OriginPath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Path.GetFileName(FullPath);
|
||||
return Path.GetFileName(OriginPath);
|
||||
}
|
||||
}
|
||||
|
||||
public string GetDir()
|
||||
{
|
||||
return Path.GetDirectoryName(FullPath);
|
||||
return Path.GetDirectoryName(OriginPath);
|
||||
}
|
||||
|
||||
public ToolFile GetDirToolFile()
|
||||
@@ -131,7 +141,7 @@ namespace Convention
|
||||
|
||||
public string GetCurrentDirName()
|
||||
{
|
||||
return Path.GetDirectoryName(FullPath);
|
||||
return Path.GetDirectoryName(OriginPath);
|
||||
}
|
||||
|
||||
public ToolFile GetParentDir()
|
||||
@@ -143,7 +153,7 @@ namespace Convention
|
||||
|
||||
#region Exists
|
||||
|
||||
public bool Exists() => File.Exists(FullPath) || Directory.Exists(FullPath);
|
||||
public bool Exists() => File.Exists(OriginPath) || Directory.Exists(OriginPath);
|
||||
|
||||
public static implicit operator bool(ToolFile file) => file.Exists();
|
||||
|
||||
@@ -154,9 +164,15 @@ namespace Convention
|
||||
if (Exists() == false)
|
||||
OriginInfo = null;
|
||||
else if (IsDir())
|
||||
OriginInfo = new DirectoryInfo(FullPath);
|
||||
{
|
||||
OriginInfo = new DirectoryInfo(OriginPath);
|
||||
OriginPath = Path.GetFullPath(OriginPath);
|
||||
}
|
||||
else
|
||||
OriginInfo = new FileInfo(FullPath);
|
||||
{
|
||||
OriginInfo = new FileInfo(OriginPath);
|
||||
OriginPath = Path.GetFullPath(OriginPath);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -168,14 +184,14 @@ namespace Convention
|
||||
}
|
||||
public T LoadAsJson<T>(string key = "data")
|
||||
{
|
||||
return ES3.Load<T>(key, FullPath);
|
||||
return ES3.Load<T>(key, OriginPath);
|
||||
}
|
||||
public string LoadAsText()
|
||||
{
|
||||
if (IsFile() == false)
|
||||
throw new InvalidOperationException("Target is not a file");
|
||||
string result = "";
|
||||
using (var fs = (this.OriginInfo as FileInfo).OpenText())
|
||||
using (var fs = new StreamReader((this.OriginInfo as FileInfo).OpenRead()))
|
||||
{
|
||||
result = fs.ReadToEnd();
|
||||
}
|
||||
@@ -204,7 +220,7 @@ namespace Convention
|
||||
if (IsFile() == false)
|
||||
throw new InvalidOperationException("Target is not a file");
|
||||
|
||||
var lines = File.ReadAllLines(FullPath);
|
||||
var lines = File.ReadAllLines(OriginPath);
|
||||
var result = new List<string[]>();
|
||||
|
||||
foreach (var line in lines)
|
||||
@@ -231,11 +247,11 @@ namespace Convention
|
||||
|
||||
public Texture2D LoadAsImage()
|
||||
{
|
||||
return ES3Plugin.LoadImage(FullPath);
|
||||
return ES3Plugin.LoadImage(OriginPath);
|
||||
}
|
||||
public IEnumerator LoadAsImage([In] Action<Texture2D> callback)
|
||||
{
|
||||
UnityWebRequest request = UnityWebRequestTexture.GetTexture(FullPath);
|
||||
UnityWebRequest request = UnityWebRequestTexture.GetTexture(OriginPath);
|
||||
yield return request.SendWebRequest();
|
||||
|
||||
if (request.result == UnityWebRequest.Result.Success)
|
||||
@@ -246,11 +262,11 @@ namespace Convention
|
||||
}
|
||||
public AudioClip LoadAsAudio()
|
||||
{
|
||||
return ES3Plugin.LoadAudio(FullPath, GetAudioType(FullPath));
|
||||
return ES3Plugin.LoadAudio(OriginPath, GetAudioType(OriginPath));
|
||||
}
|
||||
public IEnumerator LoadAsAudio([In] Action<AudioClip> callback)
|
||||
{
|
||||
UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(FullPath, GetAudioType(FullPath));
|
||||
UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(OriginPath, GetAudioType(OriginPath));
|
||||
yield return request.SendWebRequest();
|
||||
|
||||
if (request.result == UnityWebRequest.Result.Success)
|
||||
@@ -261,19 +277,26 @@ namespace Convention
|
||||
}
|
||||
public AssetBundle LoadAsAssetBundle()
|
||||
{
|
||||
return AssetBundle.LoadFromFile(FullPath);
|
||||
return AssetBundle.LoadFromFile(OriginPath);
|
||||
}
|
||||
public IEnumerator LoadAsAssetBundle([In] Action<AssetBundle> callback)
|
||||
{
|
||||
AssetBundleCreateRequest result = AssetBundle.LoadFromFileAsync(FullPath);
|
||||
result.completed += x =>
|
||||
{
|
||||
if (x.isDone)
|
||||
{
|
||||
callback(result.assetBundle);
|
||||
}
|
||||
};
|
||||
AssetBundleCreateRequest result = AssetBundle.LoadFromFileAsync(OriginPath);
|
||||
yield return result;
|
||||
callback(result.assetBundle);
|
||||
yield return null;
|
||||
}
|
||||
public IEnumerator LoadAsAssetBundle([In]Action<float> progress, [In] Action<AssetBundle> callback)
|
||||
{
|
||||
AssetBundleCreateRequest result = AssetBundle.LoadFromFileAsync(OriginPath);
|
||||
while (result.isDone == false)
|
||||
{
|
||||
progress(result.progress);
|
||||
yield return null;
|
||||
}
|
||||
yield return result;
|
||||
callback(result.assetBundle);
|
||||
yield return null;
|
||||
}
|
||||
|
||||
public string LoadAsUnknown(string suffix)
|
||||
@@ -291,11 +314,11 @@ namespace Convention
|
||||
}
|
||||
public void SaveAsJson<T>(T data, string key = "data")
|
||||
{
|
||||
ES3.Save(key, data,FullPath);
|
||||
ES3.Save(key, data,OriginPath);
|
||||
}
|
||||
public void SaveAsText(string data)
|
||||
{
|
||||
using var fs = new FileStream(FullPath, FileMode.CreateNew, FileAccess.Write);
|
||||
using var fs = new FileStream(OriginPath, FileMode.CreateNew, FileAccess.Write);
|
||||
using var sw = new StreamWriter(fs);
|
||||
sw.Write(data);
|
||||
sw.Flush();
|
||||
@@ -317,7 +340,7 @@ namespace Convention
|
||||
|
||||
public void SaveAsBinary(byte[] data)
|
||||
{
|
||||
SaveDataAsBinary(FullPath, data, (OriginInfo as FileInfo).OpenWrite());
|
||||
SaveDataAsBinary(OriginPath, data, (OriginInfo as FileInfo).OpenWrite());
|
||||
}
|
||||
|
||||
public void SaveAsCsv(List<string[]> csvData)
|
||||
@@ -326,7 +349,7 @@ namespace Convention
|
||||
throw new InvalidOperationException("Target is not a file");
|
||||
|
||||
var lines = csvData.Select(row => string.Join(",", row));
|
||||
File.WriteAllLines(FullPath, lines);
|
||||
File.WriteAllLines(OriginPath, lines);
|
||||
}
|
||||
|
||||
public void SaveAsXml(string xmlData)
|
||||
@@ -360,9 +383,9 @@ namespace Convention
|
||||
{
|
||||
if (Exists())
|
||||
{
|
||||
return Directory.Exists(this.FullPath);
|
||||
return Directory.Exists(this.OriginPath);
|
||||
}
|
||||
return this.FullPath[^1] == '\\' || this.FullPath[^1] == '/';
|
||||
return this.OriginPath[^1] == '\\' || this.OriginPath[^1] == '/';
|
||||
}
|
||||
|
||||
public bool IsFile()
|
||||
@@ -400,7 +423,7 @@ namespace Convention
|
||||
{
|
||||
if (IsDir())
|
||||
{
|
||||
return GetDirectorySize(FullPath);
|
||||
return GetDirectorySize(OriginPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -438,6 +461,20 @@ namespace Convention
|
||||
#region Operator
|
||||
|
||||
public static ToolFile operator |(ToolFile left, string rightPath)
|
||||
{
|
||||
if (rightPath == null)
|
||||
{
|
||||
return new ToolFile(left.IsDir() ? left.GetFullPath() : $"{left.GetFullPath().Replace('\\', '/')}/");
|
||||
}
|
||||
string first = left.GetFullPath().Replace('\\','/');
|
||||
string second = rightPath.Replace('\\', '/');
|
||||
if (first == "./")
|
||||
return new ToolFile(second);
|
||||
else if (first == "../")
|
||||
return new ToolFile($"{new ToolFile(left.GetAbsPath()).GetParentDir()}/{second}");
|
||||
return new ToolFile($"{first}/{second}");
|
||||
}
|
||||
public static ToolFile operator |(ToolFile left, ToolFile rightPath)
|
||||
{
|
||||
string lp = left.GetFullPath();
|
||||
return new ToolFile(Path.Combine(lp, rightPath));
|
||||
@@ -447,19 +484,19 @@ namespace Convention
|
||||
{
|
||||
if (obj is ToolFile other)
|
||||
{
|
||||
return Path.GetFullPath(FullPath).Equals(Path.GetFullPath(other.FullPath), StringComparison.OrdinalIgnoreCase);
|
||||
return Path.GetFullPath(OriginPath).Equals(Path.GetFullPath(other.OriginPath), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Path.GetFullPath(FullPath).GetHashCode();
|
||||
return Path.GetFullPath(OriginPath).GetHashCode();
|
||||
}
|
||||
|
||||
public ToolFile Open(string path)
|
||||
{
|
||||
this.FullPath = path;
|
||||
this.OriginPath = path;
|
||||
Refresh();
|
||||
return this;
|
||||
}
|
||||
@@ -472,9 +509,9 @@ namespace Convention
|
||||
if (Exists() == false)
|
||||
{
|
||||
if (IsDir())
|
||||
Directory.CreateDirectory(this.FullPath);
|
||||
Directory.CreateDirectory(this.OriginPath);
|
||||
else
|
||||
File.Create(this.FullPath).Close();
|
||||
File.Create(this.OriginPath).Close();
|
||||
Refresh();
|
||||
}
|
||||
return this;
|
||||
@@ -491,7 +528,7 @@ namespace Convention
|
||||
var file = OriginInfo as FileInfo;
|
||||
file.MoveTo(newPath);
|
||||
}
|
||||
FullPath = newPath;
|
||||
OriginPath = newPath;
|
||||
return this;
|
||||
}
|
||||
public ToolFile Move(string path)
|
||||
@@ -517,7 +554,7 @@ namespace Convention
|
||||
public ToolFile Copy(string targetPath = null)
|
||||
{
|
||||
if (targetPath == null)
|
||||
return new ToolFile(FullPath);
|
||||
return new ToolFile(OriginPath);
|
||||
|
||||
if (!Exists())
|
||||
throw new FileNotFoundException("File not found");
|
||||
@@ -527,9 +564,9 @@ namespace Convention
|
||||
targetFile = targetFile | GetFilename();
|
||||
|
||||
if (IsDir())
|
||||
CopyDirectory(FullPath, targetFile.GetFullPath());
|
||||
CopyDirectory(OriginPath, targetFile.GetFullPath());
|
||||
else
|
||||
File.Copy(FullPath, targetFile.GetFullPath());
|
||||
File.Copy(OriginPath, targetFile.GetFullPath());
|
||||
|
||||
return targetFile;
|
||||
}
|
||||
@@ -555,9 +592,9 @@ namespace Convention
|
||||
public ToolFile Delete()
|
||||
{
|
||||
if (IsDir())
|
||||
Directory.Delete(FullPath);
|
||||
Directory.Delete(OriginPath);
|
||||
else
|
||||
File.Delete(FullPath);
|
||||
File.Delete(OriginPath);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -578,7 +615,7 @@ namespace Convention
|
||||
}
|
||||
public ToolFile TryCreateParentPath()
|
||||
{
|
||||
string dirPath = Path.GetDirectoryName(FullPath);
|
||||
string dirPath = Path.GetDirectoryName(OriginPath);
|
||||
if (!string.IsNullOrEmpty(dirPath) && !Directory.Exists(dirPath))
|
||||
{
|
||||
Directory.CreateDirectory(dirPath);
|
||||
@@ -589,14 +626,14 @@ namespace Convention
|
||||
{
|
||||
if (!IsDir())
|
||||
throw new InvalidOperationException("Target is not a directory");
|
||||
return Directory.GetFileSystemEntries(FullPath).ToList();
|
||||
return Directory.GetFileSystemEntries(OriginPath).ToList();
|
||||
}
|
||||
public List<ToolFile> DirToolFileIter()
|
||||
{
|
||||
if (!IsDir())
|
||||
throw new InvalidOperationException("Target is not a directory");
|
||||
var result = new List<ToolFile>();
|
||||
foreach (var entry in Directory.GetFileSystemEntries(FullPath))
|
||||
foreach (var entry in Directory.GetFileSystemEntries(OriginPath))
|
||||
{
|
||||
result.Add(new ToolFile(entry));
|
||||
}
|
||||
@@ -604,7 +641,7 @@ namespace Convention
|
||||
}
|
||||
public ToolFile BackToParentDir()
|
||||
{
|
||||
FullPath = GetDir();
|
||||
OriginPath = GetDir();
|
||||
Refresh();
|
||||
return this;
|
||||
}
|
||||
@@ -613,7 +650,7 @@ namespace Convention
|
||||
if (!IsDir())
|
||||
throw new InvalidOperationException("Target is not a directory");
|
||||
|
||||
var entries = Directory.GetFileSystemEntries(FullPath);
|
||||
var entries = Directory.GetFileSystemEntries(OriginPath);
|
||||
if (ignore_folder)
|
||||
{
|
||||
return entries.Count(entry => File.Exists(entry));
|
||||
@@ -720,13 +757,13 @@ namespace Convention
|
||||
{
|
||||
if (IsDir())
|
||||
{
|
||||
ZipFile.CreateFromDirectory(FullPath, outputPath);
|
||||
ZipFile.CreateFromDirectory(OriginPath, outputPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var archive = ZipFile.Open(outputPath, ZipArchiveMode.Create))
|
||||
{
|
||||
archive.CreateEntryFromFile(FullPath, GetFilename());
|
||||
archive.CreateEntryFromFile(OriginPath, GetFilename());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -758,7 +795,7 @@ namespace Convention
|
||||
|
||||
try
|
||||
{
|
||||
ZipFile.ExtractToDirectory(FullPath, outputPath);
|
||||
ZipFile.ExtractToDirectory(OriginPath, outputPath);
|
||||
return new ToolFile(outputPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -877,7 +914,7 @@ namespace Convention
|
||||
try
|
||||
{
|
||||
using (var hashAlgorithm = GetHashAlgorithm(algorithm))
|
||||
using (var stream = File.OpenRead(FullPath))
|
||||
using (var stream = File.OpenRead(OriginPath))
|
||||
{
|
||||
byte[] hash = hashAlgorithm.ComputeHash(stream);
|
||||
return BitConverter.ToString(hash).Replace("-", "").ToLower();
|
||||
@@ -935,7 +972,7 @@ namespace Convention
|
||||
|
||||
// 注意:这是一个简化实现,实际的文件监控需要更复杂的实现
|
||||
// 可以使用 FileSystemWatcher 来实现完整功能
|
||||
var watcher = new FileSystemWatcher(FullPath)
|
||||
var watcher = new FileSystemWatcher(OriginPath)
|
||||
{
|
||||
IncludeSubdirectories = recursive,
|
||||
EnableRaisingEvents = true
|
||||
@@ -1067,7 +1104,7 @@ namespace Convention
|
||||
|
||||
try
|
||||
{
|
||||
var fileInfo = new FileInfo(FullPath);
|
||||
var fileInfo = new FileInfo(OriginPath);
|
||||
var attributes = fileInfo.Attributes;
|
||||
|
||||
permissions["read"] = true; // 如果能获取到文件信息,说明可读
|
||||
@@ -1094,7 +1131,7 @@ namespace Convention
|
||||
|
||||
try
|
||||
{
|
||||
var fileInfo = new FileInfo(FullPath);
|
||||
var fileInfo = new FileInfo(OriginPath);
|
||||
var attributes = fileInfo.Attributes;
|
||||
|
||||
if (write.HasValue)
|
||||
|
@@ -51,12 +51,9 @@ namespace Convention
|
||||
public ToolFile GetConfigFile() => DataDir | ConstConfigFile;
|
||||
public ToolFile ConfigFile => GetConfigFile();
|
||||
|
||||
public ToolFile GetFile(string path, bool isMustExist = false)
|
||||
public ToolFile GetFile(string path)
|
||||
{
|
||||
var file = DataDir | path;
|
||||
if (isMustExist)
|
||||
file.MustExistsPath();
|
||||
return file;
|
||||
return DataDir | path;
|
||||
}
|
||||
public bool EraseFile(string path)
|
||||
{
|
||||
@@ -130,12 +127,17 @@ namespace Convention
|
||||
public class InternalProperty
|
||||
{
|
||||
public Dictionary<string, object> property = new();
|
||||
public Dictionary<string, object> find = new();
|
||||
}
|
||||
|
||||
public GlobalConfig SaveProperties()
|
||||
{
|
||||
var configFile = this.ConfigFile;
|
||||
configFile.SaveAsJson(new InternalProperty() { property = data_pair });
|
||||
configFile.SaveAsJson(new InternalProperty()
|
||||
{
|
||||
property = data_pair,
|
||||
find = data_find
|
||||
});
|
||||
return this;
|
||||
}
|
||||
public GlobalConfig LoadProperties()
|
||||
@@ -154,7 +156,7 @@ namespace Convention
|
||||
|
||||
public ToolFile GetLogFile()
|
||||
{
|
||||
return this.GetFile(ConfigFile.GetName(true) + "_log.txt", true);
|
||||
return this.GetFile(ConfigFile.GetName(true) + "_log.txt").MustExistsPath();
|
||||
}
|
||||
public ToolFile LogFile => GetLogFile();
|
||||
|
||||
@@ -199,14 +201,18 @@ namespace Convention
|
||||
Log("Error", message);
|
||||
}
|
||||
|
||||
private Dictionary<string, object> data_find = new();
|
||||
|
||||
public object FindItem(string key, object @default = null)
|
||||
{
|
||||
if (Contains(key))
|
||||
{
|
||||
data_find.Remove(key);
|
||||
return this[key];
|
||||
}
|
||||
else
|
||||
{
|
||||
data_find[key] = @default;
|
||||
LogPropertyNotFound(key, @default);
|
||||
return @default;
|
||||
}
|
||||
|
679
Convention/[Runtime]/Interaction.cs
Normal file
679
Convention/[Runtime]/Interaction.cs
Normal file
@@ -0,0 +1,679 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace Convention
|
||||
{
|
||||
/// <summary>
|
||||
/// 统一的文件交互类,支持本地文件、网络文件和localhost路径的自适应处理
|
||||
/// 使用UnityWebRequest实现跨平台兼容,支持WebGL和IL2CPP
|
||||
///
|
||||
/// <list type="bullet"><see cref="ToolFile"/>是依赖项</list>
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public sealed class Interaction
|
||||
{
|
||||
#region Fields and Properties
|
||||
|
||||
private string originalPath;
|
||||
private string processedPath;
|
||||
private PathType pathType;
|
||||
private object cachedData;
|
||||
|
||||
public string OriginalPath => originalPath;
|
||||
public string ProcessedPath => processedPath;
|
||||
public PathType Type => pathType;
|
||||
|
||||
public enum PathType
|
||||
{
|
||||
LocalFile, // 本地文件 (file://)
|
||||
NetworkHTTP, // 网络HTTP (http://)
|
||||
NetworkHTTPS, // 网络HTTPS (https://)
|
||||
LocalServer, // 本地服务器 (localhost)
|
||||
StreamingAssets // StreamingAssets目录
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public Interaction(string path)
|
||||
{
|
||||
SetPath(path);
|
||||
}
|
||||
|
||||
#region Setup
|
||||
|
||||
/// <summary>
|
||||
/// 设置并处理路径
|
||||
/// </summary>
|
||||
public Interaction SetPath(string path)
|
||||
{
|
||||
originalPath = path;
|
||||
processedPath = ProcessPath(path);
|
||||
pathType = DeterminePathType(path);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 处理路径,转换为UnityWebRequest可识别的格式
|
||||
/// </summary>
|
||||
private string ProcessPath(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return path;
|
||||
|
||||
// 网络路径直接返回
|
||||
if (path.StartsWith("http://") || path.StartsWith("https://"))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
// localhost处理
|
||||
if (path.StartsWith("localhost"))
|
||||
{
|
||||
return path.StartsWith("localhost/") ? "http://" + path : "http://localhost/" + path;
|
||||
}
|
||||
|
||||
// StreamingAssets路径处理
|
||||
if (path.StartsWith("StreamingAssets/") || path.StartsWith("StreamingAssets\\"))
|
||||
{
|
||||
return Path.Combine(Application.streamingAssetsPath, path.Substring(16)).Replace("\\", "/");
|
||||
}
|
||||
|
||||
// 本地文件路径处理
|
||||
string fullPath = Path.IsPathRooted(path) ? path : Path.GetFullPath(path);
|
||||
|
||||
// WebGL平台特殊处理
|
||||
if (Application.platform == RuntimePlatform.WebGLPlayer)
|
||||
{
|
||||
// WebGL只能访问StreamingAssets,尝试构建StreamingAssets路径
|
||||
return Application.streamingAssetsPath + "/" + Path.GetFileName(fullPath);
|
||||
}
|
||||
|
||||
// 其他平台使用file://协议
|
||||
return "file:///" + fullPath.Replace("\\", "/");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 确定路径类型
|
||||
/// </summary>
|
||||
private PathType DeterminePathType(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return PathType.LocalFile;
|
||||
|
||||
if (path.StartsWith("https://"))
|
||||
return PathType.NetworkHTTPS;
|
||||
if (path.StartsWith("http://"))
|
||||
return PathType.NetworkHTTP;
|
||||
if (path.StartsWith("localhost"))
|
||||
return PathType.LocalServer;
|
||||
if (path.StartsWith("StreamingAssets"))
|
||||
return PathType.StreamingAssets;
|
||||
|
||||
return PathType.LocalFile;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Load
|
||||
|
||||
#region LoadAsync
|
||||
|
||||
public IEnumerator LoadAsTextAsync(Action<string> onSuccess, Action<string> onError = null)
|
||||
{
|
||||
using UnityWebRequest request = UnityWebRequest.Get(processedPath);
|
||||
yield return request.SendWebRequest();
|
||||
|
||||
if (request.result == UnityWebRequest.Result.Success)
|
||||
{
|
||||
cachedData = request.downloadHandler.text;
|
||||
onSuccess?.Invoke((string)cachedData);
|
||||
}
|
||||
else
|
||||
{
|
||||
string errorMsg = $"Failed to load text from {originalPath}: {request.error}";
|
||||
onError?.Invoke(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator LoadAsBinaryAsync(Action<byte[]> onSuccess, Action<string> onError = null)
|
||||
{
|
||||
using UnityWebRequest request = UnityWebRequest.Get(processedPath);
|
||||
yield return request.SendWebRequest();
|
||||
|
||||
if (request.result == UnityWebRequest.Result.Success)
|
||||
{
|
||||
cachedData = request.downloadHandler.data;
|
||||
onSuccess?.Invoke((byte[])cachedData);
|
||||
}
|
||||
else
|
||||
{
|
||||
string errorMsg = $"Failed to load binary from {originalPath}: {request.error}";
|
||||
onError?.Invoke(errorMsg);
|
||||
}
|
||||
}
|
||||
public IEnumerator LoadAsBinaryAsync(Action<float> progress, Action<byte[]> onSuccess, Action<string> onError = null)
|
||||
{
|
||||
using UnityWebRequest request = UnityWebRequest.Get(processedPath);
|
||||
var result = request.SendWebRequest();
|
||||
while (result.isDone == false)
|
||||
{
|
||||
progress(result.progress);
|
||||
yield return null;
|
||||
}
|
||||
if (request.result == UnityWebRequest.Result.Success)
|
||||
{
|
||||
cachedData = request.downloadHandler.data;
|
||||
onSuccess?.Invoke((byte[])cachedData);
|
||||
}
|
||||
else
|
||||
{
|
||||
string errorMsg = $"Failed to load binary from {originalPath}: {request.error}";
|
||||
onError?.Invoke(errorMsg);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator LoadAsRawJsonAsync<T>(Action<T> onSuccess, Action<string> onError = null)
|
||||
{
|
||||
yield return LoadAsTextAsync(
|
||||
text =>
|
||||
{
|
||||
try
|
||||
{
|
||||
T result = JsonUtility.FromJson<T>(text);
|
||||
cachedData = result;
|
||||
onSuccess?.Invoke(result);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
onError?.Invoke($"Failed to parse JSON: {e.Message}");
|
||||
}
|
||||
},
|
||||
onError
|
||||
);
|
||||
}
|
||||
|
||||
public IEnumerator LoadAsJsonAsync<T>(Action<T> onSuccess, Action<string> onError = null)
|
||||
{
|
||||
yield return LoadAsTextAsync(
|
||||
text =>
|
||||
{
|
||||
try
|
||||
{
|
||||
using StreamReader reader = new(new MemoryStream(System.Text.Encoding.UTF8.GetBytes(text)));
|
||||
var jsonReader = new ES3Internal.ES3JSONReader(reader.BaseStream, new(originalPath));
|
||||
onSuccess?.Invoke(jsonReader.Read<T>());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
onError?.Invoke($"Failed to parse JSON: {e.Message}");
|
||||
}
|
||||
},
|
||||
onError
|
||||
);
|
||||
}
|
||||
|
||||
public IEnumerator LoadAsImageAsync(Action<Texture2D> onSuccess, Action<string> onError = null)
|
||||
{
|
||||
using (UnityWebRequest request = UnityWebRequestTexture.GetTexture(processedPath))
|
||||
{
|
||||
yield return request.SendWebRequest();
|
||||
|
||||
if (request.result == UnityWebRequest.Result.Success)
|
||||
{
|
||||
Texture2D texture = DownloadHandlerTexture.GetContent(request);
|
||||
cachedData = texture;
|
||||
onSuccess?.Invoke(texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
string errorMsg = $"Failed to load image from {originalPath}: {request.error}";
|
||||
onError?.Invoke(errorMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator LoadAsAudioAsync(Action<AudioClip> onSuccess, Action<string> onError = null, AudioType audioType = AudioType.UNKNOWN)
|
||||
{
|
||||
if (audioType == AudioType.UNKNOWN)
|
||||
audioType = GetAudioType(originalPath);
|
||||
|
||||
using (UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(processedPath, audioType))
|
||||
{
|
||||
yield return request.SendWebRequest();
|
||||
|
||||
if (request.result == UnityWebRequest.Result.Success)
|
||||
{
|
||||
AudioClip audioClip = DownloadHandlerAudioClip.GetContent(request);
|
||||
cachedData = audioClip;
|
||||
onSuccess?.Invoke(audioClip);
|
||||
}
|
||||
else
|
||||
{
|
||||
string errorMsg = $"Failed to load audio from {originalPath}: {request.error}";
|
||||
onError?.Invoke(errorMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator LoadAsAssetBundle(Action<float> progress, Action<AssetBundle> onSuccess, Action<string> onError = null)
|
||||
{
|
||||
AssetBundleCreateRequest request = null;
|
||||
yield return LoadAsBinaryAsync(x => progress(x * 0.5f), data => request = AssetBundle.LoadFromMemoryAsync(data), onError);
|
||||
while (request.isDone == false)
|
||||
{
|
||||
progress(0.5f + request.progress * 0.5f);
|
||||
yield return null;
|
||||
}
|
||||
try
|
||||
{
|
||||
AssetBundle bundle = request.assetBundle;
|
||||
if (bundle != null)
|
||||
{
|
||||
cachedData = bundle;
|
||||
onSuccess?.Invoke(bundle);
|
||||
}
|
||||
else
|
||||
{
|
||||
onError?.Invoke($"Failed to load AssetBundle from data.");
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
onError?.Invoke($"Failed to load AssetBundle: {e.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Load Sync
|
||||
|
||||
public string LoadAsText()
|
||||
{
|
||||
string buffer = null;
|
||||
bool isEnd = false;
|
||||
bool IsError = false;
|
||||
var it = LoadAsTextAsync(x =>
|
||||
{
|
||||
buffer = x;
|
||||
isEnd = true;
|
||||
}, e =>
|
||||
{
|
||||
IsError = true;
|
||||
throw new Exception(e);
|
||||
});
|
||||
try
|
||||
{
|
||||
while (!isEnd)
|
||||
{
|
||||
it.MoveNext();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if(IsError)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public byte[] LoadAsBinary()
|
||||
{
|
||||
byte[] buffer = null;
|
||||
bool isEnd = false;
|
||||
bool IsError = false;
|
||||
var it = LoadAsBinaryAsync(x =>
|
||||
{
|
||||
buffer = x;
|
||||
isEnd = true;
|
||||
}, e =>
|
||||
{
|
||||
IsError = true;
|
||||
throw new Exception(e);
|
||||
});
|
||||
try
|
||||
{
|
||||
while (!isEnd)
|
||||
{
|
||||
it.MoveNext();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (IsError)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public T LoadAsRawJson<T>()
|
||||
{
|
||||
T buffer = default;
|
||||
bool isEnd = false;
|
||||
bool IsError = false;
|
||||
var it = LoadAsRawJsonAsync<T>(x =>
|
||||
{
|
||||
buffer = x;
|
||||
isEnd = true;
|
||||
}, e =>
|
||||
{
|
||||
IsError = true;
|
||||
throw new Exception(e);
|
||||
});
|
||||
try
|
||||
{
|
||||
while (!isEnd)
|
||||
{
|
||||
it.MoveNext();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (IsError)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public T LoadAsJson<T>()
|
||||
{
|
||||
T buffer = default;
|
||||
bool isEnd = false;
|
||||
bool IsError = false;
|
||||
var it = LoadAsJsonAsync<T>(x =>
|
||||
{
|
||||
buffer = x;
|
||||
isEnd = true;
|
||||
}, e =>
|
||||
{
|
||||
IsError = true;
|
||||
throw new Exception(e);
|
||||
});
|
||||
try
|
||||
{
|
||||
while (!isEnd)
|
||||
{
|
||||
it.MoveNext();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (IsError)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public Texture2D LoadAsImage()
|
||||
{
|
||||
Texture2D buffer = null;
|
||||
bool isEnd = false;
|
||||
bool IsError = false;
|
||||
var it = LoadAsImageAsync(x =>
|
||||
{
|
||||
buffer = x;
|
||||
isEnd = true;
|
||||
}, e =>
|
||||
{
|
||||
IsError = true;
|
||||
throw new Exception(e);
|
||||
});
|
||||
try
|
||||
{
|
||||
while (!isEnd)
|
||||
{
|
||||
it.MoveNext();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (IsError)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public AudioClip LoadAsAudio(AudioType audioType = AudioType.UNKNOWN)
|
||||
{
|
||||
AudioClip buffer = null;
|
||||
bool isEnd = false;
|
||||
bool IsError = false;
|
||||
var it = LoadAsAudioAsync(x =>
|
||||
{
|
||||
buffer = x;
|
||||
isEnd = true;
|
||||
}, e =>
|
||||
{
|
||||
IsError = true;
|
||||
throw new Exception(e);
|
||||
}, audioType);
|
||||
try
|
||||
{
|
||||
while (!isEnd)
|
||||
{
|
||||
it.MoveNext();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (IsError)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Save
|
||||
|
||||
public Interaction SaveAsText(string content)
|
||||
{
|
||||
if (Application.platform == RuntimePlatform.WebGLPlayer)
|
||||
{
|
||||
throw new NotSupportedException("WebGL平台不支持文件保存。");
|
||||
}
|
||||
|
||||
if (pathType != PathType.LocalFile)
|
||||
{
|
||||
throw new NotSupportedException("仅支持保存到本地文件路径。");
|
||||
}
|
||||
|
||||
new ToolFile(originalPath).SaveAsText(content);
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
public Interaction SaveAsBinary(byte[] data)
|
||||
{
|
||||
if (Application.platform == RuntimePlatform.WebGLPlayer)
|
||||
{
|
||||
throw new NotSupportedException("WebGL平台不支持文件保存。");
|
||||
}
|
||||
|
||||
if (pathType != PathType.LocalFile)
|
||||
{
|
||||
throw new NotSupportedException("仅支持保存到本地文件路径。");
|
||||
}
|
||||
|
||||
new ToolFile(originalPath).SaveAsBinary(data);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Interaction SaveAsRawJson<T>(T obj)
|
||||
{
|
||||
new ToolFile(originalPath).SaveAsRawJson(obj);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Interaction SaveAsJson<T>(T obj)
|
||||
{
|
||||
new ToolFile(originalPath).SaveAsJson(obj);
|
||||
return this;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Tools
|
||||
|
||||
/// <summary>
|
||||
/// 获取本地文件路径
|
||||
/// </summary>
|
||||
private string GetLocalPath()
|
||||
{
|
||||
if (processedPath.StartsWith("file:///"))
|
||||
{
|
||||
return processedPath.Substring(8);
|
||||
}
|
||||
return originalPath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据文件扩展名获取音频类型
|
||||
/// </summary>
|
||||
private AudioType GetAudioType(string path)
|
||||
{
|
||||
return BasicAudioSystem.GetAudioType(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查文件是否存在
|
||||
/// </summary>
|
||||
public bool Exists()
|
||||
{
|
||||
if (pathType == PathType.LocalFile && Application.platform != RuntimePlatform.WebGLPlayer)
|
||||
{
|
||||
return File.Exists(GetLocalPath());
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO : 网络文件和WebGL平台需要通过请求检查
|
||||
// 当前默认存在
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步检查文件是否存在
|
||||
/// </summary>
|
||||
public IEnumerator ExistsAsync(Action<bool> callback)
|
||||
{
|
||||
using UnityWebRequest request = UnityWebRequest.Head(processedPath);
|
||||
yield return request.SendWebRequest();
|
||||
callback?.Invoke(request.result == UnityWebRequest.Result.Success);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Operator
|
||||
|
||||
public static implicit operator string(Interaction interaction) => interaction?.originalPath;
|
||||
|
||||
public override string ToString() => originalPath;
|
||||
|
||||
/// <summary>
|
||||
/// 路径连接操作符
|
||||
/// </summary>
|
||||
public static Interaction operator |(Interaction left, string rightPath)
|
||||
{
|
||||
if (left.pathType == PathType.NetworkHTTP || left.pathType == PathType.NetworkHTTPS || left.pathType == PathType.LocalServer)
|
||||
{
|
||||
string baseUrl = left.originalPath;
|
||||
string newUrl = baseUrl.EndsWith("/") ? baseUrl + rightPath : baseUrl + "/" + rightPath;
|
||||
return new Interaction(newUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
string newPath = Path.Combine(left.originalPath, rightPath);
|
||||
return new Interaction(newPath);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Tools
|
||||
|
||||
/// <summary>
|
||||
/// 获取文件名
|
||||
/// </summary>
|
||||
public string GetFilename()
|
||||
{
|
||||
if (pathType == PathType.NetworkHTTP || pathType == PathType.NetworkHTTPS || pathType == PathType.LocalServer)
|
||||
{
|
||||
var uri = new Uri(processedPath);
|
||||
return Path.GetFileName(uri.AbsolutePath);
|
||||
}
|
||||
return Path.GetFileName(originalPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取文件扩展名
|
||||
/// </summary>
|
||||
public string GetExtension()
|
||||
{
|
||||
return Path.GetExtension(GetFilename());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查扩展名
|
||||
/// </summary>
|
||||
public bool ExtensionIs(params string[] extensions)
|
||||
{
|
||||
string ext = GetExtension().ToLower();
|
||||
string extWithoutDot = ext.Length > 1 ? ext[1..] : "";
|
||||
|
||||
foreach (string extension in extensions)
|
||||
{
|
||||
string checkExt = extension.ToLower();
|
||||
if (ext == checkExt || extWithoutDot == checkExt || ext == "." + checkExt)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Tools
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的Interaction实例
|
||||
/// </summary>
|
||||
public static Interaction Create(string path) => new(path);
|
||||
|
||||
/// <summary>
|
||||
/// 从StreamingAssets创建
|
||||
/// </summary>
|
||||
public static Interaction FromStreamingAssets(string relativePath)
|
||||
{
|
||||
return new Interaction("StreamingAssets/" + relativePath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从本地服务器创建
|
||||
/// </summary>
|
||||
public static Interaction FromLocalhost(string path, int port = 80)
|
||||
{
|
||||
string url = port == 80 ? $"localhost/{path}" : $"localhost:{port}/{path}";
|
||||
return new Interaction(url);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
11
Convention/[Runtime]/Interaction.cs.meta
Normal file
11
Convention/[Runtime]/Interaction.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 731a0091a68afe9458917e4dd0267656
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
584
Convention/[Runtime]/Math.cs
Normal file
584
Convention/[Runtime]/Math.cs
Normal file
@@ -0,0 +1,584 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
#if UNITY_URP
|
||||
using static Unity.Mathematics.math;
|
||||
#endif
|
||||
using static Convention.MathExtension;
|
||||
|
||||
namespace Convention
|
||||
{
|
||||
public static partial class MathExtension
|
||||
{
|
||||
#region EaseCurve
|
||||
|
||||
public static AnimationCurve MakeAnimationCurve(EaseCurveType type, float start, float end, float startValue, float endValue, int keyCount)
|
||||
{
|
||||
var curve = new AnimationCurve();
|
||||
curve.keys = new Keyframe[keyCount];
|
||||
for (int i = 0; i < keyCount; i++)
|
||||
{
|
||||
float t = i / (float)(keyCount - 1);
|
||||
curve.keys[i] = new Keyframe(
|
||||
Mathf.Lerp(start, end, t),
|
||||
Mathf.Lerp(startValue, endValue, Evaluate(t, type))
|
||||
);
|
||||
}
|
||||
return curve;
|
||||
}
|
||||
public enum EaseCurveType
|
||||
{
|
||||
Linear = 0,
|
||||
InQuad = 1,
|
||||
OutQuad = 2,
|
||||
InOutQuad = 3,
|
||||
InCubic = 4,
|
||||
OutCubic = 5,
|
||||
InOutCubic = 6,
|
||||
InQuart = 7,
|
||||
OutQuart = 8,
|
||||
InOutQuart = 9,
|
||||
InQuint = 10,
|
||||
OutQuint = 11,
|
||||
InOutQuint = 12,
|
||||
InSine = 13,
|
||||
OutSine = 14,
|
||||
InOutSine = 15,
|
||||
InExpo = 16,
|
||||
OutExpo = 17,
|
||||
InOutExpo = 18,
|
||||
InCirc = 19,
|
||||
OutCirc = 20,
|
||||
InOutCirc = 21,
|
||||
InBounce = 22,
|
||||
OutBounce = 23,
|
||||
InOutBounce = 24,
|
||||
InElastic = 25,
|
||||
OutElastic = 26,
|
||||
InOutElastic = 27,
|
||||
InBack = 28,
|
||||
OutBack = 29,
|
||||
InOutBack = 30,
|
||||
Custom = 31
|
||||
}
|
||||
|
||||
public static float Evaluate(float t, EaseCurveType curveType)
|
||||
{
|
||||
float from = 0;
|
||||
float to = 1;
|
||||
|
||||
return curveType switch
|
||||
{
|
||||
EaseCurveType.Linear => Linear(from, to, t),
|
||||
EaseCurveType.InQuad => InQuad(from, to, t),
|
||||
EaseCurveType.OutQuad => OutQuad(from, to, t),
|
||||
EaseCurveType.InOutQuad => InOutQuad(from, to, t),
|
||||
EaseCurveType.InCubic => InCubic(from, to, t),
|
||||
EaseCurveType.OutCubic => OutCubic(from, to, t),
|
||||
EaseCurveType.InOutCubic => InOutCubic(from, to, t),
|
||||
EaseCurveType.InQuart => InQuart(from, to, t),
|
||||
EaseCurveType.OutQuart => OutQuart(from, to, t),
|
||||
EaseCurveType.InOutQuart => InOutQuart(from, to, t),
|
||||
EaseCurveType.InQuint => InQuint(from, to, t),
|
||||
EaseCurveType.OutQuint => OutQuint(from, to, t),
|
||||
EaseCurveType.InOutQuint => InOutQuint(from, to, t),
|
||||
EaseCurveType.InSine => InSine(from, to, t),
|
||||
EaseCurveType.OutSine => OutSine(from, to, t),
|
||||
EaseCurveType.InOutSine => InOutSine(from, to, t),
|
||||
EaseCurveType.InExpo => InExpo(from, to, t),
|
||||
EaseCurveType.OutExpo => OutExpo(from, to, t),
|
||||
EaseCurveType.InOutExpo => InOutExpo(from, to, t),
|
||||
EaseCurveType.InCirc => InCirc(from, to, t),
|
||||
EaseCurveType.OutCirc => OutCirc(from, to, t),
|
||||
EaseCurveType.InOutCirc => InOutCirc(from, to, t),
|
||||
EaseCurveType.InBounce => InBounce(from, to, t),
|
||||
EaseCurveType.OutBounce => OutBounce(from, to, t),
|
||||
EaseCurveType.InOutBounce => InOutBounce(from, to, t),
|
||||
EaseCurveType.InElastic => InElastic(from, to, t),
|
||||
EaseCurveType.OutElastic => OutElastic(from, to, t),
|
||||
EaseCurveType.InOutElastic => InOutElastic(from, to, t),
|
||||
EaseCurveType.InBack => InBack(from, to, t),
|
||||
EaseCurveType.OutBack => OutBack(from, to, t),
|
||||
EaseCurveType.InOutBack => InOutBack(from, to, t),
|
||||
_ => throw new NotImplementedException()
|
||||
};
|
||||
}
|
||||
|
||||
public static float Linear(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 1f;
|
||||
return c * t / 1f + from;
|
||||
}
|
||||
|
||||
public static float InQuad(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 1f;
|
||||
return c * t * t + from;
|
||||
}
|
||||
|
||||
public static float OutQuad(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 1f;
|
||||
return -c * t * (t - 2f) + from;
|
||||
}
|
||||
|
||||
public static float InOutQuad(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 0.5f;
|
||||
if (t < 1) return c / 2f * t * t + from;
|
||||
t--;
|
||||
return -c / 2f * (t * (t - 2) - 1) + from;
|
||||
}
|
||||
|
||||
public static float InCubic(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 1f;
|
||||
return c * t * t * t + from;
|
||||
}
|
||||
|
||||
public static float OutCubic(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 1f;
|
||||
t--;
|
||||
return c * (t * t * t + 1) + from;
|
||||
}
|
||||
|
||||
public static float InOutCubic(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 0.5f;
|
||||
if (t < 1) return c / 2f * t * t * t + from;
|
||||
t -= 2;
|
||||
return c / 2f * (t * t * t + 2) + from;
|
||||
}
|
||||
|
||||
public static float InQuart(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 1f;
|
||||
return c * t * t * t * t + from;
|
||||
}
|
||||
|
||||
public static float OutQuart(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 1f;
|
||||
t--;
|
||||
return -c * (t * t * t * t - 1) + from;
|
||||
}
|
||||
|
||||
public static float InOutQuart(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 0.5f;
|
||||
if (t < 1) return c / 2f * t * t * t * t + from;
|
||||
t -= 2;
|
||||
return -c / 2f * (t * t * t * t - 2) + from;
|
||||
}
|
||||
|
||||
public static float InQuint(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 1f;
|
||||
return c * t * t * t * t * t + from;
|
||||
}
|
||||
|
||||
public static float OutQuint(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 1f;
|
||||
t--;
|
||||
return c * (t * t * t * t * t + 1) + from;
|
||||
}
|
||||
|
||||
public static float InOutQuint(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 0.5f;
|
||||
if (t < 1) return c / 2f * t * t * t * t * t + from;
|
||||
t -= 2;
|
||||
return c / 2f * (t * t * t * t * t + 2) + from;
|
||||
}
|
||||
|
||||
public static float InSine(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
return -c * Mathf.Cos(t / 1f * (Mathf.PI / 2f)) + c + from;
|
||||
}
|
||||
|
||||
public static float OutSine(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
return c * Mathf.Sin(t / 1f * (Mathf.PI / 2f)) + from;
|
||||
}
|
||||
|
||||
public static float InOutSine(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
return -c / 2f * (Mathf.Cos(Mathf.PI * t / 1f) - 1) + from;
|
||||
}
|
||||
|
||||
public static float InExpo(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
return c * Mathf.Pow(2, 10 * (t / 1f - 1)) + from;
|
||||
}
|
||||
|
||||
public static float OutExpo(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
return c * (-Mathf.Pow(2, -10 * t / 1f) + 1) + from;
|
||||
}
|
||||
|
||||
public static float InOutExpo(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 0.5f;
|
||||
if (t < 1f) return c / 2f * Mathf.Pow(2, 10 * (t - 1)) + from;
|
||||
t--;
|
||||
return c / 2f * (-Mathf.Pow(2, -10 * t) + 2) + from;
|
||||
}
|
||||
|
||||
public static float InCirc(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 1f;
|
||||
return -c * (Mathf.Sqrt(1 - t * t) - 1) + from;
|
||||
}
|
||||
|
||||
public static float OutCirc(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 1f;
|
||||
t--;
|
||||
return c * Mathf.Sqrt(1 - t * t) + from;
|
||||
}
|
||||
|
||||
public static float InOutCirc(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
t /= 0.5f;
|
||||
if (t < 1) return -c / 2f * (Mathf.Sqrt(1 - t * t) - 1) + from;
|
||||
t -= 2;
|
||||
return c / 2f * (Mathf.Sqrt(1 - t * t) + 1) + from;
|
||||
}
|
||||
|
||||
public static float InBounce(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
return c - OutBounce(0f, c, 1f - t) + from; //does this work?
|
||||
}
|
||||
|
||||
public static float OutBounce(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
|
||||
if ((t /= 1f) < (1 / 2.75f))
|
||||
{
|
||||
return c * (7.5625f * t * t) + from;
|
||||
}
|
||||
else if (t < (2 / 2.75f))
|
||||
{
|
||||
return c * (7.5625f * (t -= (1.5f / 2.75f)) * t + .75f) + from;
|
||||
}
|
||||
else if (t < (2.5 / 2.75))
|
||||
{
|
||||
return c * (7.5625f * (t -= (2.25f / 2.75f)) * t + .9375f) + from;
|
||||
}
|
||||
else
|
||||
{
|
||||
return c * (7.5625f * (t -= (2.625f / 2.75f)) * t + .984375f) + from;
|
||||
}
|
||||
}
|
||||
|
||||
public static float InOutBounce(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
if (t < 0.5f) return InBounce(0, c, t * 2f) * 0.5f + from;
|
||||
return OutBounce(0, c, t * 2 - 1) * 0.5f + c * 0.5f + from;
|
||||
|
||||
}
|
||||
|
||||
public static float InElastic(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
if (t == 0) return from;
|
||||
if ((t /= 1f) == 1) return from + c;
|
||||
float p = 0.3f;
|
||||
float s = p / 4f;
|
||||
return -(c * Mathf.Pow(2, 10 * (t -= 1)) * Mathf.Sin((t - s) * (2 * Mathf.PI) / p)) + from;
|
||||
}
|
||||
|
||||
public static float OutElastic(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
if (t == 0) return from;
|
||||
if ((t /= 1f) == 1) return from + c;
|
||||
float p = 0.3f;
|
||||
float s = p / 4f;
|
||||
return (c * Mathf.Pow(2, -10 * t) * Mathf.Sin((t - s) * (2 * Mathf.PI) / p) + c + from);
|
||||
}
|
||||
|
||||
public static float InOutElastic(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
if (t == 0) return from;
|
||||
if ((t /= 0.5f) == 2) return from + c;
|
||||
float p = 0.3f * 1.5f;
|
||||
float s = p / 4f;
|
||||
if (t < 1)
|
||||
return -0.5f * (c * Mathf.Pow(2, 10 * (t -= 1f)) * Mathf.Sin((t - 2) * (2 * Mathf.PI) / p)) + from;
|
||||
return c * Mathf.Pow(2, -10 * (t -= 1)) * Mathf.Sin((t - s) * (2f * Mathf.PI) / p) * 0.5f + c + from;
|
||||
}
|
||||
|
||||
public static float InBack(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
float s = 1.70158f;
|
||||
t /= 0.5f;
|
||||
return c * t * t * ((s + 1) * t - s) + from;
|
||||
}
|
||||
|
||||
public static float OutBack(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
float s = 1.70158f;
|
||||
t = t / 1f - 1f;
|
||||
return c * (t * t * ((s + 1) * t + s) + 1) + from;
|
||||
}
|
||||
|
||||
public static float InOutBack(float from, float to, float t)
|
||||
{
|
||||
float c = to - from;
|
||||
float s = 1.70158f;
|
||||
t /= 0.5f;
|
||||
if (t < 1) return c / 2f * (t * t * (((s *= (1.525f)) + 1) * t - s)) + from;
|
||||
t -= 2;
|
||||
return c / 2f * (t * t * (((s *= (1.525f)) + 1) * t + s) + 2) + from;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DataFilter
|
||||
|
||||
public interface IBaseFilter<_Type>
|
||||
{
|
||||
_Type[][] Filtrate(_Type[][] source, int width, int length);
|
||||
void FiltrateSource(_Type[][] source, int width, int length);
|
||||
}
|
||||
|
||||
public interface ITreeFilter<_Type, _NextFilter> : IBaseFilter<_Type> where _NextFilter : IBaseFilter<_Type>
|
||||
{
|
||||
_Type[][] Filtrate(_Type[][] source, int width, int length, _NextFilter next);
|
||||
}
|
||||
|
||||
public abstract class AbstractFilter : IBaseFilter<float>
|
||||
{
|
||||
protected abstract void DoFiltrate(float[][] source, float[][] result, int width, int length);
|
||||
|
||||
public float[][] Filtrate(float[][] source, int width, int length)
|
||||
{
|
||||
float[][] result = new float[width][];
|
||||
for (int i = 0; i < width; i++)
|
||||
{
|
||||
result[i] = new float[length];
|
||||
}
|
||||
DoFiltrate(source, result, width, length);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void FiltrateSource(float[][] source, int width, int length)
|
||||
{
|
||||
DoFiltrate(source, source, width, length);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class AbstractColorFilter : IBaseFilter<Color>
|
||||
{
|
||||
protected abstract void DoFiltrate(Color[][] source, Color[][] result, int width, int length);
|
||||
|
||||
public Color[][] Filtrate(Color[][] source, int width, int length)
|
||||
{
|
||||
Color[][] result = new Color[width][];
|
||||
for (int i = 0; i < width; i++)
|
||||
{
|
||||
result[i] = new Color[length];
|
||||
}
|
||||
DoFiltrate(source, result, width, length);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void FiltrateSource(Color[][] source, int width, int length)
|
||||
{
|
||||
DoFiltrate(source, source, width, length);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class TemplateLimitFilter : AbstractFilter
|
||||
{
|
||||
public float min;
|
||||
public float max;
|
||||
public float maxEnhance;
|
||||
public float maxWeakened;
|
||||
public int bufferSize;
|
||||
|
||||
private float[][] buffer;
|
||||
private int header = 0;
|
||||
|
||||
public TemplateLimitFilter(float min, float max, float maxEnhance, float maxWeakened, int bufferSize)
|
||||
{
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.maxEnhance = maxEnhance;
|
||||
this.maxWeakened = maxWeakened;
|
||||
this.bufferSize = bufferSize;
|
||||
}
|
||||
|
||||
protected override void DoFiltrate(float[][] source, float[][] result, int width, int length)
|
||||
{
|
||||
InitBuffer(source, result, width, length);
|
||||
for (int i = 0; i < width; i++)
|
||||
{
|
||||
ReadLine(source, result, i, width, length);
|
||||
BuildLine(source, result, i, width, length);
|
||||
}
|
||||
ClearBuffer();
|
||||
}
|
||||
|
||||
protected virtual void InitBuffer(float[][] source, float[][] result, int width, int length)
|
||||
{
|
||||
buffer ??= new float[bufferSize][];
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
{
|
||||
buffer[i] = new float[length];
|
||||
if (i < width)
|
||||
for (int j = 0; j < length; j++)
|
||||
{
|
||||
buffer[i][j] = source[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ClearBuffer()
|
||||
{
|
||||
for (int i = 0; i < buffer.Length; i++)
|
||||
{
|
||||
buffer[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void ReadLine(float[][] source, float[][] result, int offset, int width, int length)
|
||||
{
|
||||
//Move data to buffer
|
||||
for (int i = 0, e = length; i < e; i++)
|
||||
{
|
||||
buffer[header][i] = source[offset][i];
|
||||
}
|
||||
//Push buffer header
|
||||
header = (header + 1) % bufferSize;
|
||||
}
|
||||
|
||||
protected virtual void BuildLine(float[][] source, float[][] result, int offset, int width, int length)
|
||||
{
|
||||
int tempHeader = header;
|
||||
float[] line = new float[length];
|
||||
do
|
||||
{
|
||||
//Mark data
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
float value = buffer[tempHeader][i];
|
||||
int j = (tempHeader - 1) % bufferSize;
|
||||
if (j < 0)
|
||||
j = bufferSize + j;
|
||||
float lastValue = buffer[j][i];
|
||||
line[i] = Mathf.Clamp(Mathf.Clamp(value, lastValue - maxWeakened, lastValue + maxEnhance), min, max);
|
||||
}
|
||||
//Push buffer header
|
||||
tempHeader = (tempHeader + 1) % bufferSize;
|
||||
}
|
||||
while (tempHeader != header);
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
result[offset][i] = line[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class TemplateColorLimitFilter : AbstractColorFilter
|
||||
{
|
||||
public Color min;
|
||||
public Color max;
|
||||
public Color maxEnhance;
|
||||
public Color maxWeakened;
|
||||
|
||||
public TemplateColorLimitFilter(Color min, Color max, Color maxEnhance, Color maxWeakened)
|
||||
{
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
this.maxEnhance = maxEnhance;
|
||||
this.maxWeakened = maxWeakened;
|
||||
}
|
||||
|
||||
protected override void DoFiltrate(Color[][] source, Color[][] result, int width, int length)
|
||||
{
|
||||
for (int i = 1; i < width; i++)
|
||||
{
|
||||
BuildLine(source, result, i, width, length);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void BuildLine(Color[][] source, Color[][] result, int offset, int width, int length)
|
||||
{
|
||||
Color[] line = new Color[length];
|
||||
//Mark data
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
int j = (offset - 1) % source.Length;
|
||||
Color value = source[j][i];
|
||||
Color lastValue = source[offset][i];
|
||||
line[i] = new(BuildColorR(value, lastValue),
|
||||
BuildColorG(value, lastValue),
|
||||
BuildColorB(value, lastValue),
|
||||
BuildColorA(value, lastValue));
|
||||
}
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
result[offset][i] = line[i];
|
||||
}
|
||||
}
|
||||
|
||||
protected float BuildColorA(Color value, Color lastValue)
|
||||
{
|
||||
return Mathf.Clamp(Mathf.Clamp(value.a, lastValue.a - maxWeakened.a, lastValue.a + maxEnhance.a), min.a, max.a);
|
||||
}
|
||||
|
||||
protected float BuildColorR(Color value, Color lastValue)
|
||||
{
|
||||
return Mathf.Clamp(Mathf.Clamp(value.r, lastValue.r - maxWeakened.r, lastValue.r + maxEnhance.r), min.r, max.r);
|
||||
}
|
||||
|
||||
protected float BuildColorG(Color value, Color lastValue)
|
||||
{
|
||||
return Mathf.Clamp(Mathf.Clamp(value.g, lastValue.g - maxWeakened.g, lastValue.g + maxEnhance.g), min.g, max.g);
|
||||
}
|
||||
|
||||
protected float BuildColorB(Color value, Color lastValue)
|
||||
{
|
||||
return Mathf.Clamp(Mathf.Clamp(value.b, lastValue.b - maxWeakened.b, lastValue.b + maxEnhance.b), min.b, max.b);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
11
Convention/[Runtime]/Math.cs.meta
Normal file
11
Convention/[Runtime]/Math.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53c6be54f26ac234d9734eee0cd11766
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Convention
|
||||
{
|
||||
@@ -54,6 +55,11 @@ namespace Convention
|
||||
public readonly Func<T, T, int> _comparer_func = null;
|
||||
public readonly Comparator _comparator = Comparator.less;
|
||||
|
||||
public T GetTP(float p)
|
||||
{
|
||||
return _elements[(int)(Mathf.Clamp01(p) * _elements.Length)];
|
||||
}
|
||||
|
||||
public int Size => _size;
|
||||
public int Capacity => _capacity;
|
||||
public int Count => _size;
|
||||
|
@@ -18,7 +18,7 @@ namespace Convention.WindowsUI
|
||||
|
||||
[Content, OnlyPlayMode, Ignore] public RectTransformInfo BeforeMaximizeWindow = null;
|
||||
[Content, OnlyPlayMode, Ignore] public float BeforeMaximizeWindowBackgroundColorA = 1f;
|
||||
private bool IsMaximizeWindowMode = false;
|
||||
[SerializeField] private bool IsMaximizeWindowMode = false;
|
||||
[Content, OnlyPlayMode]
|
||||
public void MaximizeWindow()
|
||||
{
|
||||
|
@@ -34,7 +34,7 @@ namespace Convention
|
||||
{
|
||||
colorKeys = new GradientColorKey[]
|
||||
{
|
||||
new GradientColorKey(Color.white, 1),
|
||||
new GradientColorKey(Color.white, 0),
|
||||
new GradientColorKey(Color.white, 1)
|
||||
}
|
||||
};
|
||||
|
@@ -8,27 +8,51 @@ namespace Convention.WindowsUI.Variant
|
||||
{
|
||||
[Setting, Range(0, 1), Percentage(0, 1)] public float Speed = 0.36f;
|
||||
[Resources, OnlyNotNullMode] public RectTransform RectBox;
|
||||
[Resources, OnlyNotNullMode] public RectTransform RopParent;
|
||||
[Resources, OnlyNotNullMode] public RectTransform TopParent;
|
||||
[Resources] public List<RectTransform> Targets = new();
|
||||
[Content] public int TargetIndex;
|
||||
[Content, OnlyPlayMode] public RectTransform Target;
|
||||
public RectTransform Target { get; private set; }
|
||||
|
||||
private Stack<ConventionUtility.ActionStepCoroutineWrapper> Tasks = new();
|
||||
|
||||
public void SetTargetRectTransform(RectTransform target)
|
||||
{
|
||||
Target = target;
|
||||
if (target == null)
|
||||
{
|
||||
Target = null;
|
||||
RectTransformInfo.UpdateAnimationPlane(TopParent, RectBox, Speed, 0, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConventionUtility.ActionStepCoroutineWrapper task = ConventionUtility.CreateSteps();
|
||||
task.Next(() =>
|
||||
{
|
||||
if (gameObject.activeInHierarchy == false)
|
||||
RectTransformInfo.UpdateAnimationPlane(TopParent, RectBox, 1, 0, true);
|
||||
})
|
||||
.Until(() => target.gameObject.activeInHierarchy == true && Tasks.Peek() == task, () => Target = target)
|
||||
.Next(() => Tasks.TryPop(out var _))
|
||||
.Invoke();
|
||||
Tasks.Push(task);
|
||||
}
|
||||
}
|
||||
public void SelectNextTarget()
|
||||
{
|
||||
Debug.Log(TargetIndex);
|
||||
Target = Targets[TargetIndex = (TargetIndex + 1) % Targets.Count];
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (TopParent == null)
|
||||
TopParent = transform.parent as RectTransform;
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (Target != null)
|
||||
RectTransformInfo.UpdateAnimationPlane(Target, RectBox, Speed, 0, true);
|
||||
else
|
||||
RectTransformInfo.UpdateAnimationPlane(RopParent, RectBox, Speed, 0, true);
|
||||
RectTransformInfo.UpdateAnimationPlane(TopParent, RectBox, Speed, 0, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,6 +10,11 @@ namespace Convention.WindowsUI.Variant
|
||||
string HierarchyItemTitle { get; }
|
||||
}
|
||||
|
||||
public interface IHierarchyItemClickEventListener
|
||||
{
|
||||
void OnHierarchyItemClick(HierarchyItem item);
|
||||
}
|
||||
|
||||
public class HierarchyItem : PropertyListItem
|
||||
{
|
||||
[Content, HopeNotNull] public object m_target;
|
||||
@@ -43,7 +48,7 @@ namespace Convention.WindowsUI.Variant
|
||||
}
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (InspectorWindow.instance.GetTarget() == target)
|
||||
if (InspectorWindow.instance != null && InspectorWindow.instance.GetTarget() == target)
|
||||
{
|
||||
InspectorWindow.instance.ClearWindow();
|
||||
}
|
||||
@@ -64,11 +69,17 @@ namespace Convention.WindowsUI.Variant
|
||||
[Content]
|
||||
public void OnFocusHierarchyItem()
|
||||
{
|
||||
if (target == null)
|
||||
if (target != null)
|
||||
{
|
||||
if (InspectorWindow.instance != null)
|
||||
{
|
||||
throw new InvalidOperationException("target is null");
|
||||
}
|
||||
InspectorWindow.instance.SetTarget(target, this);
|
||||
}
|
||||
if(target is IHierarchyItemClickEventListener listener)
|
||||
{
|
||||
listener.OnHierarchyItemClick(this);
|
||||
}
|
||||
}
|
||||
if (!IsEnableFocusWindow)
|
||||
return;
|
||||
if (FocusWindowIndictaor.instance != null)
|
||||
|
@@ -15,7 +15,7 @@ namespace Convention.WindowsUI.Variant
|
||||
private Dictionary<object, HierarchyItem> AllReferenceItemLinker = new();
|
||||
|
||||
/// <summary>
|
||||
/// <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Լ<EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><EFBFBD>tab
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="reference"></param>
|
||||
/// <param name="item"></param>
|
||||
@@ -125,6 +125,25 @@ namespace Convention.WindowsUI.Variant
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void MakeFocusOn(HierarchyItem target)
|
||||
{
|
||||
static void BFS(HierarchyItem t)
|
||||
{
|
||||
var next = t.Entry.GetParent();
|
||||
if (next != null)
|
||||
{
|
||||
BFS(next.GetHierarchyItem());
|
||||
next.GetHierarchyItem().IsFold = false;
|
||||
}
|
||||
}
|
||||
|
||||
BFS(target);
|
||||
if (FocusWindowIndictaor.instance != null)
|
||||
{
|
||||
FocusWindowIndictaor.instance.SetTargetRectTransform(target.TextRectTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -22,8 +22,19 @@ namespace Convention.WindowsUI.Variant
|
||||
|
||||
public BaseWindowBar.RegisteredPageWrapper GameWindowIndex { get; private set; }
|
||||
|
||||
public bool IsSelectSceneCamera { get; private set; }
|
||||
|
||||
public void CameraSelect(bool isScene)
|
||||
{
|
||||
if (ModuleCamera == null)
|
||||
{
|
||||
IsSelectSceneCamera = true;
|
||||
SceneCamera.gameObject.SetActive(true);
|
||||
m_GameObjectOnSceneOnly.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
IsSelectSceneCamera = isScene;
|
||||
SceneCamera.gameObject.SetActive(isScene);
|
||||
ModuleCamera.gameObject.SetActive(!isScene);
|
||||
if (m_GameObjectOnSceneOnly != null)
|
||||
@@ -31,8 +42,15 @@ namespace Convention.WindowsUI.Variant
|
||||
m_GameObjectOnSceneOnly.SetActive(isScene);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if(IsSelectSceneCamera==false&& ModuleCamera==null)
|
||||
{
|
||||
CameraSelect(true);
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
|
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Convention.Internal;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.UI;
|
||||
@@ -289,36 +290,9 @@ namespace Convention.WindowsUI.Variant
|
||||
{
|
||||
if (ref_value != null)
|
||||
{
|
||||
ConventionUtility.StartCoroutine(Adjuster(ref_value.transform as RectTransform));
|
||||
|
||||
}
|
||||
if (parentWindow)
|
||||
{
|
||||
ConventionUtility.StartCoroutine(Adjuster(parentWindow.TargetWindowContent));
|
||||
}
|
||||
else
|
||||
{
|
||||
ConventionUtility.StartCoroutine(Adjuster2(parentEntry.ref_value.transform as RectTransform, parentEntry));
|
||||
}
|
||||
|
||||
static IEnumerator Adjuster(RectTransform rectTransform)
|
||||
{
|
||||
if (rectTransform == null)
|
||||
yield break;
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform);
|
||||
yield return null;
|
||||
if (rectTransform == null)
|
||||
yield break;
|
||||
RectTransformExtension.AdjustSizeToContainsChilds(rectTransform);
|
||||
}
|
||||
static IEnumerator Adjuster2(RectTransform rectTransform, ItemEntry parentEntry)
|
||||
{
|
||||
LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform);
|
||||
yield return null;
|
||||
RectTransformExtension.AdjustSizeToContainsChilds(rectTransform);
|
||||
yield return null;
|
||||
RectTransformExtension.AdjustSizeToContainsChilds(ref_value.transform as RectTransform);
|
||||
if (parentEntry != null)
|
||||
parentEntry.ForceRebuildLayoutImmediate();
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,6 +338,8 @@ namespace Convention.WindowsUI.Variant
|
||||
ForceRebuildLayoutImmediate();
|
||||
}
|
||||
|
||||
public bool IsRemovingChilds { get; private set; } = false;
|
||||
|
||||
public void Release()
|
||||
{
|
||||
if ((parentWindow == null && parentEntry == null) || childs == null || rootWindow == null)
|
||||
@@ -376,21 +352,18 @@ namespace Convention.WindowsUI.Variant
|
||||
ref_value.gameObject.SetActive(false);
|
||||
Destroy(ref_value.gameObject);
|
||||
}
|
||||
IsRemovingChilds = true;
|
||||
foreach (var item in childs)
|
||||
{
|
||||
item.Release();
|
||||
}
|
||||
IsRemovingChilds = false;
|
||||
if (parentWindow != null)
|
||||
parentWindow.m_Entrys.Remove(this);
|
||||
else
|
||||
else if (GetParent().IsRemovingChilds == false)
|
||||
parentEntry.childs.Remove(this);
|
||||
ref_value = null;
|
||||
}
|
||||
|
||||
~ItemEntry()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
}
|
||||
public interface IItemEntry
|
||||
{
|
||||
|
@@ -9,9 +9,11 @@ namespace Convention.WindowsUI.Variant
|
||||
{
|
||||
public class PropertyListItem : WindowUIModule, ITitle, IText, IItemEntry, IActionInvoke
|
||||
{
|
||||
[Resources, SerializeField, OnlyNotNullMode] private Button m_rawButton;
|
||||
[Resources, SerializeField, OnlyNotNullMode(nameof(m_rawButton))] private float layerTab = 7.5f;
|
||||
[Resources, SerializeField, OnlyNotNullMode(nameof(m_rawButton))] private float layerHeight = 15f;
|
||||
[Resources, SerializeField] private Button m_rawButton;
|
||||
[Resources, SerializeField] private ModernUIButton m_modernButton;
|
||||
public GameObject ButtonGameObject => m_rawButton == null ? m_modernButton.gameObject : m_rawButton.gameObject;
|
||||
[Resources, SerializeField] private float layerTab = 7.5f;
|
||||
[Resources, SerializeField] private float layerHeight = 15f;
|
||||
[Resources, SerializeField, OnlyNotNullMode] private RectTransform dropdownImage;
|
||||
[Resources, SerializeField, OnlyNotNullMode] private Text m_buttonText;
|
||||
[Resources, SerializeField, OnlyNotNullMode, Header("Self Layer")] private RectTransform m_Layer;
|
||||
@@ -44,10 +46,13 @@ namespace Convention.WindowsUI.Variant
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
m_rawButton.gameObject.AddComponent<RectTransformExtension.AdjustSizeIgnore>();
|
||||
ButtonGameObject.AddComponent<RectTransformExtension.AdjustSizeIgnore>();
|
||||
dropdownImage.gameObject.AddComponent<RectTransformExtension.AdjustSizeIgnore>();
|
||||
m_buttonText.gameObject.AddComponent<RectTransformExtension.AdjustSizeIgnore>();
|
||||
if (m_rawButton != null)
|
||||
m_rawButton.onClick.AddListener(Switch);
|
||||
else
|
||||
m_modernButton.AddListener(Switch);
|
||||
TextRectTransform = m_buttonText.GetComponent<RectTransform>();
|
||||
dropdownImage.eulerAngles = new(0, 0, IsFold ? 90 : 0);
|
||||
}
|
||||
@@ -79,7 +84,23 @@ namespace Convention.WindowsUI.Variant
|
||||
|
||||
public virtual string title { get => m_buttonText.title; set => m_buttonText.title = value; }
|
||||
public virtual string text { get => m_buttonText.text; set => m_buttonText.text = value; }
|
||||
public virtual bool interactable { get => m_rawButton.interactable; set => m_rawButton.interactable = value; }
|
||||
public virtual bool interactable
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_rawButton != null)
|
||||
return m_rawButton.interactable;
|
||||
else
|
||||
return m_modernButton.interactable;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (m_rawButton != null)
|
||||
m_rawButton.interactable = value;
|
||||
else
|
||||
m_modernButton.interactable = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Switch()
|
||||
{
|
||||
@@ -97,6 +118,14 @@ namespace Convention.WindowsUI.Variant
|
||||
dropdownImage.eulerAngles = new(0, 0, 0);
|
||||
}
|
||||
|
||||
public virtual void RefreshChilds()
|
||||
{
|
||||
ConventionUtility.CreateSteps()
|
||||
.Next(() => Switch())
|
||||
.Next(() => Switch())
|
||||
.Invoke();
|
||||
}
|
||||
|
||||
public List<ItemEntry> CreateSubPropertyItem([In] PropertiesWindow propertyWindow, int count)
|
||||
{
|
||||
List<ItemEntry> result = new();
|
||||
@@ -134,7 +163,10 @@ namespace Convention.WindowsUI.Variant
|
||||
{
|
||||
foreach (var item in action)
|
||||
{
|
||||
if (m_rawButton != null)
|
||||
m_rawButton.onClick.AddListener(item);
|
||||
else
|
||||
m_modernButton.AddListener(item);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
@@ -143,14 +175,20 @@ namespace Convention.WindowsUI.Variant
|
||||
{
|
||||
foreach (var item in action)
|
||||
{
|
||||
if (m_rawButton != null)
|
||||
m_rawButton.onClick.RemoveListener(item);
|
||||
else
|
||||
m_modernButton.RemoveListener(item);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
public IActionInvoke RemoveAllListeners()
|
||||
{
|
||||
if (m_rawButton != null)
|
||||
m_rawButton.onClick.RemoveAllListeners();
|
||||
else
|
||||
m_modernButton.RemoveAllListeners();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@@ -84,8 +84,8 @@ namespace Convention.WindowsUI.Variant
|
||||
{
|
||||
target.CreateItem(() =>
|
||||
{
|
||||
action.callback(rightTop);
|
||||
ReleaseAllCustomMenu();
|
||||
action.callback(rightTop);
|
||||
}, action.name);
|
||||
}
|
||||
CustomMenuRelease.gameObject.SetActive(true);
|
||||
|
@@ -91,7 +91,7 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier:
|
||||
Speed: 0.32
|
||||
RectBox: {fileID: 6272003121708756342}
|
||||
RopParent: {fileID: 8773560469810817739}
|
||||
TopParent: {fileID: 0}
|
||||
Targets:
|
||||
- {fileID: 0}
|
||||
- {fileID: 7709311530016948315}
|
||||
@@ -100,7 +100,6 @@ MonoBehaviour:
|
||||
- {fileID: 2403051311178796671}
|
||||
- {fileID: 5377214671440830306}
|
||||
TargetIndex: 0
|
||||
Target: {fileID: 0}
|
||||
--- !u!114 &7462675906960032546
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
|
Reference in New Issue
Block a user