' #############################################################################
' MULTIMOUSE
' ----------
' A proof of concept / experiment to try to get the computer to read
' 2 or mice plugged into the computer, as separate devices,
' to control 2 or more cursors on the screen (for multiplayer games, etc.)
'
' #############################################################################
' =============================================================================
' GLOBAL DECLARATIONS a$=string, i%=integer, L&=long, s!=single, d#=double
' =============================================================================
' INITIALIZE
' =============================================================================
' TRY THE MOUSE
main ProgramName$
' =============================================================================
' FINISH
SYSTEM ' return control to the operating system PRINT ProgramName$
+ " finished."
' /////////////////////////////////////////////////////////////////////////////
PRINT "How can we get separate input from 2 or more USB mice " PRINT "plugged into one computer?" PRINT "1. Test using _MOUSEX, _MOUSEY, etc." PRINT "2. Test using _DEVICE commands" PRINT "3. Enumerate devices with _DEVICES to try and detect >1 mouse" PRINT "What to do ('q' to exit)"
MouseInputTest in$
MouseInputTest in$
EnumerateDevices
' /////////////////////////////////////////////////////////////////////////////
' Gets mouse input using _MOUSEX, _MOUSEY, _MOUSEBUTTON commands.
' UDT TO HOLD THE INFO FOR EACH MOUSE
LeftDown
AS INTEGER ' tracks left mouse button state, TRUE=down MiddleDown
AS INTEGER ' tracks middle mouse button state, TRUE=down RightDown
AS INTEGER ' tracks right mouse button state, TRUE=down MiddleCount
AS INTEGER ' counts middle clicks
' MIN/MAX VALUES
' MAIN VARIABLES
DIM arrMouseID
(8) AS STRING ' device IDs for mice connected to system (guessing this would be a string, dunno) DIM arrInfo
(8) AS InfoType
' STORES INFO FOR EACH MOUSE DIM left%
, middle%
, right%
' temp mouse variables
' TEMP VARIABLES FOR DISPLAYING FORMATTED VALUES TO SCREEN
' MOUSE CURSORS (JUST SOME LETTERS)
CData:
' DEFAULT/INTIAL X COORDINATE OF EACH CURSOR ON SCREEN
XData:
DATA 5,15,25,35,45,55,65,75
' DEFAULT/INTIAL Y COORDINATE OF EACH CURSOR ON SCREEN
YData:
DATA 17,17,19,19,21,21,23,23
' DEFAULT/INITIAL VALUE OF EACH SCROLL WHEEL
WData:
DATA 224,192,160,128,96,64,32,0
' COUNT # OF MICE CONNECTED + GET DEVICE IDs
iCount = GetMouseCount% ' THIS FUNCTION WOULD ENUMERATE MICE, SHOULD RETURN 1+
IF (iCount
> 8) THEN iCount
= 8:
' FOR NOW ONLY SUPPORT UPTO 8 MICE GetMouseIDs arrMouseID() ' GET MOUSE IDs
' INITIALIZE CURSORS, MOUSE STATE, ETC.
iIndex = iIndex + 1
' INITIALIZED BELOW: arrInfo(iIndex).x = 0
' INITIALIZED BELOW: arrInfo(iIndex).y = 0
' INITIALIZED BELOW: arrInfo(iIndex).wheel = 127
arrInfo(iIndex).LeftDown = FALSE
arrInfo(iIndex).MiddleDown = FALSE
arrInfo(iIndex).RightDown = FALSE
arrInfo(iIndex).LeftCount = 0
arrInfo(iIndex).MiddleCount = 0
arrInfo(iIndex).RightCount = 0
' INITIALIZE X COORDINATES
iIndex = iIndex + 1
' INITIALIZE Y COORDINATES
iIndex = iIndex + 1
' INITIALIZE SCROLL WHEEL
iIndex = iIndex + 1
READ arrInfo
(iIndex
).wheel
' DRAW PLAYING FIELD
LOCATE 1, 1:
PRINT "1. PLUG 1-8 MICE INTO THE COMPUTER" LOCATE 2, 1:
PRINT "2. USE MICE TO POSITION LETTERS ON SCREEN" LOCATE 4, 1:
PRINT "--------------------------------------------------------------------------------";
LOCATE 5, 1:
PRINT "# X Y Wheel LeftDown MiddleDown RightDown LeftCount MiddleCount RightCount " LOCATE 6, 1:
PRINT "--------------------------------------------------------------------------------";
' NOTE: LEAVE THE NEXT 8 LINES FREE (ROWS 8-15)
' TO DISPLAY TEST VALUES FOR UPTO 8 MICE
' DRAW BORDER AROUND PLAYING FIELD
DrawTextLine cMinX - 1, cMinY - 1, cMinX - 1, cMaxY + 1, "#"
DrawTextLine cMinX - 1, cMinY - 1, cMaxX + 1, cMinY - 1, "#"
DrawTextLine cMaxX + 1, cMaxY + 1, cMaxX + 1, cMinY - 1, "#"
DrawTextLine cMaxX + 1, cMaxY + 1, cMinX - 1, cMaxY + 1, "#"
' GET INPUT AND MOVE PLAYERS
iIndex = iIndex + 1
' ERASE CURSORS AT CURRENT POSITION
LOCATE arrInfo
(iIndex
).y
, arrInfo
(iIndex
).x:
PRINT " ";
' GET NEXT MOUSE INPUT
ReadMouse1 arrMouseID(iIndex), arrInfo(iIndex).x, arrInfo(iIndex).y, left%, middle%, right%, arrInfo(iIndex).wheel, cMinWheel, cMaxWheel
ReadMouse2 arrMouseID(iIndex), arrInfo(iIndex).x, arrInfo(iIndex).y, left%, middle%, right%, arrInfo(iIndex).wheel, cMinWheel, cMaxWheel
' HANDLE LEFT MOUSE BUTTON
IF arrInfo
(iIndex
).LeftDown
= FALSE
THEN ' BUTTON DOWN EVENT
arrInfo(iIndex).LeftDown = TRUE
arrInfo(iIndex).LeftCount = arrInfo(iIndex).LeftCount + 1
IF arrInfo
(iIndex
).LeftDown
= TRUE
THEN ' BUTTON UP EVENT
arrInfo(iIndex).LeftDown = FALSE
' HANDLE MIDDLE MOUSE BUTTON (SCROLL WHEEL BUTTON)
IF arrInfo
(iIndex
).MiddleDown
= FALSE
THEN ' BUTTON DOWN EVENT
arrInfo(iIndex).MiddleDown = TRUE
arrInfo(iIndex).MiddleCount = arrInfo(iIndex).MiddleCount + 1
IF arrInfo
(iIndex
).MiddleDown
= TRUE
THEN ' BUTTON UP EVENT
arrInfo(iIndex).MiddleDown = FALSE
' HANDLE RIGHT MOUSE BUTTON
IF arrInfo
(iIndex
).RightDown
= FALSE
THEN ' BUTTON DOWN EVENT
arrInfo(iIndex).RightDown = TRUE
arrInfo(iIndex).RightCount = arrInfo(iIndex).RightCount + 1
IF arrInfo
(iIndex
).RightDown
= TRUE
THEN ' BUTTON UP EVENT
arrInfo(iIndex).RightDown = FALSE
' CHECK BOUNDARIES
IF arrInfo
(iIndex
).x
< cMinX
THEN arrInfo
(iIndex
).x
= cMinX
IF arrInfo
(iIndex
).x
> cMaxX
THEN arrInfo
(iIndex
).x
= cMaxX
IF arrInfo
(iIndex
).y
< cMinY
THEN arrInfo
(iIndex
).y
= cMinY
IF arrInfo
(iIndex
).y
> cMaxY
THEN arrInfo
(iIndex
).y
= cMaxY
' PLOT CURSOR
LOCATE arrInfo
(iIndex
).y
, arrInfo
(iIndex
).x:
PRINT arrInfo
(iIndex
).c;
' DISPLAY VARIABLES
'LOCATE 5, 1: PRINT "# X Y Wheel LeftDown MiddleDown RightDown LeftCount MiddleCount RightCount "
LOCATE 6 + iLoop
, 1:
PRINT sCount
+ sX
+ sY
+ sWheel
+ sLeftDown
+ sMiddleDown
+ sRightDown
+ sLeftCount
+ sMiddleCount
+ sRightCount
_LIMIT 100 ' keep loop at 100 frames per second
' /////////////////////////////////////////////////////////////////////////////
' Returns a count of # of mouse devices connected to the system
' *** Currently hardcoded to 1 until we figure out how to do this. ***
GetMouseCount% = 1
' /////////////////////////////////////////////////////////////////////////////
' Gets ID of each mouse device connected to the system (for now upto 8)
' and returns the IDs in an array of strings
' (assuming the ID is a string and not numeric?).
' If no mouse found, the ID will just be a blank string.
' *** Currently hardcoded to "1" until we figure out how to do this. ***
' CLEAR OUT IDs
arrMouseID(iLoop) = ""
' GET IDs
arrMouseID(1) = "1" ' for now just fudge it!
' /////////////////////////////////////////////////////////////////////////////
' Read mouse method #1, using _MOUSEX, _MOUSEY, etc.
' Gets input from mouse identified by deviceid$
' (or does that needs to be an ordinal position?)
' For version 1 we only return the input from the one mouse
' regardless of deviceid$.
' NOTE: click events (mouse up/mouse down) are handled by the calling sub,
' this routine just sends back
' TRUE if the given button is currently down or FALSE if it is up.
' Parameters (values returned):
' x% = x position of mouse pointer
' y% = y position of mouse pointer
' left% = current state of left mouse button (up or down)
' middle% = current state of middle mouse button / scroll wheel button (up or down)
' right% = current state of right mouse button (up or down)
' wheel% = value of mouse scroll wheel (passed in and incremented/decremented by 1 if wheel move detected)
' Parameters (input only):
' wheelmin% = minimum value to allow wheel% to be decremented to
' wheelmax% = maximum value to allow wheel% to be incremened to
SUB ReadMouse1
(deviceid$
, x%
, y%
, left%
, middle%
, right%
, wheel%
, wheelmin%
, wheelmax%
)
' read scroll wheel
scrollAmount%
= _MOUSEWHEEL ' (Returns -1 when scrolling up and 1 when scrolling down with 0 indicating no movement since last read.) IF (scrollAmount%
= -1) AND (wheel%
> wheelmin%
) THEN wheel% = wheel% + scrollAmount%
wheel% = wheel% + scrollAmount%
' read x position
' read y position
' read mouse buttons
' /////////////////////////////////////////////////////////////////////////////
' Read mouse method #2, using _DEVICE commands.
' Gets input from mouse identified by deviceid$
' (or does that needs to be an ordinal position?)
' For version 1 we only return the input from the one mouse
' regardless of deviceid$.
' NOTE: click events (mouse up/mouse down) are handled by the calling sub,
' this routine just sends back
' TRUE if the given button is currently down or FALSE if it is up.
' Parameters (values returned):
' x% = x position of mouse pointer
' y% = y position of mouse pointer
' left% = current state of left mouse button (up or down)
' middle% = current state of middle mouse button / scroll wheel button (up or down)
' right% = current state of right mouse button (up or down)
' wheel% = value of mouse scroll wheel (passed in and incremented/decremented by 1 if wheel move detected)
' Parameters (input only):
' wheelmin% = minimum value to allow wheel% to be decremented to
' wheelmax% = maximum value to allow wheel% to be incremened to
SUB ReadMouse2
(deviceid$
, x%
, y%
, left%
, middle%
, right%
, wheel%
, wheelmin%
, wheelmax%
) DIM ScreenWidth%
' screen width DIM ScreenHeight%
' screen height
' read scroll wheel
IF (scrollAmount%
= -1) AND (wheel%
> wheelmin%
) THEN wheel% = wheel% + scrollAmount%
wheel% = wheel% + scrollAmount%
WEND ' clear and update the mouse buffer
' read x position
x%
= _AXIS(1) * ScreenWidth%
+ ScreenWidth%
' read y position
y%
= _AXIS(2) * ScreenHeight%
+ ScreenHeight%
' read mouse buttons
' /////////////////////////////////////////////////////////////////////////////
' ORIGINAL VERSION OF FUNCTION FOR READING MOUSE WITH _DEVICE:
' Gets mouse input using _DEVICE commands (part 2 of 2, subroutine)
' SOURCE : https://www.qb64.org/forum/index.php?topic=1087.0
' Subject: Mouse demo using _DEVICE commands
' From : SMcNeill
' Date : February 21, 2019, 06:15:28 AM »
MouseX
= _AXIS(1) * SW
+ SW: MouseY
= _AXIS(2) * SH
+ SH
IF leftdown
THEN 'if it was down LeftMouse = 2 'clicked
LeftMouse = 0 'the mouse was just released
leftdown = 0 'timer is cleared either way
LeftMouse = 1 'the left mouse is down , timer should have already been set
leftdown
= TIMER 'set the timer to see if we have click or hold events LeftMouse = 1 'the left mouse is down
LeftMouse = 0
IF middledown
THEN 'if it was down MiddleMouse = 2 'clicked
MiddleMouse = 0 'the mouse was just released
middledown = 0 'timer is cleared either way
MiddleMouse = 1 'the middle mouse is down , timer should have already been set
middledown
= TIMER 'set the timer to see if we have click or hold events MiddleMouse = 1 'the middle mouse is down
MiddleMouse = 0
IF rightdown
THEN 'if it was down RightMouse = 2 'clicked
RightMouse = 0 'the mouse was just released
rightdown = 0 'timer is cleared either way
RightMouse = 1 'the right mouse is down , timer should have already been set
rightdown
= TIMER 'set the timer to see if we have click or hold events RightMouse = 1 'the right mouse is down
RightMouse = 0
' /////////////////////////////////////////////////////////////////////////////
' Example: Checking for the system's input devices.
' _DEVICES FUNCTION (QB64 REFERENCE)
' http://www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]/wiki/index_title_DEVICES/
'
' The _DEVICES function returns the number of INPUT devices on your computer
' including keyboard, mouse and game devices.
'
' Syntax:
'
' device_count% = _DEVICES
'
' Returns the number of devices that can be listed separately with the _DEVICE$
' function by the device number.
' Devices include keyboard, mouse, joysticks, game pads and multiple stick game
' controllers.
' Note: This function MUST be read before trying to use the _DEVICE$,
' _DEVICEINPUT or _LAST control functions!
' Note: The STRIG/STICK commands won't read from the keyboard
' or mouse device the above example lists.
devices%
= _DEVICES ' MUST be read in order for other 2 device functions to work!
PRINT "Total devices found: ";
STR$(devices%
) FOR iLoop%
= 1 TO devices%
iLen = 4
PRINT "PRESS <ESC> TO CONTINUE"
' /////////////////////////////////////////////////////////////////////////////
' based on code from:
' Qbasic Programs - Download free bas source code
' http://www.thedubber.altervista.org/qbsrc.htm
SUB DrawTextLine
(y%
, x%
, y2%
, x2%
, c$
) 'bError% = FALSE
'LOCATE 2, 2: PRINT "(" + STR$(x%) + "," + STR$(y%) + ") to (" + STR$(x2%) + "," + STR$(y2%) + ") of " + CHR$(34) + c$ + CHR$(34);
i% = 0: steep% = 0: e% = 0
steep% = 1
e% = 2 * dy% - dx%
'PSET (y%, x%), c%:
'PSET (x%, y%), c%
y% = y% + sy%: e% = e% - 2 * dx%
x% = x% + sx%: e% = e% + 2 * dy%
'PSET (x2%, y2%), c%