rokojori_action_library/Runtime/UI/Nodes/Sliders/UISlider.cs

479 lines
10 KiB
C#
Raw Normal View History

2026-02-26 14:06:27 +00:00
using Godot;
using Rokojori;
using System.Collections.Generic;
using System.Linq;
namespace Rokojori;
[Tool]
[GlobalClass,Icon("res://addons/rokojori_action_library/Icons/UIImage.svg")]
public partial class UISlider:UIImage, UIFocusProcessor
{
public enum Direction
{
Vertical,
Horizontal,
Both
}
[Export]
public Direction direction = Direction.Vertical;
[Export]
public float offsetPerInput = 1f / 20f;
[Export]
public Smoothing smoothing;
[Export]
public Action onSliderChange;
public readonly EventSlot<Vector2> _onSliderChange = new EventSlot<Vector2>();
[ExportGroup("Testing")]
// [Export( PropertyHint.Range, "0,1")]
// public Vector2 editorSliderValue = Vector2.Zero;
Vector2 _sliderValue;
[Export( PropertyHint.Range, "0,1")]
public Vector2 sliderValue
{
get { return _sliderValue; }
set
{
_sliderValue = value;
SyncSliderValue();
}
}
public float mainValue => direction == Direction.Vertical ? sliderValue.Y : sliderValue.X;
public Vector2 GetNextSliderMainValue( float value )
{
if ( Direction.Vertical == direction )
{
return new Vector2( 0.5f, value );
}
else
{
return new Vector2( value, 0.5f );
}
}
public void SetSliderMainValue( float value )
{
if ( Direction.Vertical == direction )
{
_sliderValue.Y = value;
}
else
{
_sliderValue.X = value;
}
SyncSliderValue();
_onSliderChange.DispatchEvent( _sliderValue );
onSliderChange?.Trigger();
}
void SyncSliderValue()
{
SliderShader.sliderValue.Set( Material, sliderValue );
// this.LogInfo( "Set slider value:", sliderValue, Material );
// var sm = Material as ShaderMaterial;
// sm.SetShaderParameter( "sliderValue", sliderValue );
}
public override void _Ready()
{
base._Ready();
if ( imageType == null )
{
imageType = new SliderUIImageType();
}
if ( Texture == null )
{
Texture = UI.whiteTexture.Get();
}
var uiSliderImageType = _imageType as SliderUIImageType;
if ( uiSliderImageType != null )
{
uiSliderImageType.Clear( this );
uiSliderImageType.Assign( this );
}
ComputeUIAncestorDepth();
SyncSliderValue();
AssignListener();
}
[Export]
public bool debugInfo = false;
[Export]
public string[] propertyInfos = [];
float lastLeft = 0f;
float lastRight = 0f;
float lastUp = 0f;
float lastDown = 0f;
public void OnFocusProcess( double delta )
{
var settings = GetUI().settings;
if ( settings == null )
{
return;
}
if ( Direction.Horizontal == direction )
{
var offset = 0;
if ( settings.uiLeft.IsRepeatDown( ref lastLeft ) )
{
offset --;
}
if ( settings.uiRight.IsRepeatDown( ref lastRight ) )
{
offset ++;
}
if ( offset != 0 )
{
var nextMainValue = MathX.Clamp01( mainValue + offset * offsetPerInput );
nextValue = NormalizedToButtonPosition( GetNextSliderMainValue( nextMainValue ) );
if ( ! _updatingPosition )
{
_updatingPosition = true;
GetUI().onProcess.AddAction( UpdatePosition );
}
}
}
// UpdatePosition( (float) delta );
}
// public override void _GuiInput( InputEvent inputEvent )
// {
// if ( ! processInputs )
// {
// return;
// }
// if ( ! HasFocus() )
// {
// return;
// }
// var settings = GetUI()?.settings;
// if ( settings == null )
// {
// return;
// }
// if ( Direction.Horizontal == direction )
// {
// var offset = 0;
// // this.LogInfo( Sensor.GetInputEventInfo( inputEvent ) );
// // this.LogInfo(
// // "Is Horizontal",
// // "Left:", settings.uiLeft.IsSensor( inputEvent ), "Left Down:", settings.uiLeft.IsDown( inputEvent ),
// // "Right:", settings.uiRight.IsSensor( inputEvent ), "Right Down:", settings.uiRight.IsDown( inputEvent )
// // );
// if ( settings.uiLeft.IsDown( inputEvent ) )
// {
// offset --;
// }
// if ( settings.uiRight.IsDown( inputEvent ) )
// {
// offset ++;
// }
// if ( offset != 0 )
// {
// // this.LogInfo( "Offset", offset );
// var nextValue = MathX.Clamp01( mainValue + offset * offsetPerInput );
// SetSliderMainValue( nextValue );
// }
// }
// if ( Direction.Vertical == direction )
// {
// var offset = 0;
// if ( settings.uiUp?.isActive ?? false )
// {
// offset --;
// }
// if ( settings.uiDown?.isActive ?? false )
// {
// offset ++;
// }
// var nextValue = MathX.Clamp01( mainValue + offset * offsetPerInput );
// SetSliderMainValue( nextValue );
// }
// }
public override void _Process( double delta )
{
// ProcessInputs();
if ( ! debugInfo )
{
return;
}
var it = imageType as SliderUIImageType;
if ( it == null )
{
return;
}
var propNames = it.GetNumberShaderProperties();
var tw = Texture.GetWidth();
var th = Texture.GetHeight();
var w = UINumber.Compute( this, UIStyleNumberProperty.Width, tw, tw / 100f );
var h = UINumber.Compute( this, UIStyleNumberProperty.Height, th, th / 100f );
var infos = new List<string>();
for ( int i = 0; i < propNames.Length; i++ )
{
var n = propNames[ i ];
var p = it.GetUIStyleNumberProperty( UIStyleNumberProperty.FloatShaderProperty, n );
if ( p == null )
{
continue;
}
var relative = 100f;
if ( n.EndsWith( "X" ) )
{
relative = w;
}
else if ( n.EndsWith( "Y" ) )
{
relative = h;
}
var value = UINumber.Compute( this, UIStyleNumberProperty.FloatShaderProperty, n, 0, relative );
infos.Add( "[" + n + "] (" + p.value._FFF() + " * " + p.unit +") :" + value._FFF() );
}
propertyInfos = infos.ToArray();
this.LogInfo( propertyInfos );
debugInfo = false;
}
UIDragging.UIDraggingCallbacks leftMouseCallbacks;
Vector2 cachedMouseOffset;
Vector2 cachedButtonPosition;
bool _dragging = false;
bool _updatingPosition = false;
string scrollID = IDGenerator.GenerateID();
float ComputeShaderProperty( string n, float relative = 100 )
{
return UINumber.Compute( this, UIStyleNumberProperty.FloatShaderProperty, n, 0, relative );
}
Vector2 sliderSize
{
get
{
var tw = Texture.GetWidth();
var th = Texture.GetHeight();
var w = UINumber.Compute( this, UIStyleNumberProperty.Width, tw, tw / 100f );
var h = UINumber.Compute( this, UIStyleNumberProperty.Height, th, th / 100f );
var valueX = ComputeShaderProperty( SliderShader.sliderSizeX.propertyName, w );
var valueY = ComputeShaderProperty( SliderShader.sliderSizeY.propertyName, h );
return new Vector2( valueX, valueY );
}
}
Vector2 sliderSizeMargins
{
get
{
var tw = Texture.GetWidth();
var th = Texture.GetHeight();
var w = UINumber.Compute( this, UIStyleNumberProperty.Width, tw, tw / 100f );
var h = UINumber.Compute( this, UIStyleNumberProperty.Height, th, th / 100f );
var valueX = ComputeShaderProperty( SliderShader.sliderSizeMarginX.propertyName, w );
var valueY = ComputeShaderProperty( SliderShader.sliderSizeMarginY.propertyName, h );
return new Vector2( valueX, valueY );
}
}
Vector2 sliderRange => Size - ( sliderSize + sliderSizeMargins );
Vector2 sliderOffset => sliderSize;
Vector2 buttonPositionMin
{
get { return NormalizedToButtonPosition( Vector2.Zero ); }
}
Vector2 buttonPositionMax
{
get { return NormalizedToButtonPosition( Vector2.One ); }
}
Vector2 NormalizedToButtonPosition( Vector2 normalized )
{
return normalized * sliderRange + sliderOffset;
}
Vector2 ButtonPositionToNormalized( Vector2 buttonPosition )
{
return ( buttonPosition - sliderOffset ) / sliderRange;
}
bool _listenerAssigned = false;
void AssignListener()
{
if ( _listenerAssigned )
{
return;
}
leftMouseCallbacks = UIDragging.OnLeftMouseButton( this,
( ev )=>
{
if ( ev.isStart )
{
if ( ! ( _updatingPosition || _dragging ) )
{
cachedButtonPosition = NormalizedToButtonPosition( sliderValue );
smoothing?.SetCurrent( cachedButtonPosition );
_dragging = true;
_updatingPosition = true;
ev.ui.onProcess.AddAction( UpdatePosition );
}
}
else if ( ev.isEnd )
{
_dragging = false;
}
var nextPosition = cachedButtonPosition + ev.distanceToStart;
nextValue = nextPosition.Clamp( buttonPositionMin, buttonPositionMax );
}
);
_listenerAssigned = true;
}
Vector2 nextValue;
Vector2 GetButtonScrollRange()
{
return Vector2.Zero;
// return ( Size - button.Size ).Max( Vector2.Zero );
}
Vector2 cachedOffset = Vector2.Zero;
void UpdatePosition( float delta )
{
var value = Smoothing.Apply( smoothing, nextValue, delta );
// this.LogInfo( "UpdatePosition:", value );
var uiStyleContainer = ( UIStylePropertyContainerNode ) this;
uiStyleContainer.SetLayoutDirtyFlag();
if ( ! _dragging && ( value - nextValue ).Length() < 1 )
{
var ui = UIHolder.GetUI( this );
ui.onProcess.RemoveAction( UpdatePosition );
_updatingPosition = false;
// this.LogInfo( "Removed Processing" );
value = nextValue;
uiStyleContainer.RemoveUISelectorFlag( UISelectorFlag.Scrolling, scrollID );
}
var currentSliderValue = ButtonPositionToNormalized( value );
if ( Direction.Vertical == direction )
{
currentSliderValue.X = 0.5f;
}
else if ( Direction.Horizontal == direction )
{
currentSliderValue.Y = 0.5f;
}
_sliderValue = currentSliderValue;
SyncSliderValue();
onSliderChange?.Trigger();
_onSliderChange.DispatchEvent( _sliderValue );
}
}