using Godot; using System; using System.Collections.Generic; namespace Rokojori { [Tool] [GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UI.svg")] public partial class UI : Control, IDisposable { [Export] public UISettings settings; [Export] public float fontZoom = 1; public enum UpdateMode { Always, Only_Manual_Updates } [Export] public UpdateMode updateMode = UpdateMode.Always; [Export] public bool useParentSize = false; [ExportGroup("Functions")] [ExportToolButton( "Mouse:Stop => Pass")] public Callable StopToPassButton => Callable.From( ()=>{ MakeStopToPass(); } ); [Export] public Node[] stopToPassRoots = []; [ExportGroup("Read Only")] [Export] public float X_computedFontSizePixels = 1; List _customDisposers = []; public void AddForDisposing( ICustomDisposer customDisposer ) { _customDisposers.Add( customDisposer ); } protected override void Dispose( bool disposing ) { _customDisposers.ForEach( cd => cd.Dispose() ); _customDisposers = []; } [Export] public string[] customDisposerIDs = []; public void MakeStopToPass() { var roots = stopToPassRoots; if ( roots == null || roots.Length == 0 ) { roots = [ this ]; } foreach ( var n in roots ) { if ( n is Control c ) { if ( c.MouseFilter == MouseFilterEnum.Stop ) { c.MouseFilter = MouseFilterEnum.Pass; } } n.ForEach( ( c )=> { if ( c.MouseFilter == MouseFilterEnum.Stop ) { c.MouseFilter = MouseFilterEnum.Pass; } } ); } } Vector2 cachedSize; public static UI Get( Control c ) { return UIHolder.GetUI( c ); } public static UIStylePropertyContainer GetStylePropertyContainerParent( Control c ) { var it = c as Node; var walker = NodesWalker.Get(); it = walker.Parent( it ); if ( it is UI ) { return null; } while ( it != null ) { if ( it is UIStylePropertyContainer ) { return it as UIStylePropertyContainer; } it = walker.Parent( it ); if ( it is UI ) { it = null; } } return null; } public static TimeLine GetTimeLine( Control c, TimeLine timeLine ) { if ( timeLine != null ) { return timeLine; } var ui = Get( c ); if ( ui == null || ui.settings == null ) { return null; } return ui.settings.defaultTimeline; } public override void _Process( double delta ) { if ( settings == null ) { return; } if ( useParentSize ) { var parentSize = GetParent().Size; if ( parentSize != cachedSize ) { Size = parentSize; cachedSize = parentSize; // this.LogInfo( "Size Changed" ); } } onProcess.DispatchEvent( (float)delta ); UpdateFontSize(); UpdateUIElements(); // customDisposerIDs = _customDisposers.Map( c => c.GetUID() + ":" + c.GetInfo() ).ToArray(); } public void UpdateExternal( float delta) { onProcess.DispatchEvent( delta ); UpdateFontSize(); } public readonly EventSlot onInputEvent = new EventSlot(); public readonly EventSlot onProcess = new EventSlot(); public override void _Input( InputEvent ie ) { onInputEvent.DispatchEvent( ie ); } List hoveredControls = new List(); public void SetHovered( UIHoverable control ) { hoveredControls.Add( control ); } public void BindOwnChildren() { BindChildrenOf( this ); } public void BindChildrenOf( Node node ) { node.ForEach( img => img.SetUI( this ) ); node.ForEach( info => info.SetUI( this ) ); node.ForEach( text => text.SetUI( this ) ); node.ForEach( region => region.SetUI( this ) ); } public override void _Ready() { var sm = Unique.Get(); if ( sm != null ) { sm._onActiveDeviceChange.AddAction( a => UpdateUIInputs() ); } UpdateUIInputs(); } void UpdateUIInputs() { Nodes.ForEach( this, uii => uii.updateInfo = true ); } void UpdateFontSize() { if ( settings == null ) { return; } X_computedFontSizePixels = UINumber.Compute( this, settings.fontSize ) * fontZoom; if ( Theme != null ) { Theme.DefaultFontSize = Mathf.RoundToInt( X_computedFontSizePixels ); } } void UpdateUIElements() { if ( UpdateMode.Always != updateMode ) { return; } UpdateAllUIRegions(); } public void UpdateAllUIRegions() { Nodes.ForEachDirectChild( this, r => r.Layout() ); } public static float GetWindowWidth( Control control ) { if ( Engine.IsEditorHint() ) { return ProjectSettings.GetSetting( "display/window/size/viewport_width" ).AsInt32(); } else { return control.GetWindow().Size.X; } } public static float GetWindowHeight( Control control ) { if ( Engine.IsEditorHint() ) { return ProjectSettings.GetSetting( "display/window/size/viewport_height" ).AsInt32(); } else { return control.GetWindow().Size.Y; } } } }