rj-action-library/Runtime/Animation/Flash.cs

261 lines
6.6 KiB
C#

using System.Collections;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Text;
using Godot;
namespace Rokojori
{
[Tool]
[GlobalClass]
public partial class Flash:RJSequenceAction
{
[Export]
public FlashEffect flashEffect;
[Export]
public Node3D[] targets;
int animationID = -1;
int actionID = -1;
Vector3 randomization;
List<Material> _materials;
OmniLight3D light = null;
Color ComputeLightColor( Color color, float phase )
{
if ( phase < 5/100f )
{
var n = MathX.NormalizeClamped( phase, 0, 5/100f );
color *= n;
}
else if ( phase > 95/100f )
{
var n = MathX.NormalizeClamped( phase, 1, 95/100f );
color *= n;
}
return color;
}
public override void _OnTrigger()
{
if ( actionID != -1 )
{
CancelAction( actionID );
}
actionID = DispatchStart();
// RJLog.Log( "Setting actionID id", actionID, GetLastSequenceActionID() );
var flashCurve = flashEffect.flashCurve;
var color = flashEffect.color.GetHDRColor();
var timeline = flashEffect.timeline;
randomization = flashCurve.Randomize();
var duration = flashCurve.GetRandomizedDuration( randomization );
var transparentColor = color;
var initialAlpha = transparentColor.A;
transparentColor.A = 0;
Material material = null;
if ( FlashEffect.FlashLightMode.No_Light != flashEffect.lightMode )
{
light = targets[ 0 ].CreateChild<OmniLight3D>();
light.LightColor = ComputeLightColor( color, 0 );
light.LightEnergy = 0;
light.OmniRange = flashEffect.lightRange;
light.ShadowEnabled = flashEffect.lightHasShadows;
// RJLog.Log( "Created Light", light.Name );
}
if ( FlashEffect.MaterialMode.Flat_Standard3D == flashEffect.materialMode )
{
var standardMaterial = new StandardMaterial3D();
standardMaterial.AlbedoColor = transparentColor;
standardMaterial.ShadingMode = BaseMaterial3D.ShadingModeEnum.Unshaded;
standardMaterial.Transparency = BaseMaterial3D.TransparencyEnum.Alpha;
material = standardMaterial;
}
else if ( FlashEffect.MaterialMode.Fresnel_FresnelOverlay == flashEffect.materialMode )
{
var fresnelMaterial = new FresnelOverlayMaterial();
fresnelMaterial.albedo.Set( transparentColor );
material = fresnelMaterial;
}
else if ( FlashEffect.MaterialMode.Scan_ScanGradient == flashEffect.materialMode )
{
var scanMaterial = ScanGradientMaterial.White.Get();
scanMaterial.albedo.Set( transparentColor );
material = scanMaterial;
}
else if ( FlashEffect.MaterialMode.Shield_TriPlanarOverlay == flashEffect.materialMode )
{
var shieldMaterial = TriPlanarOverlayMaterial.WhiteShield.Get();
shieldMaterial.albedo.Set( transparentColor );
material = shieldMaterial;
}
else
{
material = flashEffect.customMaterial;
flashEffect.customFlashColorProperty.Set( material, transparentColor );
}
_materials = new List<Material>();
Arrays.ForEach( targets,
t =>
{
var m = (Material) material.Duplicate( true );
_materials.Add( m );
Materials.AddOverlay( t, m );
}
);
var start = TimeLineManager.GetPosition( timeline );
var end = start + duration;
animationID = TimeLineScheduler.ScheduleSpanIn( timeline, 0, duration,
( int id, int type )=>
{
if ( animationID != id )
{
return;
}
var phase = TimeLineManager.GetRangePhase( timeline, start, end );
var value = flashCurve.Sample( phase );
var phaseColor = color;
phaseColor.A = value * initialAlpha;
if ( light != null )
{
light.LightEnergy = value * flashEffect.lightFlashCurveScale;
light.LightColor = ComputeLightColor( color, phase );
}
_materials.ForEach(
( m )=>
{
if ( FlashEffect.MaterialMode.Flat_Standard3D == flashEffect.materialMode )
{
var sm = m as StandardMaterial3D;
sm.AlbedoColor = phaseColor;
}
else if ( FlashEffect.MaterialMode.Fresnel_FresnelOverlay == flashEffect.materialMode )
{
var sm = m as FresnelOverlayMaterial;
sm.albedo.Set( phaseColor );
}
else if ( FlashEffect.MaterialMode.Scan_ScanGradient == flashEffect.materialMode )
{
var sm = m as ScanGradientMaterial;
sm.albedo.Set( phaseColor );
sm.offset.Set( phase * 3 );
}
else if ( FlashEffect.MaterialMode.Shield_TriPlanarOverlay == flashEffect.materialMode )
{
var sm = m as TriPlanarOverlayMaterial;
sm.albedo.Set( phaseColor );
}
else if ( FlashEffect.MaterialMode.Custom_Material == flashEffect.materialMode )
{
var sm = m as ShaderMaterial;
flashEffect.customFlashColorProperty.Set( sm, phaseColor );
}
}
);
if ( type == TimeLineSpan.End )
{
if ( light != null )
{
light.LightEnergy = 0;
light.LightColor = new Color( 0, 0, 0, 0 );
}
CancelAction( actionID );
DispatchEnd( actionID );
}
}
);
// RJLog.Log( "Processing animationID", animationID );
}
public override void CancelAction( int id )
{
// RJLog.Log( "CancelAction", id );
if ( false && actionID != id )
{
// RJLog.Log( "actionID != id", "id", id, "actionID", actionID );
return;
}
if ( light != null )
{
// RJLog.Log( "Removing Light", light.Name );
Nodes.RemoveAndDelete( light );
light = null;
}
RemoveMaterials();
}
void RemoveMaterials()
{
if ( _materials.Count != targets.Length )
{
return;
}
for ( int i = 0; i < targets.Length; i++ )
{
Materials.RemoveOverlay( targets[ i ], _materials[ i ] );
}
_materials.Clear();
}
}
}