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

412 lines
8.5 KiB
C#
Raw Permalink Normal View History

2024-08-09 13:52:49 +00:00
using Godot;
2025-06-19 17:22:25 +00:00
using System;
using System.Collections.Generic;
2024-08-09 13:52:49 +00:00
namespace Rokojori
{
[Tool]
[GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UI.svg")]
2025-06-19 17:22:25 +00:00
public partial class UI : Control, IDisposable
{
2024-09-14 06:41:52 +00:00
[Export]
2025-06-19 17:22:25 +00:00
public UISettings settings;
2024-08-09 13:52:49 +00:00
[Export]
2025-06-19 17:22:25 +00:00
public float fontZoom = 1;
2024-08-09 13:52:49 +00:00
2025-06-19 17:22:25 +00:00
public enum UpdateMode
{
Always,
2025-06-23 11:16:01 +00:00
Optimized,
2025-06-19 17:22:25 +00:00
Only_Manual_Updates
}
2024-08-09 13:52:49 +00:00
[Export]
2025-06-19 17:22:25 +00:00
public UpdateMode updateMode = UpdateMode.Always;
2024-08-09 13:52:49 +00:00
2025-06-19 17:22:25 +00:00
[Export]
public bool useParentSize = false;
2024-08-09 13:52:49 +00:00
2025-06-19 17:22:25 +00:00
[ExportGroup("Functions")]
[ExportToolButton( "Mouse:Stop => Pass")]
public Callable StopToPassButton => Callable.From( ()=>{ MakeStopToPass(); } );
2024-08-09 13:52:49 +00:00
[Export]
2025-06-19 17:22:25 +00:00
public Node[] stopToPassRoots = [];
2024-08-09 13:52:49 +00:00
[ExportGroup("Read Only")]
[Export]
2025-06-23 11:16:01 +00:00
public float X_computedFontSizePixels = 1;
2025-06-19 17:22:25 +00:00
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 = [];
2025-06-23 11:16:01 +00:00
2025-06-19 17:22:25 +00:00
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 );
}
2025-06-23 11:16:01 +00:00
2025-06-19 17:22:25 +00:00
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;
}
2025-06-23 11:16:01 +00:00
Vector2 windowSize = new Vector2();
bool _resizeFlag = false;
bool _fontSizeFlag = false;
public bool sizeChanged => _resizeFlag;
public bool fontSizeChanged => _fontSizeFlag;
2024-08-09 13:52:49 +00:00
public override void _Process( double delta )
{
2025-06-19 17:22:25 +00:00
if ( settings == null )
{
return;
}
2025-06-23 11:16:01 +00:00
_resizeFlag = false;
_fontSizeFlag = false;
var newWindowSize = GetWindowSize();
if ( windowSize != newWindowSize )
{
_resizeFlag = true;
}
2025-06-19 17:22:25 +00:00
if ( useParentSize )
{
var parentSize = GetParent<Control>().Size;
if ( parentSize != cachedSize )
{
Size = parentSize;
cachedSize = parentSize;
2025-06-23 11:16:01 +00:00
_resizeFlag = true;
2025-06-19 17:22:25 +00:00
}
}
onProcess.DispatchEvent( (float)delta );
2024-08-09 13:52:49 +00:00
UpdateFontSize();
UpdateUIElements();
2025-06-19 17:22:25 +00:00
// 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 );
2025-06-23 11:16:01 +00:00
}
2025-06-19 17:22:25 +00:00
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 ) );
2024-08-09 13:52:49 +00:00
}
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 );
}
2024-08-11 17:38:06 +00:00
2024-08-09 13:52:49 +00:00
void UpdateFontSize()
{
2025-06-19 17:22:25 +00:00
if ( settings == null )
{
return;
}
X_computedFontSizePixels = UINumber.Compute( this, settings.fontSize ) * fontZoom;
2024-08-09 13:52:49 +00:00
if ( Theme != null )
{
Theme.DefaultFontSize = Mathf.RoundToInt( X_computedFontSizePixels );
}
}
2025-06-23 11:16:01 +00:00
HashSet<UIStylePropertyContainerNode> _dirty = new HashSet<UIStylePropertyContainerNode>();
HashSet<UIStylePropertyContainerNode> _updated = new HashSet<UIStylePropertyContainerNode>();
public void SetDirty( UIStylePropertyContainerNode control )
{
_dirty.Add( control );
}
public void SetUpdated( UIStylePropertyContainerNode control )
{
_updated.Add( control );
}
2024-08-09 13:52:49 +00:00
void UpdateUIElements()
{
2025-06-23 11:16:01 +00:00
if ( UpdateMode.Always == updateMode )
2024-08-09 13:52:49 +00:00
{
2025-06-23 11:16:01 +00:00
UpdateAllUIRegions();
}
else if ( UpdateMode.Optimized == updateMode )
{
if ( _fontSizeFlag || _resizeFlag )
{
_dirty.Clear();
UpdateAllUIRegions();
}
else
{
UpdateUIElementsOptimized();
}
}
}
float time = 0;
void UpdateUIElementsOptimized()
{
var timeNow = TimeLine.osTime;
var elapsed = timeNow - time;
time = timeNow;
// this.LogInfo( Mathf.RoundToInt( elapsed * 1000f ) );
var parent = GetParent();
var sorted = new List<UIStylePropertyContainerNode>( [ .. _dirty ]);
if ( sorted.Count > 0 )
{
// this.LogInfo( "Updating:", sorted.Count );
}
_updated.Clear();
sorted.Sort(
( a, b ) =>
{
return Mathf.RoundToInt( Mathf.Sign( a.GetUIAncestorDepth() - b.GetUIAncestorDepth() ) );
}
);
sorted.ForEach(
( s )=>
{
if ( _updated.Contains( s ) )
{
return;
}
// ( s as Control).LogInfo( "Updating:", s );
UpdateElement( s );
}
);
_updated.Clear();
_dirty.RemoveWhere( d => ! d.IsDirty() );
foreach ( var d in _dirty )
{
d.ResetDirtyFlags();
}
}
void UpdateElement( UIStylePropertyContainerNode control )
{
if ( control is UIRegion region )
{
region.Layout();
2024-08-09 13:52:49 +00:00
}
2025-06-23 11:16:01 +00:00
else
{
UILayouting.UpdateChild( control as Control );
2024-08-09 13:52:49 +00:00
2025-06-23 11:16:01 +00:00
if ( UIStyle.Position( control ) == UIPosition.From_Layout )
{
UILayouting.SetPositionInParentAnchor( control );
}
}
2025-06-19 17:22:25 +00:00
}
2024-08-09 13:52:49 +00:00
2025-06-19 17:22:25 +00:00
public void UpdateAllUIRegions()
{
2024-08-09 13:52:49 +00:00
Nodes.ForEachDirectChild<UIRegion>( this, r => r.Layout() );
}
2024-08-11 17:38:06 +00:00
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;
}
}
2025-06-23 11:16:01 +00:00
public Vector2 GetWindowSize()
{
if ( Engine.IsEditorHint() )
{
var width = ProjectSettings.GetSetting( "display/window/size/viewport_width" ).AsInt32();
var height = ProjectSettings.GetSetting( "display/window/size/viewport_height" ).AsInt32();
return new Vector2( width, height );
}
else
{
return GetWindow().Size;
}
}
2024-08-09 13:52:49 +00:00
}
}