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

Input numbers for scaling and rotation while dragging #8

Open
Henry00IS opened this issue Sep 14, 2022 · 0 comments
Open

Input numbers for scaling and rotation while dragging #8

Henry00IS opened this issue Sep 14, 2022 · 0 comments

Comments

@Henry00IS
Copy link
Owner

Henry00IS commented Sep 14, 2022

Just like Blender, allow the user to type numbers while scaling, rotating or translating as a multiplier.

I already wrote the code for a simple keyboard recorder. The problem has been finding an elegant way to add this to tools without having to copy and paste the logic everywhere. Something almost as simple as a C# property for the tools that support this feature (or an input focus related thing).

#if UNITY_EDITOR

using System;
using UnityEditor;
using UnityEngine;

namespace AeternumGames.ShapeEditor
{
    /// <summary>Processes keyboard numbers for typing multipliers during active tools and widgets.</summary>
    [Serializable]
    public class NumericKeyboardRecorder
    {
        /// <summary>The accumulated string of characters.</summary>
        private string accumulator = "";

        private float lastValidFloat = 0.0f;

        /// <summary>Gets or sets (clears) whether the user has typed a value using the keyboard.</summary>
        public bool hasValue
        {
            get
            {
                if (accumulator.Length == 0) return false;

                return true;
            }
            set
            {
                if (!value)
                    Reset();
            }
        }

        /// <summary>The last valid value typed assuming <see cref="hasValue"/> is true.</summary>
        public float value => lastValidFloat;

        /// <summary>The text typed assuming <see cref="hasValue"/> is true.</summary>
        public string text => accumulator;

        /// <summary>Must be called on key down events.</summary>
        public bool OnKeyDown(KeyCode keyCode)
        {
            var character = (char)keyCode;

            // add floating point related characters to the accumulator.
            if (ValidateCharacter(character))
            {
                accumulator += character;
                UpdateValue();
                return true;
            }

            if (hasValue)
            {
                // backspace can be used to remove the last character.
                if (keyCode == KeyCode.Backspace)
                {
                    OnBackspace();
                    UpdateValue();
                    return true;
                }

                // minus can be used to negate the number.
                if (keyCode == KeyCode.Minus)
                {
                    OnMinus();
                    UpdateValue();
                    return true;
                }
            }

            return false;
        }

        // whitelist the input characters related to floating point numbers.
        private bool ValidateCharacter(char character)
        {
            switch (character)
            {
                case '0':
                case '1':
                case '2':
                case '3':
                case '4':
                case '5':
                case '6':
                case '7':
                case '8':
                case '9':
                case '.':
                    return true;
            }
            return false;
        }

        private void OnBackspace()
        {
            if (accumulator.Length == 0) return;
            accumulator = accumulator.Remove(accumulator.Length - 1, 1);
        }

        private void OnMinus()
        {
            if (accumulator.ContainsInvarianCulture("-"))
                accumulator = accumulator.Replace("-", "");
            else
                accumulator = "-" + accumulator;
        }

        private void UpdateValue()
        {
            if (ExpressionEvaluator.Evaluate(accumulator, out float number))
                lastValidFloat = number;
        }

        /// <summary>Resets the current input.</summary>
        public void Reset()
        {
            accumulator = "";
            lastValidFloat = 0.0f;
        }
    }
}

#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant