Reupload to new git vps.
This commit is contained in:
commit
8ad72ae00b
57 changed files with 2290 additions and 0 deletions
16
DC.Animator.asmdef
Normal file
16
DC.Animator.asmdef
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "DC.Animator",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
7
DC.Animator.asmdef.meta
Normal file
7
DC.Animator.asmdef.meta
Normal file
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fd7612f2de54f1e46a60c1460f826a43
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
8
Editor.meta
Normal file
8
Editor.meta
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a60c3d1cd509697419e16c967dfffc14
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
145
Editor/AnimationCollectionEditor.cs
Normal file
145
Editor/AnimationCollectionEditor.cs
Normal file
|
@ -0,0 +1,145 @@
|
|||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using DC.Animator.Data;
|
||||
using DC.Animator.Utils;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.Editor
|
||||
{
|
||||
[CustomEditor(typeof(AnimationCollection))]
|
||||
public class AnimationCollectionEditor : UnityEditor.Editor
|
||||
{
|
||||
private SerializedProperty _animationsProperty;
|
||||
private AnimationCollection _collection;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
_animationsProperty = serializedObject.FindProperty("animations");
|
||||
_collection = (AnimationCollection)target;
|
||||
}
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
serializedObject.Update();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Animation Presets", EditorStyles.boldLabel);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (GUILayout.Button("Add Animation", GUILayout.Height(30))) AddNewAnimation();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
for (var i = 0; i < _animationsProperty.arraySize; i++)
|
||||
{
|
||||
var animationProperty = _animationsProperty.GetArrayElementAtIndex(i);
|
||||
var nameProperty = animationProperty.FindPropertyRelative("name");
|
||||
var typeProperty = animationProperty.FindPropertyRelative("type");
|
||||
|
||||
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.PropertyField(nameProperty, GUIContent.none);
|
||||
EditorGUILayout.PropertyField(typeProperty, GUIContent.none, GUILayout.Width(100));
|
||||
|
||||
if (GUILayout.Button("X", GUILayout.Width(25)))
|
||||
{
|
||||
_animationsProperty.DeleteArrayElementAtIndex(i);
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
return;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
var foldoutName = nameProperty.stringValue;
|
||||
if (string.IsNullOrEmpty(foldoutName))
|
||||
foldoutName = "Animation " + i;
|
||||
|
||||
animationProperty.isExpanded = EditorGUILayout.Foldout(animationProperty.isExpanded, foldoutName, true);
|
||||
|
||||
if (animationProperty.isExpanded)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("duration"));
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("delay"));
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("easingType"));
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
var type = (AnimationCollection.AnimationType)typeProperty.enumValueIndex;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case AnimationCollection.AnimationType.Fade:
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("fromAlpha"));
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("toAlpha"));
|
||||
break;
|
||||
|
||||
case AnimationCollection.AnimationType.Move:
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("fromPosition"));
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("toPosition"));
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("useLocalPosition"));
|
||||
EditorGUILayout.PropertyField(
|
||||
animationProperty.FindPropertyRelative("useAnchoredPosition"));
|
||||
break;
|
||||
|
||||
case AnimationCollection.AnimationType.Scale:
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("fromScale"));
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("toScale"));
|
||||
break;
|
||||
|
||||
case AnimationCollection.AnimationType.Rotate:
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("fromEulerAngles"));
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("toEulerAngles"));
|
||||
break;
|
||||
|
||||
case AnimationCollection.AnimationType.Color:
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("fromColor"));
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("toColor"));
|
||||
EditorGUILayout.PropertyField(animationProperty.FindPropertyRelative("isTextColor"));
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndVertical();
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
|
||||
private void AddNewAnimation()
|
||||
{
|
||||
var index = _animationsProperty.arraySize;
|
||||
_animationsProperty.InsertArrayElementAtIndex(index);
|
||||
|
||||
var element = _animationsProperty.GetArrayElementAtIndex(index);
|
||||
|
||||
element.FindPropertyRelative("name").stringValue = "New Animation";
|
||||
element.FindPropertyRelative("type").enumValueIndex = 0;
|
||||
element.FindPropertyRelative("duration").floatValue = 0.5f;
|
||||
element.FindPropertyRelative("delay").floatValue = 0f;
|
||||
element.FindPropertyRelative("easingType").enumValueIndex = (int)Easing.Type.EaseOutQuad;
|
||||
|
||||
element.FindPropertyRelative("fromAlpha").floatValue = 0f;
|
||||
element.FindPropertyRelative("toAlpha").floatValue = 1f;
|
||||
|
||||
element.FindPropertyRelative("fromScale").vector3Value = Vector3.zero;
|
||||
element.FindPropertyRelative("toScale").vector3Value = Vector3.one;
|
||||
|
||||
element.FindPropertyRelative("fromColor").colorValue = Color.white;
|
||||
element.FindPropertyRelative("toColor").colorValue = Color.white;
|
||||
|
||||
element.isExpanded = true;
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
3
Editor/AnimationCollectionEditor.cs.meta
Normal file
3
Editor/AnimationCollectionEditor.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e980dad5c4f248808f571603257f2611
|
||||
timeCreated: 1747861571
|
401
Editor/AnimationEditorWindow.cs
Normal file
401
Editor/AnimationEditorWindow.cs
Normal file
|
@ -0,0 +1,401 @@
|
|||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using DC.Animator.Adapters;
|
||||
using DC.Animator.Core;
|
||||
using DC.Animator.Data;
|
||||
using DC.Animator.Utils;
|
||||
using DCAnimator.Data;
|
||||
using TMPro;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace DC.Animator.Editor
|
||||
{
|
||||
public class AnimationEditorWindow : EditorWindow
|
||||
{
|
||||
private readonly string[] _animationTypes = { "Fade", "Move", "Scale", "Rotate", "Color" };
|
||||
|
||||
private readonly string[] _tabNames = { "Create", "Test", "Manage Presets" };
|
||||
private AnimationCollection _animationCollection;
|
||||
|
||||
private AnimationData _currentAnimation = new();
|
||||
private bool _isAnimating;
|
||||
private float _lastUpdateTime;
|
||||
private string _presetName = "New Preset";
|
||||
private IAnimation _previewAnimation;
|
||||
private Vector2 _scrollPosition;
|
||||
private int _selectedAnimationType;
|
||||
|
||||
private int _selectedTabIndex;
|
||||
|
||||
private GameObject _targetObject;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
ResetCurrentAnimation();
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
_selectedTabIndex = GUILayout.Toolbar(_selectedTabIndex, _tabNames);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
switch (_selectedTabIndex)
|
||||
{
|
||||
case 0:
|
||||
DrawCreateAnimationTab();
|
||||
break;
|
||||
case 1:
|
||||
DrawTestAnimationTab();
|
||||
break;
|
||||
case 2:
|
||||
DrawManagePresetsTab();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_isAnimating || _previewAnimation == null) return;
|
||||
|
||||
var deltaTime = (float)(EditorApplication.timeSinceStartup - _lastUpdateTime);
|
||||
_lastUpdateTime = (float)EditorApplication.timeSinceStartup;
|
||||
|
||||
_previewAnimation.Update(deltaTime);
|
||||
|
||||
if (_previewAnimation.IsComplete) _isAnimating = false;
|
||||
|
||||
Repaint();
|
||||
}
|
||||
|
||||
[MenuItem("Window/DC Animator/Editor")]
|
||||
public static void ShowWindow()
|
||||
{
|
||||
GetWindow<AnimationEditorWindow>("DC Animator Editor");
|
||||
}
|
||||
|
||||
private void ResetCurrentAnimation()
|
||||
{
|
||||
_currentAnimation = new AnimationData
|
||||
{
|
||||
name = "New Animation",
|
||||
type = AnimationCollection.AnimationType.Fade,
|
||||
duration = 0.5f,
|
||||
delay = 0f,
|
||||
easingType = Easing.Type.EaseOutQuad,
|
||||
fromAlpha = 0f,
|
||||
toAlpha = 1f,
|
||||
fromScale = Vector3.zero,
|
||||
toScale = Vector3.one,
|
||||
fromColor = Color.white,
|
||||
toColor = Color.white
|
||||
};
|
||||
}
|
||||
|
||||
private void DrawCreateAnimationTab()
|
||||
{
|
||||
_scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition);
|
||||
|
||||
EditorGUILayout.LabelField("Create New Animation", EditorStyles.boldLabel);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
_currentAnimation.name = EditorGUILayout.TextField("Animation Name", _currentAnimation.name);
|
||||
|
||||
_selectedAnimationType = EditorGUILayout.Popup("Animation Type", _selectedAnimationType, _animationTypes);
|
||||
_currentAnimation.type = (AnimationCollection.AnimationType)_selectedAnimationType;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.LabelField("Common Properties", EditorStyles.boldLabel);
|
||||
_currentAnimation.duration = EditorGUILayout.FloatField("Duration", _currentAnimation.duration);
|
||||
_currentAnimation.delay = EditorGUILayout.FloatField("Delay", _currentAnimation.delay);
|
||||
|
||||
var easingNames = Enum.GetNames(typeof(Easing.Type));
|
||||
var easingIndex = (int)_currentAnimation.easingType;
|
||||
easingIndex = EditorGUILayout.Popup("Easing Type", easingIndex, easingNames);
|
||||
_currentAnimation.easingType = (Easing.Type)easingIndex;
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
// Specific Properties
|
||||
EditorGUILayout.LabelField("Animation Properties", EditorStyles.boldLabel);
|
||||
|
||||
switch (_currentAnimation.type)
|
||||
{
|
||||
case AnimationCollection.AnimationType.Fade:
|
||||
_currentAnimation.fromAlpha =
|
||||
EditorGUILayout.Slider("From Alpha", _currentAnimation.fromAlpha, 0f, 1f);
|
||||
_currentAnimation.toAlpha = EditorGUILayout.Slider("To Alpha", _currentAnimation.toAlpha, 0f, 1f);
|
||||
break;
|
||||
|
||||
case AnimationCollection.AnimationType.Move:
|
||||
_currentAnimation.fromPosition =
|
||||
EditorGUILayout.Vector3Field("From Position", _currentAnimation.fromPosition);
|
||||
_currentAnimation.toPosition =
|
||||
EditorGUILayout.Vector3Field("To Position", _currentAnimation.toPosition);
|
||||
_currentAnimation.useLocalPosition =
|
||||
EditorGUILayout.Toggle("Use Local Position", _currentAnimation.useLocalPosition);
|
||||
_currentAnimation.useAnchoredPosition = EditorGUILayout.Toggle("Use Anchored Position",
|
||||
_currentAnimation.useAnchoredPosition);
|
||||
break;
|
||||
|
||||
case AnimationCollection.AnimationType.Scale:
|
||||
_currentAnimation.fromScale =
|
||||
EditorGUILayout.Vector3Field("From Scale", _currentAnimation.fromScale);
|
||||
_currentAnimation.toScale = EditorGUILayout.Vector3Field("To Scale", _currentAnimation.toScale);
|
||||
break;
|
||||
|
||||
case AnimationCollection.AnimationType.Rotate:
|
||||
_currentAnimation.fromEulerAngles =
|
||||
EditorGUILayout.Vector3Field("From Rotation", _currentAnimation.fromEulerAngles);
|
||||
_currentAnimation.toEulerAngles =
|
||||
EditorGUILayout.Vector3Field("To Rotation", _currentAnimation.toEulerAngles);
|
||||
break;
|
||||
|
||||
case AnimationCollection.AnimationType.Color:
|
||||
_currentAnimation.fromColor = EditorGUILayout.ColorField("From Color", _currentAnimation.fromColor);
|
||||
_currentAnimation.toColor = EditorGUILayout.ColorField("To Color", _currentAnimation.toColor);
|
||||
_currentAnimation.isTextColor =
|
||||
EditorGUILayout.Toggle("Is Text Color", _currentAnimation.isTextColor);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
|
||||
_animationCollection = (AnimationCollection)EditorGUILayout.ObjectField("Save To Preset", _animationCollection,
|
||||
typeof(AnimationCollection), false);
|
||||
|
||||
if (_animationCollection && GUILayout.Button("Save")) SaveAnimationToPreset();
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (!_animationCollection)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
_presetName = EditorGUILayout.TextField("New Preset Name", _presetName);
|
||||
|
||||
if (GUILayout.Button("Create")) CreateNewPreset();
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
EditorGUILayout.EndScrollView();
|
||||
}
|
||||
|
||||
private void DrawTestAnimationTab()
|
||||
{
|
||||
EditorGUILayout.LabelField("Test Animation", EditorStyles.boldLabel);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
_targetObject =
|
||||
(GameObject)EditorGUILayout.ObjectField("Target Object", _targetObject, typeof(GameObject), true);
|
||||
_animationCollection = (AnimationCollection)EditorGUILayout.ObjectField("Animation Preset", _animationCollection,
|
||||
typeof(AnimationCollection), false);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (_targetObject && _animationCollection)
|
||||
{
|
||||
EditorGUILayout.LabelField("Available Animations:", EditorStyles.boldLabel);
|
||||
|
||||
if (_animationCollection.animations.Count == 0)
|
||||
EditorGUILayout.HelpBox("No animations in preset", MessageType.Info);
|
||||
else
|
||||
foreach (var anim in _animationCollection.animations)
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField(anim.name, EditorStyles.label);
|
||||
|
||||
if (GUILayout.Button("Play", GUILayout.Width(60))) PlayAnimation(anim.name);
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.HelpBox("Select a target object and an animation preset to test animations",
|
||||
MessageType.Info);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawManagePresetsTab()
|
||||
{
|
||||
EditorGUILayout.LabelField("Manage Animation Presets", EditorStyles.boldLabel);
|
||||
EditorGUILayout.Space();
|
||||
|
||||
_animationCollection = (AnimationCollection)EditorGUILayout.ObjectField("Animation Preset", _animationCollection,
|
||||
typeof(AnimationCollection), false);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (_animationCollection)
|
||||
{
|
||||
EditorGUILayout.LabelField("Animations in Preset:", EditorStyles.boldLabel);
|
||||
|
||||
if (_animationCollection.animations.Count == 0)
|
||||
EditorGUILayout.HelpBox("No animations in preset", MessageType.Info);
|
||||
else
|
||||
for (var i = 0; i < _animationCollection.animations.Count; i++)
|
||||
{
|
||||
var anim = _animationCollection.animations[i];
|
||||
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
EditorGUILayout.LabelField($"{anim.name} ({anim.type})", EditorStyles.label);
|
||||
|
||||
if (GUILayout.Button("Edit", GUILayout.Width(60)))
|
||||
{
|
||||
_currentAnimation = anim;
|
||||
_selectedAnimationType = (int)anim.type;
|
||||
_selectedTabIndex = 0; // Switch to Create tab
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Delete", GUILayout.Width(60)))
|
||||
if (EditorUtility.DisplayDialog("Delete Animation",
|
||||
$"Are you sure you want to delete animation '{anim.name}'?",
|
||||
"Delete", "Cancel"))
|
||||
{
|
||||
_animationCollection.animations.RemoveAt(i);
|
||||
EditorUtility.SetDirty(_animationCollection);
|
||||
AssetDatabase.SaveAssets();
|
||||
break;
|
||||
}
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (GUILayout.Button("Create New Animation", GUILayout.Height(30)))
|
||||
{
|
||||
ResetCurrentAnimation();
|
||||
_selectedTabIndex = 0; // Switch to Create tab
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
_presetName = EditorGUILayout.TextField("New Preset Name", _presetName);
|
||||
|
||||
if (GUILayout.Button("Create")) CreateNewPreset();
|
||||
|
||||
EditorGUILayout.EndHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateNewPreset()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_presetName))
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Please enter a name for the preset", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
var path = EditorUtility.SaveFilePanelInProject(
|
||||
"Save Animation Preset",
|
||||
_presetName,
|
||||
"asset",
|
||||
"Save animation preset"
|
||||
);
|
||||
|
||||
if (string.IsNullOrEmpty(path))
|
||||
return;
|
||||
|
||||
_animationCollection = CreateInstance<AnimationCollection>();
|
||||
AssetDatabase.CreateAsset(_animationCollection, path);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
SaveAnimationToPreset();
|
||||
}
|
||||
|
||||
private void SaveAnimationToPreset()
|
||||
{
|
||||
if (!_animationCollection)
|
||||
return;
|
||||
|
||||
for (var i = 0; i < _animationCollection.animations.Count; i++)
|
||||
if (_animationCollection.animations[i].name == _currentAnimation.name)
|
||||
{
|
||||
if (!EditorUtility.DisplayDialog("Overwrite Animation",
|
||||
$"Animation '{_currentAnimation.name}' already exists. Overwrite?",
|
||||
"Overwrite", "Cancel")) return;
|
||||
|
||||
_animationCollection.animations[i] = _currentAnimation;
|
||||
EditorUtility.SetDirty(_animationCollection);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_animationCollection.animations.Add(_currentAnimation);
|
||||
EditorUtility.SetDirty(_animationCollection);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
|
||||
private void PlayAnimation(string animationName)
|
||||
{
|
||||
if (!_targetObject || !_animationCollection)
|
||||
return;
|
||||
|
||||
IAnimatable adapter;
|
||||
|
||||
var image = _targetObject.GetComponent<Image>();
|
||||
if (image)
|
||||
adapter = new ImageAdapter(image);
|
||||
|
||||
var text = _targetObject.GetComponent<TextMeshProUGUI>();
|
||||
if (text)
|
||||
adapter = new TMPTextAdapter(text);
|
||||
|
||||
var tmpro = _targetObject.GetComponent<TextMeshPro>();
|
||||
if (tmpro)
|
||||
adapter = new TMPTextAdapter(tmpro);
|
||||
|
||||
var spriteRenderer = _targetObject.GetComponent<SpriteRenderer>();
|
||||
if (spriteRenderer)
|
||||
adapter = new SpriteAdapter(spriteRenderer);
|
||||
|
||||
var rectTransform = _targetObject.GetComponent<RectTransform>();
|
||||
if (rectTransform)
|
||||
{
|
||||
adapter = new RectTransformAdapter(rectTransform);
|
||||
}
|
||||
else
|
||||
{
|
||||
var transform = _targetObject.transform;
|
||||
adapter = new TransformAdapter(transform);
|
||||
}
|
||||
|
||||
_previewAnimation = _animationCollection.CreateAnimation(adapter, animationName);
|
||||
|
||||
if (_previewAnimation == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", $"Animation '{animationName}' not found in preset", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
_previewAnimation.Start();
|
||||
_isAnimating = true;
|
||||
_lastUpdateTime = (float)EditorApplication.timeSinceStartup;
|
||||
|
||||
EditorApplication.update += EditorUpdate;
|
||||
}
|
||||
|
||||
private void EditorUpdate()
|
||||
{
|
||||
if (_isAnimating && _previewAnimation != null)
|
||||
{
|
||||
Repaint();
|
||||
|
||||
if (!_previewAnimation.IsComplete) return;
|
||||
|
||||
_isAnimating = false;
|
||||
}
|
||||
|
||||
EditorApplication.update -= EditorUpdate;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
3
Editor/AnimationEditorWindow.cs.meta
Normal file
3
Editor/AnimationEditorWindow.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: f24aeb6fb1654955ac87e118100d8b1d
|
||||
timeCreated: 1747861633
|
8
Runtime.meta
Normal file
8
Runtime.meta
Normal file
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e657351d63ffca146a291a3fe1b517b0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
3
Runtime/Adapters.meta
Normal file
3
Runtime/Adapters.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 56735d71953b4e5385da5122c22cd6e1
|
||||
timeCreated: 1747861237
|
60
Runtime/Adapters/ImageAdapter.cs
Normal file
60
Runtime/Adapters/ImageAdapter.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using DC.Animator.Core;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace DC.Animator.Adapters
|
||||
{
|
||||
public class ImageAdapter : IAnimatable
|
||||
{
|
||||
private readonly Image _image;
|
||||
|
||||
public ImageAdapter(Image image) => _image = image;
|
||||
|
||||
public bool SupportsProperty(AnimatableProperty property)
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
AnimatableProperty.Alpha or AnimatableProperty.Color => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
public object GetValue(AnimatableProperty property)
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
AnimatableProperty.Alpha => _image.color.a,
|
||||
AnimatableProperty.Color => _image.color,
|
||||
_ => throw new ArgumentException($"ImageAdapter does not support property {property}")
|
||||
};
|
||||
}
|
||||
|
||||
public void SetValue(AnimatableProperty property, object value)
|
||||
{
|
||||
switch (property)
|
||||
{
|
||||
case AnimatableProperty.Alpha:
|
||||
var colorAlpha = _image.color;
|
||||
colorAlpha.a = (float)value;
|
||||
_image.color = colorAlpha;
|
||||
break;
|
||||
case AnimatableProperty.Color:
|
||||
_image.color = (Color)value;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"ImageAdapter does not support property {property}");
|
||||
}
|
||||
}
|
||||
|
||||
public Type GetPropertyType(AnimatableProperty property)
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
AnimatableProperty.Alpha => typeof(float),
|
||||
AnimatableProperty.Color => typeof(Color),
|
||||
_ => throw new ArgumentException($"ImageAdapter does not support property {property}")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
3
Runtime/Adapters/ImageAdapter.cs.meta
Normal file
3
Runtime/Adapters/ImageAdapter.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 6c004264ae534a60b0acc1e9b0a1fabf
|
||||
timeCreated: 1747861252
|
77
Runtime/Adapters/RectTransformAdapter.cs
Normal file
77
Runtime/Adapters/RectTransformAdapter.cs
Normal file
|
@ -0,0 +1,77 @@
|
|||
using System;
|
||||
using DC.Animator.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.Adapters
|
||||
{
|
||||
public class RectTransformAdapter : IAnimatable
|
||||
{
|
||||
private readonly RectTransform _rectTransform;
|
||||
|
||||
public RectTransformAdapter(RectTransform rectTransform) => _rectTransform = rectTransform;
|
||||
|
||||
public bool SupportsProperty(AnimatableProperty property)
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
AnimatableProperty.Position or AnimatableProperty.LocalPosition or AnimatableProperty.AnchoredPosition
|
||||
or AnimatableProperty.Scale or AnimatableProperty.Rotation
|
||||
or AnimatableProperty.EulerAngles => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
public object GetValue(AnimatableProperty property)
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
AnimatableProperty.Position => _rectTransform.position,
|
||||
AnimatableProperty.LocalPosition => _rectTransform.localPosition,
|
||||
AnimatableProperty.AnchoredPosition => _rectTransform.anchoredPosition,
|
||||
AnimatableProperty.Scale => _rectTransform.localScale,
|
||||
AnimatableProperty.Rotation => _rectTransform.rotation,
|
||||
AnimatableProperty.EulerAngles => _rectTransform.eulerAngles,
|
||||
_ => throw new ArgumentException($"RectTransformAdapter does not support property {property}")
|
||||
};
|
||||
}
|
||||
|
||||
public void SetValue(AnimatableProperty property, object value)
|
||||
{
|
||||
switch (property)
|
||||
{
|
||||
case AnimatableProperty.Position:
|
||||
_rectTransform.position = (Vector3)value;
|
||||
break;
|
||||
case AnimatableProperty.LocalPosition:
|
||||
_rectTransform.localPosition = (Vector3)value;
|
||||
break;
|
||||
case AnimatableProperty.AnchoredPosition:
|
||||
_rectTransform.anchoredPosition = (Vector2)value;
|
||||
break;
|
||||
case AnimatableProperty.Scale:
|
||||
_rectTransform.localScale = (Vector3)value;
|
||||
break;
|
||||
case AnimatableProperty.Rotation:
|
||||
_rectTransform.rotation = (Quaternion)value;
|
||||
break;
|
||||
case AnimatableProperty.EulerAngles:
|
||||
_rectTransform.eulerAngles = (Vector3)value;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"RectTransformAdapter does not support property {property}");
|
||||
}
|
||||
}
|
||||
|
||||
public Type GetPropertyType(AnimatableProperty property)
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
AnimatableProperty.Position or AnimatableProperty.LocalPosition or AnimatableProperty.Scale
|
||||
or AnimatableProperty.EulerAngles => typeof(Vector3),
|
||||
AnimatableProperty.AnchoredPosition => typeof(Vector2),
|
||||
AnimatableProperty.Rotation => typeof(Quaternion),
|
||||
_ => throw new ArgumentException($"RectTransformAdapter does not support property {property}")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
3
Runtime/Adapters/RectTransformAdapter.cs.meta
Normal file
3
Runtime/Adapters/RectTransformAdapter.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 3445d296a0bb42dc8cfe1d0f4ab762a1
|
||||
timeCreated: 1747861417
|
59
Runtime/Adapters/SpriteAdapter.cs
Normal file
59
Runtime/Adapters/SpriteAdapter.cs
Normal file
|
@ -0,0 +1,59 @@
|
|||
using System;
|
||||
using DC.Animator.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.Adapters
|
||||
{
|
||||
public class SpriteAdapter : IAnimatable
|
||||
{
|
||||
private readonly SpriteRenderer _spriteRenderer;
|
||||
|
||||
public SpriteAdapter(SpriteRenderer spriteRenderer) => _spriteRenderer = spriteRenderer;
|
||||
|
||||
public bool SupportsProperty(AnimatableProperty property)
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
AnimatableProperty.Alpha or AnimatableProperty.Color => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
public object GetValue(AnimatableProperty property)
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
AnimatableProperty.Alpha => _spriteRenderer.color.a,
|
||||
AnimatableProperty.Color => _spriteRenderer.color,
|
||||
_ => throw new ArgumentException($"SpriteRendererAdapter does not support property {property}")
|
||||
};
|
||||
}
|
||||
|
||||
public void SetValue(AnimatableProperty property, object value)
|
||||
{
|
||||
switch (property)
|
||||
{
|
||||
case AnimatableProperty.Alpha:
|
||||
var colorAlpha = _spriteRenderer.color;
|
||||
colorAlpha.a = (float)value;
|
||||
_spriteRenderer.color = colorAlpha;
|
||||
break;
|
||||
case AnimatableProperty.Color:
|
||||
_spriteRenderer.color = (Color)value;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"SpriteRendererAdapter does not support property {property}");
|
||||
}
|
||||
}
|
||||
|
||||
public Type GetPropertyType(AnimatableProperty property)
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
AnimatableProperty.Alpha => typeof(float),
|
||||
AnimatableProperty.Color => typeof(Color),
|
||||
_ => throw new ArgumentException($"SpriteRendererAdapter does not support property {property}")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
3
Runtime/Adapters/SpriteAdapter.cs.meta
Normal file
3
Runtime/Adapters/SpriteAdapter.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 81eaeba71eb74408976c0dbc72a8a454
|
||||
timeCreated: 1747861361
|
63
Runtime/Adapters/TMPTextAdapter.cs
Normal file
63
Runtime/Adapters/TMPTextAdapter.cs
Normal file
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using DC.Animator.Core;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.Adapters
|
||||
{
|
||||
public class TMPTextAdapter : IAnimatable
|
||||
{
|
||||
private readonly TMP_Text _text;
|
||||
|
||||
public TMPTextAdapter(TMP_Text text) => _text = text;
|
||||
|
||||
public bool SupportsProperty(AnimatableProperty property)
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
AnimatableProperty.Alpha or AnimatableProperty.Color or AnimatableProperty.TextColor => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
public object GetValue(AnimatableProperty property)
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
AnimatableProperty.Alpha => _text.alpha,
|
||||
AnimatableProperty.Color or AnimatableProperty.TextColor => _text.color,
|
||||
_ => throw new ArgumentException($"TextMeshProAdapter does not support property {property}")
|
||||
};
|
||||
}
|
||||
|
||||
public void SetValue(AnimatableProperty property, object value)
|
||||
{
|
||||
switch (property)
|
||||
{
|
||||
case AnimatableProperty.Alpha:
|
||||
_text.alpha = (float)value;
|
||||
break;
|
||||
case AnimatableProperty.Color:
|
||||
case AnimatableProperty.TextColor:
|
||||
_text.color = (Color)value;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"TextMeshProAdapter does not support property {property}");
|
||||
}
|
||||
}
|
||||
|
||||
public Type GetPropertyType(AnimatableProperty property)
|
||||
{
|
||||
switch (property)
|
||||
{
|
||||
case AnimatableProperty.Alpha:
|
||||
return typeof(float);
|
||||
case AnimatableProperty.Color:
|
||||
case AnimatableProperty.TextColor:
|
||||
return typeof(Color);
|
||||
default:
|
||||
throw new ArgumentException($"TextMeshProAdapter does not support property {property}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
3
Runtime/Adapters/TMPTextAdapter.cs.meta
Normal file
3
Runtime/Adapters/TMPTextAdapter.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: d707c0a42bba4df2bde5731ebda18905
|
||||
timeCreated: 1747861307
|
71
Runtime/Adapters/TransformAdapter.cs
Normal file
71
Runtime/Adapters/TransformAdapter.cs
Normal file
|
@ -0,0 +1,71 @@
|
|||
using System;
|
||||
using DC.Animator.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.Adapters
|
||||
{
|
||||
public class TransformAdapter : IAnimatable
|
||||
{
|
||||
private readonly Transform _transform;
|
||||
|
||||
public TransformAdapter(Transform transform) => _transform = transform;
|
||||
|
||||
public bool SupportsProperty(AnimatableProperty property)
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
AnimatableProperty.Position or AnimatableProperty.LocalPosition or AnimatableProperty.Scale
|
||||
or AnimatableProperty.Rotation or AnimatableProperty.EulerAngles => true,
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
public object GetValue(AnimatableProperty property)
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
AnimatableProperty.Position => _transform.position,
|
||||
AnimatableProperty.LocalPosition => _transform.localPosition,
|
||||
AnimatableProperty.Scale => _transform.localScale,
|
||||
AnimatableProperty.Rotation => _transform.rotation,
|
||||
AnimatableProperty.EulerAngles => _transform.eulerAngles,
|
||||
_ => throw new ArgumentException($"TransformAdapter does not support property {property}")
|
||||
};
|
||||
}
|
||||
|
||||
public void SetValue(AnimatableProperty property, object value)
|
||||
{
|
||||
switch (property)
|
||||
{
|
||||
case AnimatableProperty.Position:
|
||||
_transform.position = (Vector3)value;
|
||||
break;
|
||||
case AnimatableProperty.LocalPosition:
|
||||
_transform.localPosition = (Vector3)value;
|
||||
break;
|
||||
case AnimatableProperty.Scale:
|
||||
_transform.localScale = (Vector3)value;
|
||||
break;
|
||||
case AnimatableProperty.Rotation:
|
||||
_transform.rotation = (Quaternion)value;
|
||||
break;
|
||||
case AnimatableProperty.EulerAngles:
|
||||
_transform.eulerAngles = (Vector3)value;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"TransformAdapter does not support property {property}");
|
||||
}
|
||||
}
|
||||
|
||||
public Type GetPropertyType(AnimatableProperty property)
|
||||
{
|
||||
return property switch
|
||||
{
|
||||
AnimatableProperty.Position or AnimatableProperty.LocalPosition or AnimatableProperty.Scale
|
||||
or AnimatableProperty.EulerAngles => typeof(Vector3),
|
||||
AnimatableProperty.Rotation => typeof(Quaternion),
|
||||
_ => throw new ArgumentException($"TransformAdapter does not support property {property}")
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
3
Runtime/Adapters/TransformAdapter.cs.meta
Normal file
3
Runtime/Adapters/TransformAdapter.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 12a9475c333d43d0ade1f05f8bfd1283
|
||||
timeCreated: 1747861386
|
3
Runtime/AnimationTypeBuilders.meta
Normal file
3
Runtime/AnimationTypeBuilders.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8c757291c27645019681e3bb8f24ef0f
|
||||
timeCreated: 1747861055
|
53
Runtime/AnimationTypeBuilders/ColorAnimationBuilder.cs
Normal file
53
Runtime/AnimationTypeBuilders/ColorAnimationBuilder.cs
Normal file
|
@ -0,0 +1,53 @@
|
|||
using DC.Animator.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.AnimationTypeBuilders
|
||||
{
|
||||
public class ColorAnimationBuilder : AnimationTypeBuilderBase
|
||||
{
|
||||
private Color _fromColor = Color.white;
|
||||
private bool _hasFromColor;
|
||||
private bool _isTextColor;
|
||||
private Color _toColor = Color.white;
|
||||
|
||||
public ColorAnimationBuilder(AnimationBuilder baseBuilder) : base(baseBuilder) { }
|
||||
|
||||
public ColorAnimationBuilder From(Color color)
|
||||
{
|
||||
_fromColor = color;
|
||||
_hasFromColor = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorAnimationBuilder To(Color color)
|
||||
{
|
||||
_toColor = color;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorAnimationBuilder FromCurrent()
|
||||
{
|
||||
_hasFromColor = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ColorAnimationBuilder AsTextColor()
|
||||
{
|
||||
_isTextColor = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public override IAnimation Build()
|
||||
{
|
||||
var animation = BaseBuilder.Build();
|
||||
|
||||
var property = _isTextColor ? AnimatableProperty.TextColor : AnimatableProperty.Color;
|
||||
|
||||
if (!_hasFromColor) _fromColor = (Color)animation.GetValue(property);
|
||||
|
||||
animation.SetProperty(property, _fromColor, _toColor);
|
||||
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 906d0b3b5c8a480cbca966bd4f505e12
|
||||
timeCreated: 1747861219
|
32
Runtime/AnimationTypeBuilders/FadeAnimationBuilder.cs
Normal file
32
Runtime/AnimationTypeBuilders/FadeAnimationBuilder.cs
Normal file
|
@ -0,0 +1,32 @@
|
|||
using DC.Animator.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.AnimationTypeBuilders
|
||||
{
|
||||
public class FadeAnimationBuilder : AnimationTypeBuilderBase
|
||||
{
|
||||
private float _fromAlpha;
|
||||
private float _toAlpha = 1f;
|
||||
|
||||
public FadeAnimationBuilder(AnimationBuilder baseBuilder) : base(baseBuilder) { }
|
||||
|
||||
public FadeAnimationBuilder From(float alpha)
|
||||
{
|
||||
_fromAlpha = Mathf.Clamp01(alpha);
|
||||
return this;
|
||||
}
|
||||
|
||||
public FadeAnimationBuilder To(float alpha)
|
||||
{
|
||||
_toAlpha = Mathf.Clamp01(alpha);
|
||||
return this;
|
||||
}
|
||||
|
||||
public override IAnimation Build()
|
||||
{
|
||||
var animation = BaseBuilder.Build();
|
||||
animation.SetProperty(AnimatableProperty.Alpha, _fromAlpha, _toAlpha);
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 87ca0a0406324a70a8a5f7e8bd289a99
|
||||
timeCreated: 1747861075
|
76
Runtime/AnimationTypeBuilders/MoveAnimationBuilder.cs
Normal file
76
Runtime/AnimationTypeBuilders/MoveAnimationBuilder.cs
Normal file
|
@ -0,0 +1,76 @@
|
|||
using DC.Animator.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.AnimationTypeBuilders
|
||||
{
|
||||
public class MoveAnimationBuilder : AnimationTypeBuilderBase
|
||||
{
|
||||
private Vector3 _fromPosition;
|
||||
private bool _hasFromPosition;
|
||||
private bool _hasToPosition;
|
||||
private bool _isAnchored;
|
||||
private bool _isLocal;
|
||||
private Vector3 _toPosition;
|
||||
|
||||
public MoveAnimationBuilder(AnimationBuilder baseBuilder) : base(baseBuilder) { }
|
||||
|
||||
public MoveAnimationBuilder From(Vector3 position)
|
||||
{
|
||||
_fromPosition = position;
|
||||
_hasFromPosition = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MoveAnimationBuilder To(Vector3 position)
|
||||
{
|
||||
_toPosition = position;
|
||||
_hasToPosition = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MoveAnimationBuilder FromCurrent()
|
||||
{
|
||||
_hasFromPosition = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MoveAnimationBuilder Local()
|
||||
{
|
||||
_isLocal = true;
|
||||
_isAnchored = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public MoveAnimationBuilder Anchored()
|
||||
{
|
||||
_isAnchored = true;
|
||||
_isLocal = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public override IAnimation Build()
|
||||
{
|
||||
var animation = BaseBuilder.Build();
|
||||
AnimatableProperty property;
|
||||
|
||||
if (_isLocal)
|
||||
property = AnimatableProperty.LocalPosition;
|
||||
else if (_isAnchored)
|
||||
property = AnimatableProperty.AnchoredPosition;
|
||||
else
|
||||
property = AnimatableProperty.Position;
|
||||
|
||||
if (!_hasFromPosition) _fromPosition = (Vector3)animation.GetValue(property);
|
||||
|
||||
if (!_hasToPosition)
|
||||
{
|
||||
Debug.LogWarning("No target position specified for move animation");
|
||||
_toPosition = _fromPosition;
|
||||
}
|
||||
|
||||
animation.SetProperty(property, _fromPosition, _toPosition);
|
||||
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 800d1b5a42e24886b87d95dab0e1df99
|
||||
timeCreated: 1747861100
|
87
Runtime/AnimationTypeBuilders/RotateAnimationBuilder.cs
Normal file
87
Runtime/AnimationTypeBuilders/RotateAnimationBuilder.cs
Normal file
|
@ -0,0 +1,87 @@
|
|||
using DC.Animator.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.AnimationTypeBuilders
|
||||
{
|
||||
public class RotateAnimationBuilder : AnimationTypeBuilderBase
|
||||
{
|
||||
private Vector3 _fromEulerAngles;
|
||||
private Vector3 _toEulerAngles;
|
||||
private Quaternion _fromRotation;
|
||||
private Quaternion _toRotation;
|
||||
private bool _hasFromRotation;
|
||||
private bool _useEuler = true;
|
||||
|
||||
public RotateAnimationBuilder(AnimationBuilder baseBuilder) : base(baseBuilder) { }
|
||||
|
||||
public RotateAnimationBuilder FromEuler(Vector3 eulerAngles)
|
||||
{
|
||||
_fromEulerAngles = eulerAngles;
|
||||
_fromRotation = Quaternion.Euler(eulerAngles);
|
||||
_hasFromRotation = true;
|
||||
_useEuler = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RotateAnimationBuilder ToEuler(Vector3 eulerAngles)
|
||||
{
|
||||
_toEulerAngles = eulerAngles;
|
||||
_toRotation = Quaternion.Euler(eulerAngles);
|
||||
_useEuler = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RotateAnimationBuilder FromQuaternion(Quaternion rotation)
|
||||
{
|
||||
_fromRotation = rotation;
|
||||
_fromEulerAngles = rotation.eulerAngles;
|
||||
_hasFromRotation = true;
|
||||
_useEuler = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RotateAnimationBuilder ToQuaternion(Quaternion rotation)
|
||||
{
|
||||
_toRotation = rotation;
|
||||
_toEulerAngles = rotation.eulerAngles;
|
||||
_useEuler = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public RotateAnimationBuilder FromCurrent()
|
||||
{
|
||||
_hasFromRotation = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public override IAnimation Build()
|
||||
{
|
||||
var animation = BaseBuilder.Build();
|
||||
|
||||
var property = _useEuler ?
|
||||
AnimatableProperty.EulerAngles :
|
||||
AnimatableProperty.Rotation;
|
||||
|
||||
if (!_hasFromRotation)
|
||||
{
|
||||
if (_useEuler)
|
||||
{
|
||||
_fromEulerAngles = (Vector3)animation.GetValue(AnimatableProperty.EulerAngles);
|
||||
_fromRotation = Quaternion.Euler(_fromEulerAngles);
|
||||
}
|
||||
else
|
||||
{
|
||||
_fromRotation = (Quaternion)animation.GetValue(AnimatableProperty.Rotation);
|
||||
_fromEulerAngles = _fromRotation.eulerAngles;
|
||||
}
|
||||
}
|
||||
|
||||
var fromValue = _useEuler ? (object)_fromEulerAngles : _fromRotation;
|
||||
var toValue = _useEuler ? (object)_toEulerAngles : _toRotation;
|
||||
|
||||
animation.SetProperty(property, fromValue, toValue);
|
||||
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 735103945dcb47a9b677d3f57350514f
|
||||
timeCreated: 1747861191
|
57
Runtime/AnimationTypeBuilders/ScaleAnimationBuilder.cs
Normal file
57
Runtime/AnimationTypeBuilders/ScaleAnimationBuilder.cs
Normal file
|
@ -0,0 +1,57 @@
|
|||
using DC.Animator.Core;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.AnimationTypeBuilders
|
||||
{
|
||||
public class ScaleAnimationBuilder : AnimationTypeBuilderBase
|
||||
{
|
||||
private Vector3 _fromScale = Vector3.one;
|
||||
private bool _hasFromScale;
|
||||
private Vector3 _toScale = Vector3.one;
|
||||
|
||||
public ScaleAnimationBuilder(AnimationBuilder baseBuilder) : base(baseBuilder) { }
|
||||
|
||||
public ScaleAnimationBuilder From(Vector3 scale)
|
||||
{
|
||||
_fromScale = scale;
|
||||
_hasFromScale = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScaleAnimationBuilder From(float uniformScale)
|
||||
{
|
||||
_fromScale = new Vector3(uniformScale, uniformScale, uniformScale);
|
||||
_hasFromScale = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScaleAnimationBuilder To(Vector3 scale)
|
||||
{
|
||||
_toScale = scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScaleAnimationBuilder To(float uniformScale)
|
||||
{
|
||||
_toScale = new Vector3(uniformScale, uniformScale, uniformScale);
|
||||
return this;
|
||||
}
|
||||
|
||||
public ScaleAnimationBuilder FromCurrent()
|
||||
{
|
||||
_hasFromScale = false;
|
||||
return this;
|
||||
}
|
||||
|
||||
public override IAnimation Build()
|
||||
{
|
||||
var animation = BaseBuilder.Build();
|
||||
|
||||
if (!_hasFromScale) _fromScale = (Vector3)animation.GetValue(AnimatableProperty.Scale);
|
||||
|
||||
animation.SetProperty(AnimatableProperty.Scale, _fromScale, _toScale);
|
||||
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7b6cf6ed822b434d9635fa7841093483
|
||||
timeCreated: 1747861159
|
3
Runtime/Core.meta
Normal file
3
Runtime/Core.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7305d0795bef4bc7b5554a9a57e6d05d
|
||||
timeCreated: 1748092703
|
15
Runtime/Core/AnimatableProperty.cs
Normal file
15
Runtime/Core/AnimatableProperty.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
namespace DC.Animator.Core
|
||||
{
|
||||
public enum AnimatableProperty
|
||||
{
|
||||
Position,
|
||||
LocalPosition,
|
||||
AnchoredPosition,
|
||||
Scale,
|
||||
Rotation,
|
||||
EulerAngles,
|
||||
Alpha,
|
||||
Color,
|
||||
TextColor
|
||||
}
|
||||
}
|
3
Runtime/Core/AnimatableProperty.cs.meta
Normal file
3
Runtime/Core/AnimatableProperty.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 8be1c4fca1da458487554a4860fbd09d
|
||||
timeCreated: 1747860604
|
185
Runtime/Core/Animation.cs
Normal file
185
Runtime/Core/Animation.cs
Normal file
|
@ -0,0 +1,185 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DC.Animator.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.Core
|
||||
{
|
||||
public class Animation : IAnimation
|
||||
{
|
||||
private readonly Dictionary<AnimatableProperty, AnimationProperty> _properties = new();
|
||||
private float _currentTime;
|
||||
private float _delay;
|
||||
private float _delayTimer;
|
||||
private float _duration;
|
||||
private Easing.Function _easingFunction;
|
||||
private bool _hasStarted;
|
||||
|
||||
private IAnimatable _target;
|
||||
|
||||
public Animation() { }
|
||||
|
||||
public Animation(IAnimatable target, float duration, float delay, Easing.Function easingFunction)
|
||||
{
|
||||
_target = target;
|
||||
_duration = Mathf.Max(duration, 0.001f); // Avoid division by zero
|
||||
_delay = delay;
|
||||
_easingFunction = easingFunction ?? Easing.Linear;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
public bool IsComplete { get; private set; }
|
||||
public bool IsPlaying { get; private set; }
|
||||
|
||||
public event Action<IAnimation> OnStart;
|
||||
public event Action<IAnimation> OnComplete;
|
||||
public event Action<IAnimation> OnUpdate;
|
||||
|
||||
public void SetProperty(AnimatableProperty property, object fromValue, object toValue)
|
||||
{
|
||||
if (!_target.SupportsProperty(property))
|
||||
{
|
||||
Debug.LogWarning($"Target does not support property {property}");
|
||||
return;
|
||||
}
|
||||
|
||||
var propertyType = _target.GetPropertyType(property);
|
||||
|
||||
_properties[property] = new AnimationProperty
|
||||
{
|
||||
FromValue = fromValue,
|
||||
ToValue = toValue,
|
||||
PropertyType = propertyType
|
||||
};
|
||||
}
|
||||
|
||||
public object GetValue(AnimatableProperty property)
|
||||
{
|
||||
if (_target != null && _target.SupportsProperty(property)) return _target.GetValue(property);
|
||||
throw new ArgumentException(
|
||||
$"Cannot get value for property {property}. Either target is null or property is not supported.");
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
if (IsPlaying) return;
|
||||
|
||||
IsPlaying = true;
|
||||
IsComplete = false;
|
||||
_currentTime = 0;
|
||||
_delayTimer = 0;
|
||||
_hasStarted = false;
|
||||
|
||||
foreach (var prop in _properties) _target.SetValue(prop.Key, prop.Value.FromValue);
|
||||
}
|
||||
|
||||
public void Pause()
|
||||
{
|
||||
IsPlaying = false;
|
||||
}
|
||||
|
||||
public void Resume()
|
||||
{
|
||||
if (!IsComplete) IsPlaying = true;
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
IsPlaying = false;
|
||||
|
||||
foreach (var prop in _properties) _target.SetValue(prop.Key, prop.Value.ToValue);
|
||||
|
||||
IsComplete = true;
|
||||
OnComplete?.Invoke(this);
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
if (!IsPlaying || IsComplete) return;
|
||||
|
||||
if (_delay > 0 && _delayTimer < _delay)
|
||||
{
|
||||
_delayTimer += deltaTime;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_hasStarted)
|
||||
{
|
||||
_hasStarted = true;
|
||||
OnStart?.Invoke(this);
|
||||
}
|
||||
|
||||
_currentTime += deltaTime;
|
||||
var normalizedTime = Mathf.Clamp01(_currentTime / _duration);
|
||||
var easedTime = _easingFunction(normalizedTime);
|
||||
|
||||
foreach (var prop in _properties)
|
||||
{
|
||||
var interpolatedValue = InterpolateValue(
|
||||
prop.Value.FromValue,
|
||||
prop.Value.ToValue,
|
||||
easedTime,
|
||||
prop.Value.PropertyType
|
||||
);
|
||||
|
||||
_target.SetValue(prop.Key, interpolatedValue);
|
||||
}
|
||||
|
||||
OnUpdate?.Invoke(this);
|
||||
|
||||
if (_currentTime >= _duration)
|
||||
{
|
||||
IsPlaying = false;
|
||||
IsComplete = true;
|
||||
OnComplete?.Invoke(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
IsComplete = false;
|
||||
IsPlaying = false;
|
||||
_hasStarted = false;
|
||||
_currentTime = 0;
|
||||
_delayTimer = 0;
|
||||
_properties.Clear();
|
||||
|
||||
OnStart = null;
|
||||
OnComplete = null;
|
||||
OnUpdate = null;
|
||||
}
|
||||
|
||||
public void Initialize(IAnimatable target, float duration, float delay, Easing.Function easingFunction)
|
||||
{
|
||||
_target = target;
|
||||
_duration = Mathf.Max(duration, 0.001f);
|
||||
_delay = delay;
|
||||
_easingFunction = easingFunction ?? Easing.Linear;
|
||||
|
||||
Reset();
|
||||
}
|
||||
|
||||
private object InterpolateValue(object from, object to, float t, Type propertyType)
|
||||
{
|
||||
if (propertyType == typeof(float)) return Mathf.Lerp((float)from, (float)to, t);
|
||||
|
||||
if (propertyType == typeof(Vector2)) return Vector2.Lerp((Vector2)from, (Vector2)to, t);
|
||||
|
||||
if (propertyType == typeof(Vector3)) return Vector3.Lerp((Vector3)from, (Vector3)to, t);
|
||||
|
||||
if (propertyType == typeof(Color)) return Color.Lerp((Color)from, (Color)to, t);
|
||||
|
||||
if (propertyType == typeof(Quaternion)) return Quaternion.Slerp((Quaternion)from, (Quaternion)to, t);
|
||||
|
||||
return t < 0.5f ? from : to;
|
||||
}
|
||||
|
||||
private class AnimationProperty
|
||||
{
|
||||
public object FromValue;
|
||||
public Type PropertyType;
|
||||
public object ToValue;
|
||||
}
|
||||
}
|
||||
}
|
3
Runtime/Core/Animation.cs.meta
Normal file
3
Runtime/Core/Animation.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a3d35500f1f6469cb3baa292cfc1f882
|
||||
timeCreated: 1747860896
|
136
Runtime/Core/AnimationBuilder.cs
Normal file
136
Runtime/Core/AnimationBuilder.cs
Normal file
|
@ -0,0 +1,136 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DC.Animator.Adapters;
|
||||
using DC.Animator.AnimationTypeBuilders;
|
||||
using DC.Animator.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.Core
|
||||
{
|
||||
public sealed class AnimationBuilder
|
||||
{
|
||||
private IAnimatable _target;
|
||||
private float _duration = 1f;
|
||||
private float _delay;
|
||||
private Easing.Type _easingType = Easing.Type.Linear;
|
||||
private Action<IAnimation> _onStart;
|
||||
private Action<IAnimation> _onComplete;
|
||||
private Action<IAnimation> _onUpdate;
|
||||
private static readonly Dictionary<Type, Func<object, IAnimatable>> AdapterFactories = new();
|
||||
|
||||
static AnimationBuilder()
|
||||
{
|
||||
RegisterAdapter<UnityEngine.UI.Image>((img) => new ImageAdapter(img));
|
||||
RegisterAdapter<TMPro.TextMeshProUGUI>((text) => new TMPTextAdapter(text));
|
||||
RegisterAdapter<TMPro.TextMeshPro>((text) => new TMPTextAdapter(text));
|
||||
RegisterAdapter<SpriteRenderer>((sprite) => new SpriteAdapter(sprite));
|
||||
RegisterAdapter<Transform>((transform) => new TransformAdapter(transform));
|
||||
RegisterAdapter<RectTransform>((rectTransform) => new RectTransformAdapter(rectTransform));
|
||||
}
|
||||
|
||||
public static void RegisterAdapter<T>(Func<T, IAnimatable> adapterFactory)
|
||||
{
|
||||
AdapterFactories[typeof(T)] = obj => adapterFactory((T)obj);
|
||||
}
|
||||
|
||||
public static IAnimatable GetAdapter(object target)
|
||||
{
|
||||
var type = target.GetType();
|
||||
|
||||
if (AdapterFactories.TryGetValue(type, out var factory))
|
||||
return factory(target);
|
||||
|
||||
foreach (var entry in AdapterFactories)
|
||||
{
|
||||
if (entry.Key.IsAssignableFrom(type))
|
||||
return entry.Value(target);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static AnimationBuilder For<T>(T target) where T : UnityEngine.Object
|
||||
{
|
||||
var adapter = GetAdapter(target);
|
||||
if (adapter != null) return new AnimationBuilder().WithTarget(adapter);
|
||||
Debug.LogError($"No animation adapter registered for {typeof(T).Name}");
|
||||
return null;
|
||||
}
|
||||
|
||||
public AnimationBuilder WithTarget(IAnimatable target)
|
||||
{
|
||||
_target = target;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnimationBuilder WithDuration(float duration)
|
||||
{
|
||||
_duration = Mathf.Max(0.001f, duration);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnimationBuilder WithDelay(float delay)
|
||||
{
|
||||
_delay = Mathf.Max(0, delay);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnimationBuilder WithEasing(Easing.Type easingType)
|
||||
{
|
||||
_easingType = easingType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnimationBuilder OnStart(Action<IAnimation> callback)
|
||||
{
|
||||
_onStart = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnimationBuilder OnComplete(Action<IAnimation> callback)
|
||||
{
|
||||
_onComplete = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnimationBuilder OnUpdate(Action<IAnimation> callback)
|
||||
{
|
||||
_onUpdate = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FadeAnimationBuilder AsFade() => new(this);
|
||||
|
||||
public MoveAnimationBuilder AsMove() => new(this);
|
||||
|
||||
public ScaleAnimationBuilder AsScale() => new(this);
|
||||
|
||||
public RotateAnimationBuilder AsRotate() => new(this);
|
||||
|
||||
public ColorAnimationBuilder AsColor() => new(this);
|
||||
|
||||
public IAnimation Build()
|
||||
{
|
||||
var easingFunction = Easing.GetEasingFunction(_easingType);
|
||||
var animation = AnimationRuntime.Instance.CreateAnimation(_target, _duration, _delay, easingFunction);
|
||||
|
||||
if (_onStart != null)
|
||||
animation.OnStart += _onStart;
|
||||
|
||||
if (_onComplete != null)
|
||||
animation.OnComplete += _onComplete;
|
||||
|
||||
if (_onUpdate != null)
|
||||
animation.OnUpdate += _onUpdate;
|
||||
|
||||
return animation;
|
||||
}
|
||||
|
||||
public IAnimation Start()
|
||||
{
|
||||
var animation = Build();
|
||||
AnimationRuntime.Instance.RegisterAnimation(animation);
|
||||
animation.Start();
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
}
|
3
Runtime/Core/AnimationBuilder.cs.meta
Normal file
3
Runtime/Core/AnimationBuilder.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7363902fe7234f8296b9860043ae5a31
|
||||
timeCreated: 1747861027
|
95
Runtime/Core/AnimationRuntime.cs
Normal file
95
Runtime/Core/AnimationRuntime.cs
Normal file
|
@ -0,0 +1,95 @@
|
|||
using System.Collections.Generic;
|
||||
using DC.Animator.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.Core
|
||||
{
|
||||
public class AnimationRuntime : MonoBehaviour
|
||||
{
|
||||
private static AnimationRuntime _instance;
|
||||
|
||||
private readonly List<IAnimation> _activeAnimations = new();
|
||||
private readonly ObjectPool<Animation> _animationPool = new(() => new Animation());
|
||||
private readonly List<IAnimation> _pendingAdditions = new();
|
||||
private readonly List<IAnimation> _pendingRemovals = new();
|
||||
|
||||
public static AnimationRuntime Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instance) return _instance;
|
||||
|
||||
var go = new GameObject("AnimationManager");
|
||||
_instance = go.AddComponent<AnimationRuntime>();
|
||||
DontDestroyOnLoad(go);
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_instance && _instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
_instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (_pendingAdditions.Count > 0)
|
||||
{
|
||||
_activeAnimations.AddRange(_pendingAdditions);
|
||||
_pendingAdditions.Clear();
|
||||
}
|
||||
|
||||
var deltaTime = Time.deltaTime;
|
||||
foreach (var animation in _activeAnimations)
|
||||
{
|
||||
animation.Update(deltaTime);
|
||||
|
||||
if (animation.IsComplete) _pendingRemovals.Add(animation);
|
||||
}
|
||||
|
||||
if (_pendingRemovals.Count > 0)
|
||||
{
|
||||
foreach (var animation in _pendingRemovals)
|
||||
{
|
||||
_activeAnimations.Remove(animation);
|
||||
ReturnToPool(animation);
|
||||
}
|
||||
|
||||
_pendingRemovals.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterAnimation(IAnimation animation)
|
||||
{
|
||||
_pendingAdditions.Add(animation);
|
||||
}
|
||||
|
||||
private void ReturnToPool(IAnimation animation)
|
||||
{
|
||||
if (animation is not Animation pooledAnimation) return;
|
||||
|
||||
pooledAnimation.Reset();
|
||||
_animationPool.Return(pooledAnimation);
|
||||
}
|
||||
|
||||
public Animation GetFromPool()
|
||||
{
|
||||
return _animationPool.Get();
|
||||
}
|
||||
|
||||
public Animation CreateAnimation(IAnimatable target, float duration, float delay,
|
||||
Easing.Function easingFunction)
|
||||
{
|
||||
var animation = _animationPool.Get();
|
||||
animation.Initialize(target, duration, delay, easingFunction);
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
}
|
3
Runtime/Core/AnimationRuntime.cs.meta
Normal file
3
Runtime/Core/AnimationRuntime.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e9a1adb612d743eb87fca704d4335d1b
|
||||
timeCreated: 1747860933
|
61
Runtime/Core/AnimationTypeBuilderBase.cs
Normal file
61
Runtime/Core/AnimationTypeBuilderBase.cs
Normal file
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using DC.Animator.Utils;
|
||||
|
||||
namespace DC.Animator.Core
|
||||
{
|
||||
public abstract class AnimationTypeBuilderBase
|
||||
{
|
||||
protected AnimationBuilder BaseBuilder { get; }
|
||||
|
||||
protected AnimationTypeBuilderBase(AnimationBuilder baseBuilder)
|
||||
{
|
||||
BaseBuilder = baseBuilder;
|
||||
}
|
||||
|
||||
public AnimationTypeBuilderBase WithDuration(float duration)
|
||||
{
|
||||
BaseBuilder.WithDuration(duration);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnimationTypeBuilderBase WithDelay(float delay)
|
||||
{
|
||||
BaseBuilder.WithDelay(delay);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnimationTypeBuilderBase WithEasing(Easing.Type easingType)
|
||||
{
|
||||
BaseBuilder.WithEasing(easingType);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnimationTypeBuilderBase OnStart(Action<IAnimation> callback)
|
||||
{
|
||||
BaseBuilder.OnStart(callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnimationTypeBuilderBase OnComplete(Action<IAnimation> callback)
|
||||
{
|
||||
BaseBuilder.OnComplete(callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AnimationTypeBuilderBase OnUpdate(Action<IAnimation> callback)
|
||||
{
|
||||
BaseBuilder.OnUpdate(callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
public abstract IAnimation Build();
|
||||
|
||||
public virtual IAnimation Start()
|
||||
{
|
||||
var animation = Build();
|
||||
AnimationRuntime.Instance.RegisterAnimation(animation);
|
||||
animation.Start();
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
}
|
2
Runtime/Core/AnimationTypeBuilderBase.cs.meta
Normal file
2
Runtime/Core/AnimationTypeBuilderBase.cs.meta
Normal file
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b3992f2125ccd5e4686b9f5aba900567
|
12
Runtime/Core/IAnimatable.cs
Normal file
12
Runtime/Core/IAnimatable.cs
Normal file
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
|
||||
namespace DC.Animator.Core
|
||||
{
|
||||
public interface IAnimatable
|
||||
{
|
||||
bool SupportsProperty(AnimatableProperty property);
|
||||
object GetValue(AnimatableProperty property);
|
||||
void SetValue(AnimatableProperty property, object value);
|
||||
Type GetPropertyType(AnimatableProperty property);
|
||||
}
|
||||
}
|
3
Runtime/Core/IAnimatable.cs.meta
Normal file
3
Runtime/Core/IAnimatable.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b60cedf76ef14da8830e3b09f87fed52
|
||||
timeCreated: 1747860577
|
23
Runtime/Core/IAnimation.cs
Normal file
23
Runtime/Core/IAnimation.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
using System;
|
||||
|
||||
namespace DC.Animator.Core
|
||||
{
|
||||
public interface IAnimation
|
||||
{
|
||||
bool IsComplete { get; }
|
||||
bool IsPlaying { get; }
|
||||
|
||||
void Start();
|
||||
void Pause();
|
||||
void Resume();
|
||||
void Stop();
|
||||
void Update(float deltaTime);
|
||||
|
||||
void SetProperty(AnimatableProperty property, object fromValue, object toValue);
|
||||
object GetValue(AnimatableProperty property);
|
||||
|
||||
event Action<IAnimation> OnStart;
|
||||
event Action<IAnimation> OnComplete;
|
||||
event Action<IAnimation> OnUpdate;
|
||||
}
|
||||
}
|
2
Runtime/Core/IAnimation.cs.meta
Normal file
2
Runtime/Core/IAnimation.cs.meta
Normal file
|
@ -0,0 +1,2 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 81f201c1b2e3c4845b9becc70b689633
|
3
Runtime/Data.meta
Normal file
3
Runtime/Data.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e430bcc3743b4759ae5d6319ba0c6203
|
||||
timeCreated: 1747861443
|
101
Runtime/Data/AnimationCollection.cs
Normal file
101
Runtime/Data/AnimationCollection.cs
Normal file
|
@ -0,0 +1,101 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using DC.Animator.Core;
|
||||
using DCAnimator.Data;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.Data
|
||||
{
|
||||
[CreateAssetMenu(fileName = "New Collection", menuName = "DCAnimator/Animation Collection")]
|
||||
public class AnimationCollection : ScriptableObject
|
||||
{
|
||||
public enum AnimationType
|
||||
{
|
||||
Fade,
|
||||
Move,
|
||||
Scale,
|
||||
Rotate,
|
||||
Color
|
||||
}
|
||||
|
||||
public List<AnimationData> animations = new();
|
||||
|
||||
public IAnimation CreateAnimation(IAnimatable target)
|
||||
{
|
||||
return animations.Count == 0 ? null : CreateAnimation(target, animations[0]);
|
||||
}
|
||||
|
||||
public IAnimation CreateAnimation(IAnimatable target, string name)
|
||||
{
|
||||
foreach (var animData in animations)
|
||||
if (animData.name == name)
|
||||
return CreateAnimation(target, animData);
|
||||
|
||||
Debug.LogWarning($"Animation preset {name} not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
private static IAnimation CreateAnimation(IAnimatable target, AnimationData data)
|
||||
{
|
||||
var builder = new AnimationBuilder()
|
||||
.WithTarget(target)
|
||||
.WithDuration(data.duration)
|
||||
.WithDelay(data.delay)
|
||||
.WithEasing(data.easingType);
|
||||
|
||||
IAnimation animation;
|
||||
|
||||
switch (data.type)
|
||||
{
|
||||
case AnimationType.Fade:
|
||||
animation = builder.AsFade()
|
||||
.From(data.fromAlpha)
|
||||
.To(data.toAlpha)
|
||||
.Build();
|
||||
break;
|
||||
|
||||
case AnimationType.Move:
|
||||
var moveBuilder = builder.AsMove()
|
||||
.From(data.fromPosition)
|
||||
.To(data.toPosition);
|
||||
|
||||
if (data.useLocalPosition)
|
||||
moveBuilder.Local();
|
||||
else if (data.useAnchoredPosition)
|
||||
moveBuilder.Anchored();
|
||||
|
||||
animation = moveBuilder.Build();
|
||||
break;
|
||||
|
||||
case AnimationType.Scale:
|
||||
animation = builder.AsScale()
|
||||
.From(data.fromScale)
|
||||
.To(data.toScale)
|
||||
.Build();
|
||||
break;
|
||||
|
||||
case AnimationType.Rotate:
|
||||
animation = builder.AsRotate()
|
||||
.FromEuler(data.fromEulerAngles)
|
||||
.ToEuler(data.toEulerAngles)
|
||||
.Build();
|
||||
break;
|
||||
|
||||
case AnimationType.Color:
|
||||
var colorBuilder = builder.AsColor()
|
||||
.From(data.fromColor)
|
||||
.To(data.toColor);
|
||||
|
||||
if (data.isTextColor)
|
||||
colorBuilder.AsTextColor();
|
||||
|
||||
animation = colorBuilder.Build();
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
return animation;
|
||||
}
|
||||
}
|
||||
}
|
3
Runtime/Data/AnimationCollection.cs.meta
Normal file
3
Runtime/Data/AnimationCollection.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 19427cdf82c041459cba5387f8783925
|
||||
timeCreated: 1747861458
|
41
Runtime/Data/AnimationData.cs
Normal file
41
Runtime/Data/AnimationData.cs
Normal file
|
@ -0,0 +1,41 @@
|
|||
using System;
|
||||
using DC.Animator.Data;
|
||||
using DC.Animator.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace DCAnimator.Data
|
||||
{
|
||||
[Serializable]
|
||||
public class AnimationData
|
||||
{
|
||||
// Core properties
|
||||
public string name;
|
||||
public AnimationCollection.AnimationType type;
|
||||
public float duration = 0.5f;
|
||||
public float delay;
|
||||
public Easing.Type easingType = Easing.Type.EaseOutQuad;
|
||||
|
||||
// Fade properties
|
||||
public float fromAlpha;
|
||||
public float toAlpha = 1f;
|
||||
|
||||
// Move properties
|
||||
public Vector3 fromPosition;
|
||||
public Vector3 toPosition;
|
||||
public bool useLocalPosition = true;
|
||||
public bool useAnchoredPosition;
|
||||
|
||||
// Scale properties
|
||||
public Vector3 fromScale = Vector3.one;
|
||||
public Vector3 toScale = Vector3.one;
|
||||
|
||||
// Rotate properties
|
||||
public Vector3 fromEulerAngles;
|
||||
public Vector3 toEulerAngles;
|
||||
|
||||
// Color properties
|
||||
public Color fromColor = Color.white;
|
||||
public Color toColor = Color.white;
|
||||
public bool isTextColor;
|
||||
}
|
||||
}
|
3
Runtime/Data/AnimationData.cs.meta
Normal file
3
Runtime/Data/AnimationData.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 5c42bc264cb1491aae30842803feb809
|
||||
timeCreated: 1748092986
|
3
Runtime/Utils.meta
Normal file
3
Runtime/Utils.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: b1241ae5d1614af4a88116a9e43b8bf5
|
||||
timeCreated: 1748092717
|
278
Runtime/Utils/EasingFunctions.cs
Normal file
278
Runtime/Utils/EasingFunctions.cs
Normal file
|
@ -0,0 +1,278 @@
|
|||
using UnityEngine;
|
||||
|
||||
namespace DC.Animator.Utils
|
||||
{
|
||||
public static class Easing
|
||||
{
|
||||
public delegate float Function(float t);
|
||||
|
||||
public enum Type
|
||||
{
|
||||
Linear,
|
||||
EaseInSine,
|
||||
EaseOutSine,
|
||||
EaseInOutSine,
|
||||
EaseInQuad,
|
||||
EaseOutQuad,
|
||||
EaseInOutQuad,
|
||||
EaseInCubic,
|
||||
EaseOutCubic,
|
||||
EaseInOutCubic,
|
||||
EaseInQuart,
|
||||
EaseOutQuart,
|
||||
EaseInOutQuart,
|
||||
EaseInQuint,
|
||||
EaseOutQuint,
|
||||
EaseInOutQuint,
|
||||
EaseInExpo,
|
||||
EaseOutExpo,
|
||||
EaseInOutExpo,
|
||||
EaseInCirc,
|
||||
EaseOutCirc,
|
||||
EaseInOutCirc,
|
||||
EaseInBack,
|
||||
EaseOutBack,
|
||||
EaseInOutBack,
|
||||
EaseInElastic,
|
||||
EaseOutElastic,
|
||||
EaseInOutElastic,
|
||||
EaseInBounce,
|
||||
EaseOutBounce,
|
||||
EaseInOutBounce
|
||||
}
|
||||
|
||||
private const float PI = Mathf.PI;
|
||||
private const float C1 = 1.70158f;
|
||||
private const float C2 = C1 * 1.525f;
|
||||
private const float C3 = C1 + 1f;
|
||||
private const float C4 = 2f * PI / 3f;
|
||||
private const float C5 = 2f * PI / 4.5f;
|
||||
|
||||
public static Function GetEasingFunction(Type type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
Type.Linear => Linear,
|
||||
Type.EaseInSine => EaseInSine,
|
||||
Type.EaseOutSine => EaseOutSine,
|
||||
Type.EaseInOutSine => EaseInOutSine,
|
||||
Type.EaseInQuad => EaseInQuad,
|
||||
Type.EaseOutQuad => EaseOutQuad,
|
||||
Type.EaseInOutQuad => EaseInOutQuad,
|
||||
Type.EaseInCubic => EaseInCubic,
|
||||
Type.EaseOutCubic => EaseOutCubic,
|
||||
Type.EaseInOutCubic => EaseInOutCubic,
|
||||
Type.EaseInQuart => EaseInQuart,
|
||||
Type.EaseOutQuart => EaseOutQuart,
|
||||
Type.EaseInOutQuart => EaseInOutQuart,
|
||||
Type.EaseInQuint => EaseInQuint,
|
||||
Type.EaseOutQuint => EaseOutQuint,
|
||||
Type.EaseInOutQuint => EaseInOutQuint,
|
||||
Type.EaseInExpo => EaseInExpo,
|
||||
Type.EaseOutExpo => EaseOutExpo,
|
||||
Type.EaseInOutExpo => EaseInOutExpo,
|
||||
Type.EaseInCirc => EaseInCirc,
|
||||
Type.EaseOutCirc => EaseOutCirc,
|
||||
Type.EaseInOutCirc => EaseInOutCirc,
|
||||
Type.EaseInBack => EaseInBack,
|
||||
Type.EaseOutBack => EaseOutBack,
|
||||
Type.EaseInOutBack => EaseInOutBack,
|
||||
Type.EaseInElastic => EaseInElastic,
|
||||
Type.EaseOutElastic => EaseOutElastic,
|
||||
Type.EaseInOutElastic => EaseInOutElastic,
|
||||
Type.EaseInBounce => EaseInBounce,
|
||||
Type.EaseOutBounce => EaseOutBounce,
|
||||
Type.EaseInOutBounce => EaseInOutBounce,
|
||||
_ => Linear
|
||||
};
|
||||
}
|
||||
|
||||
public static float Linear(float t)
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
public static float EaseInSine(float t)
|
||||
{
|
||||
return 1f - Mathf.Cos(t * PI / 2f);
|
||||
}
|
||||
|
||||
public static float EaseOutSine(float t)
|
||||
{
|
||||
return Mathf.Sin(t * PI / 2f);
|
||||
}
|
||||
|
||||
public static float EaseInOutSine(float t)
|
||||
{
|
||||
return -(Mathf.Cos(PI * t) - 1f) / 2f;
|
||||
}
|
||||
|
||||
public static float EaseInQuad(float t)
|
||||
{
|
||||
return t * t;
|
||||
}
|
||||
|
||||
public static float EaseOutQuad(float t)
|
||||
{
|
||||
return 1f - (1f - t) * (1f - t);
|
||||
}
|
||||
|
||||
public static float EaseInOutQuad(float t)
|
||||
{
|
||||
return t < 0.5f ? 2f * t * t : 1f - Mathf.Pow(-2f * t + 2f, 2f) / 2f;
|
||||
}
|
||||
|
||||
public static float EaseInCubic(float t)
|
||||
{
|
||||
return t * t * t;
|
||||
}
|
||||
|
||||
public static float EaseOutCubic(float t)
|
||||
{
|
||||
return 1f - Mathf.Pow(1f - t, 3f);
|
||||
}
|
||||
|
||||
public static float EaseInOutCubic(float t)
|
||||
{
|
||||
return t < 0.5f ? 4f * t * t * t : 1f - Mathf.Pow(-2f * t + 2f, 3f) / 2f;
|
||||
}
|
||||
|
||||
public static float EaseInQuart(float t)
|
||||
{
|
||||
return t * t * t * t;
|
||||
}
|
||||
|
||||
public static float EaseOutQuart(float t)
|
||||
{
|
||||
return 1f - Mathf.Pow(1f - t, 4f);
|
||||
}
|
||||
|
||||
public static float EaseInOutQuart(float t)
|
||||
{
|
||||
return t < 0.5f ? 8f * t * t * t * t : 1f - Mathf.Pow(-2f * t + 2f, 4f) / 2f;
|
||||
}
|
||||
|
||||
public static float EaseInQuint(float t)
|
||||
{
|
||||
return t * t * t * t * t;
|
||||
}
|
||||
|
||||
public static float EaseOutQuint(float t)
|
||||
{
|
||||
return 1f - Mathf.Pow(1f - t, 5f);
|
||||
}
|
||||
|
||||
public static float EaseInOutQuint(float t)
|
||||
{
|
||||
return t < 0.5f ? 16f * t * t * t * t * t : 1f - Mathf.Pow(-2f * t + 2f, 5f) / 2f;
|
||||
}
|
||||
|
||||
public static float EaseInExpo(float t)
|
||||
{
|
||||
return t == 0f ? 0f : Mathf.Pow(2f, 10f * t - 10f);
|
||||
}
|
||||
|
||||
public static float EaseOutExpo(float t)
|
||||
{
|
||||
return t == 1f ? 1f : 1f - Mathf.Pow(2f, -10f * t);
|
||||
}
|
||||
|
||||
public static float EaseInOutExpo(float t)
|
||||
{
|
||||
return t == 0f ? 0f :
|
||||
t == 1f ? 1f :
|
||||
t < 0.5f ? Mathf.Pow(2f, 20f * t - 10f) / 2f :
|
||||
(2f - Mathf.Pow(2f, -20f * t + 10f)) / 2f;
|
||||
}
|
||||
|
||||
public static float EaseInCirc(float t)
|
||||
{
|
||||
return 1f - Mathf.Sqrt(1f - Mathf.Pow(t, 2f));
|
||||
}
|
||||
|
||||
public static float EaseOutCirc(float t)
|
||||
{
|
||||
return Mathf.Sqrt(1f - Mathf.Pow(t - 1f, 2f));
|
||||
}
|
||||
|
||||
public static float EaseInOutCirc(float t)
|
||||
{
|
||||
return t < 0.5f
|
||||
? (1f - Mathf.Sqrt(1f - Mathf.Pow(2f * t, 2f))) / 2f
|
||||
: (Mathf.Sqrt(1f - Mathf.Pow(-2f * t + 2f, 2f)) + 1f) / 2f;
|
||||
}
|
||||
|
||||
public static float EaseInBack(float t)
|
||||
{
|
||||
return C3 * t * t * t - C1 * t * t;
|
||||
}
|
||||
|
||||
public static float EaseOutBack(float t)
|
||||
{
|
||||
return 1f + C3 * Mathf.Pow(t - 1f, 3f) + C1 * Mathf.Pow(t - 1f, 2f);
|
||||
}
|
||||
|
||||
public static float EaseInOutBack(float t)
|
||||
{
|
||||
return t < 0.5f
|
||||
? Mathf.Pow(2f * t, 2f) * ((C2 + 1f) * 2f * t - C2) / 2f
|
||||
: (Mathf.Pow(2f * t - 2f, 2f) * ((C2 + 1f) * (t * 2f - 2f) + C2) + 2f) / 2f;
|
||||
}
|
||||
|
||||
public static float EaseInElastic(float t)
|
||||
{
|
||||
return t switch
|
||||
{
|
||||
0f => 0f,
|
||||
1f => 1f,
|
||||
_ => -Mathf.Pow(2f, 10f * t - 10f) * Mathf.Sin((t * 10f - 10.75f) * C4)
|
||||
};
|
||||
}
|
||||
|
||||
public static float EaseOutElastic(float t)
|
||||
{
|
||||
return t switch
|
||||
{
|
||||
0f => 0f,
|
||||
1f => 1f,
|
||||
_ => Mathf.Pow(2f, -10f * t) * Mathf.Sin((t * 10f - 0.75f) * C4) + 1f
|
||||
};
|
||||
}
|
||||
|
||||
public static float EaseInOutElastic(float t)
|
||||
{
|
||||
return t == 0f ? 0f :
|
||||
t == 1f ? 1f :
|
||||
t < 0.5f ? -(Mathf.Pow(2f, 20f * t - 10f) * Mathf.Sin((20f * t - 11.125f) * C5)) / 2f :
|
||||
Mathf.Pow(2f, -20f * t + 10f) * Mathf.Sin((20f * t - 11.125f) * C5) / 2f + 1f;
|
||||
}
|
||||
|
||||
public static float EaseInBounce(float t)
|
||||
{
|
||||
return 1f - EaseOutBounce(1f - t);
|
||||
}
|
||||
|
||||
public static float EaseOutBounce(float t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case < 1f / 2.75f:
|
||||
return 7.5625f * t * t;
|
||||
case < 2f / 2.75f:
|
||||
t -= 1.5f / 2.75f;
|
||||
return 7.5625f * t * t + 0.75f;
|
||||
case < 2.5f / 2.75f:
|
||||
t -= 2.25f / 2.75f;
|
||||
return 7.5625f * t * t + 0.9375f;
|
||||
default:
|
||||
t -= 2.625f / 2.75f;
|
||||
return 7.5625f * t * t + 0.984375f;
|
||||
}
|
||||
}
|
||||
|
||||
public static float EaseInOutBounce(float t)
|
||||
{
|
||||
return t < 0.5f ? (1f - EaseOutBounce(1f - 2f * t)) / 2f : (1f + EaseOutBounce(2f * t - 1f)) / 2f;
|
||||
}
|
||||
}
|
||||
}
|
3
Runtime/Utils/EasingFunctions.cs.meta
Normal file
3
Runtime/Utils/EasingFunctions.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 999e76d81bee4d159317479117798d57
|
||||
timeCreated: 1747860988
|
21
Runtime/Utils/ObjectPool.cs
Normal file
21
Runtime/Utils/ObjectPool.cs
Normal file
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace DC.Animator.Utils
|
||||
{
|
||||
public class ObjectPool<T> where T : class
|
||||
{
|
||||
private readonly Stack<T> _pool = new Stack<T>();
|
||||
private readonly Func<T> _createFunc;
|
||||
|
||||
public ObjectPool(Func<T> createFunc) => _createFunc = createFunc;
|
||||
|
||||
public T Get() => _pool.Count > 0 ? _pool.Pop() : _createFunc();
|
||||
|
||||
public void Return(T obj) => _pool.Push(obj);
|
||||
|
||||
public void Clear() => _pool.Clear();
|
||||
|
||||
public int Count => _pool.Count;
|
||||
}
|
||||
}
|
3
Runtime/Utils/ObjectPool.cs.meta
Normal file
3
Runtime/Utils/ObjectPool.cs.meta
Normal file
|
@ -0,0 +1,3 @@
|
|||
fileFormatVersion: 2
|
||||
guid: a9ab03e1fa84423481b0a96d7299431b
|
||||
timeCreated: 1747860957
|
13
package.json
Normal file
13
package.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "com.danielcumbor.dcanimator",
|
||||
"version": "2.0.0",
|
||||
"displayName": "DC Animator",
|
||||
"description": "A custom Unity tool for animating objects.",
|
||||
"unity": "6000.0",
|
||||
"unityRelease": "23f1",
|
||||
"author": {
|
||||
"name": "Daniel Cumbor",
|
||||
"email": "danc@ultr.uk",
|
||||
"url": "https://www.danielcumbor.uk"
|
||||
}
|
||||
}
|
7
package.json.meta
Normal file
7
package.json.meta
Normal file
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 124a82e8e8b1b684e88cc1017d606c62
|
||||
PackageManifestImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
Loading…
Reference in a new issue