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

354 lines
10 KiB
C#
Raw Normal View History

2025-01-18 12:49:14 +00:00
using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using Godot;
namespace Rokojori
{
2025-01-18 20:02:20 +00:00
public enum HighlightActionType
{
Start,
End
}
public class HighlightAnimation
{
public Node3D[] targets = new Node3D[ 0 ];
2025-01-18 20:02:20 +00:00
public int tweenID = -1;
public List<Material> materials = new List<Material>();
public float phase;
}
2025-01-18 12:49:14 +00:00
[Tool]
[GlobalClass]
public partial class HighlightEffect:Resource
{
2025-01-18 20:02:20 +00:00
[Export]
public TimeLine timeline;
2025-01-19 20:35:51 +00:00
[ExportGroup( "Transition")]
2025-01-18 20:02:20 +00:00
[Export]
public float inDuration;
[Export]
public Curve inCurve = MathX.Curve( 0, 1 );
[Export]
public float outDuration;
[Export]
public Curve outCurve = MathX.Curve( 0, 1 );
2025-01-19 20:35:51 +00:00
[ExportGroup( "Color")]
2025-01-18 20:02:20 +00:00
[Export]
public HDRColor color;
2025-01-19 20:35:51 +00:00
[Export( PropertyHint.Range, "0,1")]
public float opacityModulationStrength = 0.5f;
[Export( PropertyHint.Range, "0,10")]
public float opacityModulationDuration = 0.5f;
[Export( PropertyHint.Range, "0,1")]
public float opacityModulationTransition = 1f;
public enum OutlineMaterialMode
2025-01-18 20:02:20 +00:00
{
Flat_Outline,
2025-01-19 20:35:51 +00:00
Scanner_FancyOutline,
2025-01-18 20:02:20 +00:00
Custom_Material
}
2025-01-19 20:35:51 +00:00
[ExportGroup( "Outline")]
[Export]
public OutlineMaterialMode outlineMaterialMode;
2025-01-18 20:02:20 +00:00
[Export]
2025-01-19 20:35:51 +00:00
public Material outlineCustomMaterial;
[Export]
public ColorPropertyName outlineCustomColorProperty;
public enum OverlayMaterialMode
{
Flat_Overlay,
Custom_Material
}
[ExportGroup( "Overlay")]
[Export( PropertyHint.Range, "0,1")]
public float overlayOpacity = 0.02f;
2025-01-18 20:02:20 +00:00
[Export]
2025-01-19 20:35:51 +00:00
public OverlayMaterialMode overlayMaterialMode;
2025-01-18 20:02:20 +00:00
[Export]
2025-01-19 20:35:51 +00:00
public Material overlayCustomMaterial;
[Export]
public ColorPropertyName overlayCustomColorProperty;
2025-01-18 20:02:20 +00:00
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;
2025-01-19 20:35:51 +00:00
if ( OutlineMaterialMode.Flat_Outline == outlineMaterialMode )
2025-01-18 20:02:20 +00:00
{
var outlineMaterial = new OutlineMaterial();
outlineMaterial.albedo.Set( colorTransparent );
material = outlineMaterial;
2025-01-19 20:35:51 +00:00
outlineMaterial.opacityModulationDuration.Set( opacityModulationDuration );
outlineMaterial.opacityModulationStrength.Set( opacityModulationStrength );
}
else if ( OutlineMaterialMode.Scanner_FancyOutline == outlineMaterialMode )
{
var outlineMaterial = new FancyOutlineMaterial();
outlineMaterial.albedo.Set( colorTransparent );
material = outlineMaterial;
outlineMaterial.opacityModulationDuration.Set( opacityModulationDuration );
outlineMaterial.opacityModulationStrength.Set( opacityModulationStrength );
}
else if ( OutlineMaterialMode.Custom_Material == outlineMaterialMode )
{
material = (Material) outlineCustomMaterial.Duplicate();
outlineCustomColorProperty.Set( material, colorTransparent );
}
if ( OverlayMaterialMode.Flat_Overlay == overlayMaterialMode )
{
var overlay = new OverlayMaterial();
overlay.albedo.Set( ColorX.SetAlpha( hdrColor, 0 ) );
material.NextPass = overlay;
overlay.opacityModulationDuration.Set( opacityModulationDuration );
overlay.opacityModulationStrength.Set( opacityModulationStrength );
2025-01-18 20:02:20 +00:00
}
2025-01-19 20:35:51 +00:00
else if ( OverlayMaterialMode.Custom_Material == overlayMaterialMode )
2025-01-18 20:02:20 +00:00
{
2025-01-19 20:35:51 +00:00
var overlay = (Material) overlayCustomMaterial.Duplicate();
overlayCustomColorProperty.Set( overlay, colorTransparent );
material.NextPass = overlay;
2025-01-18 20:02:20 +00:00
}
2025-01-19 20:35:51 +00:00
2025-01-18 20:02:20 +00:00
Arrays.ForEach( targets,
t =>
{
var m = (Material) material.Duplicate( true );
animation.materials.Add( m );
Materials.AddOverlay( t, m );
}
);
}
var startPhase = animation.phase;
2025-01-19 20:35:51 +00:00
animation.tweenID = TimeLineManager.ScheduleSpanIn( timeline, 0, inDuration,
( span, type )=>
2025-01-18 20:02:20 +00:00
{
2025-01-19 20:35:51 +00:00
if ( animation.tweenID != span.id )
2025-01-18 20:02:20 +00:00
{
return;
}
2025-01-19 20:35:51 +00:00
var phase = span.phase;
animation.phase = MathX.Map( phase, 0, 1, startPhase, 1 );
2025-01-18 20:02:20 +00:00
var p = animation.phase;
if ( inCurve != null )
{
p = inCurve.Sample( p );
}
2025-01-19 20:35:51 +00:00
var transitionModulationStrength = Mathf.Lerp(
opacityModulationStrength, opacityModulationStrength * p,
opacityModulationTransition );
2025-01-18 20:02:20 +00:00
var tweenColor = ColorX.Fade( hdrColor, p );
if ( TimeLineSpanUpdateType.End == type )
{
tweenColor = hdrColor;
animation.phase = 1;
}
animation.materials.ForEach(
( m )=>
{
2025-01-19 20:35:51 +00:00
if ( OutlineMaterialMode.Flat_Outline == outlineMaterialMode )
2025-01-18 20:02:20 +00:00
{
var outlineMaterial = ( OutlineMaterial ) m;
outlineMaterial.albedo.Set( tweenColor );
2025-01-19 20:35:51 +00:00
outlineMaterial.opacityModulationStrength.Set( transitionModulationStrength );
}
else if ( OutlineMaterialMode.Scanner_FancyOutline == outlineMaterialMode )
{
var outlineMaterial = ( FancyOutlineMaterial ) m;
outlineMaterial.albedo.Set( tweenColor );
outlineMaterial.opacityModulationStrength.Set( transitionModulationStrength );
2025-01-18 20:02:20 +00:00
}
2025-01-19 20:35:51 +00:00
else if ( OutlineMaterialMode.Custom_Material == outlineMaterialMode )
2025-01-18 20:02:20 +00:00
{
2025-01-19 20:35:51 +00:00
outlineCustomColorProperty.Set( m, tweenColor);
2025-01-18 20:02:20 +00:00
}
2025-01-19 20:35:51 +00:00
if ( OverlayMaterialMode.Flat_Overlay == overlayMaterialMode )
{
var overlay = (OverlayMaterial) m.NextPass;
overlay.albedo.Set( ColorX.Fade( tweenColor, overlayOpacity ) );
overlay.opacityModulationStrength.Set( transitionModulationStrength );
}
else if ( OutlineMaterialMode.Custom_Material == outlineMaterialMode )
{
var material = (OverlayMaterial) m.NextPass;
outlineCustomColorProperty.Set( m, tweenColor);
}
2025-01-18 20:02:20 +00:00
}
);
}
2025-01-19 20:35:51 +00:00
).id;
2025-01-18 20:02:20 +00:00
}
void EndHighlight( Node3D[] targets )
{
var animation = _active.Find( a => Arrays.AreEntriesEqual( a.targets, targets ) );
if ( animation == null )
{
return;
}
var startPhase = animation.phase;
var hdrColor = ColorX.Fade( color.GetHDRColor(), startPhase );
var colorTransparent = ColorX.Fade( hdrColor, 0 );
2025-01-19 20:35:51 +00:00
animation.tweenID = TimeLineManager.ScheduleSpanIn( timeline, 0, outDuration,
( span, type )=>
2025-01-18 20:02:20 +00:00
{
2025-01-19 20:35:51 +00:00
if ( animation.tweenID != span.id )
2025-01-18 20:02:20 +00:00
{
return;
}
2025-01-19 20:35:51 +00:00
animation.phase = MathX.Map( span.phase, 0, 1, startPhase, 0 );
2025-01-18 20:02:20 +00:00
var p = animation.phase;
if ( outCurve != null )
{
p = outCurve.Sample( p );
}
2025-01-19 20:35:51 +00:00
var transitionModulationStrength = Mathf.Lerp(
opacityModulationStrength, opacityModulationStrength * p,
opacityModulationTransition );
2025-01-18 20:02:20 +00:00
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 )=>
{
2025-01-19 20:35:51 +00:00
if ( OutlineMaterialMode.Flat_Outline == outlineMaterialMode )
2025-01-18 20:02:20 +00:00
{
var outlineMaterial = ( OutlineMaterial ) m;
outlineMaterial.albedo.Set( tweenColor );
2025-01-19 20:35:51 +00:00
outlineMaterial.opacityModulationStrength.Set( transitionModulationStrength );
}
else if ( OutlineMaterialMode.Scanner_FancyOutline == outlineMaterialMode )
{
var outlineMaterial = ( FancyOutlineMaterial ) m;
outlineMaterial.albedo.Set( tweenColor );
outlineMaterial.opacityModulationStrength.Set( transitionModulationStrength );
2025-01-18 20:02:20 +00:00
}
2025-01-19 20:35:51 +00:00
else if ( OutlineMaterialMode.Custom_Material == outlineMaterialMode )
2025-01-18 20:02:20 +00:00
{
2025-01-19 20:35:51 +00:00
outlineCustomColorProperty.Set( m, tweenColor );
2025-01-18 20:02:20 +00:00
}
2025-01-19 20:35:51 +00:00
if ( OverlayMaterialMode.Flat_Overlay == overlayMaterialMode )
{
var overlay = (OverlayMaterial) m.NextPass;
overlay.albedo.Set( ColorX.Fade( tweenColor, overlayOpacity ) );
overlay.opacityModulationStrength.Set( transitionModulationStrength );
}
else if ( OutlineMaterialMode.Custom_Material == outlineMaterialMode )
{
var material = (OverlayMaterial) m.NextPass;
outlineCustomColorProperty.Set( m, tweenColor);
}
2025-01-18 20:02:20 +00:00
}
);
}
}
2025-01-19 20:35:51 +00:00
).id;
2025-01-18 20:02:20 +00:00
}
2025-01-18 12:49:14 +00:00
}
}