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

473 lines
13 KiB
C#

using Godot;
using System;
using System.Collections.Generic;
using System.Text.Json.Serialization;
namespace Rokojori
{
public class UIDragging
{
public class MappedEvent
{
public MouseButton mouseButton;
public EditableUIDraggingEvent uiEvent;
}
public class ButtonState
{
public MouseButton mouseButton;
public bool dragging;
}
public class UIDraggingCallbacks: ICustomDisposer
{
public UI ui;
public Control control;
public bool wasDisposed = false;
public bool notValid =>
wasDisposed ||
onMouseClick == null ||
onDragging == null ||
onProcess == null ||
mouseEvents == null || mouseEvents.FilterNulls().Count == 0 ||
mouseEventsDragging == null || mouseEventsDragging.FilterNulls().Count == 0;
public Action<InputEvent> onMouseClick;
public Callable callable;
public Action<InputEvent> onDragging;
public Action<float> onProcess;
// public Dictionary<MouseButton,EditableUIDraggingEvent> mouseEvents = new Dictionary<MouseButton, EditableUIDraggingEvent>();
public List<MappedEvent> mouseEvents = new List<MappedEvent>();
public List<ButtonState> mouseEventsDragging = new List<ButtonState>();
// public Dictionary<MouseButton,bool> mouseEventsDragging = new Dictionary<MouseButton, bool>();
public string uid = IDGenerator.GenerateID();
public string GetUID(){ return uid; }
string info = "";
public string GetInfo(){ return info;}
public void Set( Control c, Func<UIDraggingEvent,bool> callback )
{
var callbacks = this;
callbacks.control = c;
callbacks.ui = c.FindParentThatIs<UI>();
callbacks.ui.AddForDisposing( callbacks );
info = HierarchyName.Of( c );
callbacks.onProcess = (float delta )=>
{
callbacks.mouseEvents.ForEach(
( m )=>
{
callback( m.uiEvent );
}
);
// foreach ( var m in callbacks.mouseEvents )
// {
// callback( callbacks.mouseEvents[ m.Key ] );
// }
};
callbacks.onDragging = ( InputEvent ie ) =>
{
if ( ie is InputEventMouseButton mb && ! mb.Pressed )
{
var mdIndex = callbacks.mouseEventsDragging.FindIndex( me => me.mouseButton == mb.ButtonIndex );
var meIndex = callbacks.mouseEvents.FindIndex( md => md.mouseButton == mb.ButtonIndex );
callbacks.mouseEventsDragging[ mdIndex ].dragging = false;
callbacks.mouseEvents[ meIndex ].uiEvent.UpdatePosition( mb.GlobalPosition, true );
callback( callbacks.mouseEvents[ meIndex ].uiEvent );
if ( ! callbacks.hasAnyMouseDragging )
{
callbacks.ui.onInputEvent.RemoveAction( callbacks.onDragging );
callbacks.ui.onProcess.RemoveAction( callbacks.onProcess );
callbacks.hasDraggingCallback = false;
if ( c is UIStylePropertyContainer sc )
{
sc.GetUISelectorFlags().Remove( UISelectorFlag.Dragging );
}
}
}
if ( ie is InputEventMouseMotion mo )
{
var globalPosition = mo.GlobalPosition;
// foreach ( var m in callbacks.mouseEvents )
// {
// callbacks.mouseEvents[ m.Key ].UpdatePosition( globalPosition );
// // callback( callbacks.mouseEvents[ m.Key ] );
// }
callbacks.mouseEvents.ForEach(
( m )=>
{
m.uiEvent.UpdatePosition( globalPosition );
}
);
}
};
callbacks.onMouseClick = ( InputEvent ie )=>
{
if ( ! ( ie is InputEventMouseButton b && b.Pressed ) )
{
return;
}
var mb = ie as InputEventMouseButton;
var button = mb.ButtonIndex;
var draggingEvent = callbacks.GetMouseEvent( button );
draggingEvent.SetStart( mb.GlobalPosition );
var result = callback( draggingEvent );
if ( ! result )
{
return;
}
if ( c is UIStylePropertyContainer sc )
{
sc.GetUISelectorFlags().AddIfNotPresent( UISelectorFlag.Dragging );
}
var buttonIndex = callbacks.mouseEventsDragging.FindIndex( bs => bs.mouseButton == button );
if ( buttonIndex == -1 )
{
var bs = new ButtonState();
bs.mouseButton = button;
callbacks.mouseEventsDragging.Add( bs );
buttonIndex = callbacks.mouseEventsDragging.Count - 1;
}
callbacks.mouseEventsDragging[ buttonIndex ].dragging = true;
if ( ! callbacks.hasDraggingCallback )
{
callbacks.ui.onInputEvent.AddAction( callbacks.onDragging );
callbacks.ui.onProcess.AddAction( callbacks.onProcess );
}
};
callbacks.Connect();
wasDisposed = false;
}
public void Dispose()
{
wasDisposed = true;
if ( control != null && Node.IsInstanceValid( control ) )
{
control.Disconnect( "gui_input", callable );
}
// ui = null;
// control = null;
onMouseClick = null;
onDragging = null;
onProcess = null;
mouseEvents.Clear();
mouseEventsDragging.Clear();
// mouseEvents = null;
// mouseEventsDragging = null;
}
public bool hasAnyMouseDragging
{
get
{
foreach ( var mb in mouseEventsDragging )
{
if ( mb.dragging )
{
return true;
}
}
return false;
}
}
public bool hasDraggingCallback = false;
public EditableUIDraggingEvent GetMouseEvent( MouseButton mb )
{
var index = mouseEvents.FindIndex( m => m.mouseButton == mb );
if ( index == -1)
{
var mappedEvent = new MappedEvent();
mappedEvent.mouseButton = mb;
mappedEvent.uiEvent = new EditableUIDraggingEvent( mb );
mouseEvents.Add( mappedEvent );
index = mouseEvents.Count - 1;
}
mouseEvents[ index ].uiEvent.SetUI( ui );
return mouseEvents[ index ].uiEvent;
}
public void Clear()
{
control.Disconnect( "gui_input", callable );
}
public void Connect()
{
callable = Callable.From( onMouseClick );
control.Connect( "gui_input", callable );
}
}
public class UIDraggingEvent
{
public enum Phase
{
Start,
Dragging,
End
}
protected Phase _phase = Phase.Start;
public bool isStart => Phase.Start == _phase;
public bool isDragging => Phase.Dragging == _phase;
public bool isEnd => Phase.End == _phase;
protected UI _ui;
public UI ui => _ui;
protected MouseButton _mouseButton;
public MouseButton mouseButton => _mouseButton;
public bool isLeftMouseButton => MouseButton.Left == _mouseButton;
public bool isMiddleMouseButton => MouseButton.Middle == _mouseButton;
public bool isRightMouseButton => MouseButton.Right == _mouseButton;
public Vector2 customOffset;
protected int _touchID = -1;
protected Vector2 _startPosition;
protected Vector2 _position;
protected Vector2 _lastPosition;
protected Vector2 _furthestPointFromStart;
protected float _biggestDistance;
public Vector2 startPosition => _startPosition;
public Vector2 position => _position;
public Vector2 lastPosition => _lastPosition;
public Vector2 movementSinceLastFrame => _position - lastPosition;
public Vector2 distanceToStart => _position - _startPosition;
public Vector2 furthestPointToStart => _furthestPointFromStart;
public float maximumMovement => _biggestDistance;
public UIDraggingEvent( MouseButton mb )
{
_mouseButton = mb;
}
public UIDraggingEvent( int touchID )
{
this._touchID = touchID;
}
}
public class EditableUIDraggingEvent:UIDraggingEvent
{
public EditableUIDraggingEvent( MouseButton mb ):base( mb ){}
public EditableUIDraggingEvent( int touchID ):base( touchID ){}
public void SetUI( UI ui )
{
_ui = ui;
}
public void SetStart( Vector2 startPosition )
{
_startPosition = startPosition;
_position = startPosition;
_lastPosition = startPosition;
_furthestPointFromStart = Vector2.Zero;
_phase = Phase.Start;
}
public void UpdatePosition( Vector2 position, bool isEnd = false )
{
_lastPosition = _position;
_position = position;
var d = position.DistanceTo( _startPosition );
if ( d > _biggestDistance )
{
_biggestDistance = d;
_furthestPointFromStart = position;
}
_phase = isEnd ? Phase.End : Phase.Dragging;
}
}
public static UIDraggingCallbacks OnLeftMouseButton( Control c, Action<UIDraggingEvent> callback )
{
return OnOneMouseButton( c, MouseButton.Left, callback );
}
public static UIDraggingCallbacks OnMiddleMouseButton( Control c, Action<UIDraggingEvent> callback )
{
return OnOneMouseButton( c, MouseButton.Middle, callback );
}
public static UIDraggingCallbacks OnRightMouseButton( Control c, Action<UIDraggingEvent> callback )
{
return OnOneMouseButton( c, MouseButton.Right, callback );
}
public static UIDraggingCallbacks OnOneMouseButton( Control c, MouseButton mouseButton, Action<UIDraggingEvent> callback )
{
var oneButtonCallback = ( UIDraggingEvent ev ) =>
{
if ( ev.mouseButton != mouseButton )
{
return false;
}
callback( ev );
return true;
};
return OnAnyMouseButton( c, oneButtonCallback );
}
public static UIDraggingCallbacks OnAnyMouseButton( Control c, Func<UIDraggingEvent,bool> callback )
{
var callbacks = new UIDraggingCallbacks();
callbacks.Set( c, callback );
// callbacks.control = c;
// callbacks.ui = c.FindParentThatIs<UI>();
// callbacks.ui.AddForDisposing( callbacks );
// callbacks.onProcess = (float delta )=>
// {
// foreach ( var m in callbacks.mouseEvents )
// {
// callback( callbacks.mouseEvents[ m.Key ] );
// }
// };
// callbacks.onDragging = ( InputEvent ie ) =>
// {
// if ( ie is InputEventMouseButton mb && ! mb.Pressed )
// {
// callbacks.mouseEventsDragging[ mb.ButtonIndex ] = false;
// callbacks.mouseEvents[ mb.ButtonIndex ].UpdatePosition( mb.GlobalPosition, true );
// callback( callbacks.mouseEvents[ mb.ButtonIndex ] );
// if ( ! callbacks.hasAnyMouseDragging )
// {
// callbacks.ui.onInputEvent.RemoveAction( callbacks.onDragging );
// callbacks.ui.onProcess.RemoveAction( callbacks.onProcess );
// callbacks.hasDraggingCallback = false;
// }
// }
// if ( ie is InputEventMouseMotion mo )
// {
// var globalPosition = mo.GlobalPosition;
// foreach ( var m in callbacks.mouseEvents )
// {
// callbacks.mouseEvents[ m.Key ].UpdatePosition( globalPosition );
// // callback( callbacks.mouseEvents[ m.Key ] );
// }
// }
// };
// callbacks.onMouseClick = ( InputEvent ie )=>
// {
// if ( ! ( ie is InputEventMouseButton b && b.Pressed ) )
// {
// return;
// }
// var mb = ie as InputEventMouseButton;
// var button = mb.ButtonIndex;
// var draggingEvent = callbacks.GetMouseEvent( button );
// draggingEvent.SetStart( mb.GlobalPosition );
// var result = callback( draggingEvent );
// if ( ! result )
// {
// return;
// }
// callbacks.mouseEventsDragging[ button ] = true;
// if ( ! callbacks.hasDraggingCallback )
// {
// callbacks.ui.onInputEvent.AddAction( callbacks.onDragging );
// callbacks.ui.onProcess.AddAction( callbacks.onProcess );
// }
// };
// callbacks.Connect();
// c.Connect( "gui_input", Callable.From( callbacks.onMouseClick ) );
// c.GuiInput += callbacks.onMouseClick;
return callbacks;
}
}
}