453 lines
19 KiB
C#
453 lines
19 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Reflection;
|
||
using Ichni.RhythmGame;
|
||
using UnityEngine;
|
||
using UnityEngine.Events;
|
||
using UnityEngine.UI;
|
||
|
||
namespace Ichni.Editor
|
||
{
|
||
public partial class CompositeParameterWindow : MovableWindow
|
||
{
|
||
public Button addNewUnitButton;
|
||
public GameObject unitPrefab;
|
||
public IBaseElement connectedBaseElement;
|
||
public List<DynamicUICompositeUnit> unitList;
|
||
public string parameterName;
|
||
public UnityAction ApplyParameters;
|
||
|
||
public void Initialize(IBaseElement baseElement, string titleText, string parameterName)
|
||
{
|
||
transform.localScale = Vector3.zero;
|
||
this.connectedBaseElement = baseElement;
|
||
this.parameterName = parameterName;
|
||
unitList = new List<DynamicUICompositeUnit>();
|
||
|
||
InitializeWindow(titleText, ApplyParameters);
|
||
|
||
|
||
}
|
||
|
||
public void RemoveUnit(DynamicUICompositeUnit unit)
|
||
{
|
||
unitList.Remove(unit);
|
||
Destroy(unit.gameObject);
|
||
}
|
||
|
||
public CompositeParameterWindow AddListenerFunction(UnityAction action)
|
||
{
|
||
onQuit = action;
|
||
return this;
|
||
}
|
||
}
|
||
|
||
public partial class CompositeParameterWindow
|
||
{
|
||
public CompositeParameterWindow SetAsStringList()
|
||
{
|
||
//生成Unit
|
||
void GenerateUnit(string content)
|
||
{
|
||
DynamicUIInputFieldUnit unit = Instantiate(unitPrefab, windowRect).GetComponent<DynamicUIInputFieldUnit>();
|
||
unitList.Add(unit);
|
||
unit.SetUnit(this, content);
|
||
}
|
||
|
||
unitPrefab = EditorManager.instance.basePrefabs.inputFieldUnit;
|
||
|
||
//初始化:获取当前的List<string>,并生成对应的Unit
|
||
List<string> list = connectedBaseElement.GetType().GetField(parameterName).GetValue(connectedBaseElement) as List<string>;
|
||
foreach (string item in list)
|
||
{
|
||
GenerateUnit(item);
|
||
}
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
|
||
//为添加新的Unit的按钮设置点击事件
|
||
addNewUnitButton.onClick.AddListener(() =>
|
||
{
|
||
GenerateUnit("");
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
});
|
||
|
||
//将当前所有Unit的值应用到对应的变量中
|
||
ApplyParameters = () =>
|
||
{
|
||
List<string> stringList = unitList.Select(unit => (unit as DynamicUIInputFieldUnit).GetValue<string>()).ToList();
|
||
connectedBaseElement.GetType().GetField(parameterName).SetValue(connectedBaseElement, stringList);
|
||
};
|
||
|
||
return this;
|
||
}
|
||
|
||
|
||
public CompositeParameterWindow SetAsFloatList()
|
||
{
|
||
void GenerateUnit(float content)
|
||
{
|
||
DynamicUIInputFieldUnit unit = Instantiate(unitPrefab, windowRect).GetComponent<DynamicUIInputFieldUnit>();
|
||
unitList.Add(unit);
|
||
unit.SetUnit(this, content);
|
||
}
|
||
|
||
unitPrefab = EditorManager.instance.basePrefabs.inputFieldUnit;
|
||
List<float> list = connectedBaseElement.GetType().GetField(parameterName).GetValue(connectedBaseElement) as List<float>;
|
||
foreach (float item in list)
|
||
{
|
||
GenerateUnit(item);
|
||
}
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
|
||
addNewUnitButton.onClick.AddListener(() =>
|
||
{
|
||
GenerateUnit(0);
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
});
|
||
|
||
ApplyParameters = () =>
|
||
{
|
||
List<float> floatList = unitList.Select(unit => (unit as DynamicUIInputFieldUnit).GetValue<float>()).ToList();
|
||
connectedBaseElement.GetType().GetField(parameterName).SetValue(connectedBaseElement, floatList);
|
||
};
|
||
|
||
return this;
|
||
}
|
||
public Button GotoGraphicalAnimationEditorButton;
|
||
public CompositeParameterWindow SetAsFlexibleFloat()
|
||
{
|
||
void GenerateUnit(AnimatedFloat content)
|
||
{
|
||
DynamicUIAnimatedFloatUnit unit = Instantiate(unitPrefab, windowRect).GetComponent<DynamicUIAnimatedFloatUnit>();
|
||
unitList.Add(unit);
|
||
unit.SetUnit(this, content);
|
||
}
|
||
|
||
unitPrefab = EditorManager.instance.basePrefabs.animatedFloatUnit;
|
||
|
||
FlexibleFloat flexibleFloat = connectedBaseElement.GetType().GetField(parameterName).GetValue(connectedBaseElement) as FlexibleFloat;
|
||
foreach (AnimatedFloat animatedFloat in flexibleFloat.animations)
|
||
{
|
||
GenerateUnit(animatedFloat);
|
||
}
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
|
||
addNewUnitButton.onClick.AddListener(() =>
|
||
{
|
||
GenerateUnit(new AnimatedFloat(0, 0, 0, 0, AnimationCurveType.Linear));
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
});
|
||
|
||
ApplyParameters = () =>
|
||
{
|
||
FlexibleFloat newFlexibleFloat = new FlexibleFloat();
|
||
foreach (var unit in unitList)
|
||
{
|
||
newFlexibleFloat.animations.Add((unit as DynamicUIAnimatedFloatUnit).GetValue());
|
||
}
|
||
connectedBaseElement.GetType().GetField(parameterName).SetValue(connectedBaseElement, newFlexibleFloat);
|
||
};
|
||
|
||
GotoGraphicalAnimationEditorButton.gameObject.SetActive(true); // 隐藏按钮
|
||
GotoGraphicalAnimationEditorButton.onClick.AddListener(() =>
|
||
{
|
||
// 打开Graphical Animation Editor
|
||
IHaveInspection i = EditorManager.instance.uiManager.inspector as IHaveInspection;
|
||
i.GenerateGraphicalFlexibleFloatWindow(connectedBaseElement, "Graphical Animation Editor", new FlexibleFloat[] { flexibleFloat }, new string[] { "1" });
|
||
|
||
|
||
|
||
});
|
||
return this;
|
||
}
|
||
|
||
public CompositeParameterWindow SetAsFlexibleInt()
|
||
{
|
||
void GenerateUnit(AnimatedInt content)
|
||
{
|
||
DynamicUIAnimatedIntUnit unit = Instantiate(unitPrefab, windowRect).GetComponent<DynamicUIAnimatedIntUnit>();
|
||
unitList.Add(unit);
|
||
unit.SetUnit(this, content);
|
||
}
|
||
|
||
unitPrefab = EditorManager.instance.basePrefabs.animatedIntUnit;
|
||
|
||
FlexibleInt flexibleInt = connectedBaseElement.GetType().GetField(parameterName).GetValue(connectedBaseElement) as FlexibleInt;
|
||
foreach (AnimatedInt animatedInt in flexibleInt.animations)
|
||
{
|
||
GenerateUnit(animatedInt);
|
||
}
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
|
||
addNewUnitButton.onClick.AddListener(() =>
|
||
{
|
||
GenerateUnit(new AnimatedInt(0, 0));
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
});
|
||
|
||
ApplyParameters = () =>
|
||
{
|
||
FlexibleInt newFlexibleInt = new FlexibleInt();
|
||
foreach (var unit in unitList)
|
||
{
|
||
newFlexibleInt.animations.Add((unit as DynamicUIAnimatedIntUnit).GetValue());
|
||
}
|
||
connectedBaseElement.GetType().GetField(parameterName).SetValue(connectedBaseElement, newFlexibleInt);
|
||
};
|
||
|
||
return this;
|
||
}
|
||
|
||
public CompositeParameterWindow SetAsFlexibleBool()
|
||
{
|
||
void GenerateUnit(AnimatedBool content)
|
||
{
|
||
DynamicUIAnimatedBoolUnit unit = Instantiate(unitPrefab, windowRect).GetComponent<DynamicUIAnimatedBoolUnit>();
|
||
unitList.Add(unit);
|
||
unit.SetUnit(this, content);
|
||
}
|
||
|
||
unitPrefab = EditorManager.instance.basePrefabs.animatedBoolUnit;
|
||
FlexibleBool flexibleBool = connectedBaseElement.GetType().GetField(parameterName).GetValue(connectedBaseElement) as FlexibleBool;
|
||
foreach (AnimatedBool animatedBool in flexibleBool.animations)
|
||
{
|
||
GenerateUnit(animatedBool);
|
||
}
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
|
||
addNewUnitButton.onClick.AddListener(() =>
|
||
{
|
||
GenerateUnit(new AnimatedBool(0, false));
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
});
|
||
|
||
ApplyParameters = () =>
|
||
{
|
||
FlexibleBool newFlexibleBool = new FlexibleBool();
|
||
foreach (var unit in unitList)
|
||
{
|
||
newFlexibleBool.animations.Add((unit as DynamicUIAnimatedBoolUnit).GetValue());
|
||
}
|
||
connectedBaseElement.GetType().GetField(parameterName).SetValue(connectedBaseElement, newFlexibleBool);
|
||
};
|
||
|
||
return this;
|
||
}
|
||
|
||
|
||
|
||
public KeyframeVisualizer keyframeVisualizer;
|
||
public CompositeParameterWindow SetAsCustomCurve()
|
||
{
|
||
keyframeVisualizer.gameObject.SetActive(true);
|
||
|
||
// 获取字段信息和曲线数据
|
||
unitPrefab = EditorManager.instance.basePrefabs.customCurveKeyframeUnit;
|
||
FieldInfo fieldInfo = connectedBaseElement.GetType().GetField(parameterName);
|
||
AnimationCurve curve = fieldInfo.GetValue(connectedBaseElement) as AnimationCurve;
|
||
|
||
if (curve == null) curve = AnimationCurve.Linear(0, 0, 1, 1);
|
||
|
||
// 初始化预览器
|
||
keyframeVisualizer.curve = curve;
|
||
keyframeVisualizer.DrawCurveToRawImage();
|
||
keyframeVisualizer.RebuildInteractablePoints();
|
||
|
||
// 关键点:松开手柄时的回调
|
||
keyframeVisualizer.OnEditFinished = () =>
|
||
{
|
||
// 同步左侧 Unit 列表的数值显示(假设 unitList[0] 是 WrapMode)
|
||
for (int i = 0; i < keyframeVisualizer.curve.length; i++)
|
||
{
|
||
int unitIdx = i + 1;
|
||
if (unitIdx < unitList.Count)
|
||
{
|
||
var unit = unitList[unitIdx] as DynamicUICustomCurveKeyframeUnit;
|
||
if (unit != null) unit.SetUnit(this, keyframeVisualizer.curve.keys[i]);
|
||
}
|
||
}
|
||
ApplyParameters?.Invoke();
|
||
};
|
||
|
||
// 生成 WrapMode 单元
|
||
WarpModes warpModes = new WarpModes(curve.preWrapMode, curve.postWrapMode);
|
||
var wmUnit = Instantiate(EditorManager.instance.basePrefabs.customCurveWrapModeUnit, windowRect)
|
||
.GetComponent<DynamicUICustomCurveWrapModeUnit>();
|
||
unitList.Add(wmUnit);
|
||
wmUnit.SetUnit(this, warpModes);
|
||
|
||
// 生成 Keyframe 单元
|
||
void GenerateUnit(Keyframe content)
|
||
{
|
||
var unit = Instantiate(unitPrefab, windowRect).GetComponent<DynamicUICustomCurveKeyframeUnit>();
|
||
unitList.Add(unit);
|
||
unit.SetUnit(this, content);
|
||
}
|
||
|
||
foreach (Keyframe k in curve.keys) GenerateUnit(k);
|
||
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
addNewUnitButton.onClick.AddListener(() =>
|
||
{
|
||
Keyframe newKey = new Keyframe(0.5f, 0.5f, 0, 0);
|
||
keyframeVisualizer.curve.AddKey(newKey);
|
||
GenerateUnit(newKey);
|
||
keyframeVisualizer.RebuildInteractablePoints();
|
||
keyframeVisualizer.DrawCurveToRawImage();
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
});
|
||
|
||
// 真正的应用/保存逻辑
|
||
ApplyParameters = () =>
|
||
{
|
||
AnimationCurve newCurve = new AnimationCurve();
|
||
// 1. 获取 WrapMode
|
||
var wUnit = unitList[0] as DynamicUICustomCurveWrapModeUnit;
|
||
newCurve.preWrapMode = wUnit.GetValue().preWrapMode;
|
||
newCurve.postWrapMode = wUnit.GetValue().postWrapMode;
|
||
|
||
// 2. 获取所有 Keyframes
|
||
for (int i = 1; i < unitList.Count; i++)
|
||
{
|
||
var kUnit = unitList[i] as DynamicUICustomCurveKeyframeUnit;
|
||
newCurve.AddKey(kUnit.GetValue());
|
||
}
|
||
|
||
fieldInfo.SetValue(connectedBaseElement, newCurve);
|
||
keyframeVisualizer.curve = newCurve;
|
||
keyframeVisualizer.DrawCurveToRawImage();
|
||
};
|
||
|
||
return this;
|
||
}
|
||
public CompositeParameterWindow SetAsGradientColorKeys()
|
||
{
|
||
void GenerateUnit(GradientColorKey content)
|
||
{
|
||
DynamicUIGradientColorKeyUnit unit = Instantiate(unitPrefab, windowRect).GetComponent<DynamicUIGradientColorKeyUnit>();
|
||
unitList.Add(unit);
|
||
unit.SetUnit(this, content);
|
||
}
|
||
|
||
unitPrefab = EditorManager.instance.basePrefabs.gradientColorKeyUnit;
|
||
Gradient gradient = connectedBaseElement.GetType().GetField(parameterName).GetValue(connectedBaseElement) as Gradient;
|
||
List<GradientColorKey> colorKeys = gradient.colorKeys.ToList();
|
||
foreach (GradientColorKey colorKey in colorKeys)
|
||
{
|
||
GenerateUnit(colorKey);
|
||
}
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
|
||
addNewUnitButton.onClick.AddListener(() =>
|
||
{
|
||
GenerateUnit(new GradientColorKey(Color.white, 1));
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
});
|
||
|
||
ApplyParameters = () =>
|
||
{
|
||
List<GradientColorKey> newColorKeys = new List<GradientColorKey>();
|
||
foreach (var unit in unitList)
|
||
{
|
||
newColorKeys.Add((unit as DynamicUIGradientColorKeyUnit).GetValue());
|
||
}
|
||
FieldInfo fieldInfo = connectedBaseElement.GetType().GetField(parameterName);
|
||
Gradient originalGradient = fieldInfo.GetValue(connectedBaseElement) as Gradient;
|
||
Gradient newIndependentGradient = new Gradient();
|
||
newIndependentGradient.alphaKeys = originalGradient.alphaKeys;
|
||
newIndependentGradient.mode = originalGradient.mode;
|
||
newIndependentGradient.colorKeys = newColorKeys.ToArray();
|
||
fieldInfo.SetValue(connectedBaseElement, newIndependentGradient);
|
||
};
|
||
|
||
return this;
|
||
}
|
||
|
||
public CompositeParameterWindow SetAsGradientAlphaKeys()
|
||
{
|
||
void GenerateUnit(GradientAlphaKey content)
|
||
{
|
||
DynamicUIGradientAlphaKeyUnit unit = Instantiate(unitPrefab, windowRect).GetComponent<DynamicUIGradientAlphaKeyUnit>();
|
||
unitList.Add(unit);
|
||
unit.SetUnit(this, content);
|
||
}
|
||
|
||
unitPrefab = EditorManager.instance.basePrefabs.gradientAlphaKeyUnit;
|
||
Gradient gradient = connectedBaseElement.GetType().GetField(parameterName).GetValue(connectedBaseElement) as Gradient;
|
||
List<GradientAlphaKey> alphaKeys = gradient.alphaKeys.ToList();
|
||
foreach (GradientAlphaKey alphaKey in alphaKeys)
|
||
{
|
||
GenerateUnit(alphaKey);
|
||
}
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
|
||
addNewUnitButton.onClick.AddListener(() =>
|
||
{
|
||
GenerateUnit(new GradientAlphaKey(1, 1));
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
});
|
||
|
||
ApplyParameters = () =>
|
||
{
|
||
List<GradientAlphaKey> newAlphaKeys = new List<GradientAlphaKey>();
|
||
foreach (var unit in unitList)
|
||
{
|
||
newAlphaKeys.Add((unit as DynamicUIGradientAlphaKeyUnit).GetValue());
|
||
}
|
||
FieldInfo fieldInfo = connectedBaseElement.GetType().GetField(parameterName);
|
||
Gradient originalGradient = fieldInfo.GetValue(connectedBaseElement) as Gradient;
|
||
Gradient newIndependentGradient = new Gradient();
|
||
newIndependentGradient.colorKeys = originalGradient.colorKeys;
|
||
newIndependentGradient.mode = originalGradient.mode;
|
||
newIndependentGradient.alphaKeys = newAlphaKeys.ToArray();
|
||
fieldInfo.SetValue(connectedBaseElement, newIndependentGradient);
|
||
};
|
||
|
||
return this;
|
||
}
|
||
|
||
public CompositeParameterWindow SetAsStringIntDictionary()
|
||
{
|
||
//生成Unit
|
||
void GenerateUnit(KeyValuePair<string, int> content)
|
||
{
|
||
DynamicUIStringIntPairUnit unit = Instantiate(unitPrefab, windowRect).GetComponent<DynamicUIStringIntPairUnit>();
|
||
unitList.Add(unit);
|
||
unit.SetUnit(this, content);
|
||
}
|
||
|
||
unitPrefab = EditorManager.instance.basePrefabs.stringIntPairUnit;
|
||
|
||
Dictionary<string, int> dictionary = connectedBaseElement.GetType().GetField(parameterName).GetValue(connectedBaseElement) as Dictionary<string, int>;
|
||
foreach (var pair in dictionary)
|
||
{
|
||
GenerateUnit(pair);
|
||
}
|
||
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
|
||
//为添加新的Unit的按钮设置点击事件
|
||
addNewUnitButton.onClick.AddListener(() =>
|
||
{
|
||
GenerateUnit(new KeyValuePair<string, int>("New Variable", 0));
|
||
addNewUnitButton.GetComponent<RectTransform>().SetAsLastSibling();
|
||
});
|
||
|
||
//将当前所有Unit的值应用到对应的变量中
|
||
ApplyParameters = () =>
|
||
{
|
||
Dictionary<string, int> dictionaryList = new Dictionary<string, int>();
|
||
foreach (var unit in unitList)
|
||
{
|
||
KeyValuePair<string, int> pair = (unit as DynamicUIStringIntPairUnit).GetValue();
|
||
dictionaryList.Add(pair.Key, pair.Value);
|
||
}
|
||
FieldInfo fieldInfo = connectedBaseElement.GetType().GetField(parameterName);
|
||
fieldInfo.SetValue(connectedBaseElement, dictionaryList);
|
||
};
|
||
|
||
return this;
|
||
}
|
||
}
|
||
} |