Quote:
Originally Posted by [TTG] Yare
How does the "screen edge" stuff cope with the game in windowed mode, or with multiple monitors?
|
Here is a test version with windowed support. Because I don't have good direct access to the mouse in a DX game from outside it, the best I can do is this.
If you click in the game window, the mouse will lock to the window. The movement modes will then behave exactly like full screen. To move the mouse out of the window you must first press the 'F' key to Free the mouse.
Depending on you system, you may have to change theses values:
Code:
; windowed mode info
; I need to see if this can be read automatically
; you may have to change these to suit your computer
winBarPixels := 29 ; top bar
winBorderPixels := 3 ; other 3 edges
This version also incudes a fix where I keep sending down keystrokes when the mouse is pressed. You won't notice the difference in game, but it technically cleans up and speeds up the code.
Code:
; Script Function:
; Map mouse clicks at the edges of the screen as arrow keys
; You can also move by holding down the button and dragging the mouse
; The script will time out after 2 minutes if game is not launched
; Press 'F' in windowed mode to free the cursor
; Set this to the W&G episode you want to run with this script
; 0 = Demo
episode := 1
; set options to 0=disable 1=enable
; Left Button options
useEdgesL := 1
useCenterL := 1
; Right Button options
useEdgesR := 1
useCenterR := 1
; how long in milliseconds to press mouse button in center screen before movement is controlled by mouse dragging
; left move delay
buttonDelayL := 150
; right move delay
buttonDelayR := 50
; movement box size in pixels
boxSize := 100
; pixels at edge used to select movement
; must be 1 to 25
borderPixels := 5
; ==================================
; only change values above this line
; ==================================
; windowed mode info
; I need to see if this can be read automatically
; you may have to change these to suit your computer
winBarPixels := 29 ; top bar
winBorderPixels := 3 ; other 3 edges
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
#SingleInstance ignore ; only allow 1 running script
SetTitleMatchMode, 3 ; Names must be exact
; check values
if (borderPixels < 1 OR borderPixels > 25)
{
MsgBox, borderPixels value out of range
ExitApp
}
timeDelayL := buttonDelayL // 10
timeDelayR := buttonDelayR // 10
movePixels := boxSize // 2
edgeMargin := movePixels * 2 + borderPixels
border := borderPixels
mouseLocked := 0
; setup paths and file
if (episode = 0)
{
gameFile = WallaceGromitDemo.exe
launcherName = Wallace & Gromit Demo
}
else if (episode = 1)
{
gameFile = WallaceGromit101.exe
launcherName = Fright of the Bumblebees
}
else if (episode = 2)
{
gameFile = WallaceGromit102.exe
launcherName = The Last Resort
}
else if (episode = 3)
{
gameFile = WallaceGromit103.exe
launcherName = Muzzled!
}
else if (episode = 4)
{
gameFile = WallaceGromit104.exe
launcherName = The Bogey Man
}
else
{
MsgBox, Invalid Episode #
ExitApp
}
gameReg = SOFTWARE\Telltale Games\%gameFile%
RegRead, gameDir, HKEY_LOCAL_MACHINE, %gameReg% , Install Location
; this is the name of the game as shown on the task bar
; Demo, Ep1 and Ep2 all use the same name, so I assume all episodes will
gameName = Telltale Games
; launch game
Run, %gameFile%, %gameDir%, UseErrorLevel
if ErrorLevel = ERROR
{
MsgBox, Episode %episode% could not be found
ExitApp
}
winwait, %gameName%, , 120
if ErrorLevel
{
ExitApp
}
gameID := WinExist(gameName)
WinActivate, ahk_id %gameID%
SetTimer, gameCheck
return
gameCheck:
;------------------------------
; quit script on game exit
;------------------------------
if (mouseLocked AND isFullScreen())
{
; free the mouse if we switched modes
DllCall("ClipCursor")
mouseLocked := 0
}
IfWinNotExist, ahk_id %gameID%
{
; free the mouse just in case
DllCall("ClipCursor")
ExitApp
}
return
~LButton::
useEdges := useEdgesL
useCenter := useCenterL
timeDelay := timeDelayL
testButton = LButton
Gosub, mouseToArrows
return
~RButton::
useEdges := useEdgesR
useCenter := useCenterR
timeDelay := timeDelayR
testButton = RButton
Gosub, mouseToArrows
return
mouseToArrows:
;------------------------------
; process mouse movement
;------------------------------
usingCenterMove := 0
if (isFullScreen())
{
; fullscreen
CoordMode, Mouse, Screen
width := A_ScreenWidth
height := A_ScreenHeight
winXpos := 0
winYpos := 0
winXoffset := 0
winYoffset := 0
}
else
{
; only do mouse to key conversion in game window
IfWinNotActive, ahk_id %gameID%
Return,
CoordMode, Mouse, Relative
; get window information
WinGetPos, winXpos, winYpos, width, height, ahk_id %gameID%
; free up mouse if on bar
MouseGetPos, , curY
if (curY < winBarPixels)
Return,
; remove window border pixels
width -= winBorderPixels * 2
height -= winBarPixels + winBorderPixels
winXoffset := winBorderPixels
winYoffset := winBarPixels
; set top left of game window
; keep locking the window so the mouse does not get free
mouseLocked := 1
Gosub, lockWindow
}
; check aspect ratio and adjust
if (width * 9 // height < 16)
{
; top and bottom letterboxed
newHeight := width * 9 // 16
edgeLeft := 0
edgeRight := width
edgeUp := (height - newHeight) // 2
edgeDown := edgeUp + newHeight
}
else
{
; sides letterboxed
newWidth := height * 16 // 9
edgeLeft := (width - newWidth) // 2
edgeRight := edgeLeft + newWidth
edgeUp := 0
edgeDown := height
}
; bottom corner is one pixel in
edgeRight--
edgeDown--
if (useCenter = 1)
{
timePressed := 0
; the valid center movement area
centerLeft := edgeLeft + edgeMargin
centerRight := edgeRight - edgeMargin
centerUp := edgeUp + edgeMargin
centerDown := edgeDown - edgeMargin
}
While GetKeyState(testButton)
{
MouseGetPos, curX, curY
if (!usingCenterMove)
{
; adjust for window border
curX -= winXoffset
curY -= winYoffset
}
if (useEdges = 1 OR usingCenterMove = 1)
{
if (curX < edgeLeft + border)
{
if (!downL)
{
Send {Left Down}
downL := 1
}
}
else
{
if (downL)
{
Send {Left Up}
}
downL := 0
}
if (curX > edgeRight - border)
{
if (!downR)
{
Send {Right Down}
downR := 1
}
}
else
{
if (downR)
{
Send {Right Up}
}
downR := 0
}
if (curY < edgeUp + border)
{
if (!downU)
{
Send {Up Down}
downU := 1
}
}
else
{
if (downU)
{
Send {Up Up}
}
downU := 0
}
if (curY > edgeDown - border)
{
if (!downD)
{
Send {Down Down}
downD := 1
}
}
else
{
if (downD)
{
Send {Down Up}
}
downD := 0
}
}
if (useCenter AND !usingCenterMove)
{
; start counting if in center of screen
if (curX > centerLeft AND curX < centerRight AND curY > centerUp AND curY < centerDown)
{
timePressed++
if (timePressed > timeDelay)
{
; button down long enough, start using center move
; re-djust mousepos to real and setup movement box
curX += winXoffset
curY += winYoffset
edgeLeft := curX - movePixels
edgeUp := curY - movePixels
edgeRight := curX + movePixels
edgeDown := curY + movePixels
VarSetCapacity(R, 16, 0), NumPut(winXpos + edgeLeft, &R+0), NumPut(winYpos + edgeUp, &R+4), NumPut(winXpos + edgeRight + 1, &R+8), NumPut(winYpos + edgeDown + 1, &R + 12)
DllCall("ClipCursor", UInt, &R)
usingCenterMove := 1
border := 1
}
}
else
{
; reset count when not in center
timePressed := 0
}
}
Sleep, 10
}
if (usingCenterMove)
{
; free the cursor
if (mouseLocked)
Gosub, lockWindow
else
DllCall("ClipCursor")
; reset to view border
border := borderPixels
}
; unpress any keys that are down
if (downL)
{
Send {Left Up}
}
downL := 0
if (downR)
{
Send {Right Up}
}
downR := 0
if (downU)
{
Send {Up Up}
}
downU := 0
if (downD)
{
Send {Down Up}
}
downD := 0
Return,
isFullScreen()
;------------------------------
; check to see if fullscreen
;------------------------------
{
Global gameID
WinGet, style, Style, ahk_id %gameID%
; 0x800000 is WS_BORDER.
; 0x20000000 is WS_MINIMIZE.
; no border and not minimized
Return, (style & 0x20800000) ? 0 : 1
}
~f::
;------------------------------
; free mouse from window
;------------------------------
if (mouseLocked)
{
IfWinActive, ahk_id %gameID%
{
; free the cursor
DllCall("ClipCursor")
mouseLocked := 0
}
}
Return,
lockWindow:
;------------------------------
; lock mouse to window
;------------------------------
VarSetCapacity(R, 16, 0), NumPut(winXpos + winBorderPixels, &R+0), NumPut(winYpos + winBarPixels, &R+4), NumPut(winXpos + winBorderPixels + width, &R+8), NumPut(winYpos + winBarPixels + height, &R + 12)
DllCall("ClipCursor", UInt, &R)
Return,