更新
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public class PropertyAnimationVector3 : AnimationBase
|
||||
{
|
||||
#region [暴露属性字段与关联] Exposed Fields & References
|
||||
public string componentName;
|
||||
public string propertyName;
|
||||
public FlexibleFloat propertyValueX, propertyValueY, propertyValueZ;
|
||||
|
||||
private Component targetComponent;
|
||||
private FieldInfo targetField;
|
||||
private PropertyInfo targetProperty;
|
||||
|
||||
// 高性能赋值委托
|
||||
private Action<Vector3> vectorSetterDelegate;
|
||||
#endregion
|
||||
|
||||
#region [生命周期与工厂] Lifecycle & Factory
|
||||
public static PropertyAnimationVector3 GenerateElement(string elementName, Guid id, List<string> tags, bool isFirstGenerated,
|
||||
GameElement animatedObject, string componentName, string propertyName,
|
||||
FlexibleFloat propertyValueX, FlexibleFloat propertyValueY, FlexibleFloat propertyValueZ)
|
||||
{
|
||||
PropertyAnimationVector3 animation = Instantiate(GameManager.Instance.basePrefabs.emptyObject)
|
||||
.AddComponent<PropertyAnimationVector3>();
|
||||
|
||||
animation.Initialize(elementName, id, tags, isFirstGenerated, animatedObject);
|
||||
|
||||
animation.animatedObject = animatedObject;
|
||||
|
||||
animation.componentName = componentName;
|
||||
animation.propertyName = propertyName;
|
||||
animation.propertyValueX = propertyValueX;
|
||||
animation.propertyValueY = propertyValueY;
|
||||
animation.propertyValueZ = propertyValueZ;
|
||||
|
||||
return animation;
|
||||
}
|
||||
|
||||
public override void AfterInitialize()
|
||||
{
|
||||
if (animatedObject == null || string.IsNullOrEmpty(componentName)) return;
|
||||
|
||||
Type componentType = GetTypeFromAllAssemblies(componentName);
|
||||
if (componentType != null)
|
||||
{
|
||||
targetComponent = animatedObject.GetComponentInChildren(componentType);
|
||||
}
|
||||
|
||||
if (targetComponent != null)
|
||||
{
|
||||
InitializeReflection();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"[PropertyAnimationVector3] Cannot find Component '{componentName}' strictly on '{animatedObject.name}'.");
|
||||
}
|
||||
|
||||
base.AfterInitialize();
|
||||
}
|
||||
|
||||
private Type GetTypeFromAllAssemblies(string typeName)
|
||||
{
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
Type type = assembly.GetType(typeName);
|
||||
if (type != null) return type;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void InitializeReflection()
|
||||
{
|
||||
Type type = targetComponent.GetType();
|
||||
|
||||
targetProperty = type.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (targetProperty != null && targetProperty.CanWrite)
|
||||
{
|
||||
MethodInfo setMethod = targetProperty.GetSetMethod(nonPublic: true);
|
||||
if (setMethod != null && targetProperty.PropertyType == typeof(Vector3))
|
||||
{
|
||||
try
|
||||
{
|
||||
vectorSetterDelegate = (Action<Vector3>)Delegate.CreateDelegate(typeof(Action<Vector3>), targetComponent, setMethod);
|
||||
return;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
targetField = type.GetField(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
if (targetField == null && targetProperty == null)
|
||||
{
|
||||
Debug.LogWarning($"[PropertyAnimationVector3] Cannot find target Property or Field '{propertyName}' strictly on '{componentName}'.");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region [核心动画逻辑] Core Animation Logic
|
||||
protected override void UpdateAnimation(float songTime)
|
||||
{
|
||||
if (targetComponent == null) return;
|
||||
|
||||
propertyValueX?.UpdateFlexibleFloat(songTime);
|
||||
propertyValueY?.UpdateFlexibleFloat(songTime);
|
||||
propertyValueZ?.UpdateFlexibleFloat(songTime);
|
||||
|
||||
float x = propertyValueX != null ? propertyValueX.value : 0f;
|
||||
float y = propertyValueY != null ? propertyValueY.value : 0f;
|
||||
float z = propertyValueZ != null ? propertyValueZ.value : 0f;
|
||||
|
||||
Vector3 targetVector = new Vector3(x, y, z);
|
||||
|
||||
if (vectorSetterDelegate != null)
|
||||
{
|
||||
vectorSetterDelegate(targetVector);
|
||||
}
|
||||
else if (targetProperty != null)
|
||||
{
|
||||
targetProperty.SetValue(targetComponent, targetVector);
|
||||
}
|
||||
else if (targetField != null)
|
||||
{
|
||||
targetField.SetValue(targetComponent, targetVector);
|
||||
}
|
||||
|
||||
if (animatedObject is IHaveDirtyMarkSubmodule dirtyTarget)
|
||||
{
|
||||
dirtyTarget.dirtyMarkSubmodule.MarkDirty(propertyName);
|
||||
}
|
||||
}
|
||||
|
||||
public override void ApplyTimeOffset(float offset)
|
||||
{
|
||||
base.ApplyTimeOffset(offset);
|
||||
void ApplyOffset(FlexibleFloat ff)
|
||||
{
|
||||
if (ff == null || ff.animations == null) return;
|
||||
foreach(var a in ff.animations) { a.startTime += offset; a.endTime += offset; }
|
||||
}
|
||||
ApplyOffset(propertyValueX);
|
||||
ApplyOffset(propertyValueY);
|
||||
ApplyOffset(propertyValueZ);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user