Compare commits

..

No commits in common. "main" and "1.8" have entirely different histories.
main ... 1.8

35 changed files with 269 additions and 555 deletions

View File

@ -3,15 +3,12 @@
namespace BITKit
{
[AttributeUsage(AttributeTargets.Method)]
public class BITCommandAttribute : Attribute
{
}
public class BITCommandAttribute : Attribute { }
/// <summary>
/// 自动注入依赖
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class InjectAttribute : Attribute
[AttributeUsage(AttributeTargets.Field)]
public class InjectAttribute : System.Attribute
{
public static void Clear(object obj)
{

View File

@ -125,29 +125,6 @@ namespace BITKit
/// <param name="obj"></param>
public static void Inject(object obj)
{
foreach (var propertyInfo in obj.GetType().GetProperties(ReflectionHelper.Flags))
{
try
{
if (propertyInfo.GetCustomAttribute<ObsoleteAttribute>() is null &&
propertyInfo.GetCustomAttribute<InjectAttribute>() is not null)
{
lock (dictionary)
{
if(dictionary!.TryGetValue(propertyInfo.PropertyType,out var value))
{
BIT4Log.Log<DI>($"已为{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

View File

@ -15,7 +15,7 @@ namespace BITKit.Entities
/// 等待初始化完成,通常用于其他系统需要等待实体初始化完成
/// </summary>
void WaitForInitializationComplete();
int Id { get; }
ulong Id { get; }
CancellationToken CancellationToken { get; }
bool TryGetComponent<T>(out T component);
IEntityComponent[] Components { get; }
@ -81,18 +81,18 @@ namespace BITKit.Entities
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
IEntity Get(int id);
IEntity Get(ulong id);
/// <summary>
/// 尝试通过Id获取Entity
/// </summary>
/// <param name="id"></param>
/// <param name="entity"></param>
/// <returns></returns>
bool TryGetEntity(int id, out IEntity entity);
bool TryGetEntity(ulong id, out IEntity entity);
/// <summary>
/// 通过Id获取或添加Entity
/// </summary>
IEntity GetOrAdd(int id,Func<int,IEntity> factory);
IEntity GetOrAdd(ulong id,Func<ulong,IEntity> factory);
/// <summary>
/// 查询Entity,例如

View File

@ -220,6 +220,7 @@ namespace BITKit.Mod
private static Thread _Thread;
private static bool _IsRunning;
private static bool _IsLocked;
private static AppDomain _ModDomain;
public static void Initialize()
{
@ -240,6 +241,8 @@ namespace BITKit.Mod
try
{
_ModDomain = AppDomain.CreateDomain("ModDomain");
var modPath = Path.Combine(Environment.CurrentDirectory, "Mods\\");
PathHelper.EnsureDirectoryCreated(modPath);
var directoryInfo = new DirectoryInfo(modPath);
@ -380,6 +383,7 @@ namespace BITKit.Mod
_UnRegisterQueue.Clear();
Mods = Array.Empty<IMod>();
_InstalledMods.Clear();
AppDomain.Unload(_ModDomain);
}
catch (Exception e)
{

View File

@ -41,15 +41,6 @@
"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",
@ -579,17 +570,6 @@
"action": "Inspect",
"isComposite": false,
"isPartOfComposite": false
},
{
"name": "",
"id": "a533436d-c3bf-4cb3-93b2-1ca02791e6d1",
"path": "<Keyboard>/leftCtrl",
"interactions": "Press,Hold",
"processors": "",
"groups": "",
"action": "Crawl",
"isComposite": false,
"isPartOfComposite": false
}
]
},

View File

@ -6,10 +6,10 @@ namespace BITKit
public class AnimatorHelper : MonoBehaviour
{
[SerializeField] private Transform root;
[SerializeField] private bool allowAnimatorMove;
private void OnAnimatorMove()
{
if (root && allowAnimatorMove)
if (root)
root.SendMessageUpwards(nameof(OnAnimatorMove),SendMessageOptions.DontRequireReceiver);
}
private void AIAnimationEvent(string actionName)

View File

@ -62,7 +62,6 @@ namespace BITKit.Entities
/// </summary>
public interface IEntityMovement:IStateMachine<IEntityMovementState>
{
Vector3 Size => Vector3.one;
float ReferenceSpeed => 2.5f;
Vector3 Position { get; set; }
Quaternion Rotation { get; set; }
@ -139,6 +138,5 @@ namespace BITKit.Entities
void BeforeUpdateMovement(float deltaTime);
void AfterUpdateMovement(float deltaTime);
void ExecuteCommand<T>(T command);
void DrawGizmos();
}
}

View File

@ -81,8 +81,8 @@ namespace BITKit.Entities
{
public override DamageMessage ReadBinary(BinaryReader reader)
{
UnityEntitiesService.TryGetEntity(reader.ReadInt32(),out var initiator);
UnityEntitiesService.TryGetEntity(reader.ReadInt32(),out var target);
UnityEntitiesService.TryGetEntity(reader.ReadUInt64(),out var initiator);
UnityEntitiesService.TryGetEntity(reader.ReadUInt64(),out var target);
return new DamageMessage()
{
Initiator = initiator as Entity,

View File

@ -3,9 +3,7 @@ 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
@ -16,7 +14,6 @@ namespace BITKit
[SerializeField] private EntityHitbox[] hitboxes;
[SerializeReference,SubclassSelector] private IReference[] tagReferences;
#if UNITY_EDITOR
[BIT]
private void Build()
{
@ -76,6 +73,5 @@ namespace BITKit
}
EditorUtility.SetDirty(this);
}
#endif
}
}

View File

@ -20,7 +20,7 @@ namespace BITKit.Entities
private readonly GenericEvent genericEvent = new();
public int Id { get; set; }
public ulong Id { get; set; }
public CancellationToken CancellationToken { get; private set; }
public IEntityBehavior[] Behaviors { get;private set; }
public IEntityComponent[] Components => Behaviors.Cast<IEntityComponent>().ToArray();
@ -33,43 +33,9 @@ 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<InjectAttribute>(true) is not null))
{
var type = propertyInfo.PropertyType;
var attribute = propertyInfo.GetCustomAttribute<InjectAttribute>();
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<Entity>($"{name}未找到{obj.GetType().Name}需要的{type.FullName}");
}
}
foreach (var fieldInfo in obj
.GetType()
.GetFields(ReflectionHelper.Flags)
.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(fieldInfo=>fieldInfo.GetCustomAttribute<InjectAttribute>(true) is not null))
{
var type = fieldInfo.FieldType;
@ -131,7 +97,7 @@ namespace BITKit.Entities
private void Awake()
{
if (Id.IsDefault())
Id = GetInstanceID();
Id = (ulong)Guid.NewGuid().GetHashCode();
CancellationToken = gameObject.GetCancellationTokenOnDestroy();
Set(CancellationToken);
}

View File

@ -48,13 +48,6 @@ namespace BITKit.Entities
stateMachine.Initialize();
}
}
public override void OnDestroyComponent()
{
base.OnDestroyComponent();
CurrentState?.OnStateExit(CurrentState,null);
}
void IStateMachine<T>.Initialize()
{
stateMachine.Initialize();

View File

@ -38,10 +38,10 @@ public class UnityEntitiesServiceSingleton:IEntitiesService
public CancellationToken CancellationToken => UnityEntitiesService.CancellationToken;
public IEntity Get(int id) => UnityEntitiesService.Get(id);
public bool TryGetEntity(int id, out IEntity entity) => UnityEntitiesService.TryGetEntity(id, out entity);
public IEntity Get(ulong id) => UnityEntitiesService.Get(id);
public bool TryGetEntity(ulong id, out IEntity entity) => UnityEntitiesService.TryGetEntity(id, out entity);
public IEntity GetOrAdd(int id, Func<int, IEntity> factory)=>UnityEntitiesService.GetOrAdd(id,factory);
public IEntity GetOrAdd(ulong id, Func<ulong, IEntity> factory)=>UnityEntitiesService.GetOrAdd(id,factory);
public IEntity[] Query<T>()
@ -85,7 +85,7 @@ public class UnityEntitiesService : MonoBehaviour,IEntitiesService
return false;
}
public static CancellationToken CancellationToken;
private static readonly ConcurrentDictionary<int,IEntity> Dictionary=new();
private static readonly ConcurrentDictionary<ulong,IEntity> Dictionary=new();
private static readonly Queue<IEntity> RegisterQueue = new();
private static readonly Queue<IEntity> UnRegisterQueue = new();
private void Awake()
@ -126,18 +126,18 @@ public class UnityEntitiesService : MonoBehaviour,IEntitiesService
}
CancellationToken IEntitiesService.CancellationToken => CancellationToken;
public static IEntity Get(int id)=>Dictionary[id];
IEntity IEntitiesService.Get(int id)=>Get(id);
public static bool TryGetEntity(int id, out IEntity entity)
public static IEntity Get(ulong id)=>Dictionary[id];
IEntity IEntitiesService.Get(ulong id)=>Get(id);
public static bool TryGetEntity(ulong id, out IEntity entity)
{
return Dictionary.TryGetValue(id, out entity);
}
bool IEntitiesService.TryGetEntity(int id, out IEntity entity)=>TryGetEntity(id,out entity);
public static IEntity GetOrAdd(int id, Func<int, IEntity> factory)
bool IEntitiesService.TryGetEntity(ulong id, out IEntity entity)=>TryGetEntity(id,out entity);
public static IEntity GetOrAdd(ulong id, Func<ulong, IEntity> factory)
{
return Dictionary.GetOrAdd(id, factory);
}
IEntity IEntitiesService.GetOrAdd(int id, Func<int, IEntity> factory)=>GetOrAdd(id,factory);
IEntity IEntitiesService.GetOrAdd(ulong id, Func<ulong, IEntity> factory)=>GetOrAdd(id,factory);
IEntity[] IEntitiesService.Query<T>()=>Query<T>();
public static IEntity[] Query<T>()

View File

@ -7,14 +7,14 @@ namespace BITKit.Entities
{
public interface IdComponent
{
int Id { get; }
ulong Id { get; }
string Name { get; }
}
public class UnityIdComponent : EntityBehavior,IdComponent
{
[SerializeField] private int id;
[SerializeField] private ulong id;
[SerializeField] private string unityName;
public int Id => id;
public ulong Id => id;
public string Name => unityName;
public override void Initialize(IEntity _entity)
{

View File

@ -19,7 +19,7 @@ namespace BITKit.Entities
public struct EntitiesNetSyncBatchCommand
{
public int Length;
public int[] Ids;
public ulong[] 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.ReadInt32();
var id = reader.ReadUInt64();
var path = reader.ReadUInt64();
entitiesService.GetOrAdd(id, x => AddEntity(id, path)).TryGetComponent<IEntityBinaryHeader>(out var header);
header.Deserialize(reader);
@ -100,7 +100,7 @@ namespace BITKit.Entities
header.Deserialize(reader);
}
}
private static IEntity AddEntity(int id,ulong addressableId)
private static IEntity AddEntity(ulong id,ulong addressableId)
{
var entity = AddressableHelper.Get<GameObject>(addressableId);
var instance = Instantiate(entity).GetComponent<Entity>();
@ -146,7 +146,7 @@ namespace BITKit.Entities
var batchCommand = new EntitiesNetSyncBatchCommand()
{
Length = headers.Length,
Ids = new int[headers.Length],
Ids = new ulong[headers.Length],
AddressablePaths = new ulong[headers.Length],
Commands = new EntitiesNetSyncCommand[headers.Length]
};

View File

@ -15,8 +15,8 @@ namespace BITKit.Entities.Player
[SerializeField] private MonoStateMachine<T> stateMachine;
public override void OnAwake()
{
base.OnAwake();
stateMachine?.Initialize();
base.OnAwake();
}
public bool Enabled

View File

@ -3,121 +3,57 @@ 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);
}
[Serializable]
[System.Serializable]
public class GetClosePointFromCollider : IClosePoint
{
[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 Transform root;
public LayerMask layerMask;
public float distance;
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;
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 <detectedLength ; i++)
if (UnityEngine.Physics.Raycast(root.position, root.forward, out var raycastHit, distance, layerMask))
{
reportBuilder.AppendLine($"----------------------------检测到了碰撞体{_mainCollider[i].name}");
var collider = _mainCollider[i];
if (collider.isTrigger)
{
reportBuilder?.AppendLine("碰撞体是触发器");
continue;
}
var collider = raycastHit.collider;
if (collider.isTrigger) return false;
switch (collider)
{
case MeshCollider meshCollider:
if (meshCollider.convex is false)
{
reportBuilder?.AppendLine("MeshCollider未勾选Convex");
continue;
}
return false;
break;
}
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)
{
reportBuilder?.AppendLine("高度不足");
continue;
}
vector3 = collider.ClosestPoint(root.position + Vector3.up);
var top = collider.bounds.center + collider.bounds.extents;
var nextPos = position;
nextPos.y = collider.bounds.center.y;
if (collider.Raycast(new Ray(nextPos, transform.forward), out _, distance) is false)
if (Mathf.Abs(vector3.y - top.y) > 0.16f) return false;
if (UnityEngine.Physics.Linecast(root.position, vector3, out var raycastHit2, layerMask))
{
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;
}
if(raycastHit2.collider != collider)
return false;
};
var length = Physics.OverlapSphereNonAlloc(vector3, 0.01f, _colliders, layerMask);
switch (length)
foreach(var hit in UnityEngine.Physics.OverlapSphere(vector3, 0.1f, layerMask))
{
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;
if(hit!= collider)
return false;
}
Collider = collider;
vector3.y = top;
CurrentPoint = vector3;
reportBuilder.AppendLine("<color=green>成功</color>");
//BIT4Log.Log<GetClosePointFromCollider>(reportBuilder.ToString());
return true;
//return vector3.y >= collider.bounds.center.y + collider.bounds.extents.y;
//return true;
}
//BIT4Log.Log<GetClosePointFromCollider>(reportBuilder.ToString());
return false;
}
}
@ -138,7 +74,6 @@ namespace BITKit
public Vector3 StartPosition;
public Vector3 EndPosition;
public Vector3 CurrentPoint { get; set; }
public Collider Collider { get; set; }
private Rigidbody rigidbody;
@ -157,8 +92,7 @@ namespace BITKit
if (rigidbody.velocity.GetLength() < 0.1f) return false;
}
//var reportBuilder = new System.Text.StringBuilder();
StringBuilder reportBuilder=null;
var reportBuilder = new System.Text.StringBuilder();
var forward = root.forward;
var sourceStartPosition = groundReference.position;
@ -167,7 +101,7 @@ namespace BITKit
var collider = UnityEngine.Physics.OverlapSphere(startPosition, radius, layerMask);
reportBuilder?.AppendLine($"检测到了{collider.Length}个碰撞体");
reportBuilder.AppendLine($"检测到了{collider.Length}个碰撞体");
foreach (var hit in collider)
{
@ -178,12 +112,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;
}
@ -194,9 +128,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;
}
@ -217,15 +151,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);
}
@ -240,7 +174,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<GetVaultPointFromCollider>(reportBuilder.ToString());
continue;
@ -252,8 +186,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;
}
@ -266,26 +200,14 @@ 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<GetVaultPointFromCollider>(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;
@ -293,19 +215,14 @@ namespace BITKit
vector3 += colliderHit.normal * 0.4f;
reportBuilder?.AppendLine();
reportBuilder.AppendLine();
if(reportBuilder is not null)
BIT4Log.Log<GetVaultPointFromCollider>(reportBuilder.ToString());
CurrentPoint = vector3;
Collider = hit;
return true;
}
reportBuilder?.AppendLine($"failed");
reportBuilder.AppendLine($"failed");
if(reportBuilder is not null)
BIT4Log.Log<GetVaultPointFromCollider>(reportBuilder.ToString());
vector3 = default;

