Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C# version of plugin #81

Open
iamfobey opened this issue Oct 18, 2024 · 0 comments
Open

C# version of plugin #81

iamfobey opened this issue Oct 18, 2024 · 0 comments
Labels
enhancement New feature or request

Comments

@iamfobey
Copy link

iamfobey commented Oct 18, 2024

Hello! I converted plugin (main file haha) to C# version, because there is no C# versions of virtual joystick for mobile.
And I fixed problem for 4.4dev3 version (removed get_viewport().set_input_as_handled()). I don't know is good way or not, but it solved my problem lol.

public partial class TouchScreenVirtualJoystick : Control
{
    public enum EJoystickMode
    {
        FIXED,
        DYNAMIC,
        FOLLOWING
    }

    public enum EVisibilityMode
    {
        ALWAYS,
        TOUCHSCREEN_ONLY,
        WHEN_TOUCHED
    }

    [Export]
    public Color PressedColor = Colors.Gray;

    [Export(PropertyHint.Range, "0, 200, 1")]
    public float DeadZoneSize = 10.0f;

    [Export(PropertyHint.Range, "0, 500, 1")]
    public float ClampZoneSize = 75.0f;

    [Export] 
    public EJoystickMode JoystickMode = EJoystickMode.FIXED;
    [Export]
    public EVisibilityMode VisibilityMode = EVisibilityMode.ALWAYS;

    [Export]
    public bool UseInputActions = true;
    [Export]
    public string ActionLeft = "ui_left";
    [Export]
    public string ActionRight = "ui_right";
    [Export]
    public string ActionUp = "ui_up";
    [Export]
    public string ActionDown = "ui_down";

    public bool IsPressed = false;
    public Vector2 InputDirection = Vector2.Zero;

    private int _touchIndex = -1;
    private TextureRect _base;
    private TextureRect _tip;
    private Vector2 _baseDefaultPosition;
    private Vector2 _tipDefaultPosition;
    private Color _defaultColor;

    public override void _Ready()
    {
        _base = GetNode<TextureRect>("Base");
        _tip = GetNode<TextureRect>("Base/Tip");
        _baseDefaultPosition = _base.Position;
        _tipDefaultPosition = _tip.Position;
        _defaultColor = _tip.Modulate;

        if (!DisplayServer.IsTouchscreenAvailable() && VisibilityMode == EVisibilityMode.TOUCHSCREEN_ONLY)
            Hide();

        if (VisibilityMode == EVisibilityMode.WHEN_TOUCHED)
            Hide();
    }

    public override void _Input(InputEvent @event)
    {
        if (@event is InputEventScreenTouch eventTouch)
        {
            if (eventTouch.Pressed)
            {
                if (IsPointInsideJoystickArea(eventTouch.Position) && _touchIndex == -1)
                {
                    if (JoystickMode == EJoystickMode.DYNAMIC || JoystickMode == EJoystickMode.FOLLOWING ||
                        (JoystickMode == EJoystickMode.FIXED && IsPointInsideBase(eventTouch.Position)))
                    {
                        if (JoystickMode == EJoystickMode.DYNAMIC || JoystickMode == EJoystickMode.FOLLOWING)
                            MoveBase(eventTouch.Position);

                        if (VisibilityMode == EVisibilityMode.WHEN_TOUCHED)
                            Show();

                        _touchIndex = eventTouch.Index;
                        _tip.Modulate = PressedColor;

                        UpdateJoystick(eventTouch.Position);
                    }
                }
            }
            else if (eventTouch.Index == _touchIndex)
            {
                ResetJoystick();
                if (VisibilityMode == EVisibilityMode.WHEN_TOUCHED)
                    Hide();
            }
        }
        else if (@event is InputEventScreenDrag eventDrag)
        {
            if (eventDrag.Index == _touchIndex)
                UpdateJoystick(eventDrag.Position);
        }
    }

    private void MoveBase(Vector2 newPosition)
    {
        _base.GlobalPosition = newPosition - (_base.PivotOffset * GetGlobalTransformWithCanvas().Scale);
    }

    private void MoveTip(Vector2 newPosition)
    {
        _tip.GlobalPosition = newPosition - (_tip.PivotOffset * _base.GetGlobalTransformWithCanvas().Scale);
    }

    private bool IsPointInsideJoystickArea(Vector2 point)
    {
        bool x = point.X >= GlobalPosition.X && point.X <= GlobalPosition.X + (Size.X * GetGlobalTransformWithCanvas().Scale.X);
        bool y = point.Y >= GlobalPosition.Y && point.Y <= GlobalPosition.Y + (Size.Y * GetGlobalTransformWithCanvas().Scale.Y);

        return x && y;
    }

    private Vector2 GetBaseRadius()
    {
        return _base.Size * _base.GetGlobalTransformWithCanvas().Scale / 2;
    }

    private bool IsPointInsideBase(Vector2 point)
    {
        var baseRadius = GetBaseRadius();
        var center = _base.GlobalPosition + baseRadius;

        return (point - center).LengthSquared() <= baseRadius.X * baseRadius.X;
    }

    private void UpdateJoystick(Vector2 touchPosition)
    {
        var baseRadius = GetBaseRadius();
        var center = _base.GlobalPosition + baseRadius;
        var vector = (touchPosition - center).LimitLength(ClampZoneSize);

        if (JoystickMode == EJoystickMode.FOLLOWING && touchPosition.DistanceTo(center) > ClampZoneSize)
            MoveBase(touchPosition - vector);

        MoveTip(center + vector);

        if (vector.LengthSquared() > DeadZoneSize * DeadZoneSize)
        {
            IsPressed = true;
            InputDirection = (vector - (vector.Normalized() * DeadZoneSize)) / (ClampZoneSize - DeadZoneSize);
        }
        else
        {
            IsPressed = false;
            InputDirection = Vector2.Zero;
        }

        if (UseInputActions)
            HandleInputActions();
    }

    private void HandleInputActions()
    {
        if (InputDirection.X >= 0 && Input.IsActionPressed(ActionLeft))
            Input.ActionRelease(ActionLeft);
        if (InputDirection.X <= 0 && Input.IsActionPressed(ActionRight))
            Input.ActionRelease(ActionRight);
        if (InputDirection.Y >= 0 && Input.IsActionPressed(ActionUp))
            Input.ActionRelease(ActionUp);
        if (InputDirection.Y <= 0 && Input.IsActionPressed(ActionDown))
            Input.ActionRelease(ActionDown);

        if (InputDirection.X < 0)
            Input.ActionPress(ActionLeft, -InputDirection.X);
        if (InputDirection.X > 0)
            Input.ActionPress(ActionRight, InputDirection.X);
        if (InputDirection.Y < 0)
            Input.ActionPress(ActionUp, -InputDirection.Y);
        if (InputDirection.Y > 0)
            Input.ActionPress(ActionDown, InputDirection.Y);
    }

    private void ResetJoystick()
    {
        IsPressed = false;
        InputDirection = Vector2.Zero;

        _touchIndex = -1;
        _tip.Modulate = _defaultColor;
        _base.Position = _baseDefaultPosition;
        _tip.Position = _tipDefaultPosition;

        if (UseInputActions)
            foreach (string action in new[] { ActionLeft, ActionRight, ActionUp, ActionDown })
                Input.ActionRelease(action);
    }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants