@@ -715,7 +715,7 @@ namespace Ichni.Editor
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Animation Swaps (动画值交换)
|
||||
#region Animation (动画值)
|
||||
/// <summary>
|
||||
/// 交换 Displacement 动画值的正负号
|
||||
/// </summary>
|
||||
@@ -799,6 +799,32 @@ namespace Ichni.Editor
|
||||
anim.startValue = -anim.startValue;
|
||||
}
|
||||
}
|
||||
|
||||
// public static void randomAnimationValue(float range)
|
||||
// {
|
||||
// AnimationBase animationBase = inspector.connectedGameElement as AnimationBase;
|
||||
// if (animationBase == null)
|
||||
// {
|
||||
// LogWindow.Log("Please select a AnimationBase first!", Color.red);
|
||||
// return;
|
||||
// }
|
||||
// System.Random random = new System.Random();
|
||||
// foreach (var property in animationBase.GetType().GetProperties())
|
||||
// {
|
||||
// if (property.PropertyType == typeof(FlexibleFloat))
|
||||
// {
|
||||
// FlexibleFloat ff = property.GetValue(animationBase) as FlexibleFloat;
|
||||
// if (ff != null)
|
||||
// {
|
||||
// foreach (var anim in ff.animations)
|
||||
// {
|
||||
// float randomOffset = (float)(random.NextDouble() * 2 - 1) * range;
|
||||
// anim.endValue += randomOffset;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
#endregion
|
||||
|
||||
#region Global Utilities (全局工具)
|
||||
|
||||
@@ -53,6 +53,20 @@ namespace Ichni.RhythmGame
|
||||
interferometer.InterferomValue(ref value);
|
||||
}
|
||||
}
|
||||
public FlexibleFloat GetInterferomedValue(FlexibleFloat originalValue)
|
||||
{
|
||||
FlexibleFloat newone = new FlexibleFloat();
|
||||
foreach (var anim in originalValue.animations)
|
||||
{
|
||||
AnimatedFloat animatedFloat = new AnimatedFloat(anim.startTime, anim.endTime, anim.startValue, anim.endValue, anim.animationCurveType);
|
||||
foreach (var interferometer in Interferometers.OfType<Vector3Interferometer>())
|
||||
{
|
||||
animatedFloat = interferometer.InterferomValue(animatedFloat);
|
||||
}
|
||||
newone.Add(animatedFloat);
|
||||
}
|
||||
return newone;
|
||||
}
|
||||
public void ApplyVector3InterferometersBM(FlexibleFloat_BM X, FlexibleFloat_BM Y, FlexibleFloat_BM Z)
|
||||
{
|
||||
foreach (Vector3Interferometer interferometer in Interferometers.OfType<Vector3Interferometer>())
|
||||
|
||||
@@ -58,6 +58,32 @@ namespace Ichni.RhythmGame
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
public AnimatedFloat InterferomValue(AnimatedFloat animatedFloat)
|
||||
{
|
||||
AnimatedFloat newone = new AnimatedFloat(animatedFloat.startTime, animatedFloat.endTime, animatedFloat.startValue, animatedFloat.endValue, animatedFloat.animationCurveType);
|
||||
switch (InterferomType)
|
||||
{
|
||||
case InterferomType.Additive:
|
||||
// Additive: add interferometer effect to the current value (placeholder)
|
||||
newone.endValue += InterferomValueVector3.x;
|
||||
newone.startValue += InterferomValueVector3.x;
|
||||
break;
|
||||
case InterferomType.Multiplicative:
|
||||
// Multiplicative: multiply current value by interferometer effect (placeholder)
|
||||
newone.endValue *= InterferomValueVector3.x;
|
||||
newone.startValue *= InterferomValueVector3.x;
|
||||
break;
|
||||
case InterferomType.Override:
|
||||
// Override: replace current value with interferometer effect (placeholder)
|
||||
newone.endValue = InterferomValueVector3.x;
|
||||
newone.startValue = InterferomValueVector3.x;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return newone;
|
||||
|
||||
}
|
||||
public void InterferomValueBM(FlexibleFloat_BM X, FlexibleFloat_BM Y, FlexibleFloat_BM Z)
|
||||
{
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Beatmap;
|
||||
using Ichni;
|
||||
using Ichni.Editor;
|
||||
using Ichni.RhythmGame;
|
||||
using Ichni.RhythmGame.Beatmap;
|
||||
@@ -14,83 +12,168 @@ namespace Ichni.RhythmGame
|
||||
{
|
||||
private TransformSubmodule targetTransformSubmodule;
|
||||
public ICanBeTrackedDisplacement targetDisplacement;
|
||||
private FlexibleFloat positionX, positionY, positionZ;
|
||||
|
||||
public Vector3 PreviewValue = Vector3.zero;
|
||||
public float TimeOffset;
|
||||
public BaseElement_BM MatchingExportElement { get; set; } = null;
|
||||
public List<InterferometerBase> Interferometers { get; set; } = new();
|
||||
private bool isSwitchingReturnType = false;
|
||||
|
||||
public override void Initialize(string name, Guid elementGuid, List<string> tags, bool isFirstGenerated, GameElement parentElement)
|
||||
{
|
||||
base.Initialize(name, elementGuid, tags, isFirstGenerated, parentElement);
|
||||
positionX = new FlexibleFloat();
|
||||
positionY = new FlexibleFloat();
|
||||
positionZ = new FlexibleFloat();
|
||||
}
|
||||
public static DisplacementTracker GenerateElement(string elementName, System.Guid id,
|
||||
List<string> tags, bool isFirstGenerated, GameElement animatedObject, Displacement targetDisplacement, float timeOffset)
|
||||
{
|
||||
DisplacementTracker tracker = Instantiate(EditorManager.instance.basePrefabs.emptyObject).AddComponent<DisplacementTracker>();
|
||||
tracker.Initialize(elementName, id, tags, isFirstGenerated, animatedObject);
|
||||
tracker.animatedObject = animatedObject;
|
||||
tracker.targetDisplacement = targetDisplacement;
|
||||
tracker.SetTargetDisplacement(targetDisplacement);
|
||||
tracker.TimeOffset = timeOffset;
|
||||
tracker.targetTransformSubmodule = (animatedObject as IHaveTransformSubmodule).transformSubmodule;
|
||||
|
||||
return tracker;
|
||||
}
|
||||
|
||||
public void SetTargetDisplacement(ICanBeTrackedDisplacement newTarget)
|
||||
{
|
||||
// 解绑旧事件
|
||||
if (targetDisplacement is Displacement oldDisp)
|
||||
{
|
||||
oldDisp.positionX.OnDataChanged -= OnSourceChanged;
|
||||
}
|
||||
else if (targetDisplacement is DisplacementTracker oldTracker)
|
||||
{
|
||||
oldTracker.positionX.OnDataChanged -= OnSourceChanged;
|
||||
}
|
||||
targetDisplacement = newTarget;
|
||||
if (targetDisplacement is Displacement disp)
|
||||
{
|
||||
positionX = ManualCopyFlexibleFloat(disp.positionX);
|
||||
positionY = ManualCopyFlexibleFloat(disp.positionY);
|
||||
positionZ = ManualCopyFlexibleFloat(disp.positionZ);
|
||||
disp.positionX.OnDataChanged += OnSourceChanged;
|
||||
}
|
||||
else if (targetDisplacement is DisplacementTracker tracker)
|
||||
{
|
||||
positionX = ManualCopyFlexibleFloat(tracker.positionX);
|
||||
positionY = ManualCopyFlexibleFloat(tracker.positionY);
|
||||
positionZ = ManualCopyFlexibleFloat(tracker.positionZ);
|
||||
tracker.positionX.OnDataChanged += OnSourceChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSourceChanged()
|
||||
{
|
||||
if (targetDisplacement is Displacement disp)
|
||||
{
|
||||
CopyFlexibleFloat(positionX, disp.positionX);
|
||||
CopyFlexibleFloat(positionY, disp.positionY);
|
||||
CopyFlexibleFloat(positionZ, disp.positionZ);
|
||||
// 叠加 IHaveVector3Interferometer 偏移
|
||||
positionX = ((IHaveVector3Interferometer)disp).GetInterferomedValue(positionX);
|
||||
positionY = ((IHaveVector3Interferometer)disp).GetInterferomedValue(positionY);
|
||||
positionZ = ((IHaveVector3Interferometer)disp).GetInterferomedValue(positionZ);
|
||||
|
||||
}
|
||||
else if (targetDisplacement is DisplacementTracker tracker)
|
||||
{
|
||||
CopyFlexibleFloat(positionX, tracker.positionX);
|
||||
CopyFlexibleFloat(positionY, tracker.positionY);
|
||||
CopyFlexibleFloat(positionZ, tracker.positionZ);
|
||||
|
||||
positionX = ((IHaveVector3Interferometer)tracker).GetInterferomedValue(positionX);
|
||||
positionY = ((IHaveVector3Interferometer)tracker).GetInterferomedValue(positionY);
|
||||
positionZ = ((IHaveVector3Interferometer)tracker).GetInterferomedValue(positionZ);
|
||||
|
||||
}
|
||||
}
|
||||
public override void Refresh()
|
||||
{
|
||||
base.Refresh();
|
||||
OnSourceChanged();
|
||||
}
|
||||
|
||||
private FlexibleFloat ManualCopyFlexibleFloat(FlexibleFloat source)
|
||||
{
|
||||
var target = new FlexibleFloat();
|
||||
CopyFlexibleFloat(target, source);
|
||||
|
||||
return target;
|
||||
}
|
||||
private void CopyFlexibleFloat(FlexibleFloat target, FlexibleFloat source)
|
||||
{
|
||||
|
||||
target.animations = new List<AnimatedFloat>();
|
||||
foreach (var a in source.animations)
|
||||
{
|
||||
AnimatedFloat animatedFloat = new AnimatedFloat(a.startTime + TimeOffset, a.endTime + TimeOffset, a.startValue, a.endValue, a.animationCurveType);
|
||||
|
||||
target.animations.Add(animatedFloat);
|
||||
}
|
||||
// 如有其它字段请补充
|
||||
}
|
||||
|
||||
protected override void UpdateAnimation(float songTime)
|
||||
{
|
||||
if (targetDisplacement == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var a = GetCurrentReturnTypes(songTime);
|
||||
var (x, y, z) = (a[0], a[1], a[2]);
|
||||
positionX.UpdateFlexibleFloat(songTime);
|
||||
positionY.UpdateFlexibleFloat(songTime);
|
||||
positionZ.UpdateFlexibleFloat(songTime);
|
||||
|
||||
if (x.Item1 is FlexibleReturnType.MiddleExecuting ||
|
||||
y.Item1 is FlexibleReturnType.MiddleExecuting ||
|
||||
z.Item1 is FlexibleReturnType.MiddleExecuting)
|
||||
if (positionX.returnType is FlexibleReturnType.MiddleExecuting ||
|
||||
positionY.returnType is FlexibleReturnType.MiddleExecuting ||
|
||||
positionZ.returnType is FlexibleReturnType.MiddleExecuting)
|
||||
{
|
||||
animationReturnType = FlexibleReturnType.MiddleExecuting;
|
||||
ApplyValue(songTime);
|
||||
isSwitchingReturnType = true;
|
||||
ApplyValue();
|
||||
}
|
||||
else if (isSwitchingReturnType)
|
||||
else if (positionX.isSwitchingReturnType || positionY.isSwitchingReturnType || positionZ.isSwitchingReturnType)
|
||||
{
|
||||
animationReturnType = FlexibleReturnType.MiddleExecuting;
|
||||
isSwitchingReturnType = false;
|
||||
ApplyValue(songTime);
|
||||
ApplyValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!EditorManager.instance.musicPlayer.isPlaying && animationReturnType != FlexibleReturnType.MiddleInterval)
|
||||
{
|
||||
ApplyValue(songTime);
|
||||
ApplyValue();
|
||||
}
|
||||
animationReturnType = FlexibleReturnType.MiddleInterval;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyValue(float time)
|
||||
private void ApplyValue()
|
||||
{
|
||||
Vector3 currentPosition = targetDisplacement.getValue(time + TimeOffset);
|
||||
Vector3 currentPosition = new Vector3(positionX.value, positionY.value, positionZ.value);
|
||||
// 用接口强制调用默认实现
|
||||
((IHaveVector3Interferometer)this).ApplyVector3Interferometers(ref currentPosition);
|
||||
targetTransformSubmodule.positionOffset += currentPosition;
|
||||
targetTransformSubmodule.positionDirtyMark = true;
|
||||
PreviewValue = currentPosition;
|
||||
}
|
||||
public (FlexibleReturnType, bool)[] GetCurrentReturnTypes(float time)
|
||||
{
|
||||
return targetDisplacement.GetCurrentReturnTypes(time + TimeOffset);
|
||||
}
|
||||
|
||||
public override Vector3 getValue(float time)
|
||||
{
|
||||
Vector3 currentPosition = targetDisplacement.getValue(time + TimeOffset);
|
||||
Vector3 currentPosition = new Vector3(
|
||||
positionX.GetValue(time + TimeOffset),
|
||||
positionY.GetValue(time + TimeOffset),
|
||||
positionZ.GetValue(time + TimeOffset)
|
||||
);
|
||||
((IHaveVector3Interferometer)this).ApplyVector3Interferometers(ref currentPosition);
|
||||
return currentPosition;
|
||||
}
|
||||
|
||||
|
||||
public override void SetUpInspector()
|
||||
{
|
||||
base.SetUpInspector();
|
||||
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
|
||||
Inspector inspectorMain = EditorManager.instance.uiManager.inspector;
|
||||
|
||||
var container = inspector.GenerateContainer("Enable Control");
|
||||
var effectSettings = container.GenerateSubcontainer(2);
|
||||
var connectedGameElementInputField = inspector.GenerateInputField(effectSettings, "Try Get Displacement");
|
||||
@@ -98,26 +181,21 @@ namespace Ichni.RhythmGame
|
||||
{
|
||||
ICanBeTrackedDisplacement targetElement = EditorManager.instance.beatmapContainer.gameElementList.OfType<ICanBeTrackedDisplacement>()
|
||||
.First(e => ((GameElement)e).elementName == connectedGameElementInputField.GetValue<string>());
|
||||
|
||||
if (targetElement == null)
|
||||
{
|
||||
LogWindow.Log("Game Element not found.", Color.yellow);
|
||||
}
|
||||
|
||||
targetDisplacement = targetElement;
|
||||
//targetTransformSubmodule = (targetElement as IHaveTransformSubmodule).transformSubmodule;
|
||||
|
||||
SetTargetDisplacement(targetElement);
|
||||
inspectorMain.SetInspector(this);
|
||||
});
|
||||
string ShowConnection() => targetDisplacement == null ? "No Displacement Connected" : "Connected With: " + ((GameElement)targetDisplacement).elementName;
|
||||
var connectHintText = inspector.GenerateHintText(this, effectSettings, ShowConnection);
|
||||
var InputField = inspector.GenerateInputField(this, effectSettings, "Offset", nameof(TimeOffset));
|
||||
var interferometerButton = inspector.GenerateButton(this, effectSettings, "Interferometer", () =>
|
||||
{
|
||||
Vector3Interferometer.GenerateElement("New Vector3 Interferometer", Guid.NewGuid(), new List<string>(), true,
|
||||
this, InterferomType.Additive, Vector3.zero);
|
||||
});
|
||||
|
||||
{
|
||||
Vector3Interferometer.GenerateElement("New Vector3 Interferometer", Guid.NewGuid(), new List<string>(), true,
|
||||
this, InterferomType.Additive, Vector3.zero);
|
||||
});
|
||||
}
|
||||
|
||||
public override void SaveBM()
|
||||
@@ -125,62 +203,28 @@ namespace Ichni.RhythmGame
|
||||
matchedBM = new DisplacementTracker_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
|
||||
((GameElement)targetDisplacement).elementGuid, TimeOffset);
|
||||
}
|
||||
public bool MaybeDeadLoop = true;
|
||||
public void SaveExportBM()
|
||||
{
|
||||
|
||||
Refresh();
|
||||
SaveBM();
|
||||
MatchingExportElement = matchedBM;
|
||||
float finalTimeOffset = 0;
|
||||
Displacement displacement = GetOriginDisplacementWithOffset(ref finalTimeOffset);
|
||||
displacement.SaveBM();
|
||||
var x = ((Displacement_BM)displacement.matchedBM).positionX.DeepCopyBM();
|
||||
var y = ((Displacement_BM)displacement.matchedBM).positionY.DeepCopyBM();
|
||||
var z = ((Displacement_BM)displacement.matchedBM).positionZ.DeepCopyBM();
|
||||
x.ApplyTimeOffset(finalTimeOffset); y.ApplyTimeOffset(finalTimeOffset); z.ApplyTimeOffset(finalTimeOffset);
|
||||
|
||||
// 构建链表,从底层 Displacement 到最上层 Tracker
|
||||
List<ICanBeTrackedDisplacement> chain = new List<ICanBeTrackedDisplacement>();
|
||||
ICanBeTrackedDisplacement cur = this;
|
||||
int safeGuard = 100; // 防止死循环
|
||||
while (cur != null && safeGuard-- > 0)
|
||||
{
|
||||
chain.Insert(0, cur);
|
||||
if (cur is DisplacementTracker tracker)
|
||||
cur = tracker.targetDisplacement;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// 依次叠加 Interferometer
|
||||
foreach (var o in chain)
|
||||
((IHaveVector3Interferometer)o).ApplyVector3InterferometersBM(x, y, z);
|
||||
|
||||
// 先保存 parentElement
|
||||
parentElement.SaveBM();
|
||||
|
||||
// 用当前 elementName/tags
|
||||
var a = new Displacement_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM, x, y, z);
|
||||
var a = new Displacement_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
|
||||
positionX.ConvertToBM(), positionY.ConvertToBM(), positionZ.ConvertToBM());
|
||||
MatchingExportElement = a;
|
||||
}
|
||||
|
||||
public Displacement GetOriginDisplacementWithOffset(ref float timeOffset)
|
||||
{
|
||||
timeOffset += TimeOffset;
|
||||
if (targetDisplacement is Displacement disp)
|
||||
{
|
||||
return disp;
|
||||
}
|
||||
else if (targetDisplacement is DisplacementTracker dispt)
|
||||
{
|
||||
return dispt.GetOriginDisplacementWithOffset(ref timeOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("WTF type of tracked displacement.");
|
||||
}
|
||||
// 兼容旧接口,直接返回 null
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public (FlexibleReturnType, bool)[] GetCurrentReturnTypes(float time)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
public interface ICanBeTracked
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Ichni.RhythmGame
|
||||
public float TimeOffset;
|
||||
public BaseElement_BM MatchingExportElement { get; set; } = null;
|
||||
public List<InterferometerBase> Interferometers { get; set; } = new();
|
||||
private bool isSwitchingReturnType = false;
|
||||
private FlexibleFloat scaleX, scaleY, scaleZ;
|
||||
|
||||
public static ScaleTracker GenerateElement(string elementName, Guid id,
|
||||
List<string> tags, bool isFirstGenerated, GameElement animatedObject, ICanBeTrackedScale targetScale, float timeOffset)
|
||||
@@ -31,54 +31,133 @@ namespace Ichni.RhythmGame
|
||||
tracker.targetTransformSubmodule = (animatedObject as IHaveTransformSubmodule).transformSubmodule;
|
||||
return tracker;
|
||||
}
|
||||
|
||||
public override void Initialize(string name, Guid elementGuid, List<string> tags, bool isFirstGenerated, GameElement parentElement)
|
||||
{
|
||||
base.Initialize(name, elementGuid, tags, isFirstGenerated, parentElement);
|
||||
scaleX = new FlexibleFloat();
|
||||
scaleY = new FlexibleFloat();
|
||||
scaleZ = new FlexibleFloat();
|
||||
}
|
||||
|
||||
public void SetTargetScale(ICanBeTrackedScale newTarget)
|
||||
{
|
||||
if (targetScale is Scale oldScale)
|
||||
{
|
||||
oldScale.scaleX.OnDataChanged -= OnSourceChanged;
|
||||
}
|
||||
else if (targetScale is ScaleTracker oldTracker)
|
||||
{
|
||||
oldTracker.scaleX.OnDataChanged -= OnSourceChanged;
|
||||
}
|
||||
targetScale = newTarget;
|
||||
if (targetScale is Scale scale)
|
||||
{
|
||||
scaleX = ManualCopyFlexibleFloat(scale.scaleX);
|
||||
scaleY = ManualCopyFlexibleFloat(scale.scaleY);
|
||||
scaleZ = ManualCopyFlexibleFloat(scale.scaleZ);
|
||||
scale.scaleX.OnDataChanged += OnSourceChanged;
|
||||
}
|
||||
else if (targetScale is ScaleTracker tracker)
|
||||
{
|
||||
scaleX = ManualCopyFlexibleFloat(tracker.scaleX);
|
||||
scaleY = ManualCopyFlexibleFloat(tracker.scaleY);
|
||||
scaleZ = ManualCopyFlexibleFloat(tracker.scaleZ);
|
||||
tracker.scaleX.OnDataChanged += OnSourceChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSourceChanged()
|
||||
{
|
||||
if (targetScale is Scale scale)
|
||||
{
|
||||
CopyFlexibleFloat(scaleX, scale.scaleX);
|
||||
CopyFlexibleFloat(scaleY, scale.scaleY);
|
||||
CopyFlexibleFloat(scaleZ, scale.scaleZ);
|
||||
scaleX = ((IHaveVector3Interferometer)scale).GetInterferomedValue(scaleX);
|
||||
scaleY = ((IHaveVector3Interferometer)scale).GetInterferomedValue(scaleY);
|
||||
scaleZ = ((IHaveVector3Interferometer)scale).GetInterferomedValue(scaleZ);
|
||||
}
|
||||
else if (targetScale is ScaleTracker tracker)
|
||||
{
|
||||
CopyFlexibleFloat(scaleX, tracker.scaleX);
|
||||
CopyFlexibleFloat(scaleY, tracker.scaleY);
|
||||
CopyFlexibleFloat(scaleZ, tracker.scaleZ);
|
||||
scaleX = ((IHaveVector3Interferometer)tracker).GetInterferomedValue(scaleX);
|
||||
scaleY = ((IHaveVector3Interferometer)tracker).GetInterferomedValue(scaleY);
|
||||
scaleZ = ((IHaveVector3Interferometer)tracker).GetInterferomedValue(scaleZ);
|
||||
}
|
||||
}
|
||||
|
||||
private FlexibleFloat ManualCopyFlexibleFloat(FlexibleFloat source)
|
||||
{
|
||||
var target = new FlexibleFloat();
|
||||
CopyFlexibleFloat(target, source);
|
||||
return target;
|
||||
}
|
||||
|
||||
private void CopyFlexibleFloat(FlexibleFloat target, FlexibleFloat source)
|
||||
{
|
||||
target.animations = new List<AnimatedFloat>();
|
||||
foreach (var a in source.animations)
|
||||
{
|
||||
AnimatedFloat animatedFloat = new AnimatedFloat(a.startTime + TimeOffset, a.endTime + TimeOffset, a.startValue, a.endValue, a.animationCurveType);
|
||||
target.animations.Add(animatedFloat);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void UpdateAnimation(float songTime)
|
||||
{
|
||||
if (targetScale == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var a = GetCurrentReturnTypes(songTime);
|
||||
var (x, y, z) = (a[0], a[1], a[2]);
|
||||
|
||||
if (x.Item1 is FlexibleReturnType.MiddleExecuting ||
|
||||
y.Item1 is FlexibleReturnType.MiddleExecuting ||
|
||||
z.Item1 is FlexibleReturnType.MiddleExecuting)
|
||||
scaleX.UpdateFlexibleFloat(songTime);
|
||||
scaleY.UpdateFlexibleFloat(songTime);
|
||||
scaleZ.UpdateFlexibleFloat(songTime);
|
||||
if (scaleX.returnType is FlexibleReturnType.MiddleExecuting ||
|
||||
scaleY.returnType is FlexibleReturnType.MiddleExecuting ||
|
||||
scaleZ.returnType is FlexibleReturnType.MiddleExecuting)
|
||||
{
|
||||
animationReturnType = FlexibleReturnType.MiddleExecuting;
|
||||
ApplyValue(songTime);
|
||||
isSwitchingReturnType = true;
|
||||
ApplyValue();
|
||||
}
|
||||
else if (isSwitchingReturnType)
|
||||
else if (scaleX.isSwitchingReturnType || scaleY.isSwitchingReturnType || scaleZ.isSwitchingReturnType)
|
||||
{
|
||||
animationReturnType = FlexibleReturnType.MiddleExecuting;
|
||||
isSwitchingReturnType = false;
|
||||
ApplyValue(songTime);
|
||||
ApplyValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!EditorManager.instance.musicPlayer.isPlaying && animationReturnType != FlexibleReturnType.MiddleInterval)
|
||||
{
|
||||
ApplyValue(songTime);
|
||||
ApplyValue();
|
||||
}
|
||||
animationReturnType = FlexibleReturnType.MiddleInterval;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyValue(float time)
|
||||
private void ApplyValue()
|
||||
{
|
||||
Vector3 currentScale = targetScale.getValue(time + TimeOffset);
|
||||
Vector3 currentScale = new Vector3(scaleX.value, scaleY.value, scaleZ.value);
|
||||
((IHaveVector3Interferometer)this).ApplyVector3Interferometers(ref currentScale);
|
||||
targetTransformSubmodule.scaleOffset += currentScale;
|
||||
targetTransformSubmodule.scaleDirtyMark = true;
|
||||
PreviewValue = currentScale;
|
||||
}
|
||||
|
||||
public (FlexibleReturnType, bool)[] GetCurrentReturnTypes(float time)
|
||||
{
|
||||
return targetScale.GetCurrentReturnTypes(time + TimeOffset);
|
||||
}
|
||||
|
||||
public override Vector3 getValue(float time)
|
||||
{
|
||||
Vector3 currentScale = targetScale.getValue(time + TimeOffset);
|
||||
Vector3 currentScale = new Vector3(
|
||||
scaleX.GetValue(time + TimeOffset),
|
||||
scaleY.GetValue(time + TimeOffset),
|
||||
scaleZ.GetValue(time + TimeOffset)
|
||||
);
|
||||
((IHaveVector3Interferometer)this).ApplyVector3Interferometers(ref currentScale);
|
||||
return currentScale;
|
||||
}
|
||||
@@ -121,32 +200,18 @@ namespace Ichni.RhythmGame
|
||||
matchedBM = new ScaleTracker_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
|
||||
((GameElement)targetScale).elementGuid, TimeOffset);
|
||||
}
|
||||
|
||||
public bool MaybeDeadLoop = true;
|
||||
|
||||
public void SaveExportBM()
|
||||
{
|
||||
|
||||
Refresh();
|
||||
SaveBM();
|
||||
MatchingExportElement = matchedBM;
|
||||
float finalTimeOffset = 0;
|
||||
Scale scale = GetOriginScaleWithOffset(ref finalTimeOffset);
|
||||
scale.SaveBM();
|
||||
var x = ((Scale_BM)scale.matchedBM).scaleX.DeepCopyBM();
|
||||
var y = ((Scale_BM)scale.matchedBM).scaleY.DeepCopyBM();
|
||||
var z = ((Scale_BM)scale.matchedBM).scaleZ.DeepCopyBM();
|
||||
x.ApplyTimeOffset(finalTimeOffset); y.ApplyTimeOffset(finalTimeOffset); z.ApplyTimeOffset(finalTimeOffset);
|
||||
|
||||
List<ICanBeTrackedScale> ICanBeTrackedScales = new List<ICanBeTrackedScale> { this as ICanBeTrackedScale };
|
||||
while (MaybeDeadLoop && ICanBeTrackedScales[0] is not Scale)
|
||||
{
|
||||
ICanBeTrackedScale ao = (ICanBeTrackedScales[0] as ScaleTracker).targetScale;
|
||||
ICanBeTrackedScales.Insert(0, ao);
|
||||
}
|
||||
ICanBeTrackedScales.ForEach(o =>
|
||||
{
|
||||
((IHaveVector3Interferometer)o).ApplyVector3InterferometersBM(x, y, z);
|
||||
});
|
||||
parentElement.SaveBM();
|
||||
Scale_BM a = new Scale_BM("Scale", elementGuid, new List<string>(), parentElement.matchedBM as GameElement_BM,
|
||||
x, y, z);
|
||||
var a = new Scale_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
|
||||
scaleX.ConvertToBM(), scaleY.ConvertToBM(), scaleZ.ConvertToBM());
|
||||
MatchingExportElement = a;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Ichni.RhythmGame
|
||||
public float TimeOffset;
|
||||
public BaseElement_BM MatchingExportElement { get; set; } = null;
|
||||
public List<InterferometerBase> Interferometers { get; set; } = new();
|
||||
private bool isSwitchingReturnType = false;
|
||||
private FlexibleFloat eulerAngleX, eulerAngleY, eulerAngleZ;
|
||||
|
||||
public static SwirlTracker GenerateElement(string elementName, Guid id,
|
||||
List<string> tags, bool isFirstGenerated, GameElement animatedObject, Swirl targetSwirl, float timeOffset)
|
||||
@@ -31,27 +31,94 @@ namespace Ichni.RhythmGame
|
||||
tracker.targetTransformSubmodule = (animatedObject as IHaveTransformSubmodule).transformSubmodule;
|
||||
return tracker;
|
||||
}
|
||||
public override void Initialize(string name, Guid elementGuid, List<string> tags, bool isFirstGenerated, GameElement parentElement)
|
||||
{
|
||||
base.Initialize(name, elementGuid, tags, isFirstGenerated, parentElement);
|
||||
eulerAngleX = new FlexibleFloat();
|
||||
eulerAngleY = new FlexibleFloat();
|
||||
eulerAngleZ = new FlexibleFloat();
|
||||
}
|
||||
public void SetTargetSwirl(ICanBeTrackedSwirl newTarget)
|
||||
{
|
||||
if (targetSwirl is Swirl oldSwirl)
|
||||
{
|
||||
oldSwirl.eulerAngleX.OnDataChanged -= OnSourceChanged;
|
||||
}
|
||||
else if (targetSwirl is SwirlTracker oldTracker)
|
||||
{
|
||||
oldTracker.eulerAngleX.OnDataChanged -= OnSourceChanged;
|
||||
}
|
||||
targetSwirl = newTarget;
|
||||
if (targetSwirl is Swirl swirl)
|
||||
{
|
||||
eulerAngleX = ManualCopyFlexibleFloat(swirl.eulerAngleX);
|
||||
eulerAngleY = ManualCopyFlexibleFloat(swirl.eulerAngleY);
|
||||
eulerAngleZ = ManualCopyFlexibleFloat(swirl.eulerAngleZ);
|
||||
swirl.eulerAngleX.OnDataChanged += OnSourceChanged;
|
||||
}
|
||||
else if (targetSwirl is SwirlTracker tracker)
|
||||
{
|
||||
eulerAngleX = ManualCopyFlexibleFloat(tracker.eulerAngleX);
|
||||
eulerAngleY = ManualCopyFlexibleFloat(tracker.eulerAngleY);
|
||||
eulerAngleZ = ManualCopyFlexibleFloat(tracker.eulerAngleZ);
|
||||
tracker.eulerAngleX.OnDataChanged += OnSourceChanged;
|
||||
}
|
||||
}
|
||||
private void OnSourceChanged()
|
||||
{
|
||||
if (targetSwirl is Swirl swirl)
|
||||
{
|
||||
CopyFlexibleFloat(eulerAngleX, swirl.eulerAngleX);
|
||||
CopyFlexibleFloat(eulerAngleY, swirl.eulerAngleY);
|
||||
CopyFlexibleFloat(eulerAngleZ, swirl.eulerAngleZ);
|
||||
eulerAngleX = ((IHaveVector3Interferometer)swirl).GetInterferomedValue(eulerAngleX);
|
||||
eulerAngleY = ((IHaveVector3Interferometer)swirl).GetInterferomedValue(eulerAngleY);
|
||||
eulerAngleZ = ((IHaveVector3Interferometer)swirl).GetInterferomedValue(eulerAngleZ);
|
||||
}
|
||||
else if (targetSwirl is SwirlTracker tracker)
|
||||
{
|
||||
CopyFlexibleFloat(eulerAngleX, tracker.eulerAngleX);
|
||||
CopyFlexibleFloat(eulerAngleY, tracker.eulerAngleY);
|
||||
CopyFlexibleFloat(eulerAngleZ, tracker.eulerAngleZ);
|
||||
eulerAngleX = ((IHaveVector3Interferometer)tracker).GetInterferomedValue(eulerAngleX);
|
||||
eulerAngleY = ((IHaveVector3Interferometer)tracker).GetInterferomedValue(eulerAngleY);
|
||||
eulerAngleZ = ((IHaveVector3Interferometer)tracker).GetInterferomedValue(eulerAngleZ);
|
||||
}
|
||||
}
|
||||
private FlexibleFloat ManualCopyFlexibleFloat(FlexibleFloat source)
|
||||
{
|
||||
var target = new FlexibleFloat();
|
||||
CopyFlexibleFloat(target, source);
|
||||
return target;
|
||||
}
|
||||
private void CopyFlexibleFloat(FlexibleFloat target, FlexibleFloat source)
|
||||
{
|
||||
target.animations = new List<AnimatedFloat>();
|
||||
foreach (var a in source.animations)
|
||||
{
|
||||
AnimatedFloat animatedFloat = new AnimatedFloat(a.startTime + TimeOffset, a.endTime + TimeOffset, a.startValue, a.endValue, a.animationCurveType);
|
||||
target.animations.Add(animatedFloat);
|
||||
}
|
||||
}
|
||||
protected override void UpdateAnimation(float songTime)
|
||||
{
|
||||
if (targetSwirl == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var a = GetCurrentReturnTypes(songTime);
|
||||
var (x, y, z) = (a[0], a[1], a[2]);
|
||||
|
||||
if (x.Item1 is FlexibleReturnType.MiddleExecuting ||
|
||||
y.Item1 is FlexibleReturnType.MiddleExecuting ||
|
||||
z.Item1 is FlexibleReturnType.MiddleExecuting)
|
||||
eulerAngleX.UpdateFlexibleFloat(songTime);
|
||||
eulerAngleY.UpdateFlexibleFloat(songTime);
|
||||
eulerAngleZ.UpdateFlexibleFloat(songTime);
|
||||
if (eulerAngleX.returnType is FlexibleReturnType.MiddleExecuting ||
|
||||
eulerAngleY.returnType is FlexibleReturnType.MiddleExecuting ||
|
||||
eulerAngleZ.returnType is FlexibleReturnType.MiddleExecuting)
|
||||
{
|
||||
animationReturnType = FlexibleReturnType.MiddleExecuting;
|
||||
ApplyValue(songTime);
|
||||
isSwitchingReturnType = true;
|
||||
}
|
||||
else if (isSwitchingReturnType)
|
||||
else if (eulerAngleX.isSwitchingReturnType || eulerAngleY.isSwitchingReturnType || eulerAngleZ.isSwitchingReturnType)
|
||||
{
|
||||
animationReturnType = FlexibleReturnType.MiddleExecuting;
|
||||
isSwitchingReturnType = false;
|
||||
ApplyValue(songTime);
|
||||
}
|
||||
else
|
||||
@@ -63,10 +130,9 @@ namespace Ichni.RhythmGame
|
||||
animationReturnType = FlexibleReturnType.MiddleInterval;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyValue(float time)
|
||||
{
|
||||
Vector3 currentEulerAngles = targetSwirl.getValue(time + TimeOffset);
|
||||
Vector3 currentEulerAngles = new Vector3(eulerAngleX.value, eulerAngleY.value, eulerAngleZ.value);
|
||||
((IHaveVector3Interferometer)this).ApplyVector3Interferometers(ref currentEulerAngles);
|
||||
targetTransformSubmodule.eulerAnglesOffset += currentEulerAngles;
|
||||
targetTransformSubmodule.eulerAnglesDirtyMark = true;
|
||||
@@ -78,7 +144,11 @@ namespace Ichni.RhythmGame
|
||||
}
|
||||
public override Vector3 getValue(float time)
|
||||
{
|
||||
Vector3 currentEulerAngles = targetSwirl.getValue(time + TimeOffset);
|
||||
Vector3 currentEulerAngles = new Vector3(
|
||||
eulerAngleX.GetValue(time + TimeOffset),
|
||||
eulerAngleY.GetValue(time + TimeOffset),
|
||||
eulerAngleZ.GetValue(time + TimeOffset)
|
||||
);
|
||||
((IHaveVector3Interferometer)this).ApplyVector3Interferometers(ref currentEulerAngles);
|
||||
return currentEulerAngles;
|
||||
}
|
||||
@@ -123,29 +193,12 @@ namespace Ichni.RhythmGame
|
||||
public bool MaybeDeadLoop = true;
|
||||
public void SaveExportBM()
|
||||
{
|
||||
Refresh();
|
||||
SaveBM();
|
||||
MatchingExportElement = matchedBM;
|
||||
float finalTimeOffset = 0;
|
||||
Swirl swirl = GetOriginSwirlWithOffset(ref finalTimeOffset);
|
||||
swirl.SaveBM();
|
||||
var x = ((Swirl_BM)swirl.matchedBM).eulerAngleX.DeepCopyBM();
|
||||
var y = ((Swirl_BM)swirl.matchedBM).eulerAngleY.DeepCopyBM();
|
||||
var z = ((Swirl_BM)swirl.matchedBM).eulerAngleZ.DeepCopyBM();
|
||||
x.ApplyTimeOffset(finalTimeOffset); y.ApplyTimeOffset(finalTimeOffset); z.ApplyTimeOffset(finalTimeOffset);
|
||||
|
||||
List<ICanBeTrackedSwirl> ICanBeTrackedSwirls = new List<ICanBeTrackedSwirl> { this as ICanBeTrackedSwirl };
|
||||
while (MaybeDeadLoop && ICanBeTrackedSwirls[0] is not Swirl)
|
||||
{
|
||||
ICanBeTrackedSwirl ao = (ICanBeTrackedSwirls[0] as SwirlTracker).targetSwirl;
|
||||
ICanBeTrackedSwirls.Insert(0, ao);
|
||||
}
|
||||
ICanBeTrackedSwirls.ForEach(o =>
|
||||
{
|
||||
((IHaveVector3Interferometer)o).ApplyVector3InterferometersBM(x, y, z);
|
||||
});
|
||||
parentElement.SaveBM();
|
||||
Swirl_BM a = new Swirl_BM("Swirl", elementGuid, new List<string>(), parentElement.matchedBM as GameElement_BM,
|
||||
x, y, z);
|
||||
var a = new Swirl_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
|
||||
eulerAngleX.ConvertToBM(), eulerAngleY.ConvertToBM(), eulerAngleZ.ConvertToBM());
|
||||
MatchingExportElement = a;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace Ichni.RhythmGame
|
||||
public bool isSwitchingReturnType;
|
||||
public FlexibleReturnType lastReturnType;
|
||||
public FlexibleReturnType returnType;
|
||||
public event Action OnDataChanged;
|
||||
|
||||
public FlexibleFloat(bool withFirstAnimation = false)
|
||||
{
|
||||
@@ -71,11 +72,14 @@ namespace Ichni.RhythmGame
|
||||
public void Add(AnimatedFloat animatedFloat)
|
||||
{
|
||||
animations.Add(animatedFloat);
|
||||
OnDataChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void Sort()
|
||||
{
|
||||
animations.Sort();
|
||||
OnDataChanged?.Invoke();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Ichni.RhythmGame
|
||||
public partial class EnvironmentObject : SubstantialObject
|
||||
{
|
||||
public bool isStatic;
|
||||
|
||||
|
||||
public static EnvironmentObject GenerateElement(string elementName, Guid id, List<string> tags,
|
||||
bool isFirstGenerated, string themeBundleName, string objectName, GameElement parentElement, bool isStatic)
|
||||
{
|
||||
@@ -52,7 +52,12 @@ namespace Ichni.RhythmGame
|
||||
var generateAnimation = container.GenerateSubcontainer(3);
|
||||
var generateBaseColorChangeButton = inspector.GenerateButton(this, generateAnimation, "Base Color Change",
|
||||
() => BaseColorChange.GenerateElement("New Base Color Change", Guid.NewGuid(), new List<string>(), true,
|
||||
this, new FlexibleFloat(), new FlexibleFloat(), new FlexibleFloat(), new FlexibleFloat()));
|
||||
this,
|
||||
new FlexibleFloat(new List<AnimatedFloat> { new AnimatedFloat(0f, 0.1f, colorSubmodule.originalBaseColor.r, colorSubmodule.originalBaseColor.r, animationCurveType: AnimationCurveType.Linear) }),
|
||||
new FlexibleFloat(new List<AnimatedFloat> { new AnimatedFloat(0f, 0.1f, colorSubmodule.originalBaseColor.g, colorSubmodule.originalBaseColor.g, animationCurveType: AnimationCurveType.Linear) }),
|
||||
new FlexibleFloat(new List<AnimatedFloat> { new AnimatedFloat(0f, 0.1f, colorSubmodule.originalBaseColor.b, colorSubmodule.originalBaseColor.b, animationCurveType: AnimationCurveType.Linear) }),
|
||||
new FlexibleFloat(new List<AnimatedFloat> { new AnimatedFloat(0f, 0.1f, colorSubmodule.originalBaseColor.a, colorSubmodule.originalBaseColor.a, animationCurveType: AnimationCurveType.Linear) })
|
||||
));
|
||||
if (haveEmissionColor)
|
||||
{
|
||||
var generateEmissionColorChangeButton = inspector.GenerateButton(this, generateAnimation, "Emission Color Change",
|
||||
|
||||
@@ -130,7 +130,12 @@ namespace Ichni.RhythmGame
|
||||
StandardInspectionElement.GenerateForTransform(this, container);
|
||||
var generateBaseColorChangeButton = inspector.GenerateButton(this, generateAnimation, "Base Color Change",
|
||||
() => BaseColorChange.GenerateElement("New Base Color Change", Guid.NewGuid(), new List<string>(), true,
|
||||
this, new FlexibleFloat(true), new FlexibleFloat(true), new FlexibleFloat(true), new FlexibleFloat(true)));
|
||||
this,
|
||||
new FlexibleFloat(new List<AnimatedFloat> { new AnimatedFloat(0f, 0.1f, colorSubmodule.originalBaseColor.r, colorSubmodule.originalBaseColor.r, animationCurveType: AnimationCurveType.Linear) }),
|
||||
new FlexibleFloat(new List<AnimatedFloat> { new AnimatedFloat(0f, 0.1f, colorSubmodule.originalBaseColor.g, colorSubmodule.originalBaseColor.g, animationCurveType: AnimationCurveType.Linear) }),
|
||||
new FlexibleFloat(new List<AnimatedFloat> { new AnimatedFloat(0f, 0.1f, colorSubmodule.originalBaseColor.b, colorSubmodule.originalBaseColor.b, animationCurveType: AnimationCurveType.Linear) }),
|
||||
new FlexibleFloat(new List<AnimatedFloat> { new AnimatedFloat(0f, 0.1f, colorSubmodule.originalBaseColor.a, colorSubmodule.originalBaseColor.a, animationCurveType: AnimationCurveType.Linear) })
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ namespace Ichni.RhythmGame
|
||||
public class NoteManager : MonoBehaviour
|
||||
{
|
||||
public List<(NoteBase note, float activationTime, float finishTime)> pendingNotes = new List<(NoteBase, float, float)>();
|
||||
private int nextNoteIndex = 0;
|
||||
private List<(NoteBase note1, bool isActive, float activationTime)> ProcessingNotes = new List<(NoteBase, bool, float)>();
|
||||
public void RegisterNote(NoteBase note, float activationTime, float finishTime)
|
||||
{
|
||||
|
||||
@@ -499,7 +499,7 @@ public class SkyboxBlender : MonoBehaviour
|
||||
if (reflectionProbe.texture != null)
|
||||
{
|
||||
Graphics.CopyTexture(reflectionProbe.texture, cubemap as Texture);
|
||||
RenderSettings.customReflection = cubemap;
|
||||
RenderSettings.customReflectionTexture = cubemap;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user