rj-action-library/Runtime/Animation/Highlight/HighlightEffect.cs

239 lines
5.6 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using Godot;
namespace Rokojori
{
public enum HighlightActionType
{
Start,
End
}
public class HighlightAnimation
{
public Node3D[] targets;
public int tweenID = -1;
public List<Material> materials = new List<Material>();
public float phase;
}
[Tool]
[GlobalClass]
public partial class HighlightEffect:Resource
{
[Export]
public TimeLine timeline;
[Export]
public float inDuration;
[Export]
public Curve inCurve = MathX.Curve( 0, 1 );
[Export]
public float outDuration;
[Export]
public Curve outCurve = MathX.Curve( 0, 1 );
[Export]
public HDRColor color;
public enum MaterialMode
{
Flat_Outline,
Custom_Material
}
[Export]
public MaterialMode materialMode;
[Export]
public Material customMaterial;
[Export]
public ColorPropertyName customColorProperty;
List<HighlightAnimation> _active = new List<HighlightAnimation>();
public void Highlight( HighlightActionType type, Node3D[] targets )
{
if ( HighlightActionType.Start == type )
{
StartHighlight( targets );
}
else if ( HighlightActionType.End == type )
{
EndHighlight( targets );
}
}
void StartHighlight( Node3D[] targets )
{
var animation = _active.Find( a => Arrays.AreEntriesEqual( a.targets, targets ) );
var hdrColor = color.GetHDRColor();
var colorTransparent = ColorX.Fade( hdrColor, 0 );
if ( animation == null )
{
animation = new HighlightAnimation();
animation.targets = targets;
_active.Add( animation );
Material material = null;
if ( MaterialMode.Flat_Outline == materialMode )
{
var outlineMaterial = new OutlineMaterial();
outlineMaterial.albedo.Set( colorTransparent );
material = outlineMaterial;
}
else if ( MaterialMode.Custom_Material == materialMode )
{
material = (Material) customMaterial.Duplicate();
customColorProperty.Set( material, colorTransparent );
}
Arrays.ForEach( targets,
t =>
{
var m = (Material) material.Duplicate( true );
animation.materials.Add( m );
Materials.AddOverlay( t, m );
}
);
}
var startPhase = animation.phase;
animation.tweenID = TimeLineManager.Tween( timeline, inDuration,
( id, type, phase )=>
{
// RJLog.Log( "Start Highlight: ", id, "Active:",animation.tweenID, "Phase:", phase );
if ( animation.tweenID != id )
{
return;
}
animation.phase = MathX.Map( phase, 0, 1, startPhase, 1 );
var p = animation.phase;
if ( inCurve != null )
{
p = inCurve.Sample( p );
}
var tweenColor = ColorX.Fade( hdrColor, p );
if ( TimeLineSpanUpdateType.End == type )
{
tweenColor = hdrColor;
animation.phase = 1;
}
animation.materials.ForEach(
( m )=>
{
if ( MaterialMode.Flat_Outline == materialMode )
{
var outlineMaterial = ( OutlineMaterial ) m;
outlineMaterial.albedo.Set( tweenColor );
}
else if ( MaterialMode.Custom_Material == materialMode )
{
customColorProperty.Set( m, tweenColor);
}
}
);
}
);
}
void EndHighlight( Node3D[] targets )
{
var animation = _active.Find( a => Arrays.AreEntriesEqual( a.targets, targets ) );
if ( animation == null )
{
// RJLog.Log( "No animation found:", targets );
return;
}
var startPhase = animation.phase;
var hdrColor = ColorX.Fade( color.GetHDRColor(), startPhase );
var colorTransparent = ColorX.Fade( hdrColor, 0 );
animation.tweenID = TimeLineManager.Tween( timeline, outDuration,
( id, type, phase )=>
{
// RJLog.Log( "End Highlight: ", id, "Active:",animation.tweenID, "Phase:", phase );
if ( animation.tweenID != id )
{
return;
}
animation.phase = MathX.Map( phase, 0, 1, startPhase, 0 );
var p = animation.phase;
if ( outCurve != null )
{
p = outCurve.Sample( p );
}
var tweenColor = ColorX.Fade( hdrColor, p );
if ( TimeLineSpanUpdateType.End == type )
{
tweenColor = colorTransparent;
animation.phase = 0;
for ( int i = 0; i < animation.targets.Length; i ++ )
{
Materials.RemoveOverlay( targets[ i ], animation.materials[ i ] );
}
_active.Remove( animation );
}
else
{
animation.materials.ForEach(
( m )=>
{
if ( MaterialMode.Flat_Outline == materialMode )
{
var outlineMaterial = ( OutlineMaterial ) m;
outlineMaterial.albedo.Set( tweenColor );
}
else if ( MaterialMode.Custom_Material == materialMode )
{
customColorProperty.Set( m, tweenColor );
}
}
);
}
}
);
}
}
}