gd_core/addons/core/ui/TextAnimate.cs

244 lines
4.8 KiB
C#

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// D E R E L I C T
//
/// // (c) 2003..2024
using Godot;
using Microsoft.Diagnostics.Tracing.Parsers.IIS_Trace;
using System;
/*
T O D O:
x) Add blinking cursor
D O I N G:
D O N E:
*/
[GlobalClass]
public partial class TextAnimate : Control
{
public Action<string> OnFinshed;
[Export]
public NodePath TargetPath = "..";
[Export]
public int TrimStartCount = 0;
[Export]
public int TrimeEndCount = 0;
[Export]
public double InitialDelay = 0;
[Export]
public double MSPerChar = 100;
[Export]
public string OriginalText = "{ERR_BROKEN_TextAnimate}";
[Export]
public string Cursor = "";
[ExportCategory( "Runtime" )]
[Export]
public Control TargetControl = null;
[Export]
public string TextSuffix = "";
[Export]
public int CharCount = 0;
[Export]
public double TimeTillNextChar = 0;
//Dont need prefix string since thats implicit in OriginalText
[Export]
public string SuffixStr = "";
Func<String> GetNodeText;
Action<String> SetNodeText;
// Called when the node enters the scene tree for the first time.
public override void _Ready()
{
log.var( this.Name );
//log.info($"{this?.Name}");
if( TargetPath == null || TargetPath.IsEmpty )
{
var parent = GetParent();
if( parent != null )
{
log.info( $"{Name}: No TargetPath set, using parent {parent.Name}" );
TargetPath = parent.GetPath();
}
else
{
log.warn( $"{Name}: No TargetPath set and no parent to use" );
ProcessMode = ProcessModeEnum.Disabled;
return;
}
return;
}
TargetControl = GetNode<Control>( TargetPath );
if( TargetControl == null )
{
log.warn( $"{Name}({this.NamePath()}): No node at {TargetPath}" );
return;
}
//*
if( TargetControl is LineEdit tcLineEdit )
{
log.info( $"{Name} Connect to {TargetControl.Name}'s TextChanged" );
tcLineEdit.TextChanged += ( text ) => Reset();
}
else if( TargetControl is RichTextLabel richTextLabel )
{
log.info( $"{Name} Connect to {TargetControl.Name}'s TextChanged" );
}
else if( TargetControl is Button button )
{
log.info( $"{Name} Connect to {TargetControl.Name}'s TextChanged" );
}
else
//*/
{
log.high( $"{this?.Name} NOT CONNECTED {TargetControl?.Name}'s TextChanged" );
}
//if( TargetControl is RichTextLabel rtLabel ) rtLabel.TextChanged += ( text ) => Reset();
log.info( $"{this.Name}: TargetControl is {TargetControl?.GetType().Name}" );
var propInfo = TargetControl?.GetType().GetProperty( "Text" );
var getMethod = propInfo?.GetGetMethod();
var setMethod = propInfo?.GetSetMethod();
if( getMethod == null || setMethod == null )
{
log.warn( $"{Name}: No Text property on {TargetControl?.GetType().Name}" );
return;
}
GetNodeText = (Func<String>)Delegate.CreateDelegate( typeof( Func<String> ), TargetControl, getMethod );
SetNodeText = (Action<String>)Delegate.CreateDelegate( typeof( Action<String> ), TargetControl, setMethod );
OriginalText = GetNodeText();
SuffixStr = OriginalText.Substring( OriginalText.Length - TrimeEndCount );
Reset();
//log.debug( $"D O N E {GetType().Name}._Ready" );
}
public void Reset( double delayMs = -1, string origText = "" )
{
if( ProcessMode == ProcessModeEnum.Disabled )
return;
if( GetNodeText == null || SetNodeText == null )
{
log.warn( $"{Name}: No Text property on {TargetControl?.GetType().Name}" );
return;
}
if( string.IsNullOrWhiteSpace( origText ) )
origText = GetNodeText();
InitialDelay = delayMs / 1000.0;
ProcessMode = ProcessModeEnum.Inherit;
OriginalText = origText;
if( delayMs < 0 )
{
delayMs = MSPerChar;
}
//log.debug( $"TA.Text Reset {OriginalText}" );
CharCount = TrimStartCount;
var text = OriginalText.Substring( 0, TrimStartCount );
TimeTillNextChar = delayMs / 1000.0;
SetNodeText( $"{text}{Cursor}{SuffixStr}" );
++CharCount;
}
// Called every frame. 'delta' is the elapsed time since the previous frame.
public override void _Process( double delta )
{
if( ProcessMode == ProcessModeEnum.Disabled )
return;
if( GetNodeText == null || SetNodeText == null )
{
return;
}
//log.info($"{this.Name}");
if( InitialDelay > 0 )
{
InitialDelay -= delta;
return;
}
TimeTillNextChar -= delta;
if( TimeTillNextChar <= 0 )
{
TimeTillNextChar += ( MSPerChar / 1000.0 );
if( CharCount < OriginalText.Length )
{
//SetNodeText( TextPrefix + OriginalText.Substring( 0, CharCount ) + TextSuffix );
var newText = $"{OriginalText.Substring( 0, CharCount )}{Cursor}{SuffixStr}";
SetNodeText( newText );
++CharCount;
}
else
{
SetNodeText( OriginalText );
OnFinshed?.Invoke( OriginalText );
//ProcessMode = ProcessModeEnum.Disabled;
}
}
}
}