376 lines
10 KiB
C#
376 lines
10 KiB
C#
|
|
using Godot;
|
|
using System;
|
|
using System.IO;
|
|
|
|
namespace Rokojori
|
|
{
|
|
[Tool][GlobalClass]
|
|
public partial class UISlider : Node, IAssemblyReload
|
|
{
|
|
|
|
[Export]
|
|
public Control button;
|
|
|
|
[Export]
|
|
public Control background;
|
|
|
|
[Export]
|
|
public Smoothing smoothing;
|
|
|
|
public enum Direction
|
|
{
|
|
Vertical,
|
|
Horizontal,
|
|
Both
|
|
}
|
|
|
|
[Export]
|
|
public Direction direction = Direction.Vertical;
|
|
|
|
[Export]
|
|
public Vector2 sliderValue;
|
|
|
|
[ExportGroup( "Scrolling")]
|
|
[Export]
|
|
public Control scrollTarget;
|
|
[Export]
|
|
public Control scrollContainer;
|
|
|
|
[Export]
|
|
public bool adjustButtonSizeToScrollContent;
|
|
|
|
[Export( PropertyHint.Range, "0,500, suffix:px")]
|
|
public float mouseWheelAbsoluteScroll = 10f;
|
|
|
|
[Export( PropertyHint.Range, "0,100, suffix:%")]
|
|
public float mouseWheelRelativeScroll = 10f;
|
|
|
|
Vector2 cachedMouseOffset;
|
|
Vector2 cachedButtonPosition;
|
|
|
|
public void OnAssemblyReloaded()
|
|
{
|
|
AddDraggingListener();
|
|
}
|
|
|
|
string scrollID = IDGenerator.GenerateID();
|
|
|
|
public override void _Ready()
|
|
{
|
|
// button.GuiInput += OnGUIInput;
|
|
|
|
// this.LogInfo( "S Adding new listeners" );
|
|
AddDraggingListener();
|
|
|
|
if ( scrollTarget != null && scrollContainer != null )
|
|
{
|
|
scrollContainer.Resized += SyncScroll;
|
|
|
|
scrollContainer.GuiInput += ( InputEvent ie )=>
|
|
{
|
|
|
|
if ( ie is InputEventMouseButton mb &&
|
|
( mb.ButtonIndex == MouseButton.WheelUp || mb.ButtonIndex == MouseButton.WheelDown ||
|
|
mb.ButtonIndex == MouseButton.WheelLeft || mb.ButtonIndex == MouseButton.WheelRight )
|
|
)
|
|
{
|
|
var range = GetScrollRange();
|
|
// var percentageAmount = 0.1f;
|
|
// var relativeToAbsolute = percentageAmount * range;
|
|
var absoluteAmount = mouseWheelAbsoluteScroll;
|
|
var absoluteToRelative = mouseWheelAbsoluteScroll * Vector2.One / range;
|
|
var buttonRange = absoluteToRelative * GetButtonScrollRange();
|
|
|
|
var scrollDelta = buttonRange;
|
|
|
|
// this.LogInfo( leftMouseCallback == null, leftMouseCallback?.GetUID(), leftMouseCallback?.GetInfo(), leftMouseCallback?.wasDisposed );
|
|
|
|
|
|
// scrollContainer.LogInfo( "Input", ie );
|
|
|
|
if ( mb.ButtonIndex == MouseButton.WheelUp )
|
|
{
|
|
scrollDelta.Y *= -1;
|
|
}
|
|
|
|
if ( mb.ButtonIndex == MouseButton.WheelLeft )
|
|
{
|
|
scrollDelta.X *= -1;
|
|
}
|
|
|
|
// sliderValue += scrollDelta;
|
|
// sliderValue = sliderValue.Clamp( 0, 1 );
|
|
// SyncScroll();
|
|
|
|
if ( Direction.Horizontal == direction )
|
|
{
|
|
scrollDelta.Y = 0;
|
|
}
|
|
else if ( Direction.Vertical == direction )
|
|
{
|
|
scrollDelta.X = 0;
|
|
}
|
|
|
|
|
|
nextValue = ( button.Position + scrollDelta ).Clamp( Vector2.Zero, GetButtonScrollRange() );
|
|
|
|
// this.LogInfo( scrollDelta );
|
|
|
|
var ui = this.FindParentThatIs<UI>();
|
|
|
|
ui.onProcess.AddAction( UpdatePosition );
|
|
( button as UIStylePropertyContainer ).AddUISelectorFlag( UISelectorFlag.Scrolling, scrollID );
|
|
( button as UIStylePropertyContainerNode ).SetDirty();
|
|
|
|
}
|
|
};
|
|
}
|
|
|
|
if ( adjustButtonSizeToScrollContent )
|
|
{
|
|
scrollTarget.Resized += UpdateButtonSize;
|
|
scrollContainer.Resized += UpdateButtonSize;
|
|
|
|
UpdateButtonSize();
|
|
}
|
|
|
|
|
|
}
|
|
|
|
void UpdateButtonSize()
|
|
{
|
|
var value = new UINumber();
|
|
var target = button as UIStylePropertyContainer;
|
|
|
|
if ( Direction.Vertical == direction )
|
|
{
|
|
value.value = Mathf.Min( 10, background.Size.Y - Mathf.Max( 10, scrollTarget.Size.Y - scrollContainer.Size.Y ) );
|
|
target.SetUIStyleNumberProperty( UIStyleNumberProperty.Height, value );
|
|
}
|
|
|
|
if ( Direction.Horizontal == direction )
|
|
{
|
|
value.value = Mathf.Min( 10, background.Size.X - Mathf.Max( 10, scrollTarget.Size.X - scrollContainer.Size.X ) );
|
|
target.SetUIStyleNumberProperty( UIStyleNumberProperty.Width, value );
|
|
}
|
|
}
|
|
|
|
bool _dragging = false;
|
|
bool _updatingPosition = false;
|
|
|
|
UIDragging.UIDraggingCallbacks leftMouseCallbacks;
|
|
UIDragging.UIDraggingCallbacks middleMouseCallbacks;
|
|
|
|
|
|
public override void _Process( double delta )
|
|
{
|
|
if (
|
|
leftMouseCallbacks == null || leftMouseCallbacks.notValid ||
|
|
middleMouseCallbacks == null || middleMouseCallbacks.notValid
|
|
)
|
|
{
|
|
AddDraggingListener();
|
|
}
|
|
}
|
|
|
|
void AddDraggingListener()
|
|
{
|
|
|
|
leftMouseCallbacks = UIDragging.OnLeftMouseButton( button,
|
|
( ev )=>
|
|
{
|
|
if ( ev.isStart )
|
|
{
|
|
cachedButtonPosition = button.Position;
|
|
smoothing.SetCurrent( cachedButtonPosition );
|
|
|
|
_dragging = true;
|
|
_updatingPosition = true;
|
|
|
|
ev.ui.onProcess.AddAction( UpdatePosition );
|
|
( button as UIStylePropertyContainer ).AddUISelectorFlag( UISelectorFlag.Scrolling, scrollID );
|
|
}
|
|
else if ( ev.isEnd )
|
|
{
|
|
_dragging = false;
|
|
}
|
|
|
|
var nextPosition = cachedButtonPosition + ev.distanceToStart;
|
|
nextValue = nextPosition.Clamp( Vector2.Zero, GetButtonScrollRange() );
|
|
|
|
}
|
|
);
|
|
|
|
middleMouseCallbacks = UIDragging.OnMiddleMouseButton( scrollContainer,
|
|
( ev )=>
|
|
{
|
|
if ( ev.isStart )
|
|
{
|
|
cachedButtonPosition = button.Position;
|
|
smoothing.SetCurrent( cachedButtonPosition );
|
|
|
|
_dragging = true;
|
|
_updatingPosition = true;
|
|
|
|
ev.ui.onProcess.AddAction( UpdatePosition );
|
|
( button as UIStylePropertyContainer ).AddUISelectorFlag( UISelectorFlag.Scrolling, scrollID );
|
|
ev.customOffset = Vector2.Zero;
|
|
}
|
|
else if ( ev.isEnd )
|
|
{
|
|
_dragging = false;
|
|
}
|
|
|
|
ev.customOffset += ev.distanceToStart * 0.1f;
|
|
var nextPosition = cachedButtonPosition + ev.customOffset;
|
|
nextValue = nextPosition.Clamp( Vector2.Zero, GetButtonScrollRange() );
|
|
ev.customOffset = nextValue - cachedButtonPosition;
|
|
|
|
}
|
|
);
|
|
|
|
|
|
}
|
|
|
|
Vector2 cachedOffset = Vector2.Zero;
|
|
void UpdatePosition( float delta )
|
|
{
|
|
// this.LogInfo( "UpdatePosition" );
|
|
var value = Smoothing.Apply( smoothing, nextValue, delta );
|
|
|
|
var uiStyleContainer = ( UIStylePropertyContainerNode ) button;
|
|
|
|
uiStyleContainer.SetLayoutDirtyFlag();
|
|
|
|
if ( ! _dragging && ( value - nextValue ).Length() < 1 )
|
|
{
|
|
var ui = this.FindParentThatIs<UI>();
|
|
ui.onProcess.RemoveAction( UpdatePosition );
|
|
_updatingPosition = false;
|
|
// this.LogInfo( "Removed Processing" );
|
|
|
|
value = nextValue;
|
|
|
|
uiStyleContainer.RemoveUISelectorFlag( UISelectorFlag.Scrolling, scrollID );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if ( Direction.Both == direction || Direction.Horizontal == direction )
|
|
{
|
|
var left = new UINumber();
|
|
left.value = value.X;
|
|
uiStyleContainer.SetUIStyleNumberProperty( UIStyleNumberProperty.Left, left );
|
|
|
|
}
|
|
|
|
if ( Direction.Both == direction || Direction.Vertical == direction )
|
|
{
|
|
var top = new UINumber();
|
|
top.value = value.Y;
|
|
uiStyleContainer.SetUIStyleNumberProperty( UIStyleNumberProperty.Top, top );
|
|
}
|
|
|
|
var range = background.Size - button.Size;
|
|
sliderValue = button.Position / range;
|
|
|
|
if ( scrollTarget != null && scrollContainer != null )
|
|
{
|
|
var scrollRange = scrollTarget.Size - scrollContainer.Size;
|
|
|
|
var scrollOffset = scrollRange * sliderValue;
|
|
|
|
var scrollTargetNode = scrollTarget as UIStylePropertyContainerNode;
|
|
|
|
if ( Direction.Both == direction || Direction.Horizontal == direction )
|
|
{
|
|
var left = new UINumber();
|
|
left.value = -scrollOffset.X;
|
|
scrollTargetNode.SetUIStyleNumberProperty( UIStyleNumberProperty.Left, left );
|
|
}
|
|
|
|
if ( Direction.Both == direction || Direction.Vertical == direction )
|
|
{
|
|
var top = new UINumber();
|
|
top.value = -scrollOffset.Y;
|
|
scrollTargetNode.SetUIStyleNumberProperty( UIStyleNumberProperty.Top, top );
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
Vector2 nextValue;
|
|
|
|
Vector2 GetButtonScrollRange()
|
|
{
|
|
return ( background.Size - button.Size ).Max( Vector2.Zero );
|
|
}
|
|
|
|
Vector2 GetScrollRange()
|
|
{
|
|
return ( scrollTarget.Size - scrollContainer.Size ).Max( Vector2.Zero );
|
|
}
|
|
|
|
void SyncScroll()
|
|
{
|
|
|
|
if ( _dragging || _updatingPosition )
|
|
{
|
|
// this.LogInfo( "SyncScroll blocked" );
|
|
return;
|
|
}
|
|
|
|
// this.LogInfo( "SyncScroll" );
|
|
|
|
var uiStyleContainer = ( UIStylePropertyContainerNode ) button;
|
|
var value = GetButtonScrollRange() * sliderValue;
|
|
|
|
uiStyleContainer.SetDirty();
|
|
|
|
if ( Direction.Both == direction || Direction.Horizontal == direction )
|
|
{
|
|
var left = new UINumber();
|
|
left.value = value.X;
|
|
uiStyleContainer.SetUIStyleNumberProperty( UIStyleNumberProperty.Left, left );
|
|
}
|
|
|
|
if ( Direction.Both == direction || Direction.Vertical == direction )
|
|
{
|
|
var top = new UINumber();
|
|
top.value = value.Y;
|
|
uiStyleContainer.SetUIStyleNumberProperty( UIStyleNumberProperty.Top, top );
|
|
}
|
|
|
|
if ( scrollTarget != null && scrollContainer != null )
|
|
{
|
|
var scrollRange = scrollTarget.Size - scrollContainer.Size;
|
|
|
|
var scrollOffset = scrollRange * sliderValue;
|
|
|
|
if ( Direction.Both == direction || Direction.Horizontal == direction )
|
|
{
|
|
var left = new UINumber();
|
|
left.value = -scrollOffset.X;
|
|
( scrollTarget as UIStylePropertyContainer ).SetUIStyleNumberProperty( UIStyleNumberProperty.Left, left );
|
|
}
|
|
|
|
if ( Direction.Both == direction || Direction.Vertical == direction )
|
|
{
|
|
var top = new UINumber();
|
|
top.value = -scrollOffset.Y;
|
|
( scrollTarget as UIStylePropertyContainer ).SetUIStyleNumberProperty( UIStyleNumberProperty.Top, top );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
} |