View File

@ -2,9 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace Quadtree
{
@ -407,12 +405,10 @@ 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);
}

View File

@ -5,6 +5,7 @@ using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Pool;
using System.Linq;
using UnityEditor.Search;
namespace BITKit.Sensors
{
@ -18,8 +19,6 @@ namespace BITKit.Sensors
[SerializeField] private bool autoUpdate;
[SerializeField]private float radius;
private readonly CacheList<Transform> cache = new();
private readonly CacheList<AudioSensorService.AudioSensorData> data = new();
public AudioSensorService.AudioSensorData[] Noises => data.ValueArray;
private void OnEnable()
{
Id = GetInstanceID();
@ -33,19 +32,14 @@ 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;
if (x.Transform)
cache.Add(x.Transform);
data.Add(x);
var distance = Vector3.Distance(position, x.Position);
if(distance>radius) continue;
cache.Add(x.Transform);
}
return UniTask.CompletedTask;
}
public HashSet<int> Ignores { get; } = new();
public int Id { get; set; }
public IEnumerable<Transform> Get() => cache.ValueArray;
public bool IsValid(Collider _collider) => false;

View File

@ -10,7 +10,6 @@ using UnityEngine.Pool;
namespace BITKit.Sensors
{
public struct ClassicNoise{}
public class AudioSensorService : MonoBehaviour
{
public class AudioSensorData:IItem<AudioSensorData,Node<AudioSensorData>>
@ -21,7 +20,6 @@ namespace BITKit.Sensors
public Transform Transform;
public Bounds Bounds;
public ITag Tag;
public object NoiseType;
public Bounds GetBounds() => Bounds;
public Node<AudioSensorData> ParentNode { get; set; }
public void QuadTree_Root_Initialized(IQuadtreeRoot<AudioSensorData, Node<AudioSensorData>> root){}
@ -31,25 +29,20 @@ namespace BITKit.Sensors
private static Pool<AudioSensorData> pool = new(()=>new(), x=>{}, 1000);
private static int count;
public static async void MakeNoise(Vector3 position, Transform transform, float radius = 1,
object noiseType = null)
public static async void MakeNoise(Vector3 position,Transform transform)
{
var data = pool.Take();
data.Id = count++;
data.Position = position;
data.Transform = transform;
data.Bounds = new Bounds(position, Vector3.one * 1);
if (transform)
data.Tag = transform.GetComponent<ITag>();
data.Radius = radius;
data.Bounds = new Bounds(position, Vector3.one *1);
data.Tag = transform.GetComponent<ITag>();
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()

View File

@ -47,7 +47,6 @@ namespace BITKit.Sensors
/// </summary>
/// <returns></returns>
UniTask Execute(float delta);
HashSet<int> Ignores{ get; }
}
[Serializable]
@ -75,7 +74,6 @@ namespace BITKit.Sensors
{
return _sensorImplementation.Execute(delta);
}
public HashSet<int> Ignores => _sensorImplementation.Ignores;
}
[System.Serializable]
public class SensorMonoProxy:ISensor
@ -103,7 +101,6 @@ namespace BITKit.Sensors
{
return _sensorImplementation.Execute(delta);
}
public HashSet<int> Ignores => _sensorImplementation.Ignores;
}
public abstract class Sensor : MonoBehaviour, ISensor
{
@ -112,11 +109,13 @@ namespace BITKit.Sensors
public bool autoUpdate;
[Header(Constant.Header.Gameobjects)]
public Collider[] ignoreColliders;
[Header(Constant.Header.InternalVariables)]
[SerializeField,ReadOnly]
public Transform[] detected = Array.Empty<Transform>();
public abstract IEnumerable<Transform> Get();
public abstract bool IsValid(Collider _collider);
public abstract float GetDistance();
public virtual UniTask Execute(float delta)=>UniTask.CompletedTask;
public HashSet<int> Ignores { get; } = new();
public int Id { get; private set; }
bool ISensor.AutoUpdate => autoUpdate;

View File

@ -4,7 +4,6 @@ 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;
@ -14,23 +13,19 @@ namespace BITKit.Sensors
{
public class RangeSensor : Sensor
{
[Header(Constant.Header.Settings)]
[SerializeField] private float radius;
[SerializeField] private float detectedHeightWeight=0.5f;
[Header(Constant.Header.Optional)]
[SerializeField] private Optional<int> fov;
[SerializeField] private Optional<LayerMask> requireSight;
[SerializeField] private Optional<float> perceptionRadius;
[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;
public float DetectedHeightWeight
{
get=>detectedHeightWeight;
set=>detectedHeightWeight=value;
}
private readonly Collider[] colliders = new Collider[32];
private readonly RaycastHit[] hits = new RaycastHit[32];
private float _delta;
private RaycastHit[] hits = new RaycastHit[32];
private readonly HashSet<int> tempHashSet = new();
public override IEnumerable<Transform> Get()
{
if (!_detectedDoubleBuffer.TryGetRelease(out var newRelease)) return _detectedBuffer;
@ -45,7 +40,7 @@ namespace BITKit.Sensors
public override UniTask Execute(float delta)
{
_delta = delta;
tempHashSet.Clear();
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;
@ -58,21 +53,10 @@ namespace BITKit.Sensors
{
switch (_collider)
{
case var _ when Ignores.Contains(_collider.GetInstanceID()):
case var _ when ignoreColliders.Contains(_collider):
return 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:
case var _ when fov > 0 && CheckFov(ref _collider) is false:
case var _ when requireSight && CheckSight(ref _collider) is false:
return false;
default:
return true;
@ -91,21 +75,23 @@ namespace BITKit.Sensors
private bool CheckSight(ref Collider _collider)
{
var bounds = _collider.bounds;
var position = bounds.center;
position.y += bounds.size.y * detectedHeightWeight /2;
var selfPosition = Transform.position;
if (!requireSight) return false;
var position = _collider.bounds.center;
//是检测bounds的顶部
position.y += _collider.bounds.extents.y;
var location = new Location(Transform);
var length = Physics.RaycastNonAlloc(
selfPosition,
position - selfPosition,
location.position,
position - location,
hits,
Vector3.Distance(selfPosition, position),
requireSight.Value
Vector3.Distance(location, position),
blockLayer
);
switch (length)
{
case 0:
Debug.DrawLine(selfPosition, position, Color.green,_delta);
Debug.DrawLine(location, position, Color.green, 1);
return true;
case 1:
return hits[0].collider == _collider;
@ -121,8 +107,7 @@ namespace BITKit.Sensors
var result = ignoreColliders.Contains(x.collider) is false && x.collider != collider1;
if (result)
{
Debug.DrawLine(selfPosition, x.point, Color.yellow,_delta);
Debug.DrawLine(selfPosition, position, Color.red,_delta);
Debug.DrawLine(location, x.point, Color.red, 1);
}
return result;
}

View File

@ -2,9 +2,7 @@ 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
{
@ -13,11 +11,8 @@ namespace BITKit.Sensors
[Header(Constant.Header.Settings)]
[SerializeField] private float radius = 0.16f;
public float distance;
public override IEnumerable<Transform> Get() => detected.ValueArray;
public override IEnumerable<Transform> Get() => detected;
private readonly RaycastHit[] raycasts = new RaycastHit[16];
private readonly Queue<(Vector3,Vector3)> _drawGizmosQueue = new();
private readonly CacheList<Transform> detected = new();
public override UniTask Execute(float delta)
{
var _transform = transform;
@ -33,43 +28,25 @@ 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);
}
//var reportBuilder = new StringBuilder();
detected.Clear();
foreach (var hit in raycasts
.Take(size)
.Where(IsValid)
.OrderBy(ByDistance))
{
detected.Add(hit.transform);
}
//Debug.Log(reportBuilder);
detected = raycasts
.Take(size)
.Select(x => x.collider)
.Where(IsValid)
.Select(x=>x.transform)
.ToArray();
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 OnDrawGizmosSelected()
private void Update()
{
while (_drawGizmosQueue.TryDequeue(out var p))
if (autoUpdate)
{
var (closePoint, point) = p;
Gizmos.DrawWireCube(point,Vector3.one*0.01f);
Gizmos.DrawLine(closePoint,point);
Execute(Time.deltaTime).Forget();
}
}
}

View File

@ -16,6 +16,8 @@ namespace BITKit.Sensors
[SerializeField,ReadOnly] private int _position;
private static int[] _keys;
public static void Register(int id,ISensor sensor)
{
Sensors.Add(id,sensor);
@ -31,6 +33,7 @@ namespace BITKit.Sensors
IsDirty = true;
}
[SerializeField] private MonoBehaviour[] sensors;
[SerializeReference,SubclassSelector] private ITicker ticker;
private bool _isBusy;
@ -53,7 +56,9 @@ namespace BITKit.Sensors
if(IsDirty)
{
_position = 0;
_keys = Sensors.Where(IsEnabled).Select(x=>x.Key).ToArray();
IsDirty = false;
sensors = Sensors.Values.Where(IsEnabled).OfType<MonoBehaviour>().ToArray();
}
if (Sensors.Count is 0)
@ -63,22 +68,26 @@ namespace BITKit.Sensors
}
var current = Sensors.ElementAt(_position++).Value;
if (current.AutoUpdate)
{
var currentUpdateTime = LastDetectedTime.GetOrAdd(current.Id,Time.time);
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;
return;
float UpdateValueFactory(int key, float old) => Time.time;
}
private bool IsEnabled(ISensor sensor)
{
return sensor.AutoUpdate;
}
private bool IsEnabled(KeyValuePair<int,ISensor> pair)
{
return pair.Value.AutoUpdate;
}
}

View File

@ -30,7 +30,6 @@ namespace BITKit.Sensors
[SerializeField] private AudioSensor audioSensor;
public int Id { get; set; }
private readonly CacheList<Transform> _detected=new();
public HashSet<int> Ignores { get; } = new();
private void OnEnable()
{
Id = GetInstanceID();

View File

@ -28,7 +28,6 @@ namespace BITKit.Sensors
[Header(Constant.Header.InternalVariables)]
// ReSharper disable once FieldCanBeMadeReadOnly.Local
private List<Collider> detected = new();
public HashSet<int> Ignores { get; } = new();
private readonly Queue<Collider> triggerEnterQueue = new();
private readonly Queue<Collider> triggerExitQueue = new();
@ -172,7 +171,7 @@ namespace BITKit.Sensors
if (!agent || detectedContainer is null) return;
if (BITAppForUnity.IsPlaying is false) return;
detectedContainer.Clear();
foreach (var x in agent.Get())
foreach (var x in agent.detected)
{
ObjectField objectField = new()
{

View File

@ -8,8 +8,7 @@
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
"GUID:d8b63aba1907145bea998dd612889d6b",
"GUID:6de01b04fa4e14662b03fa46366da151",
"GUID:f19bbd83e3c264a5680926bf75d7e494",
"GUID:1c2aa13aa706ffc49a1a0044cad55436"
"GUID:f19bbd83e3c264a5680926bf75d7e494"
],
"includePlatforms": [],
"excludePlatforms": [],

View File

@ -1,8 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using SkiaSharp;
using UnityEngine;
@ -34,31 +31,5 @@ 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;
}
}
}
}

View File

@ -1,5 +1,5 @@
{
"name": "BITKit.UX.Painter.Runtime",
"name": "BITKit.UX.Chart.Tests",
"rootNamespace": "",
"references": [
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
@ -9,7 +9,7 @@
"GUID:d8b63aba1907145bea998dd612889d6b",
"GUID:6de01b04fa4e14662b03fa46366da151",
"GUID:f19bbd83e3c264a5680926bf75d7e494",
"GUID:1c2aa13aa706ffc49a1a0044cad55436"
"GUID:994a3fb33a5627740b0712e7c483cc1f"
],
"includePlatforms": [],
"excludePlatforms": [],

View File

@ -0,0 +1,99 @@
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<SKPoint> 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);
}
}
}

View File

@ -1,104 +0,0 @@
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<SkiaPainter, UxmlTraits> { }
public SkiaPainter()
{
RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
RegisterCallback<MouseDownEvent>(OnMouseDown);
RegisterCallback<MouseUpEvent>(OnMouseUp);
RegisterCallback<MouseMoveEvent>(OnMouseMove);
}
private bool _isPainting;
private readonly List<Vector2> _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<Vector2> 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();
}
}

