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

302 lines
6.8 KiB
C#

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
{
public enum Direction
{
Vertical,
Horizontal,
Both
}
[Export]
public Direction direction = Direction.Vertical;
[Export]
public Smoothing smoothing;
Vector2 _sliderValue;
[Export]
public Vector2 sliderValue
{
get { return _sliderValue; }
set
{
_sliderValue = value;
SyncSliderValue();
}
}
void SyncSliderValue()
{
SliderShader.sliderValue.Set( Material, 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 = [];
public override void _Process( double delta )
{
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.sliderSize.propertyNameX, w );
var valueY = ComputeShaderProperty( SliderShader.sliderSize.propertyNameY, 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.sliderSizeMargins.propertyNameX, w );
var valueY = ComputeShaderProperty( SliderShader.sliderSizeMargins.propertyNameY, 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 )
{
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 )
{
// this.LogInfo( "UpdatePosition" );
var value = Smoothing.Apply( smoothing, nextValue, delta );
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.Vertical == direction )
{
currentSliderValue.Y = 0.5f;
}
_sliderValue = currentSliderValue;
SyncSliderValue();
}
}
}