@@ -205,8 +205,8 @@ namespace Ichni.Editor
|
||||
{
|
||||
string a = arg.Trim();
|
||||
|
||||
// Vector2/3: [1,2] 或 [1,2,3]
|
||||
if (Regex.IsMatch(a, @"^\[\s*-?\d+(\.\d+)?\s*,\s*-?\d+(\.\d+)?(\s*,\s*-?\d+(\.\d+)?)*\s*\]$"))
|
||||
// Vector2/3: [1,2] 或 [1,2,3],支持小数
|
||||
if (Regex.IsMatch(a, @"^\[\s*-?\d*\.?\d+\s*,\s*-?\d*\.?\d+(\s*,\s*-?\d*\.?\d+)*\s*\]$"))
|
||||
{
|
||||
// 去除中括号和空格
|
||||
string content = a.Substring(1, a.Length - 2).Trim();
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Ichni.Editor
|
||||
}
|
||||
|
||||
|
||||
public static void Lgp(int loop, Vector3 start, Vector3 end, bool Clear = false)
|
||||
public static void Lgp(int loop, Vector3 start, Vector3 end, bool Clear = false, bool offsetOrigin = false)
|
||||
{
|
||||
if (inspector.connectedGameElement == null || inspector.connectedGameElement.GetType() != typeof(Track))
|
||||
{
|
||||
@@ -54,10 +54,18 @@ namespace Ichni.Editor
|
||||
return;
|
||||
}
|
||||
Track track = (Track)inspector.connectedGameElement;
|
||||
List<PathNode> oldNodes = track.trackPathSubmodule.pathNodeList.ToList();
|
||||
List<PathNode> newNodes = new List<PathNode>();
|
||||
// 如果 Clear 且有旧节点,迁移变换
|
||||
|
||||
if (Clear)
|
||||
{
|
||||
if (offsetOrigin && oldNodes.Count > 0 && newNodes.Count > 0)
|
||||
{
|
||||
AdjustPathNodesToNearest(track, newNodes, oldNodes);
|
||||
}
|
||||
// 清除之前的PathNode
|
||||
foreach (var node in track.trackPathSubmodule.pathNodeList.ToList())
|
||||
foreach (var node in oldNodes)
|
||||
{
|
||||
EditorManager.instance.operationManager.CopyPasteDeleteModule.DeleteElement(node);
|
||||
}
|
||||
@@ -70,7 +78,38 @@ namespace Ichni.Editor
|
||||
float z = start.z + (end.z - start.z) * t;
|
||||
PathNode j = PathNode.GenerateElement("PathNode" + i.ToString(), Guid.NewGuid(), new List<string>(), true, track, true);
|
||||
j.transformSubmodule.originalPosition = new Vector3(x, y, z);
|
||||
newNodes.Add(j);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将原有 PathNode 的变换(位置、旋转、缩放)迁移到新生成的最近 PathNode 上
|
||||
/// </summary>
|
||||
public static bool AdjustPathNodesToNearest(Track track, List<PathNode> newNodes, List<PathNode> oldNodes)
|
||||
{
|
||||
foreach (var oldNode in oldNodes)
|
||||
{
|
||||
// 找到距离 oldNode 最近的新节点
|
||||
PathNode nearest = newNodes
|
||||
.OrderBy(n => Vector3.Distance(n.transformSubmodule.originalPosition, oldNode.transformSubmodule.originalPosition))
|
||||
.FirstOrDefault();
|
||||
|
||||
if (nearest != null)
|
||||
{
|
||||
// 计算 oldNode 的变换(直接用欧拉角,不用四元数)
|
||||
Vector3 deltaPos = oldNode.transformSubmodule.originalPosition - oldNode.transformSubmodule.originalPosition;
|
||||
Vector3 deltaEuler = oldNode.transformSubmodule.originalEulerAngles - oldNode.transformSubmodule.originalEulerAngles;
|
||||
Vector3 deltaScale = oldNode.transformSubmodule.originalScale - oldNode.transformSubmodule.originalScale;
|
||||
|
||||
// 将变换应用到新节点
|
||||
nearest.transformSubmodule.originalPosition += deltaPos;
|
||||
nearest.transformSubmodule.originalEulerAngles += deltaEuler;
|
||||
nearest.transformSubmodule.originalScale += deltaScale;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Ichni.Editor
|
||||
public Hierarchy hierarchy;
|
||||
public Inspector inspector;
|
||||
public Timeline timeline;
|
||||
|
||||
public Canvas WindowsCanvas;
|
||||
public List<StaticWindow> staticWindows;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -23,21 +23,21 @@ namespace Ichni.Editor
|
||||
{
|
||||
CompositeParameterWindow compositeParameterWindow =
|
||||
Object.Instantiate(EditorManager.instance.basePrefabs.compositeParameterWindow,
|
||||
EditorManager.instance.uiManager.inspector.inspectorCanvas.GetComponent<RectTransform>())
|
||||
EditorManager.instance.uiManager.WindowsCanvas.GetComponent<RectTransform>())
|
||||
.GetComponent<CompositeParameterWindow>();
|
||||
compositeParameterWindow.Initialize(baseElement, title, parameterName);
|
||||
return compositeParameterWindow;
|
||||
}
|
||||
public GraphicalFlexibleFloatWindow GenerateGraphicalFlexibleFloatWindow(IBaseElement baseElement, string title, FlexibleFloat[] FlexibleFloats, string[] subTitle)
|
||||
{
|
||||
GraphicalFlexibleFloatWindow graphicalFlexibleFloatWindow = Object.Instantiate(EditorManager.instance.basePrefabs.graphicalFlexibleFloatWindow, EditorManager.instance.uiManager.inspector.inspectorCanvas.GetComponent<RectTransform>())
|
||||
GraphicalFlexibleFloatWindow graphicalFlexibleFloatWindow = Object.Instantiate(EditorManager.instance.basePrefabs.graphicalFlexibleFloatWindow, EditorManager.instance.uiManager.WindowsCanvas.GetComponent<RectTransform>())
|
||||
.GetComponent<GraphicalFlexibleFloatWindow>();
|
||||
graphicalFlexibleFloatWindow.Initialize(baseElement, title, FlexibleFloats, subTitle);
|
||||
return graphicalFlexibleFloatWindow;
|
||||
}
|
||||
public SampleWindow GenerateSampler(GameElement baseElement, string title)
|
||||
{
|
||||
SampleWindow sampler = Object.Instantiate(EditorManager.instance.basePrefabs.sampler, EditorManager.instance.uiManager.inspector.inspectorCanvas.GetComponent<RectTransform>())
|
||||
SampleWindow sampler = Object.Instantiate(EditorManager.instance.basePrefabs.sampler, EditorManager.instance.uiManager.WindowsCanvas.GetComponent<RectTransform>())
|
||||
.GetComponent<SampleWindow>();
|
||||
sampler.Initialize(baseElement, title);
|
||||
return sampler;
|
||||
@@ -130,7 +130,7 @@ namespace Ichni.Editor
|
||||
subcontainer.dynamicUIElements.Add(vector3InputField);
|
||||
return vector3InputField;
|
||||
}
|
||||
|
||||
|
||||
public DynamicUIVector2InputField GenerateVector2InputField(IBaseElement baseElement,
|
||||
DynamicUISubcontainer subcontainer, string title, string parameterName, bool isAutoUpdate = false)
|
||||
{
|
||||
|
||||
@@ -3,23 +3,26 @@ using System.Collections.Generic;
|
||||
using Lean.Pool;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace Ichni.Editor
|
||||
{
|
||||
public class LogText : MonoBehaviour
|
||||
{
|
||||
public TMP_Text logText;
|
||||
|
||||
|
||||
public void SetLogText(string text, Color color)
|
||||
{
|
||||
logText.text = text;
|
||||
logText.color = color;
|
||||
|
||||
|
||||
string logFilePath = EditorManager.instance.projectInformation.projectPath + "/Logs/EditorLog.txt";
|
||||
|
||||
|
||||
// if(!ES3.FileExists(logFilePath)) System.IO.File.Create(logFilePath).Dispose();
|
||||
//
|
||||
// System.IO.File.AppendAllText(logFilePath, text + "\n");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using DG.Tweening;
|
||||
using Lean.Pool;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Serialization;
|
||||
@@ -13,18 +14,17 @@ namespace Ichni.Editor
|
||||
public GameObject logTextPrefab;
|
||||
|
||||
List<string> savedTexts;
|
||||
|
||||
public RectTransform textRect;
|
||||
public Button copyAllTextsButton;
|
||||
public Button removeAllTextsButton;
|
||||
public Queue<LogText> logTexts;
|
||||
public List<LogText> logTexts; // 改为 List
|
||||
public int logTextCapacity = 4;
|
||||
|
||||
protected override void Start()
|
||||
{
|
||||
base.Start();
|
||||
savedTexts = new List<string>();
|
||||
logTexts = new Queue<LogText>();
|
||||
logTexts = new List<LogText>(); // 初始化为 List
|
||||
copyAllTextsButton.onClick.AddListener(CopyAllText);
|
||||
removeAllTextsButton.onClick.AddListener(RemoveAllText);
|
||||
}
|
||||
@@ -36,19 +36,37 @@ namespace Ichni.Editor
|
||||
|
||||
private void AddLog(string text, Color color = default)
|
||||
{
|
||||
CheckLogTextCapacity();
|
||||
LogText logText = LeanPool.Spawn(logTextPrefab, textRect).GetComponent<LogText>();
|
||||
if (color == default) color = Color.white;
|
||||
savedTexts.Add(text);
|
||||
logText.SetLogText(text, color);
|
||||
logTexts.Enqueue(logText);
|
||||
}
|
||||
|
||||
private void CheckLogTextCapacity()
|
||||
{
|
||||
if (logTexts.Count >= logTextCapacity)
|
||||
// 插入到头部
|
||||
logTexts.Insert(0, logText);
|
||||
|
||||
// 超出容量则移除最后一个
|
||||
if (logTexts.Count > logTextCapacity)
|
||||
{
|
||||
LeanPool.Despawn(logTexts.Dequeue().gameObject);
|
||||
LogText logText1 = logTexts[logTexts.Count - 1];
|
||||
RectTransform rt = logText1.GetComponent<RectTransform>();
|
||||
rt.DOComplete();
|
||||
rt.DOAnchorPos(new Vector2(0, -23 * (logTexts.Count - 1)), 0.2f).SetEase(Ease.OutCubic);
|
||||
logText1.logText.DOColor(new Color(0, 0, 0, 0), 0.2f).OnComplete(() =>
|
||||
{
|
||||
LeanPool.Despawn(logText1.gameObject);
|
||||
});
|
||||
|
||||
logTexts.RemoveAt(logTexts.Count - 1);
|
||||
|
||||
}
|
||||
logText.logText.color = new Color(0, 0, 0, 0);
|
||||
logText.logText.DOColor(color, 0.2f);
|
||||
// 更新所有 log 的位置
|
||||
for (int i = 0; i < logTexts.Count; i++)
|
||||
{
|
||||
RectTransform rt = logTexts[i].GetComponent<RectTransform>();
|
||||
rt.DOComplete();
|
||||
rt.DOAnchorPos(new Vector2(0, -23 * i), 0.2f).SetEase(Ease.OutCubic);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using DG.Tweening;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
@@ -24,7 +25,10 @@ namespace Ichni.Editor
|
||||
{
|
||||
onCloseWindow?.Invoke();
|
||||
onQuit?.Invoke();
|
||||
Destroy(gameObject);
|
||||
this.transform.DOScale(Vector3.zero, 0.15f).SetEase(Ease.InCirc).OnComplete(() =>
|
||||
{
|
||||
Destroy(gameObject);
|
||||
});
|
||||
});
|
||||
StartCoroutine(WindowAnim.ShowPanelOnScale(gameObject));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using DG.Tweening;
|
||||
using Sirenix.OdinInspector;
|
||||
using TMPro;
|
||||
using UniRx;
|
||||
@@ -26,6 +27,13 @@ namespace Ichni.Editor
|
||||
// anchoredPosition = this.GetComponent<RectTransform>().anchoredPosition;
|
||||
// anchoredPosition3D = this.GetComponent<RectTransform>().anchoredPosition3D;
|
||||
// }
|
||||
|
||||
public void PlayAnim()
|
||||
{
|
||||
intervalUnitText.transform.DOKill();
|
||||
intervalUnitText.transform.DOScale(Vector3.one * 1.5f, 0.1f).SetEase(Ease.OutCubic).OnComplete(() =>
|
||||
{
|
||||
intervalUnitText.transform.DOScale(Vector3.one, 0.5f).SetEase(Ease.OutCubic);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using Ichni.RhythmGame;
|
||||
using UniRx;
|
||||
using UnityEngine;
|
||||
@@ -15,7 +16,9 @@ namespace Ichni.Editor
|
||||
|
||||
public GameObject timePointerPrefab;
|
||||
public List<TimePointer> timePointerList;
|
||||
public List<TimePointer> ActivePointer => timePointerList.FindAll(pointer => pointer.gameObject.activeSelf);
|
||||
private TimePointer NowPointer;
|
||||
|
||||
public RectTransform moveTabPoint;
|
||||
public RectTransform timePointerContainer;
|
||||
public RectTransform rightSide;
|
||||
@@ -38,7 +41,7 @@ namespace Ichni.Editor
|
||||
{
|
||||
TimePointer timePointer = Instantiate(timePointerPrefab, timePointerContainer).GetComponent<TimePointer>();
|
||||
timePointerList.Add(timePointer);
|
||||
|
||||
timePointer.time = i * timeline.timePerBeat;
|
||||
timePointer.intervalUnitText.text = (i * timeline.timePerBeat).ToString("F3");
|
||||
timePointer.GetComponent<RectTransform>().localPosition = new Vector3(i * timePointerInterval, 0f, 0f);
|
||||
timePointer.index = i;
|
||||
@@ -94,5 +97,6 @@ namespace Ichni.Editor
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@ namespace Ichni.Editor
|
||||
public TimePointerModule timePointerModule;
|
||||
public MusicPlayModule musicPlayModule;
|
||||
|
||||
|
||||
private TimePointer MarkedPointer;
|
||||
public TMP_InputField TimeField;
|
||||
public TMP_InputField BeatField;
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace Ichni.Editor
|
||||
{
|
||||
|
||||
DetectSetRange();
|
||||
DetectPointer();
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +87,71 @@ namespace Ichni.Editor
|
||||
}
|
||||
}
|
||||
}
|
||||
private void DetectPointer()
|
||||
{
|
||||
if (Mouse.current.leftButton.wasPressedThisFrame)
|
||||
{
|
||||
foreach (var pointer in timePointerModule.ActivePointer)
|
||||
{
|
||||
if (RectTransformUtility.RectangleContainsScreenPoint(pointer.intervalUnitText.GetComponent<RectTransform>(), Mouse.current.position.ReadValue()))
|
||||
{
|
||||
GUIUtility.systemCopyBuffer = pointer.intervalUnitText.text;
|
||||
LogWindow.Log("Copied Time: " + pointer.intervalUnitText.text + " Marked Pointer");
|
||||
if (MarkedPointer != null) MarkedPointer.intervalUnitText.color = Color.white;
|
||||
|
||||
pointer.intervalUnitText.color = Color.yellow;
|
||||
pointer.PlayAnim();
|
||||
MarkedPointer = pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Mouse.current.rightButton.wasPressedThisFrame)
|
||||
{
|
||||
foreach (var pointer in timePointerModule.ActivePointer)
|
||||
{
|
||||
if (RectTransformUtility.RectangleContainsScreenPoint(pointer.intervalUnitText.GetComponent<RectTransform>(), Mouse.current.position.ReadValue()))
|
||||
{
|
||||
GUIUtility.systemCopyBuffer = Mathf.Abs(pointer.time - MarkedPointer.time).ToString("F3");
|
||||
LogWindow.Log("Total Time: " + Mathf.Abs(pointer.time - MarkedPointer.time).ToString("F3"));
|
||||
|
||||
pointer.PlayAnim();
|
||||
pointer.intervalUnitText.color = Color.yellow;
|
||||
pointer.intervalUnitText.DOColor(Color.white, 0.5f);
|
||||
// 灰色矩形动画效果
|
||||
if (MarkedPointer != null && pointer != MarkedPointer)
|
||||
{
|
||||
var rt1 = pointer.intervalUnitText.GetComponent<RectTransform>();
|
||||
var rt2 = MarkedPointer.intervalUnitText.GetComponent<RectTransform>();
|
||||
var parentRect = timePointerModule.timePointerContainer;
|
||||
|
||||
// 世界坐标转父级本地坐标
|
||||
Vector3 localPos1 = parentRect.InverseTransformPoint(rt1.position);
|
||||
Vector3 localPos2 = parentRect.InverseTransformPoint(rt2.position);
|
||||
|
||||
float minX = Mathf.Min(localPos1.x, localPos2.x);
|
||||
float width = Mathf.Abs(localPos1.x - localPos2.x);
|
||||
float minY = Mathf.Min(localPos1.y, localPos2.y);
|
||||
float height = Mathf.Max(rt1.rect.height, rt2.rect.height);
|
||||
|
||||
GameObject rectObj = new GameObject("PointerRangeRect", typeof(RectTransform), typeof(Image));
|
||||
rectObj.transform.SetParent(parentRect, false);
|
||||
var rectTrans = rectObj.GetComponent<RectTransform>();
|
||||
var image = rectObj.GetComponent<Image>();
|
||||
image.color = new Color(1f, 1f, 1f, 0.5f);
|
||||
|
||||
rectTrans.anchorMin = new Vector2(0, 0);
|
||||
rectTrans.anchorMax = new Vector2(0, 0);
|
||||
rectTrans.pivot = new Vector2(0, 0);
|
||||
rectTrans.localPosition = new Vector3(minX, minY - (height / 2), 0);
|
||||
rectTrans.sizeDelta = new Vector2(width, height);
|
||||
|
||||
DOTween.ToAlpha(() => image.color, c => image.color = c, 0f, 1f)
|
||||
.OnComplete(() => Destroy(rectObj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private void UpdateTime()
|
||||
{
|
||||
TimeField.text = songTime.ToString("F2");
|
||||
|
||||
@@ -18,18 +18,7 @@ namespace Ichni.RhythmGame
|
||||
|
||||
public void SelectGameElement()
|
||||
{
|
||||
if (EditorManager.instance.uiManager.inspector.connectedGameElement == this.elementToSelect)
|
||||
{
|
||||
EditorManager.instance.uiManager.hierarchy.FindTab(elementToSelect.parentElement);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorManager.instance.uiManager.hierarchy.FindTab(elementToSelect);
|
||||
}
|
||||
// EditorManager.instance.operationManager.ClearSelectedElements();
|
||||
// EditorManager.instance.operationManager.AddSelectElement(elementToSelect);
|
||||
// EditorManager.instance.uiManager.inspector.SetInspector(elementToSelect);
|
||||
// EditorManager.instance.timeline.SetTimeLine(elementToSelect);
|
||||
EditorManager.instance.uiManager.hierarchy.FindTab(elementToSelect);
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
|
||||
@@ -92,10 +92,10 @@ namespace Ichni.RhythmGame
|
||||
public override void SetDefaultSubmodules()
|
||||
{
|
||||
base.SetDefaultSubmodules();
|
||||
noteAudioSubmodule ??= new NoteAudioSubmodule(this, new List<string>(){"DefaultEndHold"},
|
||||
noteAudioSubmodule ??= new NoteAudioSubmodule(this, new List<string>() { "DefaultEndHold" },
|
||||
new List<string>(), new List<string>(),
|
||||
new List<string>(), new List<string>(),
|
||||
new List<string>(){"DefaultStartHold"});
|
||||
new List<string>() { "DefaultStartHold" });
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
@@ -128,6 +128,7 @@ namespace Ichni.RhythmGame
|
||||
{
|
||||
effect.effectTime = holdingTime;
|
||||
});
|
||||
holdEndTimeInputField.inputField.text = holdEndTime.ToString();
|
||||
});
|
||||
inspector.MarkedElements["ExactJudgeTime"].AddListenerFunction(() =>
|
||||
{
|
||||
|
||||
@@ -11,7 +11,7 @@ using UnityEngine;
|
||||
|
||||
namespace Ichni.RhythmGame
|
||||
{
|
||||
public partial class PathNode : GameElement, IHaveTransformSubmodule, IHaveTimeDurationSubmodule, IHaveColorSubmodule
|
||||
public partial class PathNode : GameElement, IHaveTransformSubmodule, IHaveTimeDurationSubmodule, IHaveColorSubmodule, IHaveSelectSubmodule
|
||||
{
|
||||
public Track track;
|
||||
public SplinePoint node;
|
||||
@@ -22,6 +22,9 @@ namespace Ichni.RhythmGame
|
||||
public bool haveEmissionColor => false;
|
||||
public override int HierarchyPriority => -100;
|
||||
|
||||
|
||||
public SelectSubmodule selectSubmodule { get; set; }
|
||||
|
||||
[Title("Editor独有参数")]
|
||||
[SerializeField]
|
||||
[HideInPlayMode]
|
||||
@@ -47,7 +50,7 @@ namespace Ichni.RhythmGame
|
||||
{
|
||||
track.trackPathSubmodule.pathNodeList.Insert(index, pathNode);
|
||||
}
|
||||
|
||||
pathNode.SetEditorSubmodules();
|
||||
|
||||
return pathNode;
|
||||
}
|
||||
@@ -58,7 +61,10 @@ namespace Ichni.RhythmGame
|
||||
timeDurationSubmodule = new TimeDurationSubmodule(this);
|
||||
colorSubmodule = new ColorSubmodule(this);
|
||||
}
|
||||
|
||||
public override void SetEditorSubmodules()
|
||||
{
|
||||
selectSubmodule ??= new SelectSubmodule(this, this);
|
||||
}
|
||||
|
||||
public override void AfterInitialize()
|
||||
{
|
||||
@@ -119,7 +125,7 @@ namespace Ichni.RhythmGame
|
||||
var isShowingSphereToggle =
|
||||
inspector.GenerateToggle(this, pathNodeSettings, "Is Showing Sphere", nameof(isShowingSphere))
|
||||
.AddListenerFunction(() => SetPathNodeSphere(isShowingSphere));
|
||||
|
||||
|
||||
var generateAnimation = container.GenerateSubcontainer(3);
|
||||
StandardInspectionElement.GenerateForTransform(this, container);
|
||||
var generateBaseColorChangeButton = inspector.GenerateButton(this, generateAnimation, "Base Color Change",
|
||||
|
||||
@@ -150,7 +150,17 @@ namespace Ichni.RhythmGame
|
||||
|
||||
var trackMajorPointSubcontainer = generateContainer.GenerateSubcontainer(3);
|
||||
var trackPercentPointButton = inspector.GenerateButton(this, trackMajorPointSubcontainer, "Track Percent Point",
|
||||
() => { TrackPercentPoint.GenerateElement("New Track Percent Point", Guid.NewGuid(), new List<string>(), true, this, new FlexibleFloat()); }); //百分比点
|
||||
() =>
|
||||
{
|
||||
var a = TrackPercentPoint.GenerateElement("New Track Percent Point", Guid.NewGuid(), new List<string>(), true, this, new FlexibleFloat());
|
||||
//添加默认动画
|
||||
if (trackTimeSubmodule != null && trackTimeSubmodule is TrackTimeSubmoduleMovable trackTimeSubmoduleMovable)
|
||||
a.trackPercent.Add(
|
||||
new AnimatedFloat(trackTimeSubmoduleMovable.trackStartTime, trackTimeSubmoduleMovable.trackEndTime, 0, 1, AnimationCurveType.Linear)); //添加一个默认的动画
|
||||
|
||||
|
||||
|
||||
}); //百分比点
|
||||
var trackHeadPointButton = inspector.GenerateButton(this, trackMajorPointSubcontainer, "Track Head Point",
|
||||
() => { TrackHeadPoint.GenerateElement("New Track Head Point", Guid.NewGuid(), new List<string>(), true, this, false, Vector3.zero); }); //头部点(必须先有TrackTimeSubmoduleMovable)
|
||||
if (trackTimeSubmodule is not TrackTimeSubmoduleMovable) trackHeadPointButton.button.interactable = false;
|
||||
|
||||
@@ -22,8 +22,6 @@ namespace Ichni.RhythmGame
|
||||
|
||||
public TimeDurationSubmodule timeDurationSubmodule { get; set; }
|
||||
|
||||
private bool isBeyond1 = false;
|
||||
|
||||
public bool MotionAngles = false;
|
||||
|
||||
public static TrackPercentPoint GenerateElement(string elementName, Guid id, List<string> tags,
|
||||
@@ -39,17 +37,6 @@ namespace Ichni.RhythmGame
|
||||
point.trackPositioner.spline = track.trackPathSubmodule.path;
|
||||
point.trackPercent = trackPercent;
|
||||
|
||||
point.isBeyond1 = trackPercent.animations.Any(animation => animation.endValue > 1); //判断是否有超过1的动画,超过1将会循环
|
||||
|
||||
//添加默认动画
|
||||
if (isFirstGenerated && point.parentElement is Track track1 && track1.submoduleList.Where(submodule => submodule is TrackTimeSubmoduleMovable).Count() == 1)
|
||||
{
|
||||
TrackTimeSubmoduleMovable trackTimeSubmoduleMovable = track1.submoduleList.Where(submodule => submodule is TrackTimeSubmoduleMovable).FirstOrDefault() as TrackTimeSubmoduleMovable;
|
||||
point.trackPercent.Add(
|
||||
new AnimatedFloat(trackTimeSubmoduleMovable.trackStartTime, trackTimeSubmoduleMovable.trackEndTime, 0, 1, AnimationCurveType.Linear)); //添加一个默认的动画
|
||||
|
||||
}
|
||||
|
||||
point.trackPositioner.motion.rotationOffset = Vector3.zero;
|
||||
point.trackPositioner.motion.applyRotation = false;
|
||||
|
||||
@@ -69,11 +56,8 @@ namespace Ichni.RhythmGame
|
||||
if (trackPercent.returnType == FlexibleReturnType.MiddleExecuting)
|
||||
{
|
||||
float finalValue = trackPercent.value;
|
||||
if (finalValue > 1 && finalValue > Mathf.Floor(finalValue)) finalValue -= Mathf.Floor(finalValue);
|
||||
|
||||
if (isBeyond1)
|
||||
{
|
||||
finalValue -= Mathf.Floor(finalValue);
|
||||
}
|
||||
|
||||
trackPositioner.SetPercent(finalValue);
|
||||
}
|
||||
@@ -118,8 +102,8 @@ namespace Ichni.RhythmGame
|
||||
var generateParticleEmitterButton = inspector.GenerateButton(this, generation, "Generate Particle Emitter", () =>
|
||||
{
|
||||
ParticleEmitter.GenerateElement("New Particle Emitter", Guid.NewGuid(), new List<string>(), true,
|
||||
this, "", "",false,0, 1, ParticleSystemSimulationSpace.World,
|
||||
10, 5, 1, 1 ,true, Vector3.zero);
|
||||
this, "", "", false, 0, 1, ParticleSystemSimulationSpace.World,
|
||||
10, 5, 1, 1, true, Vector3.zero);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Eventing.Reader;
|
||||
using System.Linq;
|
||||
using DG.Tweening;
|
||||
using Ichni;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame;
|
||||
@@ -78,7 +79,10 @@ public partial class GraphicalFlexibleFloatWindow : MovableWindow
|
||||
{
|
||||
ApplyParameters();
|
||||
//StartCoroutine(WindowAnim.HidePanel(gameObject, true));
|
||||
Destroy(gameObject);
|
||||
this.transform.DOScale(Vector3.zero, 0.15f).SetEase(Ease.InCirc).OnComplete(() =>
|
||||
{
|
||||
Destroy(gameObject);
|
||||
});
|
||||
}
|
||||
public float scalevalue;
|
||||
public void CurveScale(string Rawvalue)
|
||||
@@ -203,9 +207,12 @@ public partial class GraphicalFlexibleFloatWindow
|
||||
RemoveConnectedPoint();
|
||||
}
|
||||
|
||||
if (Keyboard.current.shiftKey.isPressed && Keyboard.current.vKey.wasPressedThisFrame)
|
||||
if (Keyboard.current.shiftKey.isPressed)
|
||||
{
|
||||
PasteClipboard();
|
||||
if (Keyboard.current.vKey.wasPressedThisFrame)
|
||||
PasteClipboard(1f);
|
||||
else if (Keyboard.current.bKey.wasPressedThisFrame)
|
||||
PasteClipboard(-1f);
|
||||
}
|
||||
if (Keyboard.current.escapeKey.wasPressedThisFrame)
|
||||
{
|
||||
@@ -220,6 +227,7 @@ public partial class GraphicalFlexibleFloatWindow
|
||||
j.LeftSide.sizeDelta = new Vector2(15, j.EvDrawimage.rectTransform.sizeDelta.y);
|
||||
}
|
||||
}
|
||||
updateClipBoardMuM();
|
||||
}
|
||||
if (ConnectedPoint != null && RectTransformUtility.RectangleContainsScreenPoint(GetComponent<RectTransform>(), Mouse.current.position.ReadValue()))
|
||||
{
|
||||
@@ -257,7 +265,7 @@ public partial class GraphicalFlexibleFloatWindow
|
||||
|
||||
}
|
||||
|
||||
public void PasteClipboard()
|
||||
public void PasteClipboard(float valuescale = 1f)
|
||||
{
|
||||
// 获取当前时间线的节拍位置
|
||||
float time = unitList[0].GetBeat();
|
||||
@@ -279,7 +287,8 @@ public partial class GraphicalFlexibleFloatWindow
|
||||
{
|
||||
// 克隆动画数据并应用时间偏移
|
||||
AnimatedFloat newFloat = EventPoint.CloneWithOffset(animatedFloat, time - MinCopyTime);
|
||||
|
||||
newFloat.startValue *= valuescale;
|
||||
newFloat.endValue *= valuescale;
|
||||
// 在对应的 FlexibleFloatTab 中生成事件点
|
||||
unitList.Find(x => x.Title == key).SpawnEvent(newFloat);
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace Ichni.Editor
|
||||
Vector2 mousePosition = Mouse.current.position.ReadValue();
|
||||
Ray ray = editorCamera.ScreenPointToRay(mousePosition);
|
||||
|
||||
if (Physics.Raycast(ray, out RaycastHit hit, float.MaxValue, LayerMask.GetMask("Default")))
|
||||
if (Physics.Raycast(ray, out RaycastHit hit, float.MaxValue, LayerMask.GetMask("Selectable")))
|
||||
{
|
||||
if (hit.collider == colliderX)
|
||||
{
|
||||
|
||||
@@ -43,7 +43,7 @@ public class NotefabContoler : MonoBehaviour
|
||||
}
|
||||
public void Update()
|
||||
{
|
||||
if (RectTransformUtility.RectangleContainsScreenPoint(this.GetComponent<RectTransform>(), Mouse.current.position.ReadValue()))
|
||||
if (sampleWindow.isExpand && RectTransformUtility.RectangleContainsScreenPoint(this.GetComponent<RectTransform>(), Mouse.current.position.ReadValue()))
|
||||
{
|
||||
if (Mouse.current.leftButton.wasPressedThisFrame)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,8 @@ namespace Ichni.Editor
|
||||
public GameObject hoveredUI;
|
||||
public EventSystem eventSystem;
|
||||
public List<GraphicRaycaster> graphicRaycasters;
|
||||
private List<SelectionConnector> lastHitConnectors = new List<SelectionConnector>();
|
||||
private int currentSelectIndex = 0;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
@@ -260,15 +262,31 @@ namespace Ichni.Editor
|
||||
|
||||
private void ClickSelectElement()
|
||||
{
|
||||
|
||||
if (Mouse.current.leftButton.wasPressedThisFrame && !isPointerOverUI)
|
||||
{
|
||||
Vector2 mousePosition = Mouse.current.position.ReadValue();
|
||||
Ray ray = EditorManager.instance.cameraManager.currentCamera.ScreenPointToRay(mousePosition);
|
||||
if (Physics.Raycast(ray, out RaycastHit hit, float.MaxValue, LayerMask.GetMask("Selectable")))
|
||||
RaycastHit[] hits = Physics.RaycastAll(ray, 500f, LayerMask.GetMask("Selectable"));
|
||||
|
||||
var hitConnectors = hits
|
||||
.Select(hit => hit.collider.GetComponent<SelectionConnector>())
|
||||
.Where(connector => connector != null)
|
||||
.ToList();
|
||||
|
||||
if (hitConnectors.Count == 0) return;
|
||||
|
||||
// 如果点击对象列表变化,重置索引
|
||||
if (!Enumerable.SequenceEqual(hitConnectors, lastHitConnectors))
|
||||
{
|
||||
SelectionConnector connector = hit.collider.GetComponent<SelectionConnector>();//TODO: 对于Hold这种复杂的元素,需要使用连接脚本进行获取
|
||||
(connector.connectedGameElement as IHaveSelectSubmodule)?.selectSubmodule.SelectGameElement();
|
||||
lastHitConnectors = hitConnectors;
|
||||
currentSelectIndex = 0;
|
||||
}
|
||||
|
||||
var connector = lastHitConnectors[currentSelectIndex];
|
||||
(connector.connectedGameElement as IHaveSelectSubmodule)?.selectSubmodule.SelectGameElement();
|
||||
|
||||
currentSelectIndex = (currentSelectIndex + 1) % lastHitConnectors.Count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user