Files
ichni_Creator_Studio/Assets/Scripts/Graphical Animation Editor/EventPoint.cs

283 lines
11 KiB
C#
Raw Normal View History

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Ichni;
using Ichni.RhythmGame;
using TMPro;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.UI;
public class EventPoint : MonoBehaviour
{
public AnimatedFloat animatedFloat;
public EventPoint LastEventPoint;
public EventPoint NextEventPoint;
public Image EvDrawimage;
public Image OvDrawimage;
public RectTransform LeftSide;
public RectTransform RightSide;
public Button selectButton;
public RawImage CurveCanvas;
public FlexibleFloatTab FatherTab;
2025-05-11 00:20:27 +08:00
public TMP_Text ViewText;
public int BeatDeviver => FatherTab.BeatDeviver;
public void Initialize(AnimatedFloat animatedFloat)
{
this.animatedFloat = animatedFloat;
transform.localPosition = new Vector3(
animatedFloat.startTime / EditorManager.instance.timeline.timePerBeat * BeatDeviver, 0, 0
);
RightSide.localPosition = new Vector3(
(animatedFloat.endTime - animatedFloat.startTime) / EditorManager.instance.timeline.timePerBeat * BeatDeviver, 0, 0);
EvDrawimage.rectTransform.sizeDelta = new Vector2(RightSide.localPosition.x - LeftSide.localPosition.x, EvDrawimage.rectTransform.sizeDelta.y);
EvDrawimage.transform.localPosition = new Vector3(EvDrawimage.rectTransform.sizeDelta.x / 2, 0, 0);
OvDrawimage.transform.localPosition = RightSide.localPosition;
CurveCanvas.rectTransform.sizeDelta = new Vector2(EvDrawimage.rectTransform.sizeDelta.x, EvDrawimage.rectTransform.sizeDelta.y);
}
public float value => FatherTab.scalevalue;
public void ReDraw(float value)
{
Texture2D Texture = new Texture2D((int)CurveCanvas.rectTransform.sizeDelta.x / 5, (int)CurveCanvas.rectTransform.sizeDelta.y / 5);
for (int i = 0; i < Texture.width; i++)
{
for (int j = 0; j < Texture.height; j++)
{
Texture.SetPixel(i, j, new Color(0, 0, 0, 0));
}
}
Texture.Apply();
int LastEventPointY = 0;
for (int i = 0; i < Texture.width; i++)
{
float t = (float)i / Texture.width;
int f = (int)(
(Texture.height / 2) + (animatedFloat.startValue * value + ((animatedFloat.endValue - animatedFloat.startValue)
* AnimationCurveEvaluator.Evaluate(animatedFloat.animationCurveType, t) * value))
);
//不是哥们
for (int j = LastEventPointY; j < f; j++)
{
if (j < Texture.height) Texture.SetPixel(i, j, Color.green);
else Texture.SetPixel(i, j, Color.red);
}
for (int j = LastEventPointY; j > f; j--)
{
if (j > 0) Texture.SetPixel(i, j, Color.green);
else Texture.SetPixel(i, j, Color.red);
}
if (f < Texture.height && f > 0) Texture.SetPixel(i, f, Color.green);//丑陋
else Texture.SetPixel(i, f, Color.red);
LastEventPointY = f;
}
Texture.Apply();
CurveCanvas.texture = Texture;
if (NextEventPoint != null)
{
OvDrawimage.transform.localPosition = new Vector3(RightSide.transform.localPosition.x,
animatedFloat.endValue * value * 5, 0);
OvDrawimage.rectTransform.sizeDelta = new Vector2((NextEventPoint.animatedFloat.startTime - animatedFloat.endTime) / EditorManager.instance.uiManager.timeline.timePerBeat * FatherTab.BeatDeviver,
OvDrawimage.rectTransform.sizeDelta.y);
OvDrawimage.color = new Color(0, 1, 0, 1);
while (OvDrawimage.transform.localPosition.y > 100)
{
OvDrawimage.color = new Color(1, 0, 0, 0.3f);
OvDrawimage.transform.localPosition = new Vector3(OvDrawimage.transform.localPosition.x, OvDrawimage.transform.localPosition.y - 200, OvDrawimage.transform.localPosition.z);
}
while (OvDrawimage.transform.localPosition.y < -100)
{
OvDrawimage.color = new Color(1, 0, 0, 0.3f);
OvDrawimage.transform.localPosition = new Vector3(OvDrawimage.transform.localPosition.x, OvDrawimage.transform.localPosition.y + 200, OvDrawimage.transform.localPosition.z);
}
}
else
{
OvDrawimage.rectTransform.sizeDelta = new Vector2(0, OvDrawimage.rectTransform.sizeDelta.y
);
}
selectButton.transform.localPosition = EvDrawimage.transform.localPosition;
selectButton.GetComponent<RectTransform>().sizeDelta = EvDrawimage.rectTransform.sizeDelta;
2025-05-11 00:20:27 +08:00
ViewText.text = animatedFloat.startTime.ToString("0.00") + "s" + "\n" +
animatedFloat.startValue.ToString("0.0") + "\n" + animatedFloat.endValue.ToString("0.0") + "\n" + animatedFloat.endTime.ToString("0.00") + "s" + "\n" +
animatedFloat.animationCurveType.ToString();
ViewText.color = new Color(1, 1, 1, EvDrawimage.rectTransform.sizeDelta.x < 100 ? 0 : 1);
}
2025-05-11 00:20:27 +08:00
public void SelectButtonClick()//unity内当按钮按下时
{
if (Keyboard.current.leftShiftKey.isPressed)
{
if (FatherTab.FatherWindow.ClipBoard[FatherTab.Title].Contains(animatedFloat))
{
FatherTab.FatherWindow.ClipBoard[FatherTab.Title].Remove(animatedFloat);
LeftSide.sizeDelta = new Vector2(15, EvDrawimage.rectTransform.sizeDelta.y);
2025-05-11 00:20:27 +08:00
}
else
{
FatherTab.FatherWindow.ClipBoard[FatherTab.Title].Add(animatedFloat);
LeftSide.sizeDelta = EvDrawimage.rectTransform.sizeDelta;
}
2025-05-11 00:20:27 +08:00
FatherTab.FatherWindow.updateClipBoardMuM();
}
else UpLoad();
}
public void UpLoad()
{
FatherTab.FatherWindow.animationCurveTypeDropdown.onValueChanged.RemoveAllListeners();
// 如果当前点是已连接点,则取消连接并隐藏可见区域
if (FatherTab.FatherWindow.ConnectedPoint == this)
{
FatherTab.FatherWindow.VisibleArea.SetActive(false);
FatherTab.FatherWindow.ConnectedPoint = null;
EvDrawimage.color = new Color(EvDrawimage.color.r, 0.3019607843137255f, EvDrawimage.color.b, 0.5f);
FatherTab.FatherWindow.StartText.text = "";
FatherTab.FatherWindow.EndText.text = "";
FatherTab.FatherWindow.StartValueText.text = "";
FatherTab.FatherWindow.EndValueText.text = "";
return;
}
// 如果有已连接点,则重置其颜色
if (FatherTab.FatherWindow.ConnectedPoint != null)
{
2025-05-11 00:20:27 +08:00
FatherTab.TabButton.onClick.RemoveAllListeners();
FatherTab.TabButton.onClick.AddListener(FatherTab.AddEvent);
FatherTab.FatherWindow.EvEndpointChangeButton.GetComponent<Image>().color = new Color(1f, 1f, 1f, 1);
FatherTab.FatherWindow.ConnectedPoint.EvDrawimage.color = new Color(
FatherTab.FatherWindow.ConnectedPoint.EvDrawimage.color.r,
0.3019607843137255f,
FatherTab.FatherWindow.ConnectedPoint.EvDrawimage.color.b, 0.5f
);
}
// 设置新的连接点并更新UI
FatherTab.FatherWindow.ConnectedPoint = this;
EvDrawimage.color = new Color(EvDrawimage.color.r, 0.75f, EvDrawimage.color.b, 1f);
// 更新下拉选项
FatherTab.FatherWindow.animationCurveTypeDropdown.ClearOptions();
List<string> enumNameList = System.Enum.GetNames(typeof(AnimationCurveType)).ToList();
FatherTab.FatherWindow.VisibleArea.SetActive(true);
FatherTab.FatherWindow.animationCurveTypeDropdown.AddOptions(enumNameList);
FatherTab.FatherWindow.animationCurveTypeDropdown.value = (int)animatedFloat.animationCurveType;
// 更新文本
FatherTab.FatherWindow.StartText.text = animatedFloat.startTime.ToString();
FatherTab.FatherWindow.EndText.text = animatedFloat.endTime.ToString();
FatherTab.FatherWindow.StartValueText.text = animatedFloat.startValue.ToString();
FatherTab.FatherWindow.EndValueText.text = animatedFloat.endValue.ToString();
FatherTab.FatherWindow.animationCurveTypeDropdown.onValueChanged.AddListener(value => FatherTab.FatherWindow.ChangeValue());
}
2025-05-11 00:20:27 +08:00
// 添加静态方法:查找插入索引
public static int FindInsertIndex(List<EventPoint> eventPoints, float startTime)
{
int low = 0;
int high = eventPoints.Count - 1;
while (low <= high)
{
int mid = (low + high) / 2;
if (eventPoints[mid].animatedFloat.startTime < startTime)
{
low = mid + 1;
}
else
{
high = mid - 1;
}
}
return low;
}
// 添加实例方法:连接事件点
public void LinkEventPoints(List<EventPoint> eventPoints, int index)
{
if (index - 1 >= 0)
{
LastEventPoint = eventPoints[index - 1];
LastEventPoint.NextEventPoint = this;
}
else
{
LastEventPoint = null;
}
if (index == eventPoints.Count - 1)
{
NextEventPoint = null;
}
}
// 添加实例方法:连接新事件点
public void LinkNewEventPoint(List<EventPoint> eventPoints, bool link, float scalevalue)
{
int index = eventPoints.IndexOf(this);
if (index - 1 >= 0)
{
LastEventPoint = eventPoints[index - 1];
LastEventPoint.NextEventPoint = this;
LastEventPoint.ReDraw(scalevalue);
}
if (index + 1 < eventPoints.Count)
{
NextEventPoint = eventPoints[index + 1];
if (link) animatedFloat.endTime = NextEventPoint.animatedFloat.startTime;
Initialize(animatedFloat);
NextEventPoint.LastEventPoint = this;
}
}
// 添加静态方法:克隆 AnimatedFloat 并应用时间偏移
/// <summary>
/// 克隆一个 AnimatedFloat 对象,并根据偏移量调整其开始和结束时间。
/// </summary>
/// <param name="animatedFloat">要克隆的 AnimatedFloat 对象。</param>
/// <param name="offset">时间偏移量。</param>
/// <returns>克隆后的 AnimatedFloat 对象。</returns>
public static AnimatedFloat CloneWithOffset(AnimatedFloat animatedFloat, float offset)
{
return new AnimatedFloat(
animatedFloat.startTime + offset,
animatedFloat.endTime + offset,
animatedFloat.startValue,
animatedFloat.endValue,
animatedFloat.animationCurveType
);
}
}