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(); 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(); } } }