using Godot; namespace Rokojori { [Tool] [GlobalClass ] public partial class TweenMaterial : SequenceAction, Animator { public void OnAnimatorStart(){} public void OnAnimatorEnd(){} public void OnAnimatorCancel(){} [Export] public Material material; [Export] public float duration; [Export] public Curve tweenCurve = MathX.Curve( 0, 1 ); [Export] public TimeLine timeLine; [Export] public ColorProperty[] colors = []; [Export] public FloatProperty[] floats = []; public enum MaterialAssignmentMode { No_Assignment, Assignment, Unique_Assignment } [ExportGroup( "Target Assignment")] [Export] public MaterialAssignmentMode assignmentMode; [Export] public Node3D target; [Export] public MaterialSlot slot = MaterialSlot.None; [Export] public int index = 0; Material _assignedMaterial = null; protected override void _OnTrigger() { if ( material == null && _assignedMaterial == null ) { return; } SetAssignedMaterial(); var tl = TimeLineManager.Ensure( timeLine ); var start = tl.position; var startColors = new Color[ colors.Length ]; var startFloats = new float[ floats.Length ]; var index = 0; var assignedMaterial = _assignedMaterial; foreach ( var c in colors ) { AnimationManager.StartAnimation( this, assignedMaterial, c.propertyName ); startColors[ index ] = c.propertyName.Get( assignedMaterial ); index ++; } index = 0; foreach ( var f in floats ) { AnimationManager.StartAnimation( this, assignedMaterial, f.propertyName ); startFloats[ index ] = f.propertyName.Get( assignedMaterial ); index ++; } var sequenceID = DispatchStart(); TimeLineManager.ScheduleSpanIn( tl, 0, duration, ( span, type )=> { var timeNow = tl.position; var elapsed = timeNow - start; var index = 0; var state = span.phase; if ( tweenCurve != null ) { state = tweenCurve.Sample( state ); } foreach ( var c in colors ) { if ( AnimationManager.IsAnimating( this, assignedMaterial, c.propertyName ) ) { c.ApplyLerped( assignedMaterial, startColors[ index ], state ); } index ++; } index = 0; foreach ( var f in floats ) { if ( AnimationManager.IsAnimating( this, assignedMaterial, f.propertyName ) ) { f.ApplyLerped( assignedMaterial, startFloats[ index ], state ); } index ++; } if ( type == TimeLineSpanUpdateType.End ) { foreach ( var c in colors ) { AnimationManager.EndAnimation( this, assignedMaterial, c.propertyName ); } foreach ( var f in floats ) { AnimationManager.EndAnimation( this, assignedMaterial, f.propertyName ); } DispatchEnd( sequenceID ); } } ); } void SetAssignedMaterial() { if ( _assignedMaterial != null ) { return; } if ( MaterialAssignmentMode.No_Assignment == assignmentMode ) { _assignedMaterial = material; return; } _assignedMaterial = material; if ( MaterialAssignmentMode.Unique_Assignment == assignmentMode ) { _assignedMaterial = (Material)material.Duplicate(); } var msc = MaterialSurfaceContainer.From( target, index ); msc.SetMaterialInSlot( slot, _assignedMaterial ); } } }