diff --git a/Assets/BITKit/Core/Attributes/IBITCommand.cs b/Assets/BITKit/Core/Attributes/IBITCommand.cs index b4f978ef..4ce44573 100644 --- a/Assets/BITKit/Core/Attributes/IBITCommand.cs +++ b/Assets/BITKit/Core/Attributes/IBITCommand.cs @@ -3,12 +3,15 @@ namespace BITKit { [AttributeUsage(AttributeTargets.Method)] - public class BITCommandAttribute : Attribute { } + public class BITCommandAttribute : Attribute + { + } + /// /// 自动注入依赖 /// - [AttributeUsage(AttributeTargets.Field)] - public class InjectAttribute : System.Attribute + [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)] + public class InjectAttribute : Attribute { public static void Clear(object obj) { diff --git a/Assets/BITKit/Core/DependencyInjection/DependencyInjection.cs b/Assets/BITKit/Core/DependencyInjection/DependencyInjection.cs index 5990cce8..e8cbd68e 100644 --- a/Assets/BITKit/Core/DependencyInjection/DependencyInjection.cs +++ b/Assets/BITKit/Core/DependencyInjection/DependencyInjection.cs @@ -125,6 +125,29 @@ namespace BITKit /// public static void Inject(object obj) { + foreach (var propertyInfo in obj.GetType().GetProperties(ReflectionHelper.Flags)) + { + try + { + if (propertyInfo.GetCustomAttribute() is null && + propertyInfo.GetCustomAttribute() is not null) + { + lock (dictionary) + { + if(dictionary!.TryGetValue(propertyInfo.PropertyType,out var value)) + { + BIT4Log.Log($"已为{obj.GetType().Name}.{propertyInfo.Name}注入{value.GetType().Name}"); + propertyInfo.SetValue(obj,value); + } + } + } + } + catch (Exception e) + { + BIT4Log.LogException(e); + } + + } foreach (var field in obj.GetType().GetFields(ReflectionHelper.Flags)) { try diff --git a/Assets/BITKit/Core/ECS/EntityComponentSystem.cs b/Assets/BITKit/Core/ECS/EntityComponentSystem.cs index a2c3d243..c5adcd16 100644 --- a/Assets/BITKit/Core/ECS/EntityComponentSystem.cs +++ b/Assets/BITKit/Core/ECS/EntityComponentSystem.cs @@ -15,7 +15,7 @@ namespace BITKit.Entities /// 等待初始化完成,通常用于其他系统需要等待实体初始化完成 /// void WaitForInitializationComplete(); - ulong Id { get; } + int Id { get; } CancellationToken CancellationToken { get; } bool TryGetComponent(out T component); IEntityComponent[] Components { get; } @@ -81,18 +81,18 @@ namespace BITKit.Entities /// /// /// - IEntity Get(ulong id); + IEntity Get(int id); /// /// 尝试通过Id获取Entity /// /// /// /// - bool TryGetEntity(ulong id, out IEntity entity); + bool TryGetEntity(int id, out IEntity entity); /// /// 通过Id获取或添加Entity /// - IEntity GetOrAdd(ulong id,Func factory); + IEntity GetOrAdd(int id,Func factory); /// /// 查询Entity,例如 diff --git a/Assets/BITKit/Core/Mod/ModService.cs b/Assets/BITKit/Core/Mod/ModService.cs index f9000196..8160e4bb 100644 --- a/Assets/BITKit/Core/Mod/ModService.cs +++ b/Assets/BITKit/Core/Mod/ModService.cs @@ -220,7 +220,6 @@ namespace BITKit.Mod private static Thread _Thread; private static bool _IsRunning; private static bool _IsLocked; - private static AppDomain _ModDomain; public static void Initialize() { @@ -241,8 +240,6 @@ namespace BITKit.Mod try { - _ModDomain = AppDomain.CreateDomain("ModDomain"); - var modPath = Path.Combine(Environment.CurrentDirectory, "Mods\\"); PathHelper.EnsureDirectoryCreated(modPath); var directoryInfo = new DirectoryInfo(modPath); @@ -383,7 +380,6 @@ namespace BITKit.Mod _UnRegisterQueue.Clear(); Mods = Array.Empty(); _InstalledMods.Clear(); - AppDomain.Unload(_ModDomain); } catch (Exception e) { diff --git a/Assets/BITKit/Unity/Configs/Input/BITController.inputactions b/Assets/BITKit/Unity/Configs/Input/BITController.inputactions index cdb2837b..db946df6 100644 --- a/Assets/BITKit/Unity/Configs/Input/BITController.inputactions +++ b/Assets/BITKit/Unity/Configs/Input/BITController.inputactions @@ -41,6 +41,15 @@ "interactions": "Press,Tap", "initialStateCheck": false }, + { + "name": "Crawl", + "type": "Button", + "id": "350ae177-bf96-40b1-aff0-e10865947df9", + "expectedControlType": "Button", + "processors": "", + "interactions": "", + "initialStateCheck": false + }, { "name": "HoldCrouch", "type": "Button", @@ -570,6 +579,17 @@ "action": "Inspect", "isComposite": false, "isPartOfComposite": false + }, + { + "name": "", + "id": "a533436d-c3bf-4cb3-93b2-1ca02791e6d1", + "path": "/leftCtrl", + "interactions": "Press,Hold", + "processors": "", + "groups": "", + "action": "Crawl", + "isComposite": false, + "isPartOfComposite": false } ] }, diff --git a/Assets/BITKit/Unity/Scripts/Animator/AnimatorHelper.cs b/Assets/BITKit/Unity/Scripts/Animator/AnimatorHelper.cs index a2d77ac6..654cb946 100644 --- a/Assets/BITKit/Unity/Scripts/Animator/AnimatorHelper.cs +++ b/Assets/BITKit/Unity/Scripts/Animator/AnimatorHelper.cs @@ -6,10 +6,10 @@ namespace BITKit public class AnimatorHelper : MonoBehaviour { [SerializeField] private Transform root; - + [SerializeField] private bool allowAnimatorMove; private void OnAnimatorMove() { - if (root) + if (root && allowAnimatorMove) root.SendMessageUpwards(nameof(OnAnimatorMove),SendMessageOptions.DontRequireReceiver); } private void AIAnimationEvent(string actionName) diff --git a/Assets/BITKit/Unity/Scripts/Entity/Components/EntityMovement/EntityMovement.cs b/Assets/BITKit/Unity/Scripts/Entity/Components/EntityMovement/EntityMovement.cs index 4e9e927f..1708320f 100644 --- a/Assets/BITKit/Unity/Scripts/Entity/Components/EntityMovement/EntityMovement.cs +++ b/Assets/BITKit/Unity/Scripts/Entity/Components/EntityMovement/EntityMovement.cs @@ -62,6 +62,7 @@ namespace BITKit.Entities /// public interface IEntityMovement:IStateMachine { + Vector3 Size => Vector3.one; float ReferenceSpeed => 2.5f; Vector3 Position { get; set; } Quaternion Rotation { get; set; } @@ -138,5 +139,6 @@ namespace BITKit.Entities void BeforeUpdateMovement(float deltaTime); void AfterUpdateMovement(float deltaTime); void ExecuteCommand(T command); + void DrawGizmos(); } } \ No newline at end of file diff --git a/Assets/BITKit/Unity/Scripts/Entity/Components/Health/DamageService.cs b/Assets/BITKit/Unity/Scripts/Entity/Components/Health/DamageService.cs index f3d6ca1a..bf39b0b6 100644 --- a/Assets/BITKit/Unity/Scripts/Entity/Components/Health/DamageService.cs +++ b/Assets/BITKit/Unity/Scripts/Entity/Components/Health/DamageService.cs @@ -81,8 +81,8 @@ namespace BITKit.Entities { public override DamageMessage ReadBinary(BinaryReader reader) { - UnityEntitiesService.TryGetEntity(reader.ReadUInt64(),out var initiator); - UnityEntitiesService.TryGetEntity(reader.ReadUInt64(),out var target); + UnityEntitiesService.TryGetEntity(reader.ReadInt32(),out var initiator); + UnityEntitiesService.TryGetEntity(reader.ReadInt32(),out var target); return new DamageMessage() { Initiator = initiator as Entity, diff --git a/Assets/BITKit/Unity/Scripts/Entity/Components/Hitbox/EntityHitboxBuilder.cs b/Assets/BITKit/Unity/Scripts/Entity/Components/Hitbox/EntityHitboxBuilder.cs index e11c467f..3bf0d54e 100644 --- a/Assets/BITKit/Unity/Scripts/Entity/Components/Hitbox/EntityHitboxBuilder.cs +++ b/Assets/BITKit/Unity/Scripts/Entity/Components/Hitbox/EntityHitboxBuilder.cs @@ -3,7 +3,9 @@ using System.Collections.Generic; using BITFALL.Rig; using BITKit.Entities; using Cysharp.Threading.Tasks.Triggers; +#if UNITY_EDITOR using UnityEditor; +#endif using UnityEngine; namespace BITKit @@ -14,6 +16,7 @@ namespace BITKit [SerializeField] private EntityHitbox[] hitboxes; [SerializeReference,SubclassSelector] private IReference[] tagReferences; +#if UNITY_EDITOR [BIT] private void Build() { @@ -73,5 +76,6 @@ namespace BITKit } EditorUtility.SetDirty(this); } + #endif } } diff --git a/Assets/BITKit/Unity/Scripts/Entity/Core/Entity.cs b/Assets/BITKit/Unity/Scripts/Entity/Core/Entity.cs index 14331ac1..c7ac1091 100644 --- a/Assets/BITKit/Unity/Scripts/Entity/Core/Entity.cs +++ b/Assets/BITKit/Unity/Scripts/Entity/Core/Entity.cs @@ -20,7 +20,7 @@ namespace BITKit.Entities private readonly GenericEvent genericEvent = new(); - public ulong Id { get; set; } + public int Id { get; set; } public CancellationToken CancellationToken { get; private set; } public IEntityBehavior[] Behaviors { get;private set; } public IEntityComponent[] Components => Behaviors.Cast().ToArray(); @@ -33,9 +33,43 @@ namespace BITKit.Entities IServiceProvider Entities.IEntity.ServiceProvider=> throw new InvalidOperationException("Unity Entity can't register component"); public void Inject(object obj) { + foreach (var propertyInfo in obj + .GetType() + .GetProperties(ReflectionHelper.Flags) + .Where(x=>x.GetCustomAttribute(true) is not null)) + { + var type = propertyInfo.PropertyType; + var attribute = propertyInfo.GetCustomAttribute(); + var currentValue = propertyInfo.GetValue(obj); + try + { + switch (currentValue) + { + case null: + break; + case IEntityComponent entityComponent: + if(entityComponent.Entity.Id == Id) + continue; + break; + case MonoBehaviour { destroyCancellationToken: { IsCancellationRequested: false } }: + continue; + case not null: + continue; + } + } + catch (MissingReferenceException){} + if(genericEvent.TryGetObjectDirect(type.FullName,out var value)) + { + propertyInfo.SetValue(obj,value,null); + } + else if(attribute?.CanBeNull is false) + { + BIT4Log.Warning($"{name}未找到{obj.GetType().Name}需要的{type.FullName}"); + } + } foreach (var fieldInfo in obj .GetType() - .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + .GetFields(ReflectionHelper.Flags) .Where(fieldInfo=>fieldInfo.GetCustomAttribute(true) is not null)) { var type = fieldInfo.FieldType; @@ -97,7 +131,7 @@ namespace BITKit.Entities private void Awake() { if (Id.IsDefault()) - Id = (ulong)Guid.NewGuid().GetHashCode(); + Id = GetInstanceID(); CancellationToken = gameObject.GetCancellationTokenOnDestroy(); Set(CancellationToken); } diff --git a/Assets/BITKit/Unity/Scripts/Entity/Core/StateBasedComponent.cs b/Assets/BITKit/Unity/Scripts/Entity/Core/StateBasedComponent.cs index 67df1601..bf38d879 100644 --- a/Assets/BITKit/Unity/Scripts/Entity/Core/StateBasedComponent.cs +++ b/Assets/BITKit/Unity/Scripts/Entity/Core/StateBasedComponent.cs @@ -48,6 +48,13 @@ namespace BITKit.Entities stateMachine.Initialize(); } } + + public override void OnDestroyComponent() + { + base.OnDestroyComponent(); + CurrentState?.OnStateExit(CurrentState,null); + } + void IStateMachine.Initialize() { stateMachine.Initialize(); diff --git a/Assets/BITKit/Unity/Scripts/Entity/Core/UnityEntitiesService.cs b/Assets/BITKit/Unity/Scripts/Entity/Core/UnityEntitiesService.cs index 5e72a9df..877e6bec 100644 --- a/Assets/BITKit/Unity/Scripts/Entity/Core/UnityEntitiesService.cs +++ b/Assets/BITKit/Unity/Scripts/Entity/Core/UnityEntitiesService.cs @@ -38,10 +38,10 @@ public class UnityEntitiesServiceSingleton:IEntitiesService public CancellationToken CancellationToken => UnityEntitiesService.CancellationToken; - public IEntity Get(ulong id) => UnityEntitiesService.Get(id); - public bool TryGetEntity(ulong id, out IEntity entity) => UnityEntitiesService.TryGetEntity(id, out entity); + public IEntity Get(int id) => UnityEntitiesService.Get(id); + public bool TryGetEntity(int id, out IEntity entity) => UnityEntitiesService.TryGetEntity(id, out entity); - public IEntity GetOrAdd(ulong id, Func factory)=>UnityEntitiesService.GetOrAdd(id,factory); + public IEntity GetOrAdd(int id, Func factory)=>UnityEntitiesService.GetOrAdd(id,factory); public IEntity[] Query() @@ -85,7 +85,7 @@ public class UnityEntitiesService : MonoBehaviour,IEntitiesService return false; } public static CancellationToken CancellationToken; - private static readonly ConcurrentDictionary Dictionary=new(); + private static readonly ConcurrentDictionary Dictionary=new(); private static readonly Queue RegisterQueue = new(); private static readonly Queue UnRegisterQueue = new(); private void Awake() @@ -126,18 +126,18 @@ public class UnityEntitiesService : MonoBehaviour,IEntitiesService } CancellationToken IEntitiesService.CancellationToken => CancellationToken; - public static IEntity Get(ulong id)=>Dictionary[id]; - IEntity IEntitiesService.Get(ulong id)=>Get(id); - public static bool TryGetEntity(ulong id, out IEntity entity) + public static IEntity Get(int id)=>Dictionary[id]; + IEntity IEntitiesService.Get(int id)=>Get(id); + public static bool TryGetEntity(int id, out IEntity entity) { return Dictionary.TryGetValue(id, out entity); } - bool IEntitiesService.TryGetEntity(ulong id, out IEntity entity)=>TryGetEntity(id,out entity); - public static IEntity GetOrAdd(ulong id, Func factory) + bool IEntitiesService.TryGetEntity(int id, out IEntity entity)=>TryGetEntity(id,out entity); + public static IEntity GetOrAdd(int id, Func factory) { return Dictionary.GetOrAdd(id, factory); } - IEntity IEntitiesService.GetOrAdd(ulong id, Func factory)=>GetOrAdd(id,factory); + IEntity IEntitiesService.GetOrAdd(int id, Func factory)=>GetOrAdd(id,factory); IEntity[] IEntitiesService.Query()=>Query(); public static IEntity[] Query() diff --git a/Assets/BITKit/Unity/Scripts/Entity/Core/UnityIdComponent.cs b/Assets/BITKit/Unity/Scripts/Entity/Core/UnityIdComponent.cs index 59d013d9..2589b5fd 100644 --- a/Assets/BITKit/Unity/Scripts/Entity/Core/UnityIdComponent.cs +++ b/Assets/BITKit/Unity/Scripts/Entity/Core/UnityIdComponent.cs @@ -7,14 +7,14 @@ namespace BITKit.Entities { public interface IdComponent { - ulong Id { get; } + int Id { get; } string Name { get; } } public class UnityIdComponent : EntityBehavior,IdComponent { - [SerializeField] private ulong id; + [SerializeField] private int id; [SerializeField] private string unityName; - public ulong Id => id; + public int Id => id; public string Name => unityName; public override void Initialize(IEntity _entity) { diff --git a/Assets/BITKit/Unity/Scripts/Entity/Net/EntitiesNetService.cs b/Assets/BITKit/Unity/Scripts/Entity/Net/EntitiesNetService.cs index b558fc7b..aa308b91 100644 --- a/Assets/BITKit/Unity/Scripts/Entity/Net/EntitiesNetService.cs +++ b/Assets/BITKit/Unity/Scripts/Entity/Net/EntitiesNetService.cs @@ -19,7 +19,7 @@ namespace BITKit.Entities public struct EntitiesNetSyncBatchCommand { public int Length; - public ulong[] Ids; + public int[] Ids; public ulong[] AddressablePaths; public EntitiesNetSyncCommand[] Commands; } @@ -81,7 +81,7 @@ namespace BITKit.Entities { using var ms = new MemoryStream(obj.Data); using var reader = new BinaryReader(ms); - var id = reader.ReadUInt64(); + var id = reader.ReadInt32(); var path = reader.ReadUInt64(); entitiesService.GetOrAdd(id, x => AddEntity(id, path)).TryGetComponent(out var header); header.Deserialize(reader); @@ -100,7 +100,7 @@ namespace BITKit.Entities header.Deserialize(reader); } } - private static IEntity AddEntity(ulong id,ulong addressableId) + private static IEntity AddEntity(int id,ulong addressableId) { var entity = AddressableHelper.Get(addressableId); var instance = Instantiate(entity).GetComponent(); @@ -146,7 +146,7 @@ namespace BITKit.Entities var batchCommand = new EntitiesNetSyncBatchCommand() { Length = headers.Length, - Ids = new ulong[headers.Length], + Ids = new int[headers.Length], AddressablePaths = new ulong[headers.Length], Commands = new EntitiesNetSyncCommand[headers.Length] }; diff --git a/Assets/BITKit/Unity/Scripts/Entity/Player/StateBasedPlayerComponent.cs b/Assets/BITKit/Unity/Scripts/Entity/Player/StateBasedPlayerComponent.cs index a15c2cfa..07b26b0f 100644 --- a/Assets/BITKit/Unity/Scripts/Entity/Player/StateBasedPlayerComponent.cs +++ b/Assets/BITKit/Unity/Scripts/Entity/Player/StateBasedPlayerComponent.cs @@ -15,8 +15,8 @@ namespace BITKit.Entities.Player [SerializeField] private MonoStateMachine stateMachine; public override void OnAwake() { - stateMachine?.Initialize(); base.OnAwake(); + stateMachine?.Initialize(); } public bool Enabled diff --git a/Assets/BITKit/Unity/Scripts/Physics/IClosePoint.cs b/Assets/BITKit/Unity/Scripts/Physics/IClosePoint.cs index e1831c2e..5a539ff9 100644 --- a/Assets/BITKit/Unity/Scripts/Physics/IClosePoint.cs +++ b/Assets/BITKit/Unity/Scripts/Physics/IClosePoint.cs @@ -3,57 +3,121 @@ using System.Collections; using System.Collections.Generic; using System.Data; using System.Linq; +using System.Text; using UnityEngine; namespace BITKit { public interface IClosePoint { + Vector3 CurrentPoint { get; } Collider Collider { get; } bool TryGetClosePoint(out Vector3 vector3); } - [System.Serializable] + [Serializable] public class GetClosePointFromCollider : IClosePoint { - public Transform root; - public LayerMask layerMask; - public float distance; + [SerializeField] private string name; + [SerializeField] private Transform transform; + [SerializeField] private Vector3 offset = Vector3.one; + [SerializeField] private LayerMask layerMask; + [SerializeField] private float distance; + [SerializeField] private float minHeight=0.32f; + [SerializeField] private float maxHeight = 1f; + public Vector3 CurrentPoint { get; set; } public Collider Collider { get; set; } - + private Collider[] _colliders=new Collider[8]; + private Collider[] _mainCollider=new Collider[8]; public bool TryGetClosePoint(out Vector3 vector3) { vector3 = default; - if (UnityEngine.Physics.Raycast(root.position, root.forward, out var raycastHit, distance, layerMask)) + StringBuilder reportBuilder = new(); + reportBuilder.AppendLine($"检测任务:{name}"); + var position = transform.position + transform.rotation * offset; + var detectedLength = Physics.OverlapSphereNonAlloc(position, distance, _mainCollider, layerMask); + reportBuilder.AppendLine($"检测到了{detectedLength}个碰撞体"); + for (var i = 0; i 0.16f) return false; - - if (UnityEngine.Physics.Linecast(root.position, vector3, out var raycastHit2, layerMask)) + var bounds = collider.bounds; + vector3 = collider.ClosestPoint(transform.position + Vector3.up*64); + var top = bounds.center.y + bounds.extents.y; + Debug.DrawLine(transform.position,transform.position + Vector3.up * top,Color.blue,8f); + if (transform.position.y + minHeight > top) { - if(raycastHit2.collider != collider) - return false; + reportBuilder?.AppendLine("高度不足"); + continue; + } + + var nextPos = position; + nextPos.y = collider.bounds.center.y; + if (collider.Raycast(new Ray(nextPos, transform.forward), out _, distance) is false) + { + reportBuilder?.AppendLine("未检测到前方"); + continue; + } + var height = Mathf.Abs(top - transform.position.y); + if (height > maxHeight) + { + reportBuilder?.AppendLine($"高度差距过大:{height}"); + continue; + } + if (Physics.Linecast(transform.position, vector3, out var raycastHit2, layerMask)) + { + if (raycastHit2.collider != collider) + { + reportBuilder?.AppendLine($"检测到了其他碰撞体:{raycastHit2.transform.name}"); + continue; + } }; - foreach(var hit in UnityEngine.Physics.OverlapSphere(vector3, 0.1f, layerMask)) + + var length = Physics.OverlapSphereNonAlloc(vector3, 0.01f, _colliders, layerMask); + switch (length) { - if(hit!= collider) - return false; + case 1: + if (_colliders[0] != collider) + { + reportBuilder.AppendLine($"检测到了其他碰撞体{_colliders[0].name}"); + continue; + } + break; + case > 1: + reportBuilder.AppendLine("检测到了更多碰撞体"); + for (var ii = 0; ii < length; ii++) + { + //Debug.DrawLine(vector3, _colliders[ii].ClosestPoint(vector3), Color.red, 8); + reportBuilder.AppendLine($"\t{_colliders[ii].name}"); + } + continue; } Collider = collider; + + vector3.y = top; + CurrentPoint = vector3; + + + + reportBuilder.AppendLine("成功"); + //BIT4Log.Log(reportBuilder.ToString()); return true; - //return vector3.y >= collider.bounds.center.y + collider.bounds.extents.y; - //return true; } + //BIT4Log.Log(reportBuilder.ToString()); return false; } } @@ -74,6 +138,7 @@ namespace BITKit public Vector3 StartPosition; public Vector3 EndPosition; + public Vector3 CurrentPoint { get; set; } public Collider Collider { get; set; } private Rigidbody rigidbody; @@ -92,7 +157,8 @@ namespace BITKit if (rigidbody.velocity.GetLength() < 0.1f) return false; } - var reportBuilder = new System.Text.StringBuilder(); + //var reportBuilder = new System.Text.StringBuilder(); + StringBuilder reportBuilder=null; var forward = root.forward; var sourceStartPosition = groundReference.position; @@ -101,7 +167,7 @@ namespace BITKit var collider = UnityEngine.Physics.OverlapSphere(startPosition, radius, layerMask); - reportBuilder.AppendLine($"检测到了{collider.Length}个碰撞体"); + reportBuilder?.AppendLine($"检测到了{collider.Length}个碰撞体"); foreach (var hit in collider) { @@ -112,12 +178,12 @@ namespace BITKit continue; } - reportBuilder.AppendLine(); - reportBuilder.AppendLine($">{hit.name}"); + reportBuilder?.AppendLine(); + reportBuilder?.AppendLine($">{hit.name}"); if(top.y>groundReference.transform.position.y+maxHeight) { - reportBuilder.AppendLine("高度超出可翻越高度"); + reportBuilder?.AppendLine("高度超出可翻越高度"); continue; } @@ -128,9 +194,9 @@ namespace BITKit if (hit.Raycast(ray, out var colliderHit, 8) is false) { - reportBuilder.AppendLine("未检测到背面,算法错误"); + reportBuilder?.AppendLine("未检测到背面,算法错误"); - Debug.DrawRay(ray.origin, ray.direction * 8, Color.red, 8); + //Debug.DrawRay(ray.origin, ray.direction * 8, Color.red, 8); continue; } @@ -151,15 +217,15 @@ namespace BITKit } catch (OperationCanceledException e) { - reportBuilder.AppendLine(e.Message); + reportBuilder?.AppendLine(e.Message); continue; } if(UnityEngine.Physics.Raycast(EndPosition,Vector3.down,out _,1.6f,layerMask) is false) { - Debug.DrawRay(EndPosition, Vector3.down*1.6f, Color.red, 8); - reportBuilder.AppendLine("未检测到地面,跳过"); + //Debug.DrawRay(EndPosition, Vector3.down*1.6f, Color.red, 8); + reportBuilder?.AppendLine("未检测到地面,跳过"); continue; //Debug.DrawRay(EndPosition, Vector3.down, Color.red, 8); } @@ -174,7 +240,7 @@ namespace BITKit end2.y -= 0.1f; if(UnityEngine.Physics.Linecast(start2,end2,out var downHit,layerMask)) { - reportBuilder.AppendLine($"检测到了障碍物{downHit.collider.name}"); + reportBuilder?.AppendLine($"检测到了障碍物{downHit.collider.name}"); //BIT4Log.Log(reportBuilder.ToString()); continue; @@ -186,8 +252,8 @@ namespace BITKit ray = new Ray(start, forward); if(hit.Raycast(ray,out colliderHit,8) is false) { - reportBuilder.AppendLine("未检测到正面,算法错误"); - Debug.DrawRay(ray.origin, ray.direction * 8, Color.red, 8); + reportBuilder?.AppendLine("未检测到正面,算法错误"); + //Debug.DrawRay(ray.origin, ray.direction * 8, Color.red, 8); continue; } @@ -200,14 +266,26 @@ namespace BITKit var lineDistance = Vector3.Distance(closeStart, closeEnd); if(lineDistance > maxVaultDistance) { - reportBuilder.AppendLine($"长度{lineDistance}超出可翻越距离{maxVaultDistance}"); + reportBuilder?.AppendLine($"长度{lineDistance}超出可翻越距离{maxVaultDistance}"); - Debug.DrawLine(closeStart,closeEnd, Color.yellow, 4); + //Debug.DrawLine(closeStart,closeEnd, Color.yellow, 4); //BIT4Log.Log(reportBuilder.ToString()); continue; } + if(Physics.Linecast(closeStart+Vector3.up*0.1f,closeEnd+Vector3.up*0.1f,out var _hit,layerMask)) + { + + //Debug.DrawLine(closeStart+Vector3.up*0.1f,_hit.point, Color.red, 4); + reportBuilder?.AppendLine("检测到了障碍物"); + continue; + } + else + { + //Debug.DrawLine(closeStart+Vector3.up*0.1f,closeEnd+Vector3.up*0.1f, Color.green, 4); + } + vector3 = colliderHit.point; @@ -215,14 +293,19 @@ namespace BITKit vector3 += colliderHit.normal * 0.4f; - reportBuilder.AppendLine(); + reportBuilder?.AppendLine(); + if(reportBuilder is not null) BIT4Log.Log(reportBuilder.ToString()); + + CurrentPoint = vector3; + Collider = hit; return true; } - reportBuilder.AppendLine($"failed"); + reportBuilder?.AppendLine($"failed"); + if(reportBuilder is not null) BIT4Log.Log(reportBuilder.ToString()); vector3 = default; diff --git a/Assets/BITKit/Unity/Scripts/Quadtree/NodeBase.cs b/Assets/BITKit/Unity/Scripts/Quadtree/NodeBase.cs index 82fb7d5d..a01caf22 100644 --- a/Assets/BITKit/Unity/Scripts/Quadtree/NodeBase.cs +++ b/Assets/BITKit/Unity/Scripts/Quadtree/NodeBase.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.Linq; using UnityEngine; +#if UNITY_EDITOR using UnityEditor; +#endif namespace Quadtree { @@ -405,10 +407,12 @@ namespace Quadtree public void DrawBounds(bool displayNumberOfItems = false) { +#if UNITY_EDITOR if (displayNumberOfItems) Handles.Label(Bounds.center, _items.Count.ToString()); Gizmos.DrawWireCube(Bounds.center, Bounds.size); + #endif foreach (var subNode in SubNodes) subNode.DrawBounds(displayNumberOfItems); } diff --git a/Assets/BITKit/Unity/Scripts/Sensor/AudioSensor.cs b/Assets/BITKit/Unity/Scripts/Sensor/AudioSensor.cs index 5200a24f..aeed0df9 100644 --- a/Assets/BITKit/Unity/Scripts/Sensor/AudioSensor.cs +++ b/Assets/BITKit/Unity/Scripts/Sensor/AudioSensor.cs @@ -5,7 +5,6 @@ using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.Pool; using System.Linq; -using UnityEditor.Search; namespace BITKit.Sensors { @@ -19,6 +18,8 @@ namespace BITKit.Sensors [SerializeField] private bool autoUpdate; [SerializeField]private float radius; private readonly CacheList cache = new(); + private readonly CacheList data = new(); + public AudioSensorService.AudioSensorData[] Noises => data.ValueArray; private void OnEnable() { Id = GetInstanceID(); @@ -32,14 +33,19 @@ namespace BITKit.Sensors { var position = transform.position; cache.Clear(); + data.Clear(); foreach (var x in AudioSensorService.QuadtreeRoot.Find(new Bounds(position, Vector3.one * radius))) { - var distance = Vector3.Distance(position, x.Position); - if(distance>radius) continue; - cache.Add(x.Transform); + var distance = Vector3.Distance(position, x.Position); + if (distance > radius) continue; + if (x.Transform) + cache.Add(x.Transform); + data.Add(x); } + return UniTask.CompletedTask; } + public HashSet Ignores { get; } = new(); public int Id { get; set; } public IEnumerable Get() => cache.ValueArray; public bool IsValid(Collider _collider) => false; diff --git a/Assets/BITKit/Unity/Scripts/Sensor/AudioSensorService.cs b/Assets/BITKit/Unity/Scripts/Sensor/AudioSensorService.cs index 2718f4da..b98f0380 100644 --- a/Assets/BITKit/Unity/Scripts/Sensor/AudioSensorService.cs +++ b/Assets/BITKit/Unity/Scripts/Sensor/AudioSensorService.cs @@ -10,6 +10,7 @@ using UnityEngine.Pool; namespace BITKit.Sensors { + public struct ClassicNoise{} public class AudioSensorService : MonoBehaviour { public class AudioSensorData:IItem> @@ -20,6 +21,7 @@ namespace BITKit.Sensors public Transform Transform; public Bounds Bounds; public ITag Tag; + public object NoiseType; public Bounds GetBounds() => Bounds; public Node ParentNode { get; set; } public void QuadTree_Root_Initialized(IQuadtreeRoot> root){} @@ -29,20 +31,25 @@ namespace BITKit.Sensors private static Pool pool = new(()=>new(), x=>{}, 1000); private static int count; - public static async void MakeNoise(Vector3 position,Transform transform) + + public static async void MakeNoise(Vector3 position, Transform transform, float radius = 1, + object noiseType = null) { var data = pool.Take(); data.Id = count++; data.Position = position; data.Transform = transform; - data.Bounds = new Bounds(position, Vector3.one *1); - data.Tag = transform.GetComponent(); + data.Bounds = new Bounds(position, Vector3.one * 1); + if (transform) + data.Tag = transform.GetComponent(); + data.Radius = radius; QuadtreeRoot.Insert(data); await UniTask.Delay(3000); if (disposed) return; QuadtreeRoot.Remove(data); pool.Return(data); } + private static bool disposed; [SerializeReference, SubclassSelector] private ITicker ticker; private void Start() diff --git a/Assets/BITKit/Unity/Scripts/Sensor/Core/Sensor.cs b/Assets/BITKit/Unity/Scripts/Sensor/Core/Sensor.cs index 983ad286..f3626836 100644 --- a/Assets/BITKit/Unity/Scripts/Sensor/Core/Sensor.cs +++ b/Assets/BITKit/Unity/Scripts/Sensor/Core/Sensor.cs @@ -47,6 +47,7 @@ namespace BITKit.Sensors /// /// UniTask Execute(float delta); + HashSet Ignores{ get; } } [Serializable] @@ -74,6 +75,7 @@ namespace BITKit.Sensors { return _sensorImplementation.Execute(delta); } + public HashSet Ignores => _sensorImplementation.Ignores; } [System.Serializable] public class SensorMonoProxy:ISensor @@ -101,6 +103,7 @@ namespace BITKit.Sensors { return _sensorImplementation.Execute(delta); } + public HashSet Ignores => _sensorImplementation.Ignores; } public abstract class Sensor : MonoBehaviour, ISensor { @@ -109,13 +112,11 @@ namespace BITKit.Sensors public bool autoUpdate; [Header(Constant.Header.Gameobjects)] public Collider[] ignoreColliders; - [Header(Constant.Header.InternalVariables)] - [SerializeField,ReadOnly] - public Transform[] detected = Array.Empty(); public abstract IEnumerable Get(); public abstract bool IsValid(Collider _collider); public abstract float GetDistance(); public virtual UniTask Execute(float delta)=>UniTask.CompletedTask; + public HashSet Ignores { get; } = new(); public int Id { get; private set; } bool ISensor.AutoUpdate => autoUpdate; diff --git a/Assets/BITKit/Unity/Scripts/Sensor/RangeSensor.cs b/Assets/BITKit/Unity/Scripts/Sensor/RangeSensor.cs index 54262d4f..b9628df1 100644 --- a/Assets/BITKit/Unity/Scripts/Sensor/RangeSensor.cs +++ b/Assets/BITKit/Unity/Scripts/Sensor/RangeSensor.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using UnityEngine; using System.Linq; using Cysharp.Threading.Tasks; +using Unity.Mathematics; using UnityEngine.Jobs; using UnityEngine.Pool; using UnityEngine.Profiling; @@ -13,19 +14,23 @@ namespace BITKit.Sensors { public class RangeSensor : Sensor { - [Header(Constant.Header.Settings)] public float radius; - public int fov; - public bool requireSight; - - [Header(Constant.Header.Settings)] public LayerMask blockLayer; - - [Header(Constant.Header.Debug)] [Header(Constant.Header.InternalVariables)] - private FrameUpdate frameUpdater; + [Header(Constant.Header.Settings)] + [SerializeField] private float radius; + [SerializeField] private float detectedHeightWeight=0.5f; + [Header(Constant.Header.Optional)] + [SerializeField] private Optional fov; + [SerializeField] private Optional requireSight; + [SerializeField] private Optional perceptionRadius; + public float DetectedHeightWeight + { + get=>detectedHeightWeight; + set=>detectedHeightWeight=value; + } private readonly Collider[] colliders = new Collider[32]; - private RaycastHit[] hits = new RaycastHit[32]; - private readonly HashSet tempHashSet = new(); - + private readonly RaycastHit[] hits = new RaycastHit[32]; + private float _delta; + public override IEnumerable Get() { if (!_detectedDoubleBuffer.TryGetRelease(out var newRelease)) return _detectedBuffer; @@ -40,7 +45,7 @@ namespace BITKit.Sensors public override UniTask Execute(float delta) { - tempHashSet.Clear(); + _delta = delta; var length = Physics.OverlapSphereNonAlloc(Transform.position, radius, colliders, detectLayer); Profiler.BeginSample("Filter Detected Colliders"); var _newDetected = from x in colliders.Take(length) where IsValid(x) select x.transform; @@ -53,10 +58,21 @@ namespace BITKit.Sensors { switch (_collider) { + case var _ when Ignores.Contains(_collider.GetInstanceID()): case var _ when ignoreColliders.Contains(_collider): return false; - case var _ when fov > 0 && CheckFov(ref _collider) is false: - case var _ when requireSight && CheckSight(ref _collider) is false: + } + + if (perceptionRadius.Allow) + { + var distance = Vector3.Distance(Transform.position, _collider.bounds.center); + if(distance<=perceptionRadius.Value) return !requireSight.Allow || CheckSight(ref _collider); + } + switch (_collider) + { + + case var _ when fov.Allow && CheckFov(ref _collider) is false: + case var _ when requireSight.Allow && CheckSight(ref _collider) is false: return false; default: return true; @@ -75,23 +91,21 @@ namespace BITKit.Sensors private bool CheckSight(ref Collider _collider) { - if (!requireSight) return false; - var position = _collider.bounds.center; - //是检测bounds的顶部 - position.y += _collider.bounds.extents.y; - var location = new Location(Transform); + var bounds = _collider.bounds; + var position = bounds.center; + position.y += bounds.size.y * detectedHeightWeight /2; + var selfPosition = Transform.position; var length = Physics.RaycastNonAlloc( - location.position, - position - location, + selfPosition, + position - selfPosition, hits, - Vector3.Distance(location, position), - blockLayer + Vector3.Distance(selfPosition, position), + requireSight.Value ); - switch (length) { case 0: - Debug.DrawLine(location, position, Color.green, 1); + Debug.DrawLine(selfPosition, position, Color.green,_delta); return true; case 1: return hits[0].collider == _collider; @@ -107,7 +121,8 @@ namespace BITKit.Sensors var result = ignoreColliders.Contains(x.collider) is false && x.collider != collider1; if (result) { - Debug.DrawLine(location, x.point, Color.red, 1); + Debug.DrawLine(selfPosition, x.point, Color.yellow,_delta); + Debug.DrawLine(selfPosition, position, Color.red,_delta); } return result; } diff --git a/Assets/BITKit/Unity/Scripts/Sensor/RaySensor.cs b/Assets/BITKit/Unity/Scripts/Sensor/RaySensor.cs index a8493314..6f86a841 100644 --- a/Assets/BITKit/Unity/Scripts/Sensor/RaySensor.cs +++ b/Assets/BITKit/Unity/Scripts/Sensor/RaySensor.cs @@ -2,7 +2,9 @@ using System; using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Text; using Cysharp.Threading.Tasks; +using Unity.Mathematics; using UnityEngine; namespace BITKit.Sensors { @@ -11,8 +13,11 @@ namespace BITKit.Sensors [Header(Constant.Header.Settings)] [SerializeField] private float radius = 0.16f; public float distance; - public override IEnumerable Get() => detected; + public override IEnumerable Get() => detected.ValueArray; private readonly RaycastHit[] raycasts = new RaycastHit[16]; + private readonly Queue<(Vector3,Vector3)> _drawGizmosQueue = new(); + private readonly CacheList detected = new(); + public override UniTask Execute(float delta) { var _transform = transform; @@ -28,25 +33,43 @@ namespace BITKit.Sensors } else { - var ray = new Ray(_transform.position,_transform.forward); + var ray = new Ray(_transform.position, _transform.forward); size = Physics.RaycastNonAlloc(ray, raycasts, distance, detectLayer); } - - detected = raycasts - .Take(size) - .Select(x => x.collider) - .Where(IsValid) - .Select(x=>x.transform) - .ToArray(); + //var reportBuilder = new StringBuilder(); + + detected.Clear(); + foreach (var hit in raycasts + .Take(size) + .Where(IsValid) + .OrderBy(ByDistance)) + { + detected.Add(hit.transform); + } + + //Debug.Log(reportBuilder); return UniTask.CompletedTask; + + float ByDistance(RaycastHit arg) + { + var x = Vector3.Distance(arg.point, position); + //_drawGizmosQueue.Enqueue(new(arg.collider.bounds.center, arg.point)); + //reportBuilder.AppendLine($"Name:{arg.collider.name},Distance:{x}"); + return x; + } } + + public bool IsValid(RaycastHit hit) => IsValid(hit.collider); public override bool IsValid(Collider _collider) => ignoreColliders.Contains(_collider) is false; public override float GetDistance() => distance; - private void Update() + + private void OnDrawGizmosSelected() { - if (autoUpdate) + while (_drawGizmosQueue.TryDequeue(out var p)) { - Execute(Time.deltaTime).Forget(); + var (closePoint, point) = p; + Gizmos.DrawWireCube(point,Vector3.one*0.01f); + Gizmos.DrawLine(closePoint,point); } } } diff --git a/Assets/BITKit/Unity/Scripts/Sensor/SensorQueue.cs b/Assets/BITKit/Unity/Scripts/Sensor/SensorQueue.cs index 6bdd9bf3..bcb1a912 100644 --- a/Assets/BITKit/Unity/Scripts/Sensor/SensorQueue.cs +++ b/Assets/BITKit/Unity/Scripts/Sensor/SensorQueue.cs @@ -16,8 +16,6 @@ namespace BITKit.Sensors [SerializeField,ReadOnly] private int _position; - private static int[] _keys; - public static void Register(int id,ISensor sensor) { Sensors.Add(id,sensor); @@ -33,7 +31,6 @@ namespace BITKit.Sensors IsDirty = true; } - [SerializeField] private MonoBehaviour[] sensors; [SerializeReference,SubclassSelector] private ITicker ticker; private bool _isBusy; @@ -56,9 +53,7 @@ namespace BITKit.Sensors if(IsDirty) { _position = 0; - _keys = Sensors.Where(IsEnabled).Select(x=>x.Key).ToArray(); IsDirty = false; - sensors = Sensors.Values.Where(IsEnabled).OfType().ToArray(); } if (Sensors.Count is 0) @@ -68,26 +63,22 @@ namespace BITKit.Sensors } var current = Sensors.ElementAt(_position++).Value; - var currentUpdateTime = LastDetectedTime.GetOrAdd(current.Id,Time.time); + if (current.AutoUpdate) + { + + var currentUpdateTime = LastDetectedTime.GetOrAdd(current.Id,Time.time); await current.Execute(Time.time-currentUpdateTime); - float UpdateValueFactory(int key, float old) => Time.time; LastDetectedTime.AddOrUpdate(current.Id,Time.time,UpdateValueFactory); - if (destroyCancellationToken.IsCancellationRequested) { - _isBusy = false; - return; + if (destroyCancellationToken.IsCancellationRequested) { + _isBusy = false; + return; + } } - _position %= Sensors.Count; _isBusy = false; - } - private bool IsEnabled(ISensor sensor) - { - return sensor.AutoUpdate; - } - private bool IsEnabled(KeyValuePair pair) - { - return pair.Value.AutoUpdate; + return; + float UpdateValueFactory(int key, float old) => Time.time; } } diff --git a/Assets/BITKit/Unity/Scripts/Sensor/Smart/SmartTargetSensor.cs b/Assets/BITKit/Unity/Scripts/Sensor/Smart/SmartTargetSensor.cs index 88746620..3513c74e 100644 --- a/Assets/BITKit/Unity/Scripts/Sensor/Smart/SmartTargetSensor.cs +++ b/Assets/BITKit/Unity/Scripts/Sensor/Smart/SmartTargetSensor.cs @@ -30,6 +30,7 @@ namespace BITKit.Sensors [SerializeField] private AudioSensor audioSensor; public int Id { get; set; } private readonly CacheList _detected=new(); + public HashSet Ignores { get; } = new(); private void OnEnable() { Id = GetInstanceID(); diff --git a/Assets/BITKit/Unity/Scripts/Sensor/TriggerSensor.cs b/Assets/BITKit/Unity/Scripts/Sensor/TriggerSensor.cs index abcff7f9..52ae3a35 100644 --- a/Assets/BITKit/Unity/Scripts/Sensor/TriggerSensor.cs +++ b/Assets/BITKit/Unity/Scripts/Sensor/TriggerSensor.cs @@ -28,6 +28,7 @@ namespace BITKit.Sensors [Header(Constant.Header.InternalVariables)] // ReSharper disable once FieldCanBeMadeReadOnly.Local private List detected = new(); + public HashSet Ignores { get; } = new(); private readonly Queue triggerEnterQueue = new(); private readonly Queue triggerExitQueue = new(); @@ -171,7 +172,7 @@ namespace BITKit.Sensors if (!agent || detectedContainer is null) return; if (BITAppForUnity.IsPlaying is false) return; detectedContainer.Clear(); - foreach (var x in agent.detected) + foreach (var x in agent.Get()) { ObjectField objectField = new() { diff --git a/Assets/BITKit/Unity/Scripts/UX/Chart/BITKit.UX.Chart.Runtime.asmdef b/Assets/BITKit/Unity/Scripts/UX/Chart/BITKit.UX.Chart.Runtime.asmdef index b6b8f394..863e4391 100644 --- a/Assets/BITKit/Unity/Scripts/UX/Chart/BITKit.UX.Chart.Runtime.asmdef +++ b/Assets/BITKit/Unity/Scripts/UX/Chart/BITKit.UX.Chart.Runtime.asmdef @@ -8,7 +8,8 @@ "GUID:49b49c76ee64f6b41bf28ef951cb0e50", "GUID:d8b63aba1907145bea998dd612889d6b", "GUID:6de01b04fa4e14662b03fa46366da151", - "GUID:f19bbd83e3c264a5680926bf75d7e494" + "GUID:f19bbd83e3c264a5680926bf75d7e494", + "GUID:1c2aa13aa706ffc49a1a0044cad55436" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Assets/BITKit/Unity/Scripts/UX/Chart/Test/SKPaintComponent.cs b/Assets/BITKit/Unity/Scripts/UX/Chart/Test/SKPaintComponent.cs deleted file mode 100644 index 86875066..00000000 --- a/Assets/BITKit/Unity/Scripts/UX/Chart/Test/SKPaintComponent.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using SkiaSharp; -using UnityEngine; - -namespace BITKit.UX -{ - public class SKPaintComponent : MonoBehaviour - { - [SerializeField] private Texture2D texture; - [SerializeField] private float[] data; - - [BIT] - private void Draw() - { - var info = new SKImageInfo( - width: 384, - height: 128, - colorType: SKColorType.Rgba8888, - alphaType: SKAlphaType.Premul - ); - - using var surface = SKSurface.Create(info); - - - using var canvas = surface.Canvas; - - //canvas.Clear(new Color32(31,31,31,255).ToSKColor()); - - using var linePaint = new SKPaint(); - linePaint.Color = new SKColor(255, 0, 0, 255); - linePaint.StrokeWidth = 8; - linePaint.IsAntialias = true; - linePaint.Style = SKPaintStyle.Stroke; - - using var helpLinePaint = new SKPaint(); - helpLinePaint.Color = new SKColor(200, 200, 200, 200); - helpLinePaint.StrokeWidth = 4; - helpLinePaint.Style = SKPaintStyle.Stroke; - - using var textPaint = new SKPaint(); - textPaint.TextAlign = SKTextAlign.Center; - textPaint.TextSize = 14; - textPaint.ColorF = new SKColor(0, 255, 0, 255); - - using var filePaint = new SKPaint(); - filePaint.Color = new SKColor(200, 200, 200, 200); - filePaint.Style=SKPaintStyle.Fill; - - var min = data.Min(); - var max = data.Max(); - - DoubleBuffer buffer = new(); - - var path = new SKPath { FillType = SKPathFillType.EvenOdd }; - - path.MoveTo(0,0); - path.LineTo(0,0); - - for (var i = 0; i < data.Length; i++) - { - var value = data[i]; - var posX = (float)info.Width / (data.Length - 1) * (i); - var d = max - min; - var p = (value - min) / d; - var poxY = info.Height * p; - - var currentPoint = new SKPoint(posX, poxY); - if (buffer.TryGetRelease(out var previousPoint)) - { - canvas.DrawLine(previousPoint, currentPoint, linePaint); - } - - canvas.DrawText( - value.ToString() - , currentPoint - , new SKFont( - SKTypeface.FromFile(@"D:\Iris\Documents\GitHub\iFactory-YL106.Unity\Assets\BITKit\Unity\Art\Fonts\TTF\Roboto\Roboto-Regular.ttf") - ), textPaint); - canvas.DrawLine(posX, 0, posX, poxY, helpLinePaint); - - path.LineTo(posX,poxY); - - buffer.Release(currentPoint); - } - - path.LineTo(info.Width,0); - path.Close(); - - - //canvas.DrawPath(path,filePaint); - - texture = info.ToTexture2D(surface); - } - } -} - diff --git a/Assets/BITKit/Unity/Scripts/UX/Chart/Test/BITKit.UX.Chart.Tests.asmdef b/Assets/BITKit/Unity/Scripts/UX/Painter/BITKit.UX.Painter.Runtime.asmdef similarity index 88% rename from Assets/BITKit/Unity/Scripts/UX/Chart/Test/BITKit.UX.Chart.Tests.asmdef rename to Assets/BITKit/Unity/Scripts/UX/Painter/BITKit.UX.Painter.Runtime.asmdef index 27085d9b..086a9147 100644 --- a/Assets/BITKit/Unity/Scripts/UX/Chart/Test/BITKit.UX.Chart.Tests.asmdef +++ b/Assets/BITKit/Unity/Scripts/UX/Painter/BITKit.UX.Painter.Runtime.asmdef @@ -1,5 +1,5 @@ { - "name": "BITKit.UX.Chart.Tests", + "name": "BITKit.UX.Painter.Runtime", "rootNamespace": "", "references": [ "GUID:14fe60d984bf9f84eac55c6ea033a8f4", @@ -9,7 +9,7 @@ "GUID:d8b63aba1907145bea998dd612889d6b", "GUID:6de01b04fa4e14662b03fa46366da151", "GUID:f19bbd83e3c264a5680926bf75d7e494", - "GUID:994a3fb33a5627740b0712e7c483cc1f" + "GUID:1c2aa13aa706ffc49a1a0044cad55436" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Assets/BITKit/Unity/Scripts/UX/Painter/SkiaPainter.cs b/Assets/BITKit/Unity/Scripts/UX/Painter/SkiaPainter.cs new file mode 100644 index 00000000..382c0a86 --- /dev/null +++ b/Assets/BITKit/Unity/Scripts/UX/Painter/SkiaPainter.cs @@ -0,0 +1,104 @@ +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Net.Sockets.Kcp; +using SkiaSharp; +using UnityEngine; +using UnityEngine.UIElements; + +namespace BITKit.UX +{ + public class SkiaPainter : VisualElement + { + public new class UxmlFactory : UxmlFactory { } + public SkiaPainter() + { + RegisterCallback(OnGeometryChanged); + RegisterCallback(OnMouseDown); + RegisterCallback(OnMouseUp); + RegisterCallback(OnMouseMove); + } + private bool _isPainting; + private readonly List _points = new(); + private SKImageInfo _info; + private SKCanvas _canvas; + private SKSurface _surface; + private Rect _rect; + private readonly SKPaint _linePaint = new() + { + Style = SKPaintStyle.Stroke, + Color = SKColors.Red, + StrokeWidth = 5 + }; + public void ClearCanvas() + { + _points.Clear(); + Rebuild(); + } + private void OnMouseMove(MouseMoveEvent evt) + { + if (_isPainting is false) return; + var pos = evt.localMousePosition; + pos.y = layout.height - pos.y; + if (_rect.Contains(pos) is false) + { + var last = _points.LastOrDefault(); + if (last == default) return; + _points.Add(default); + return; + } + _points.Add(pos); + Rebuild(); + } + + private void OnMouseUp(MouseUpEvent evt) + { + _isPainting = false; + var last = _points.LastOrDefault(); + if (last != default) + _points.Add(default); + } + + private void OnMouseDown(MouseDownEvent evt) + { + _isPainting = true; + } + private void OnGeometryChanged(GeometryChangedEvent evt) + { + if(float.IsNaN(layout.width) || float.IsNaN(layout.height)) + return; + _linePaint.Color = resolvedStyle.color.ToSKColor(); + _surface?.Dispose(); + _info = new SKImageInfo((int)layout.width, (int)layout.height); + _surface = SKSurface.Create(_info); + _canvas = _surface.Canvas; + _rect = new Rect(0, 0, layout.width, layout.height); + Rebuild(); + } + private void Rebuild() + { + if (_canvas is null) return; + _canvas.Clear(); + DoubleBuffer buffer = new(); + foreach (var pos in _points) + { + if (pos == default) + { + buffer.Clear(); + } + else + { + if (buffer.TryGetRelease(out var previousPoint)) + { + _canvas.DrawLine(previousPoint.x, previousPoint.y, pos.x, pos.y, _linePaint); + } + buffer.Release(pos); + } + } + var texture = _info.ToTexture2D(_surface); + style.backgroundImage = texture; + } + public string Base64 => _surface?.GetBase64(); + } +} + diff --git a/Assets/BITKit/Unity/Scripts/Utility/Extensions.cs b/Assets/BITKit/Unity/Scripts/Utility/Extensions.cs index 4ed00157..caf9939f 100644 --- a/Assets/BITKit/Unity/Scripts/Utility/Extensions.cs +++ b/Assets/BITKit/Unity/Scripts/Utility/Extensions.cs @@ -4,17 +4,12 @@ using UnityEngine; using UnityEngine.Events; using System.Linq; using System.Reflection; -using System.IO; -using System.Runtime.CompilerServices; -using UnityEngine.Networking; using System; using System.Threading.Tasks; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Linq; using System.Text; -using System.IO.Compression; -using System.Data; using UnityEngine.UIElements; namespace BITKit { @@ -402,18 +397,6 @@ namespace BITKit text = text.Remove(0, text.Split('\n')[0].Length + 1); return text; } - public static TaskAwaiter GetAwaiter(this AsyncOperation asyncOp) - { - var tcs = new TaskCompletionSource(); - asyncOp.completed += obj => { tcs.SetResult(null); }; - return ((Task)tcs.Task).GetAwaiter(); - } - public static TaskAwaiter GetAwaiter(this System.Action action) - { - var tcs = new TaskCompletionSource(); - action += () => { tcs.SetResult(null); }; - return ((Task)tcs.Task).GetAwaiter(); - } public static float GetDifference(this IEnumerable self) { return self.Max() - self.Min(); @@ -665,13 +648,32 @@ namespace BITKit public static Vector2 GetScreenPosition(this VisualElement self, Vector3 worldPosition) { - var pos = RuntimePanelUtils - .CameraTransformWorldToPanel(self.panel, worldPosition, Camera.main); + try + { + var panel = self.panel; + if (panel is null) + { + panel = self.parent.panel; + } - pos.x -= self.layout.width / 2; - pos.y -= self.layout.height / 2; + if (panel is null) + { + panel = self.parent.parent.panel; + } - return pos; + var pos = RuntimePanelUtils + .CameraTransformWorldToPanel(panel, worldPosition, Camera.main); + + pos.x -= self.layout.width / 2; + pos.y -= self.layout.height / 2; + + return pos; + } + catch (Exception e) + { + Debug.LogException(e); + } + return default; } public static Vector2 GetPosition(this VisualElement self) diff --git a/Assets/BITKit/Unity/Scripts/WorldChunk/ChunkBehaviour.cs b/Assets/BITKit/Unity/Scripts/WorldChunk/ChunkBehaviour.cs index 6e237ff0..aa199e70 100644 --- a/Assets/BITKit/Unity/Scripts/WorldChunk/ChunkBehaviour.cs +++ b/Assets/BITKit/Unity/Scripts/WorldChunk/ChunkBehaviour.cs @@ -16,7 +16,7 @@ namespace BITKit.OpenWorld base.OnLodChanged(oldLod, newLod); OnLodChangedEvent?.Invoke(oldLod,newLod); } - + #if UNITY_EDITOR [BIT] private void CalculateBounds() { @@ -41,6 +41,7 @@ namespace BITKit.OpenWorld offset = bounds.center - transform.position; EditorUtility.SetDirty(this); } + #endif } } diff --git a/Assets/BITKit/Unity/Scripts/WorldChunk/WorldTerrainBehaviour.cs b/Assets/BITKit/Unity/Scripts/WorldChunk/WorldTerrainBehaviour.cs index 35a6eba6..68085b24 100644 --- a/Assets/BITKit/Unity/Scripts/WorldChunk/WorldTerrainBehaviour.cs +++ b/Assets/BITKit/Unity/Scripts/WorldChunk/WorldTerrainBehaviour.cs @@ -3,7 +3,9 @@ using System.Collections; using System.Collections.Generic; using Cysharp.Threading.Tasks; using Quadtree; +#if UNITY_EDITOR using UnityEditor.SceneManagement; +#endif using UnityEngine; using UnityEngine.SceneManagement; using YooAsset; @@ -16,9 +18,7 @@ namespace BITKit.OpenWorld [SerializeField] private Vector3 size; [SerializeField] private Vector3 position; [SerializeField, ReadOnly] private int lod = -1; - private SceneHandle _sceneHandle; - [BIT] public async void Load() { diff --git a/Assets/BITKit/Unity/UX/Common/Common.uss b/Assets/BITKit/Unity/UX/Common/Common.uss index ab2f7f7d..e56cbbcf 100644 --- a/Assets/BITKit/Unity/UX/Common/Common.uss +++ b/Assets/BITKit/Unity/UX/Common/Common.uss @@ -314,3 +314,6 @@ Label { .armorPlate-container:hover { background-color: rgba(255, 255, 255, 0.78); } + +.flex-center { +} diff --git a/Assets/BITKit/UnityPluginsSupport/SkiaSharp/BITKit.Extensions.SkiaSharp.asmdef b/Assets/BITKit/UnityPluginsSupport/SkiaSharp/BITKit.Extensions.SkiaSharp.asmdef new file mode 100644 index 00000000..25e21a16 --- /dev/null +++ b/Assets/BITKit/UnityPluginsSupport/SkiaSharp/BITKit.Extensions.SkiaSharp.asmdef @@ -0,0 +1,24 @@ +{ + "name": "BITKit.Extensions.SkiaSharp", + "rootNamespace": "", + "references": [ + "GUID:14fe60d984bf9f84eac55c6ea033a8f4", + "GUID:6ef4ed8ff60a7aa4bb60a8030e6f4008", + "GUID:d525ad6bd40672747bde77962f1c401e", + "GUID:49b49c76ee64f6b41bf28ef951cb0e50", + "GUID:d8b63aba1907145bea998dd612889d6b", + "GUID:6de01b04fa4e14662b03fa46366da151", + "GUID:f19bbd83e3c264a5680926bf75d7e494" + ], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [ + "_SkiaSharp" + ], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/BITKit/Unity/Scripts/UX/Chart/SkiaExtensions.cs b/Assets/BITKit/UnityPluginsSupport/SkiaSharp/SkiaExtensions.cs similarity index 61% rename from Assets/BITKit/Unity/Scripts/UX/Chart/SkiaExtensions.cs rename to Assets/BITKit/UnityPluginsSupport/SkiaSharp/SkiaExtensions.cs index f849a787..c466618b 100644 --- a/Assets/BITKit/Unity/Scripts/UX/Chart/SkiaExtensions.cs +++ b/Assets/BITKit/UnityPluginsSupport/SkiaSharp/SkiaExtensions.cs @@ -1,5 +1,8 @@ +using System; using System.Collections; using System.Collections.Generic; +using System.IO; +using System.Text; using SkiaSharp; using UnityEngine; @@ -31,5 +34,31 @@ namespace BITKit.UX { return new SKColor(color.r, color.g, color.b, color.a); } + public static string GetBase64(this SKSurface self) + { + try + { + using var image = self.Snapshot(); + using var data = image.Encode(SKEncodedImageFormat.Png, 50); + //using var stream = File.OpenWrite(exportPath.Value); + var ms = new MemoryStream(); + // save the data to a stream + data.SaveTo(ms); + + var bytes = ms.ToArray(); + + var base64 = Convert.ToBase64String(bytes); + + return "data:image/jpeg;base64," + base64; + } + catch (Exception e) + { + StringBuilder exceptionBuilder = new(); + exceptionBuilder.AppendLine($"Surface:{self is not null}"); + BIT4Log.LogException( new InGameException(exceptionBuilder.ToString(),e)); + throw; + } + + } } }