using System; using Godot; namespace Rokojori { [Tool] [GlobalClass ] public partial class TweenMaterial : SequenceAction, Animator { public void OnAnimatorStart(){} public void OnAnimatorEnd(){} public void OnAnimatorCancel(){} // [Export] // public Material fromMaterial; [Export] public Material toMaterial; [Export] public TweenType tweenType = new TweenTimeCurve(); [Export] public TimeLine timeLine; ColorProperty[] colors = []; FloatProperty[] floats = []; public enum MaterialAssignmentMode { No_Assignment, Assignment_Once, Unique_Once, Temporary_Duplicate_For_Each_Tween } // [Export] // public MaterialAssignmentMode assignmentMode = MaterialAssignmentMode.Temporary_Duplicate_For_Each_Tween; [ExportGroup( "Target")] [Export] public Node3D target; [Export] public MaterialSlot slot = MaterialSlot.None; [Export] public int index = 0; // [ExportToolButton( "Assign From-Material")] // public Callable AssignFromMaterialButton => Callable.From( // () => // { // MaterialSurfaceContainer.SetMaterialInSlot( target, index, slot, fromMaterial ); // } // ); [ExportToolButton( "Assign To-Material")] public Callable AssignToMaterialButton => Callable.From( () => { MaterialSurfaceContainer.SetMaterialInSlot( target, index, slot, toMaterial ); } ); [ExportToolButton( "Get Material Delta")] public Callable GetMaterialDeltaButton => Callable.From( () => { var from = MaterialSurfaceContainer.GetMaterialInSlot( target, index, slot ); this.LogInfo( "Delta", MaterialDelta.Create( from, toMaterial ) ); } ); Material _assignedMaterial = null; protected override void _OnTrigger() { if ( toMaterial == null && this._assignedMaterial == null ) { return; } var fromMaterial = MaterialSurfaceContainer.From( target, this.index ).GetMaterialInSlot( slot ); SetAssignedMaterial( fromMaterial ); var tl = TimeLineManager.Ensure( timeLine ); var start = tl.position; var delta = MaterialDelta.Create( fromMaterial, toMaterial ); this.LogInfo( "Delta:", delta ); colors = delta.colorProperties.ToArray(); floats = delta.floatProperties.ToArray(); var startColors = new Color[ colors.Length ]; var startFloats = new float[ floats.Length ]; var elementIndex = 0; foreach ( var c in colors ) { AnimationManager.StartAnimation( this, _assignedMaterial, c.propertyName ); startColors[ elementIndex ] = c.propertyName.Get( fromMaterial ); elementIndex ++; } elementIndex = 0; foreach ( var f in floats ) { AnimationManager.StartAnimation( this, _assignedMaterial, f.propertyName ); startFloats[ elementIndex ] = f.propertyName.Get( fromMaterial ); elementIndex ++; } var sequenceID = DispatchStart(); var tweenType = this.tweenType; if ( tweenType == null ) { tweenType = TweenTimeCurve.defaultCurve; } TimeLineManager.ScheduleSpanIn( tl, 0, tweenType.GetTweenDuration(), ( span, type )=> { var timeNow = tl.position; var elapsed = timeNow - start; var elementIndex = 0; var state = tweenType.GetTweenPhaseForPhase( span.phase ); foreach ( var c in colors ) { if ( AnimationManager.IsAnimating( this, _assignedMaterial, c.propertyName ) ) { c.ApplyLerped( _assignedMaterial, startColors[ elementIndex ], state ); } elementIndex ++; } elementIndex = 0; foreach ( var f in floats ) { if ( AnimationManager.IsAnimating( this, _assignedMaterial, f.propertyName ) ) { f.ApplyLerped( _assignedMaterial, startFloats[ elementIndex ], state ); } elementIndex ++; } 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 ); } if ( MaterialAssignmentMode.Temporary_Duplicate_For_Each_Tween == assignmentMode ) { _assignedMaterial = null; var msc = MaterialSurfaceContainer.From( target, index ); msc.SetMaterialInSlot( slot, toMaterial ); } DispatchEnd( sequenceID ); } } ); } void SetAssignedMaterial( Material material ) { if ( MaterialAssignmentMode.Temporary_Duplicate_For_Each_Tween == assignmentMode ) { _assignedMaterial = (Material)material.Duplicate(); var tmsc = MaterialSurfaceContainer.From( target, index ); tmsc.SetMaterialInSlot( slot, _assignedMaterial ); return; } if ( _assignedMaterial != null ) { return; } if ( MaterialAssignmentMode.No_Assignment == assignmentMode ) { _assignedMaterial = toMaterial; return; } _assignedMaterial = toMaterial; if ( MaterialAssignmentMode.Unique_Once == assignmentMode ) { _assignedMaterial = (Material)toMaterial.Duplicate(); } var msc = MaterialSurfaceContainer.From( target, index ); msc.SetMaterialInSlot( slot, _assignedMaterial ); } } }