using System; using Godot; using Rokojori.Extensions; namespace Rokojori { [Tool] [GlobalClass, Icon("res://addons/rokojori_action_library/Icons/Tween.svg")] public partial class TweenFloatShaderProperty:SequenceAction, Animator { [Export] public Material material; [Export] public GeometryInstance3D instanceTarget; [Export] public FloatPropertyName propertyName; [Export] public float endValue; [Export] public Duration duration; [Export] public Curve curve; [ExportGroup( "Stop")] [Export] public bool stopAnimation = false; [Export] public bool setStopValue = false; [ExportGroup( "Animate")] [Export] public bool animateStartValue = false; [Export] public float animationStartValue = 0f; [ExportGroup( "Editor Testing")] [Export] public bool forceStartValue = false; [Export] public float forcedStartValue = 0f; public void OnAnimatorStart(){} public void OnAnimatorEnd(){} public void OnAnimatorCancel(){} int _actionID = -1; int _timeID = -1; [Export] public bool interruptCurrent = true; protected override void _OnTrigger() { if ( material != null && ! IsInstanceValid( material ) ) { material = null; } if ( instanceTarget != null && ! IsInstanceValid( instanceTarget ) ) { instanceTarget = null; } if ( propertyName == null ) { return; } // this.LogInfo( "TRIGGERED" ); if ( instanceTarget != null ) { // this.LogInfo( "INSTANCE" ); TweenInstanceUniform(); return; } if ( material != null ) { // this.LogInfo( "MATERIAL" ); TweenMaterial(); return; } } void TweenMaterial() { if ( ! interruptCurrent && _actionID != -1 ) { return; } if ( _actionID != -1 ) { CancelAction( _actionID ); } if ( stopAnimation ) { AnimationManager.StartAnimation( this, material, propertyName ); if ( setStopValue ) { propertyName.Set( material, endValue ); } AnimationManager.EndAnimation( this, material, propertyName ); return; } _actionID = DispatchStart(); var startValue = propertyName.Get( material ); if ( forceStartValue && Engine.IsEditorHint() ) { startValue = forcedStartValue; } if ( animateStartValue ) { startValue = animationStartValue; } AnimationManager.StartAnimation( this, material, propertyName ); // this.LogInfo( "Get Float Tween", startValue ); _timeID = TimelineManager.ScheduleSpanWith( duration, ( span, type )=> { // this.LogInfo( "Update Float Tween", startValue ); if ( span.id != _timeID ) { return; } if ( ! AnimationManager.IsAnimating( this, material, propertyName ) ) { return; } var phase = span.phase; if ( curve != null ) { phase = curve.Sample( phase ); } var value = Mathf.Lerp( startValue, endValue, phase ); // this.LogInfo( "Updating Float Tween", "phase:", phase, "value:", value, target ); propertyName.Set( material, value ); // ReflectionHelper.SetValue( material, propertyName , value ); if ( type == TimelineSpanUpdateType.End ) { // this.LogInfo( "End Float Tween", endValue ); // target._Set( targetMember, endValue ); propertyName.Set( material, endValue ); AnimationManager.EndAnimation( this, material, propertyName ); DispatchEnd( _actionID ); _actionID = -1; _timeID = -1; } }, this ).id; } void TweenInstanceUniform() { if ( ! interruptCurrent && _actionID != -1 ) { return; } if ( _actionID != -1 ) { CancelAction( _actionID ); } if ( stopAnimation ) { AnimationManager.StartAnimation( this, instanceTarget, propertyName.propertyName ); if ( setStopValue ) { propertyName.SetInstance( instanceTarget, endValue ); } AnimationManager.EndAnimation( this, instanceTarget, propertyName.propertyName ); return; } _actionID = DispatchStart(); var startValue = propertyName.GetInstance( instanceTarget ); if ( forceStartValue && Engine.IsEditorHint() ) { startValue = forcedStartValue; } if ( animateStartValue ) { startValue = animationStartValue; } AnimationManager.StartAnimation( this, instanceTarget, propertyName.propertyName ); // this.LogInfo( "Get Float Tween", startValue ); _timeID = TimelineManager.ScheduleSpanWith( duration, ( span, type )=> { // this.LogInfo( "Update Float Tween", startValue ); if ( span.id != _timeID ) { return; } if ( ! AnimationManager.IsAnimating( this, instanceTarget, propertyName.propertyName ) ) { return; } var phase = span.phase; if ( curve != null ) { phase = curve.Sample( phase ); } var value = Mathf.Lerp( startValue, endValue, phase ); // this.LogInfo( "Updating Float Tween", "phase:", phase, "value:", value, instanceTarget ); propertyName.SetInstance( instanceTarget, value ); // ReflectionHelper.SetValue( material, propertyName , value ); if ( type == TimelineSpanUpdateType.End ) { // this.LogInfo( "End Float Tween", endValue ); // target._Set( targetMember, endValue ); propertyName.SetInstance( instanceTarget, endValue ); AnimationManager.EndAnimation( this, instanceTarget, propertyName.propertyName ); DispatchEnd( _actionID ); _actionID = -1; _timeID = -1; } }, this ).id; } } }