英文:
Advice on how I can go about writting this program?
问题
长时间以来,我一直在研究这些类型的设备,希望得到一个既具有压力敏感性又提供触觉反馈的硬件接口。我最接近的是3DConnextion的太空鼠标。它非常完美,输入速率与我对旋钮施加的压力成比例,但它受到专有实现的困扰,因此只有少数软件支持它。
但最重要的是,对于所有这些设备,如果我希望设备由AutoHotkey(AHK)代码驱动,我基本上必须将它们转化为虚拟鼠标/键盘设备。这将使它们的卖点(压力敏感/触觉反馈)失效。
在使用Autodesk Maya时,我找到了一个解决方案。我意识到解决方案一直就在我眼前,那就是我的可靠鼠标:
- 在AHK中是一流的公民
- 在任何软件中都是一流的公民
- 在操作上已经非常出色
但是鼠标如何作为既具有压力敏感性又提供触觉反馈的接口?
通过沿X
或Y
轴拖动鼠标:
- 鼠标拖动速度=压力敏感性,即增加的速度有多快
- 鼠标方向=旋钮方向,向左拖动会减小值,向右拖动会增加值
这里是我在说什么的一个小演示。将鼠标向左移动,动画倒退1帧;将鼠标向右移动,动画前进1帧。正如你所看到的,我可以慢慢移动(逐帧)到极快的刷帧。我有一只相当不错的游戏鼠标。整个操作提供完美的触觉反馈,甚至到像素级别。
因此,要在2D动画软件中实现与Maya中相同的功能:
- 向左移动鼠标,动画后退1帧,通过发送
Left
箭头键,软件的键盘快捷键后退1帧 - 向右移动鼠标,动画前进1帧,通过发送
Right
箭头键,软件的键盘快捷键前进1帧
问题是,我陷入了如何在AutoHotkey中实际实现这一普遍操作的困境,该操作可以绑定到任何键上,而且更加复杂,因为我还想利用X
和Y
轴。
例如,假设在按住Space
键的同时,鼠标每移动10像素:
- 向上触发
SendInput,{up}
- 向下触发
SendInput,{Down}
- 向左触发
SendInput,{Left}
- 向右触发
SendInput,{Right}
经过一小时的尝试后,以下是我得到的代码:
#singleinstance, force
#Persistent
#NoEnv
#Warn, All, OutputDebug
#MaxHotkeysPerInterval 500
SetBatchLines, -1
Return
~space::
CoordMode, Mouse, Screen
MouseGetPos, StartX, StartY
ToolTip, % "StartX: " StartX "`nStartY1: " Starty ;Temporary, for Debugging
KeyWait, Space
Sleep, 500 ;Temporary sleep command for diffrentiating "Start" and "current" Tooltip
MouseGetPos, CurrentX, CurrentY
ToolTip, % "CurrentX: " CurrentX "`nCurrentY: " CurrentY ;Temporary, for Debugging
If(CurrentX > StartX)
SendInput, {Right}
If(CurrentX < StartX)
SendInput, {Left}
If(CurrentY > StartY)
SendInput, {Up}
If(CurrentY < StartY)
SendInput, {Down}
Return
Esc::ExitApp
这不是有效的代码,我感觉我的AHK知识正在受到极限的考验。我认为我被困在建立核心底层机制上,似乎出现在If(CurrentX < StartX)
,但我无法弄清楚。
例如,我如何定期检查StartX
和CurrentX
之间是否有10像素的差异?
检查这样的差异是否有必要?我将感激任何关于如何解决这个问题的意见和示例。谢谢。
英文:
For a long time, I have been going through THESE types of devices in hopes of getting a hardware interface that is pressure sensitive and also provides tactile feedback. The closest I have gotten was the space mouse by 3DConnextion. It was perfect, The input rate was proportional to how much pressure I was applying to the knob but its plagued with proprietary implementation, thus only a handful of software's support it.
But mostly importantly with all these devices, if I wanted the device to be driven by AHK code, I had to essentially turn them into dummy mouse/keyboard devices. Which would nullify their selling point (pressure sensitive/tactile feedback)
While using Autodesk Maya, I came across a solution. I realised the solution was all along right under my nose, my trusty mouse:
- First class citizen in AHK
- First class citizen in any software
- Already very good at operating it
But how does a mouse act as an interface that is pressure sensitive and also provides tactile feedback?
By dragging the mouse either along X
or Y
axis:
- Mouse drag speed = Pressure sensitivity, how fast to increment
- Mouse direction = knob direction, dragging left will decrement values and dragging right will increment values
HERE is a little demonstration of what I am talking about. Moving mouse left the animation goes back by 1 frame, moving mouse right the animation goes forward by 1 frame, as you can see, I can go very slow (frame by frame) to scrubbing extremely fast. I have a pretty good gaming mouse. The whole operation provides perfect tactile feedback, down to the pixel level.
So to implement the same feature found in Maya, in a 2D animation software:
- Moving mouse left the animation goes back by 1 frame by sending
Left
arrow key , the software's keyboard shortcut Step 1 frame back - Moving mouse right the animation goes forward by 1 frame by sending
Right
arrow key , the software's keyboard shortcut Step 1 frame forward
The thing is am stuck on how I can actually go about implementing this in AutoHotkey as a general operation that can be bound to any key, It gets even more complicated because I want to also take advantage of both the X
and Y
axis.
Lets say for example, while the Space
key is down held down, for every 10 pixels the mouse moves:
- Up, trigger
SendInput, {up}
- Down, trigger
SendInput, {Down}
- Left, trigger
SendInput, {Left}
- Right, trigger `SendInput, {Right}
After an hour of mucking about, the following is what I have:
#singleinstance, force
#Persistent
#NoEnv
#Warn, All, OutputDebug
#MaxHotkeysPerInterval 500
SetBatchLines, -1
Return
~space::
CoordMode, Mouse, Screen
MouseGetPos, StartX, StartY
ToolTip, % "StartX: " StartX "`nStartY1: " Starty ;Temporary, for Debugging
KeyWait, Space
Sleep, 500 ;Temporary sleep command for diffrentiating "Start" and "current" Tooltip
MouseGetPos, CurrentX, CurrentY
ToolTip, % "CurrentX: " CurrentX "`nCurrentY: " CurrentY ;Temporary, for Debugging
If(CurrentX > StartX)
SendInput, {Right}
If(CurrentX < StartX)
SendInput, {Left}
If(CurrentY > StartY)
SendInput, {Up}
If(CurrentY < StartY)
SendInput, {Down}
Return
Esc::ExitApp
Its not working code, I feel my AHK knowledge is being tested to its limit. I think I am stuck on establishing the core underlying mechanism, which seem to be at If(CurrentX < StartX)
but I cant quite figure it out.
How do I for example routinely check if there is a difference of 10 pixels between StartX
and CurrentX
Is it even necessary to check for such a difference? I would appreciate any input and examples of how I can go about this. Thank you.
EDIT 1:
So after some more experimenting I came up with this, which sort of works:
#singleinstance, force
#Persistent
#NoEnv
#Warn, All, OutputDebug
#MaxHotkeysPerInterval 500
SetBatchLines, -1
Return
space::
CoordMode, Mouse, Screen
while GetKeyState("space", "p")
{
StartX := CurrentX
StartY := CurrentY
MouseGetPos, CurrentX, CurrentY
Sleep, 555
ToolTip, % "StartX: " StartX "`nStartY1: " StartY
Sleep, 555
If(CurrentX > StartX)
ToolTip, CurrentX > StartX
If(CurrentX < StartX)
ToolTip, CurrentX < StartX
If(CurrentY > StartY)
ToolTip, CurrentY > StartY
If(CurrentY < StartY)
Tooltip, CurrentY < StartY
}
Return
Esc::ExitApp
When I move 1 pixel to the Left, the message CurrentX < StartX
is printed
When I move 1 pixel to the Right, the message CurrentX > StartX
is printed
When I move 1 pixel to the Up, the message CurrentY < StartY
is printed
When I move 1 pixel to the Down , the message CurrentY > StartY
is printed
But its extremely error prone, as the threshold is only 1 pixel, attempting to move 1 pixel up can sometimes be taken as 1 pixel left.
答案1
得分: 1
以下是翻译好的内容:
你可以在自动执行部分定义自定义阈值(例如10像素):
#NoEnv
#SingleInstance Force
threshold=10
CoordMode, Mouse, Screen
space::
while GetKeyState("space", "p")
{
MouseGetPos, X1, Y1
Sleep, 500
MouseGetPos, X2, Y2
If (X2 > X1+threshold)
SendInput, {Right}
If(X2 < X1-threshold)
SendInput, {Left}
If(Y2 > Y1+threshold)
SendInput, {Down}
If(Y2 < Y1-threshold)
SendInput, {Up}
}
return
编辑:
也尝试这个:
#NoEnv
#SingleInstance Force
threshold = 10
space::
X1 := ""
Y1 := ""
while GetKeyState("space", "p")
{
X2 := X1
Y2 := Y1
MouseGetPos, X1, Y1
dX := dX = "" ? X1 - X2 : dX + X1 - X2
dY := dY = "" ? Y1 - Y2 : dY + Y1 - Y2
if (dX**2 >= threshold**2)
{
SendInput % (dX > 0 ? "{Right}" : "{Left}")
dX -= threshold * ((dX > 0) * 2-1)
}
if (dY**2 >= threshold**2)
{
SendInput % (dY > 0 ? "{Down}" : "{up}")
dY -= threshold * ((dY > 0) * 2-1)
}
}
return
英文:
You can define a custom threshold (e.g 10 pixels) in the auto-execute section:
#NoEnv
#SingleInstance Force
threshold=10
CoordMode, Mouse, Screen
space::
while GetKeyState("space", "p")
{
MouseGetPos, X1, Y1
Sleep, 500
MouseGetPos, X2, Y2
If (X2 > X1+threshold)
SendInput, {Right}
If(X2 < X1-threshold)
SendInput, {Left}
If(Y2 > Y1+threshold)
SendInput, {Down}
If(Y2 < Y1-threshold)
SendInput, {Up}
}
return
EDIT:
Try also this:
#NoEnv
#SingleInstance Force
threshold = 10
space::
X1 := ""
Y1 := ""
while GetKeyState("space", "p")
{
X2 := X1
Y2 := Y1
MouseGetPos, X1, Y1
dX := dX = "" ? X1 - X2 : dX + X1 - X2
dY := dY = "" ? Y1 - Y2 : dY + Y1 - Y2
if (dX**2 >= threshold**2)
{
SendInput % (dX > 0 ? "{Right}" : "{Left}")
dX -= threshold * ((dX > 0) * 2-1)
}
if (dY**2 >= threshold**2)
{
SendInput % (dY > 0 ? "{Down}" : "{up}")
dY -= threshold * ((dY > 0) * 2-1)
}
}
return
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论