1
This commit is contained in:
@@ -5,6 +5,7 @@ using UnityEngine.UIElements;
|
||||
using System.Reflection;
|
||||
using System;
|
||||
#if UNITY_EDITOR
|
||||
using MackySoft.SerializeReferenceExtensions.Editor;
|
||||
using UnityEditor;
|
||||
using Editor = UnityEditor.Editor;
|
||||
using UnityEditor.UIElements;
|
||||
@@ -16,6 +17,7 @@ namespace BITKit
|
||||
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
[CanEditMultipleObjects]
|
||||
[CustomEditor(typeof(MonoBehaviour),true)]
|
||||
public class MonoBehaviorInspector : BITInspector<MonoBehaviour>
|
||||
{
|
||||
@@ -46,6 +48,89 @@ namespace BITKit
|
||||
}
|
||||
return (T)field.GetValue(obj);
|
||||
}
|
||||
public static void FillDefaultInspector(VisualElement container, SerializedObject serializedObject, bool hideScript)
|
||||
{
|
||||
container.Clear();
|
||||
|
||||
if (serializedObject.targetObject is null)
|
||||
{
|
||||
var label = container.Create<Label>();
|
||||
label.text = "Null";
|
||||
return;
|
||||
}
|
||||
var property = serializedObject.GetIterator();
|
||||
|
||||
if (!property.NextVisible(true)) return; // Expand first child.
|
||||
do
|
||||
{
|
||||
if (property.propertyPath == "m_Script" && hideScript)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var type = serializedObject.targetObject.GetType();
|
||||
var fieldInfo = serializedObject.targetObject.GetType().GetField(property.propertyPath, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (fieldInfo is not null && Attribute.IsDefined(fieldInfo, typeof(ReadOnlyAttribute)))
|
||||
{
|
||||
var attribute = fieldInfo.GetCustomAttribute<ReadOnlyAttribute>();
|
||||
var _container = container.Create<VisualElement>();
|
||||
_container.style.flexDirection = FlexDirection.Row;
|
||||
|
||||
if (attribute.HideLabel is false)
|
||||
{
|
||||
_container.Create<Label>().text = $"{property.displayName}:";
|
||||
_container.Create<VisualElement>().style.flexGrow = 1;
|
||||
}
|
||||
_container.Create<Label>().bindingPath = property.propertyPath;
|
||||
}
|
||||
else if (PropertyDrawerCache.TryGetPropertyDrawer(type, out var drawer))
|
||||
{
|
||||
var ve = drawer.CreatePropertyGUI(property);
|
||||
container.Add(ve);
|
||||
}
|
||||
else
|
||||
{
|
||||
//var label = container.Create<Label>();
|
||||
//label.text =$"propertyPath:{property.propertyPath} fieldInfo:{fieldInfo} type:{type} fieldInfo:{fieldInfo}";
|
||||
var field = new PropertyField(property)
|
||||
{
|
||||
name = "PropertyField:" + property.propertyPath
|
||||
};
|
||||
if (property.propertyPath == "m_Script" && serializedObject.targetObject != null)
|
||||
{
|
||||
field.SetEnabled(false);
|
||||
}
|
||||
|
||||
container.Add(field);
|
||||
}
|
||||
// try
|
||||
// {
|
||||
// var header = type?.GetCustomAttribute<HeaderAttribute>();
|
||||
// if (header != null)
|
||||
// {
|
||||
// var label = new Label(header.header);
|
||||
// label.AddToClassList("subTitle");
|
||||
// container.Add(label);
|
||||
// }
|
||||
// }
|
||||
// catch (System.Exception e)
|
||||
// {
|
||||
// Debug.LogException(e);
|
||||
// }
|
||||
} while (property.NextVisible(false));
|
||||
|
||||
foreach (var method in serializedObject.targetObject.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
|
||||
{
|
||||
if (method.GetCustomAttribute<BITAttribute>() is null) continue;
|
||||
if (method.GetParameters().Length is not 0) continue;
|
||||
var button = new Button(() => method.Invoke(serializedObject.targetObject, null))
|
||||
{
|
||||
text = method.Name
|
||||
};
|
||||
|
||||
container.Add(button);
|
||||
}
|
||||
}
|
||||
}
|
||||
public class BITInspector<T> : Editor
|
||||
{
|
||||
@@ -113,96 +198,26 @@ namespace BITKit
|
||||
root.root.styleSheets.Add(css);
|
||||
|
||||
EditorApplication.update += OnUpdate;
|
||||
|
||||
OnEnabled();
|
||||
}
|
||||
protected virtual void OnEnabled(){}
|
||||
void OnDisable()
|
||||
{
|
||||
EditorApplication.update -= OnUpdate;
|
||||
|
||||
OnDisabled();
|
||||
}
|
||||
protected virtual void OnDisabled(){}
|
||||
protected virtual void OnUpdate()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected void FillDefaultInspector()
|
||||
{
|
||||
root.root.Clear();
|
||||
FillDefaultInspector(root, serializedObject, true);
|
||||
}
|
||||
|
||||
protected static void FillDefaultInspector(VisualElement container, SerializedObject serializedObject, bool hideScript)
|
||||
{
|
||||
container.Clear();
|
||||
|
||||
if (serializedObject.targetObject is null)
|
||||
{
|
||||
var label = container.Create<Label>();
|
||||
label.text = "Null";
|
||||
return;
|
||||
}
|
||||
var property = serializedObject.GetIterator();
|
||||
|
||||
if (!property.NextVisible(true)) return; // Expand first child.
|
||||
do
|
||||
{
|
||||
if (property.propertyPath == "m_Script" && hideScript)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var type = serializedObject.targetObject.GetType();
|
||||
var fieldInfo = serializedObject.targetObject.GetType().GetField(property.propertyPath, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (fieldInfo is not null && Attribute.IsDefined(fieldInfo, typeof(ReadOnlyAttribute)))
|
||||
{
|
||||
var _container = container.Create<VisualElement>();
|
||||
_container.style.flexDirection = FlexDirection.Row;
|
||||
|
||||
_container.Create<Label>().text = $"{property.displayName}:";
|
||||
_container.Create<VisualElement>().style.flexGrow = 1;
|
||||
_container.Create<Label>().bindingPath = property.propertyPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
//var label = container.Create<Label>();
|
||||
//label.text =$"propertyPath:{property.propertyPath} fieldInfo:{fieldInfo} type:{type} fieldInfo:{fieldInfo}";
|
||||
var field = new PropertyField(property)
|
||||
{
|
||||
name = "PropertyField:" + property.propertyPath
|
||||
};
|
||||
if (property.propertyPath == "m_Script" && serializedObject.targetObject != null)
|
||||
{
|
||||
field.SetEnabled(false);
|
||||
}
|
||||
|
||||
container.Add(field);
|
||||
}
|
||||
// try
|
||||
// {
|
||||
// var header = type?.GetCustomAttribute<HeaderAttribute>();
|
||||
// if (header != null)
|
||||
// {
|
||||
// var label = new Label(header.header);
|
||||
// label.AddToClassList("subTitle");
|
||||
// container.Add(label);
|
||||
// }
|
||||
// }
|
||||
// catch (System.Exception e)
|
||||
// {
|
||||
// Debug.LogException(e);
|
||||
// }
|
||||
} while (property.NextVisible(false));
|
||||
|
||||
foreach (var method in serializedObject.targetObject.GetType().GetMethods())
|
||||
{
|
||||
if (method.GetCustomAttribute<BITAttribute>() is null) continue;
|
||||
if (method.GetParameters().Length is not 0) continue;
|
||||
var button = new Button(() => method.Invoke(serializedObject.targetObject, null))
|
||||
{
|
||||
text = method.Name
|
||||
};
|
||||
|
||||
container.Add(button);
|
||||
}
|
||||
BITInspectorExtensions.FillDefaultInspector(root, serializedObject, true);
|
||||
}
|
||||
}
|
||||
public class BITProperty : PropertyDrawer
|
||||
|
@@ -44,13 +44,23 @@ namespace BITKit
|
||||
var deltaRot = targetRotation * Quaternion.Inverse(transform.rotation);
|
||||
deltaRot.ToAngleAxis(out var angle, out var axis);
|
||||
var angleDelta = axis * (angle * Mathf.Deg2Rad);
|
||||
|
||||
angleDelta.x = MathV.TransientRotationAxis(angleDelta.x);
|
||||
|
||||
var torqueLocal = transform.InverseTransformDirection(angleDelta);
|
||||
// torqueLocal = rigidbody.inertiaTensorRotation * torqueLocal;
|
||||
// torqueLocal.Scale(rigidbody.inertiaTensor);
|
||||
// torqueLocal = Quaternion.Inverse(rigidbody.inertiaTensorRotation) * torqueLocal;
|
||||
var torque = transform.TransformDirection(torqueLocal);
|
||||
return torque;
|
||||
|
||||
var minTorque = MathV.TransientRotationAxis(torque);
|
||||
|
||||
return new Vector3()
|
||||
{
|
||||
x = Mathf.Min(torque.x, minTorque.x),
|
||||
y = Mathf.Min(torque.y, minTorque.y),
|
||||
z = Mathf.Min(torque.z, minTorque.z),
|
||||
};
|
||||
}
|
||||
public static Vector3 Multiply(params Vector3[] vectors)
|
||||
{
|
||||
@@ -175,6 +185,10 @@ namespace BITKit
|
||||
return remainder > snapSize / 2 ? size + 1 : size;
|
||||
}
|
||||
}
|
||||
public static float GetLength(this Vector2 self)
|
||||
{
|
||||
return Mathf.Max(Mathf.Abs(self.x), Mathf.Abs(self.y));
|
||||
}
|
||||
public static float GetLength(this Vector3 self)
|
||||
{
|
||||
return Mathf.Max(Mathf.Abs(self.x), Mathf.Abs(self.y), Mathf.Abs(self.z));
|
||||
@@ -200,21 +214,19 @@ namespace BITKit
|
||||
}
|
||||
public static bool InRange(this Vector2Int self, Vector2Int other)
|
||||
{
|
||||
return self.x >= 0
|
||||
&& self.y >= 0
|
||||
&& other.x >= 0
|
||||
&& other.y >= 0
|
||||
&& other.x <= self.x
|
||||
&& other.y <= self.y
|
||||
&& (self + other).x >= 0
|
||||
&& (self + other).y >= 0;
|
||||
return self is { x: >= 0, y: >= 0 }
|
||||
&& other is { x: >= 0, y: >= 0 }
|
||||
&& other.x <= self.x
|
||||
&& other.y <= self.y
|
||||
&& (self + other).x >= 0
|
||||
&& (self + other).y >= 0;
|
||||
}
|
||||
public static float TransientRotationAxis(this float transientAxis)
|
||||
{
|
||||
return (transientAxis %= 360) switch
|
||||
{
|
||||
var x when x > 180 => transientAxis - 360,
|
||||
var x when x < -180 => transientAxis + 360,
|
||||
> 180 => transientAxis - 360,
|
||||
< -180 => transientAxis + 360,
|
||||
_ => transientAxis,
|
||||
};
|
||||
}
|
||||
@@ -297,6 +309,7 @@ namespace BITKit
|
||||
}
|
||||
public static T Random<T>(this T[] self)
|
||||
{
|
||||
if (self is null || self.Length is 0) return default;
|
||||
return self[UnityEngine.Random.Range(0, self.Length)];
|
||||
}
|
||||
public static bool IsNullOrEmpty(this string self)
|
||||
@@ -614,6 +627,10 @@ namespace BITKit
|
||||
{
|
||||
self.style.display = new(active ? DisplayStyle.Flex : DisplayStyle.None);
|
||||
}
|
||||
public static void SetVisible(this VisualElement self, bool visible)
|
||||
{
|
||||
self.style.visibility = new(visible ? Visibility.Visible : Visibility.Hidden);
|
||||
}
|
||||
public static float GetOpacity(this VisualElement self) => self.style.opacity.value;
|
||||
public static void SetOpacity(this VisualElement self, float value) => self.style.opacity = new(value);
|
||||
public static void ScrollToBottom(this ScrollView self)
|
||||
@@ -623,50 +640,66 @@ namespace BITKit
|
||||
}
|
||||
public static async void ScrollToBottomAutomatic(this ScrollView self, float delay = 0.02f)
|
||||
{
|
||||
if (Math.Abs(self.verticalScroller.value - self.verticalScroller.highValue) < 0.01)
|
||||
switch (true)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(delay), BITApp.CancellationToken);
|
||||
ScrollToBottom(self);
|
||||
}
|
||||
catch (OperationCanceledException) { }
|
||||
catch (System.Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
case true when Math.Abs(self.verticalScroller.value - self.verticalScroller.highValue) < 0.01:
|
||||
case true when self.verticalScroller.highValue < 0.01f:
|
||||
case true when Math.Abs(self.verticalScroller.value - self.verticalScroller.highValue) < 0.01f:
|
||||
try
|
||||
{
|
||||
await Task.Delay(TimeSpan.FromSeconds(delay), BITApp.CancellationToken);
|
||||
ScrollToBottom(self);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
public static bool IsVisible(this VisualElement self,Vector3 worldPosition)
|
||||
{
|
||||
var cameraTrans = Camera.main.transform;
|
||||
return Vector3.Dot(cameraTrans.forward, worldPosition - cameraTrans.position) > 0;
|
||||
}
|
||||
|
||||
public static Vector2 GetScreenPosition(this VisualElement self, Vector3 worldPosition)
|
||||
{
|
||||
var pos = RuntimePanelUtils
|
||||
.CameraTransformWorldToPanel(self.panel, worldPosition, Camera.main);
|
||||
|
||||
pos.x -= self.layout.width / 2;
|
||||
pos.y -= self.layout.height / 2;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
public static Vector2 GetPosition(this VisualElement self)
|
||||
{
|
||||
return new Vector2(self.style.left.value.value, self.style.top.value.value);
|
||||
}
|
||||
|
||||
public static void SetPosition(this VisualElement self, Vector2 screenPosition)
|
||||
{
|
||||
self.style.right = new StyleLength(StyleKeyword.Auto);
|
||||
self.style.bottom = new StyleLength(StyleKeyword.Auto);
|
||||
self.style.position = Position.Absolute;
|
||||
self.style.left = screenPosition.x;
|
||||
self.style.top = screenPosition.y;
|
||||
}
|
||||
public static void SetPosition(this VisualElement self,Vector3 worldPosition)
|
||||
{
|
||||
try
|
||||
{
|
||||
var camera = Camera.main;
|
||||
if (camera is null) return;
|
||||
var cameraTrans = camera.transform;
|
||||
var pos = RuntimePanelUtils
|
||||
.CameraTransformWorldToPanel(self.panel, worldPosition, camera);
|
||||
|
||||
pos.x = (pos.x - self.layout.width / 2);
|
||||
pos.y = (pos.y - self.layout.height / 2);
|
||||
|
||||
self.style.left = 0;
|
||||
self.style.top = 0;
|
||||
self.style.right = new StyleLength(StyleKeyword.Auto);
|
||||
self.style.bottom = new StyleLength(StyleKeyword.Auto);
|
||||
self.style.position = Position.Absolute;
|
||||
// self.transform.position = pos;
|
||||
self.style.left = pos.x;
|
||||
self.style.top = pos.y;
|
||||
self.SetOpacity(Vector3.Dot(cameraTrans.forward, worldPosition - cameraTrans.position) > 0 ? 1 : 0);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BIT4Log.LogException(e);
|
||||
}
|
||||
var pos = self.GetScreenPosition(worldPosition);
|
||||
var visible = self.IsVisible(worldPosition);
|
||||
|
||||
self.style.right = new StyleLength(StyleKeyword.Auto);
|
||||
self.style.bottom = new StyleLength(StyleKeyword.Auto);
|
||||
self.style.position = Position.Absolute;
|
||||
// self.transform.position = pos;
|
||||
self.style.left = pos.x;
|
||||
self.style.top = pos.y;
|
||||
|
||||
self.SetOpacity(visible ? 1 : 0);
|
||||
}
|
||||
}
|
||||
}
|
@@ -16,6 +16,7 @@ namespace BITKit
|
||||
if (so is null)
|
||||
{
|
||||
so = ScriptableObject.CreateInstance<T>();
|
||||
|
||||
AssetDatabase.CreateAsset(so, $"Assets/Resources/{name}.asset");
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
|
@@ -119,6 +119,8 @@ namespace BITKit
|
||||
}
|
||||
public double Interval=1;
|
||||
private double allowUpdateTime=0;
|
||||
public bool AllowUpdateWithoutReset => BITApp.Time.TimeAsDouble >= allowUpdateTime;
|
||||
public double Remaining => allowUpdateTime - BITApp.Time.TimeAsDouble;
|
||||
public bool AllowUpdate
|
||||
{
|
||||
get
|
||||
@@ -128,7 +130,7 @@ namespace BITKit
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public bool AllowUpdateWithoutReset => BITApp.Time.TimeAsDouble >= allowUpdateTime;
|
||||
|
||||
public void Reset(bool immediately = false)
|
||||
{
|
||||
allowUpdateTime = BITApp.Time.TimeAsDouble + (immediately ? 0 : Interval);
|
||||
@@ -144,6 +146,10 @@ namespace BITKit
|
||||
{
|
||||
allowUpdateTime = currentTime + Interval + interval;
|
||||
}
|
||||
else
|
||||
{
|
||||
allowUpdateTime += interval;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -1,15 +0,0 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
namespace BITKit
|
||||
{
|
||||
public static class UtilityHelper
|
||||
{
|
||||
public static bool isPlaying => BehaviourHelper.Actived;
|
||||
public static bool isValid => BehaviourHelper.Actived;
|
||||
}
|
||||
|
||||
}
|
@@ -1,11 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7c5f3cc357dddd47a323357b05c62a5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Reference in New Issue
Block a user