using Godot; using System.Collections.Generic; namespace Rokojori { [Tool] [GlobalClass] public partial class FontFX:Node3D { [ExportToolButton( "Update")] public Callable updateButton => Callable.From( ()=>{ _Update(); } ); [ExportToolButton( "Clear Cache")] public Callable clearCacheButton => Callable.From( ()=>{ ClearCache(); } ); [Export] public FontDefinition font { get => _font; set { _font = value; _Update(); } } FontDefinition _font; [Export] public LocaleText text{ get => _text; set{ _text = value; _Update(); } } LocaleText _text; FontFXLayouter _layouter = new FontFXLayouter(); Transformable _layout; Dictionary _glyphMap = new Dictionary(); void ClearCache() { _glyphMap = new Dictionary(); } PackedScene GetGlyph( string character ) { if ( _glyphMap.ContainsKey( character ) ) { return _glyphMap[ character ]; } var g = font.GetFontGlyph( character ); _glyphMap[ character ] = g == null ? null : g.glyphMesh.LoadScene(); return _glyphMap[ character ]; } void _Update() { if ( _font == null || _text == null ) { return; } this.DestroyChildren(); var realText = _text.currentValue; var lines = _layouter.Layout( realText, _font ); var offset = 0f; lines.ForEach( ( line )=> { offset = CreateLine( line, offset ); } ); } float CreateLine( FontFXLine line, float offset ) { line.ComptuteOffsets(); line.groups.ForEach( ( g )=> { CreateGroup( g, offset ); } ); return offset + font.baseToBottom + font.baseToTop; } void CreateGroup( FontFXGroup group, float offset ) { for ( int i = 0; i < group.characters.Length; i++ ) { var sc = GetGlyph( group.characters[ i ] + "" ); if ( sc == null ) { continue; } var n = sc.Instantiate(); n.Name = this.GetChildCount() + "-" + group.characters[ i ].MapCharacterToName(); n.SetParent( this ); n.SetLocalX( group.absoluteOffsets[ i ] ); n.SetLocalY( -offset ); } } } }