1
\$\begingroup\$

I'm making a little program that's a bit like paint but instead of filling in pixels, it drops a block on mousebutton(0). I'm now trying to add a straight line toggle on it to make the mouse only move up/down + left/right. Tried a few things so far, but none worked and can't find anything on this specific question. Have you guys done something similar and if not, how would you approach this?

Current code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MouseStraightLine : MonoBehaviour
{
    //If the shift key is pressed the mouse should only move in a straight line
    public bool straightLine = false;

    void Update()
    {
        if (Input.GetKey(KeyCode.LeftShift))
        {
            straightLine = true;
            StraightLine();
        }
        else
        {
            straightLine = false;
        }
    }

    public void StraightLine() 
    {
        //Locks the mouse to only be able to move in a straight line up/down or left/right
        //Get the mouse position and store it
        Vector3 mousePos = Input.mousePosition;
        //If the mouse is moving in the x axis
        if (Input.GetAxis("Mouse X") != 0)
        {
            //Lock the mouse to only move in the x axis
            mousePos.y = 0;
            mousePos.z = 0;

            //Disable y axis movement
            
        }
        //If the mouse is moving in the y axis
        if (Input.GetAxis("Mouse Y") != 0)
        {
            //Lock the mouse to only move in the y axis
            mousePos.x = 0;
            mousePos.z = 0;
        }

        //Set the mouse position to the new position
        Input.mousePosition.Set(mousePos.x, mousePos.y, mousePos.z);
    }
}
```
\$\endgroup\$
2
  • \$\begingroup\$ Show us what you tried and how the result differed from what you wanted. I'd assume you did basic things like listening for Shift to be pressed, recording the cursor position when it is pressed, checking whether it's pressed when laying the next block and if so snapping the block position to be in line with the position where Shift was pressed, something like that? Where specifically did you run into trouble? \$\endgroup\$
    – DMGregory
    Sep 7 at 15:32
  • \$\begingroup\$ @DMGregory updated the original just don't understand the whole sequence of actions to get the effect of MSPaint shift click. \$\endgroup\$ Sep 7 at 16:31

1 Answer 1

3
\$\begingroup\$

Cache relevant x or y value after shift key is detected

PseudoCode:

Vector2 oldMousePos, mousePos
float x, y

Update
 mousePos = mouse.position
 x = mousePos.x
 y = mousePos.y
 if ShiftKeyDown //fires on frame shift key is first pressed
   //detect users desired axis: x or y
   if (ABS(mousePos.x - oldMousePos.x) > ABS(mousePos.y - oldMousePos.y)) //user is going left to right
     y = mousePos.y
   else 
     x = mousePos.x

// Do drawing here or whatever, using x & y coords

  oldMousePos = mousePos

Here's a tested implementation (C#):

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShiftLine : MonoBehaviour
{
    [SerializeField] GameObject cube; //our voxel prefab
    List<Vector2> occupiedVoxels; //to record filled positions
    public enum LockedState
    {
        none,
        x,
        y
    }

    public LockedState state;

    void Start()
    {
        occupiedVoxels = new List<Vector2>();
        state = LockedState.none;
    }

    Vector2 oldMousePos, mousePos;
    float x, y;

    void Update()
    {
        mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);

        if (Input.GetKeyDown(KeyCode.RightShift))
        {
            // which way are we moving?
            if (Mathf.Abs(x - oldMousePos.x) > Mathf.Abs(y - oldMousePos.y))
            {
                y = oldMousePos.y;
                state = LockedState.y;
            }
            else
            {
                x = oldMousePos.x;
                state = LockedState.x;
            }
        }
        else if (Input.GetKeyUp(KeyCode.RightShift))
        {
            state = LockedState.none;
        }

        if (Input.GetMouseButton(0))
        {
            switch (state)
            {
                case LockedState.none:
                    x = mousePos.x;
                    y = mousePos.y;
                    break;

                case LockedState.x:
                    y = mousePos.y;
                    break;

                case LockedState.y:
                    x = mousePos.x;
                    break;
            }

            // round coordinates down 
            x = Mathf.Floor(x);
            y = Mathf.Floor(y);
            
           // is this voxel position already occupied?
           // only drop voxel if position is empty.

            if(!occupiedVoxels.Contains(new Vector2(x, y)))
            {
                occupiedVoxels.Add(new Vector2(x, y));
                var go = Instantiate(cube);
                go.transform.position = new Vector3(x, y, 0);   
            }
        }
        oldMousePos = mousePos;
    }
}

Demo:

Demo of mouse lock implementation

\$\endgroup\$
1
  • \$\begingroup\$ Yup that's the one I was looking for, thanks man! \$\endgroup\$ Sep 8 at 8:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .