using System.Collections; using System.Collections.Generic; using System; using UnityEngine; using UnityEngine.Events; using UnityEngine.UIElements; using Sirenix.OdinInspector; namespace BITKit { public abstract class Provider : MonoBehaviour, IProvider { public virtual T Get() { throw new NotImplementedException(); } public abstract void Set(T obj); } public abstract class Provider : Provider, IProvider { public abstract T Get(); public abstract void Set(T t); public override void Set(Unknow obj) { if (obj is T t) { Set(t); } } } public abstract class BITAction : MonoBehaviour, IAction { public abstract void Excute(); } public interface ICustomInspector { VisualElement GetVisualElement(); } [System.Serializable] public struct FrameUpdate { float prevframe; bool updatedThisFrame; public static implicit operator bool(FrameUpdate self) { var updatedThisFrame = Utility.Time.time <= self.prevframe; if (updatedThisFrame) { return false; } else { self.prevframe = Utility.Time.time; return true; } } } [System.Serializable] public class CompletionRate { public IntervalUpdate resetInterval = new(1); int requestCount; int successCount; public float rate; public int resetWhen = 64; public static implicit operator float(CompletionRate cr) { return cr.rate; } public void Get() { requestCount++; } public void Release() { successCount++; rate = (float)successCount / (float)requestCount; if (requestCount > resetWhen) { requestCount = successCount = 0; } } } [System.Serializable] public class Counter { public int count; int currentCount; public IntervalUpdate updater = new(1); public static implicit operator int(Counter self) => self.Get(); public int Excute() { if (updater) { count = currentCount; currentCount = 0; } currentCount++; return count; } public int Get() => currentCount; } [System.Serializable] public class IntervalUpdate { public IntervalUpdate(float updateInterval = 0) { this.updateInterval = updateInterval; } public bool enable = true; public float updateInterval; private double enableUpdateTime; public bool canUpdate => (Utility.Time.timeAsDouble >= enableUpdateTime); private bool canUpdateThisFrame; public event Action onSetActive; public static implicit operator bool(IntervalUpdate value) { return value is not null && value.CanUpdate(); } public static implicit operator float(IntervalUpdate value) { return value is not null ? value.updateInterval : 0; } public bool CanUpdate() { canUpdateThisFrame = canUpdate; if (canUpdate) { Reset(); } return enable && canUpdateThisFrame; } public float GetDuration() { var duration = (float)(Utility.Time.timeAsDouble - enableUpdateTime); //duration = duration.Round(2); return duration; } public void Reset(bool immediately = false) { enableUpdateTime = Utility.Time.timeAsDouble + (immediately ? 0 : updateInterval); } public void AddDelay(float value) { Reset(); enableUpdateTime += value; } public void SetActive(bool active) { enable = active; onSetActive?.Invoke(active); } } public struct Location { public Location(Transform transform, bool local = false) { if (local) { position = transform.localPosition; rotation = transform.localRotation; } else { position = transform.position; rotation = transform.rotation; } forward = transform.forward; } public Location(Component component) { var transform = component.transform; position = transform.position; rotation = transform.rotation; forward = transform.forward; } public Vector3 position; public Vector3 forward; public Quaternion rotation; public Location Set(Vector3 value) { position = value; return this; } public Location Set(Quaternion value) { rotation = value; return this; } public Location Set(Transform value, bool isLocal) { if (isLocal) { position = value.localPosition; rotation = value.localRotation; } else { Set(value); } return this; } public Location Set(Transform value) { position = value.position; rotation = value.rotation; return this; } public static Location Lerp(Location a, Location b, float t) { if (Quaternion.Dot(a, a) < Quaternion.kEpsilon) a.rotation = Quaternion.identity; if (Quaternion.Dot(b, b) < Quaternion.kEpsilon) b.rotation = Quaternion.identity; return new() { position = Vector3.Lerp(a.position, b.position, t), rotation = Quaternion.Lerp(a.rotation, b.rotation, t) }; } public static implicit operator Vector3(Location self) { return self.position; } public static implicit operator Quaternion(Location self) { return self.rotation; } public static Location operator +(Location self, Location b) { return new() { position = self.position + b.position, rotation = Quaternion.Euler(self.rotation.eulerAngles + b.rotation.eulerAngles), }; } public static Location operator -(Location self, Location b) { return new() { position = self.position - b.position, rotation = Quaternion.Euler(self.rotation.eulerAngles - b.rotation.eulerAngles), }; } public static Location operator *(Location self, float weight) { return new() { position = self.position * weight, rotation = Quaternion.Euler(self.rotation.eulerAngles * weight), }; } public static Location operator /(Location self, float weight) { return new() { position = self.position / weight, rotation = Quaternion.Euler(self.rotation.eulerAngles / weight), }; } public bool isNull { get { return position == Vector3.zero && rotation == Quaternion.identity; } } } }