OldBlueWater/BlueWater/Assets/Doozy/Runtime/Nody/Nodes/TimeScaleNode.cs
2023-08-02 15:08:03 +09:00

116 lines
4.0 KiB
C#

// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved.
// This code can only be used under the standard Unity Asset Store End User License Agreement
// A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms
using System;
using Doozy.Runtime.Nody.Nodes.Internal;
using Doozy.Runtime.Reactor.Easings;
using Doozy.Runtime.Reactor.Internal;
using Doozy.Runtime.Reactor.Reactions;
using UnityEngine;
// ReSharper disable RedundantOverriddenMember
namespace Doozy.Runtime.Nody.Nodes
{
/// <summary>
/// TimeScale Node sets the scale at which the time is passing (it updates Time.timeScale). This can be used for slow motion effects.
/// It can do that that either instantly or over a set duration (animated).
/// The node can also wait until the current Time.timeScale value has reached the target value, before activating the next node in the Graph.
/// </summary>
[Serializable]
[NodyMenuPath("Time", "TimeScale")]
public sealed class TimeScaleNode : SimpleNode
{
public static string timescaleAnimationId => $"{nameof(TimeScaleNode)} TimeScale Animation";
public FloatReaction timeScaleReaction { get; private set; }
public float TargetValue;
public bool AnimateValue;
public float AnimationDuration;
public Ease AnimationEase;
public bool WaitForAnimationToFinish;
public TimeScaleNode()
{
TargetValue = 1f;
AnimateValue = false;
AnimationDuration = 1f;
AnimationEase = Ease.Linear;
WaitForAnimationToFinish = false;
AddInputPort()
.SetCanBeDeleted(false)
.SetCanBeReordered(false);
AddOutputPort()
.SetCanBeDeleted(false)
.SetCanBeReordered(false);
}
public override void OnEnter(FlowNode previousNode = null, FlowPort previousPort = null)
{
base.OnEnter(previousNode, previousPort);
StartTimer();
}
private void StartTimer()
{
if (Math.Abs(Time.timeScale - TargetValue) < 0.01f)
{
Time.timeScale = TargetValue;
GoToNextNode(firstOutputPort);
return;
}
timeScaleReaction?.Recycle();
timeScaleReaction =
Reaction
.Get<FloatReaction>()
.SetStringId(timescaleAnimationId)
.SetSetter(value => Time.timeScale = value)
.SetGetter(() => Time.timeScale);
timeScaleReaction.SetEase(AnimationEase);
if (AnimateValue && AnimationDuration > 0)
{
timeScaleReaction.settings.duration = AnimationDuration;
timeScaleReaction.SetFrom(Time.timeScale);
timeScaleReaction.SetTo(TargetValue);
timeScaleReaction.ClearOnFinishCallback();
if (WaitForAnimationToFinish)
{
timeScaleReaction.AddOnFinishCallback(() =>
{
StopTimer();
GoToNextNode(firstOutputPort);
timeScaleReaction?.Recycle();
});
timeScaleReaction.Play();
return;
}
timeScaleReaction.AddOnFinishCallback(StopTimer);
timeScaleReaction.Play();
GoToNextNode(firstOutputPort);
timeScaleReaction?.Recycle();
return;
}
Time.timeScale = TargetValue;
GoToNextNode(firstOutputPort);
}
private void StopTimer()
{
if (timeScaleReaction == null)
return;
timeScaleReaction.Finish();
timeScaleReaction.ClearOnFinishCallback();
timeScaleReaction.Recycle();
timeScaleReaction = null;
}
}
}