导入角色动画,和增加角色控制
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
using KINEMATION.KAnimationCore.Runtime.Misc;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KINEMATION.KAnimationCore.Editor.Misc
|
||||
{
|
||||
public abstract class AssetDragAndDrop<T1, T2> where T1 : MonoBehaviour where T2 : ScriptableObject
|
||||
{
|
||||
protected static DragAndDropVisualMode HandleDragAndDrop(bool perform)
|
||||
{
|
||||
var asset = DragAndDrop.objectReferences[0] as T2;
|
||||
if (asset == null)
|
||||
{
|
||||
return DragAndDropVisualMode.None;
|
||||
}
|
||||
|
||||
if (perform)
|
||||
{
|
||||
var selection = Selection.activeGameObject;
|
||||
if (selection != null)
|
||||
{
|
||||
var component = selection.GetComponent<T1>();
|
||||
if (component == null) component = selection.AddComponent<T1>();
|
||||
if(component is IAssetDragAndDrop assetDragAndDrop) assetDragAndDrop.SetAsset(asset);
|
||||
}
|
||||
}
|
||||
|
||||
return DragAndDropVisualMode.Copy;
|
||||
}
|
||||
|
||||
protected static DragAndDropVisualMode OnHierarchyDrop(int dropTargetInstanceID, HierarchyDropFlags dropMode,
|
||||
Transform parentForDraggedObjects, bool perform)
|
||||
{
|
||||
return HandleDragAndDrop(perform);
|
||||
}
|
||||
|
||||
protected static DragAndDropVisualMode OnInspectorDrop(UnityEngine.Object[] targets, bool perform)
|
||||
{
|
||||
return HandleDragAndDrop(perform);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dfc97017ea654dc9b3fe8cab522f0afc
|
||||
timeCreated: 1744450300
|
||||
@@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace KINEMATION.KAnimationCore.Editor.Misc
|
||||
{
|
||||
public class AssetObjectWidget<T> where T : Object
|
||||
{
|
||||
public UnityEditor.Editor editor;
|
||||
|
||||
public string _objectLabel;
|
||||
|
||||
private Object _cachedObject;
|
||||
private Object _parentAsset;
|
||||
|
||||
private SerializedObject _targetObject;
|
||||
private SerializedProperty _targetProperty;
|
||||
|
||||
private bool _isExpanded;
|
||||
|
||||
private bool IsSubAsset(Object asset)
|
||||
{
|
||||
return AssetDatabase.GetAssetPath(_parentAsset).Equals(AssetDatabase.GetAssetPath(asset));
|
||||
}
|
||||
|
||||
private void DestroyObject(Object objectToDestroy, bool displayDialog)
|
||||
{
|
||||
if (objectToDestroy != null && IsSubAsset(objectToDestroy))
|
||||
{
|
||||
if (!displayDialog || EditorUtility.DisplayDialog("Deletion",
|
||||
$"Are you sure you want to delete {objectToDestroy.name}?", "Yes", "No"))
|
||||
{
|
||||
Undo.DestroyObjectImmediate(objectToDestroy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCreatePressed()
|
||||
{
|
||||
DestroyObject(_targetProperty.objectReferenceValue, true);
|
||||
|
||||
Object newComponent = Activator.CreateInstance<T>();
|
||||
newComponent.name = _objectLabel.Replace(" ", string.Empty);
|
||||
newComponent.hideFlags = HideFlags.HideInInspector | HideFlags.HideInHierarchy;
|
||||
|
||||
Undo.RegisterCreatedObjectUndo(newComponent, "Add Component");
|
||||
AssetDatabase.AddObjectToAsset(newComponent, _parentAsset);
|
||||
EditorUtility.SetDirty(_parentAsset);
|
||||
AssetDatabase.SaveAssetIfDirty(_parentAsset);
|
||||
|
||||
_targetProperty.objectReferenceValue = newComponent;
|
||||
}
|
||||
|
||||
public AssetObjectWidget(SerializedObject target, string propertyName, string label)
|
||||
{
|
||||
_objectLabel = label;
|
||||
_targetObject = target;
|
||||
_targetProperty = _targetObject.FindProperty(propertyName);
|
||||
_parentAsset = target.targetObject;
|
||||
}
|
||||
|
||||
public void OnInspectorGUI()
|
||||
{
|
||||
_targetObject.Update();
|
||||
|
||||
if (EditorUtility.IsPersistent(_parentAsset))
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
Object objectRef = _targetProperty.objectReferenceValue;
|
||||
objectRef = (T) EditorGUILayout.ObjectField(_objectLabel, objectRef, typeof(T), false);
|
||||
_targetProperty.objectReferenceValue = objectRef;
|
||||
|
||||
if (GUILayout.Button("Create"))
|
||||
{
|
||||
OnCreatePressed();
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Show"))
|
||||
{
|
||||
if(editor != null) _isExpanded = !_isExpanded;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (_cachedObject != _targetProperty.objectReferenceValue)
|
||||
{
|
||||
if (!IsSubAsset(_targetProperty.objectReferenceValue))
|
||||
{
|
||||
DestroyObject(_cachedObject, false);
|
||||
}
|
||||
|
||||
editor = _targetProperty.objectReferenceValue == null
|
||||
? null
|
||||
: UnityEditor.Editor.CreateEditor(_targetProperty.objectReferenceValue);
|
||||
}
|
||||
|
||||
_cachedObject = _targetProperty.objectReferenceValue;
|
||||
|
||||
if (_isExpanded && editor != null)
|
||||
{
|
||||
var style = GUI.skin.box;
|
||||
style.padding = new RectOffset(15, 5, 5, 5);
|
||||
|
||||
EditorGUILayout.BeginVertical(style);
|
||||
editor.OnInspectorGUI();
|
||||
EditorGUILayout.EndVertical();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.PropertyField(_targetProperty);
|
||||
}
|
||||
|
||||
_targetObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bea5203406494b3880cef647734069f5
|
||||
timeCreated: 1722236084
|
||||
@@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KINEMATION.KAnimationCore.Editor.Widgets
|
||||
{
|
||||
public enum SplitOrientation
|
||||
{
|
||||
Horizontal,
|
||||
Vertical
|
||||
}
|
||||
|
||||
public class KSplitterWidget
|
||||
{
|
||||
public Action onDrawFirstGUI;
|
||||
public Action onDrawSecondGUI;
|
||||
public SplitOrientation orientation = SplitOrientation.Horizontal;
|
||||
public float splitRatio = 0.35f;
|
||||
public float splitterSize = 4f;
|
||||
public bool drawSplitterLine = true;
|
||||
|
||||
private bool _resizing;
|
||||
private float _dragMinRatio;
|
||||
private float _dragMaxRatio;
|
||||
private Vector2 _firstScroll;
|
||||
private Vector2 _secondScroll;
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
var host = GUILayoutUtility.GetRect(GUIContent.none, GUIStyle.none,
|
||||
GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true));
|
||||
OnGUI(host);
|
||||
}
|
||||
|
||||
public void OnGUI(Rect rect)
|
||||
{
|
||||
var e = Event.current;
|
||||
|
||||
float axis = orientation == SplitOrientation.Horizontal ? rect.width : rect.height;
|
||||
float avail = Mathf.Max(0f, axis - splitterSize);
|
||||
|
||||
float firstSize = avail * Mathf.Clamp01(splitRatio);
|
||||
float secondSize = Mathf.Max(0f, avail - firstSize);
|
||||
|
||||
Rect firstRect, splitterRect, secondRect;
|
||||
if (orientation == SplitOrientation.Horizontal)
|
||||
{
|
||||
firstRect = new Rect(0f, 0f, firstSize, rect.height);
|
||||
splitterRect = new Rect(firstRect.xMax, 0f, splitterSize, rect.height);
|
||||
secondRect = new Rect(splitterRect.xMax, 0f, secondSize, rect.height);
|
||||
}
|
||||
else
|
||||
{
|
||||
firstRect = new Rect(0f, 0f, rect.width, firstSize);
|
||||
splitterRect = new Rect(0f, firstRect.yMax, rect.width, splitterSize);
|
||||
secondRect = new Rect(0f, splitterRect.yMax, rect.width, secondSize);
|
||||
}
|
||||
|
||||
// First pane
|
||||
GUILayout.BeginArea(firstRect);
|
||||
_firstScroll = EditorGUILayout.BeginScrollView(_firstScroll);
|
||||
onDrawFirstGUI?.Invoke();
|
||||
EditorGUILayout.EndScrollView();
|
||||
GUILayout.EndArea();
|
||||
|
||||
// Splitter
|
||||
var cursor = orientation == SplitOrientation.Horizontal
|
||||
? MouseCursor.ResizeHorizontal
|
||||
: MouseCursor.ResizeVertical;
|
||||
EditorGUIUtility.AddCursorRect(splitterRect, cursor);
|
||||
|
||||
if (e.type == EventType.MouseDown && splitterRect.Contains(e.mousePosition))
|
||||
{
|
||||
_resizing = true;
|
||||
|
||||
// Capture allowed range based on current ratio
|
||||
float r = Mathf.Clamp01(splitRatio);
|
||||
float minR = Mathf.Min(r, 1f - r);
|
||||
_dragMinRatio = minR;
|
||||
_dragMaxRatio = 1f - minR;
|
||||
|
||||
e.Use();
|
||||
}
|
||||
|
||||
if (_resizing && e.type == EventType.MouseDrag)
|
||||
{
|
||||
float rel = orientation == SplitOrientation.Horizontal ? e.mousePosition.x : e.mousePosition.y;
|
||||
|
||||
float desiredFirst = Mathf.Clamp(rel, 0f, avail);
|
||||
float rawRatio = avail > 0f ? desiredFirst / avail : splitRatio;
|
||||
|
||||
// Clamp within the drag-bounded range
|
||||
splitRatio = Mathf.Clamp(rawRatio, _dragMinRatio, _dragMaxRatio);
|
||||
GUI.changed = true;
|
||||
}
|
||||
|
||||
if (e.type == EventType.MouseUp)
|
||||
{
|
||||
_resizing = false;
|
||||
}
|
||||
|
||||
if (drawSplitterLine)
|
||||
{
|
||||
if (orientation == SplitOrientation.Horizontal)
|
||||
EditorGUI.DrawRect(new Rect(splitterRect.x, splitterRect.y, 1f, splitterRect.height),
|
||||
new Color(0f, 0f, 0f, 0.25f));
|
||||
else
|
||||
EditorGUI.DrawRect(new Rect(splitterRect.x, splitterRect.y, splitterRect.width, 1f),
|
||||
new Color(0f, 0f, 0f, 0.25f));
|
||||
}
|
||||
|
||||
// Second pane
|
||||
GUILayout.BeginArea(secondRect);
|
||||
_secondScroll = EditorGUILayout.BeginScrollView(_secondScroll);
|
||||
onDrawSecondGUI?.Invoke();
|
||||
EditorGUILayout.EndScrollView();
|
||||
GUILayout.EndArea();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3f963d6ef48456893e2a2b9c4706c77
|
||||
timeCreated: 1756475661
|
||||
@@ -0,0 +1,40 @@
|
||||
// Designed by KINEMATION, 2024.
|
||||
|
||||
using UnityEngine;
|
||||
|
||||
namespace KINEMATION.KAnimationCore.Editor.Tools
|
||||
{
|
||||
public struct KToolbarTab
|
||||
{
|
||||
public delegate void KOnTabRendered();
|
||||
|
||||
public string name;
|
||||
public KOnTabRendered onTabRendered;
|
||||
}
|
||||
|
||||
public class KToolbarWidget
|
||||
{
|
||||
private int _toolbarIndex = 0;
|
||||
private string[] _toolbarTabNames;
|
||||
private KToolbarTab[] _toolbarTabs;
|
||||
|
||||
public KToolbarWidget(KToolbarTab[] tabs)
|
||||
{
|
||||
_toolbarTabs = tabs;
|
||||
_toolbarTabNames = new string[_toolbarTabs.Length];
|
||||
|
||||
for (int i = 0; i < _toolbarTabs.Length; i++)
|
||||
{
|
||||
_toolbarTabNames[i] = _toolbarTabs[i].name;
|
||||
}
|
||||
}
|
||||
|
||||
public void Render()
|
||||
{
|
||||
if (_toolbarTabNames.Length == 0) return;
|
||||
|
||||
_toolbarIndex = GUILayout.Toolbar(_toolbarIndex, _toolbarTabNames);
|
||||
_toolbarTabs[_toolbarIndex].onTabRendered?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7a907f9eb19f45c58dd635954e1fb352
|
||||
timeCreated: 1704274518
|
||||
@@ -0,0 +1,110 @@
|
||||
// Designed by KINEMATION, 2024.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using KINEMATION.KAnimationCore.Runtime.Attributes;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace KINEMATION.KAnimationCore.Editor.Widgets
|
||||
{
|
||||
public struct EditorTab
|
||||
{
|
||||
public string name;
|
||||
public List<SerializedProperty> properties;
|
||||
}
|
||||
|
||||
public class TabInspectorWidget
|
||||
{
|
||||
private SerializedObject _serializedObject;
|
||||
|
||||
private List<SerializedProperty> _defaultProperties;
|
||||
private List<EditorTab> _editorTabs;
|
||||
|
||||
private string[] _tabNames;
|
||||
private bool _foundTab;
|
||||
|
||||
private int _selectedIndex = 0;
|
||||
|
||||
private T[] GetPropertyAttributes<T>(SerializedProperty property) where T : System.Attribute
|
||||
{
|
||||
T[] output = null;
|
||||
|
||||
FieldInfo fieldInfo = _serializedObject.targetObject.GetType().GetField(property.propertyPath,
|
||||
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (fieldInfo != null)
|
||||
{
|
||||
output = (T[]) fieldInfo.GetCustomAttributes(typeof(T), true);
|
||||
}
|
||||
|
||||
if (output == null || output.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public TabInspectorWidget(SerializedObject targetObject)
|
||||
{
|
||||
_serializedObject = targetObject;
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
_defaultProperties = new List<SerializedProperty>();
|
||||
_editorTabs = new List<EditorTab>();
|
||||
|
||||
SerializedProperty property = _serializedObject.GetIterator();
|
||||
property.NextVisible(true);
|
||||
|
||||
while (property.NextVisible(false))
|
||||
{
|
||||
TabAttribute[] tabAttributes = GetPropertyAttributes<TabAttribute>(property);
|
||||
if (tabAttributes == null)
|
||||
{
|
||||
if (_foundTab)
|
||||
{
|
||||
_editorTabs[^1].properties.Add(property.Copy());
|
||||
continue;
|
||||
}
|
||||
|
||||
_defaultProperties.Add(property.Copy());
|
||||
continue;
|
||||
}
|
||||
|
||||
_editorTabs.Add(new EditorTab()
|
||||
{
|
||||
name = tabAttributes[0].tabName,
|
||||
properties = new List<SerializedProperty>() { property.Copy() }
|
||||
});
|
||||
|
||||
_foundTab = true;
|
||||
}
|
||||
|
||||
_tabNames = _editorTabs.Select(item => item.name).ToArray();
|
||||
}
|
||||
|
||||
public void OnGUI()
|
||||
{
|
||||
_serializedObject.Update();
|
||||
|
||||
foreach (var defaultProperty in _defaultProperties)
|
||||
{
|
||||
EditorGUILayout.PropertyField(defaultProperty, true);
|
||||
}
|
||||
|
||||
if (_tabNames.Length > 0)
|
||||
{
|
||||
_selectedIndex = GUILayout.Toolbar(_selectedIndex, _tabNames);
|
||||
foreach (var tabProperty in _editorTabs[_selectedIndex].properties)
|
||||
{
|
||||
EditorGUILayout.PropertyField(tabProperty, true);
|
||||
}
|
||||
}
|
||||
|
||||
_serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3d77a1c3adc04e6fb61aa62d804e0a5a
|
||||
timeCreated: 1712129746
|
||||
Reference in New Issue
Block a user