View File

@ -4,12 +4,17 @@ 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
{
@ -397,6 +402,18 @@ 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<object>();
asyncOp.completed += obj => { tcs.SetResult(null); };
return ((Task)tcs.Task).GetAwaiter();
}
public static TaskAwaiter GetAwaiter(this System.Action action)
{
var tcs = new TaskCompletionSource<object>();
action += () => { tcs.SetResult(null); };
return ((Task)tcs.Task).GetAwaiter();
}
public static float GetDifference(this IEnumerable<float> self)
{
return self.Max() - self.Min();
@ -648,32 +665,13 @@ namespace BITKit
public static Vector2 GetScreenPosition(this VisualElement self, Vector3 worldPosition)
{
try
{
var panel = self.panel;
if (panel is null)
{
panel = self.parent.panel;
}
var pos = RuntimePanelUtils
.CameraTransformWorldToPanel(self.panel, worldPosition, Camera.main);
if (panel is null)
{
panel = self.parent.parent.panel;
}
pos.x -= self.layout.width / 2;
pos.y -= self.layout.height / 2;
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;
return pos;
}
public static Vector2 GetPosition(this VisualElement self)

View File

@ -16,7 +16,7 @@ namespace BITKit.OpenWorld
base.OnLodChanged(oldLod, newLod);
OnLodChangedEvent?.Invoke(oldLod,newLod);
}
#if UNITY_EDITOR
[BIT]
private void CalculateBounds()
{
@ -41,7 +41,6 @@ namespace BITKit.OpenWorld
offset = bounds.center - transform.position;
EditorUtility.SetDirty(this);
}
#endif
}
}

View File

@ -3,9 +3,7 @@ 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;
@ -18,7 +16,9 @@ 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()
{

View File

@ -314,6 +314,3 @@ Label {
.armorPlate-container:hover {
background-color: rgba(255, 255, 255, 0.78);
}
.flex-center {
}

View File

@ -1,24 +0,0 @@
{
"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
}