rj-action-library/Runtime/UI/UI.cs

288 lines
5.7 KiB
C#

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<ICustomDisposer> _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<Control>(
( 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<Control>().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<InputEvent> onInputEvent = new EventSlot<InputEvent>();
public readonly EventSlot<float> onProcess = new EventSlot<float>();
public override void _Input( InputEvent ie )
{
onInputEvent.DispatchEvent( ie );
}
List<UIHoverable> hoveredControls = new List<UIHoverable>();
public void SetHovered( UIHoverable control )
{
hoveredControls.Add( control );
}
public void BindOwnChildren()
{
BindChildrenOf( this );
}
public void BindChildrenOf( Node node )
{
node.ForEach<UIImage>( img => img.SetUI( this ) );
node.ForEach<UIInputInfo>( info => info.SetUI( this ) );
node.ForEach<UIText>( text => text.SetUI( this ) );
node.ForEach<UIRegion>( region => region.SetUI( this ) );
}
public override void _Ready()
{
var sm = Unique<SensorManager>.Get();
if ( sm != null )
{
sm._onActiveDeviceChange.AddAction( a => UpdateUIInputs() );
}
UpdateUIInputs();
}
void UpdateUIInputs()
{
Nodes.ForEach<UIInputInfo>( 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<UIRegion>( 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;
}
}
}
}