关于我如何开始编写这个程序的建议?

huangapple go评论43阅读模式
英文:

Advice on how I can go about writting this program?

问题

长时间以来,我一直在研究这些类型的设备,希望得到一个既具有压力敏感性又提供触觉反馈的硬件接口。我最接近的是3DConnextion的太空鼠标。它非常完美,输入速率与我对旋钮施加的压力成比例,但它受到专有实现的困扰,因此只有少数软件支持它。

但最重要的是,对于所有这些设备,如果我希望设备由AutoHotkey(AHK)代码驱动,我基本上必须将它们转化为虚拟鼠标/键盘设备。这将使它们的卖点(压力敏感/触觉反馈)失效。

在使用Autodesk Maya时,我找到了一个解决方案。我意识到解决方案一直就在我眼前,那就是我的可靠鼠标:

  • 在AHK中是一流的公民
  • 在任何软件中都是一流的公民
  • 在操作上已经非常出色

但是鼠标如何作为既具有压力敏感性又提供触觉反馈的接口?

通过沿XY轴拖动鼠标:

  • 鼠标拖动速度=压力敏感性,即增加的速度有多快
  • 鼠标方向=旋钮方向,向左拖动会减小值,向右拖动会增加值

这里是我在说什么的一个小演示。将鼠标向左移动,动画倒退1帧;将鼠标向右移动,动画前进1帧。正如你所看到的,我可以慢慢移动(逐帧)到极快的刷帧。我有一只相当不错的游戏鼠标。整个操作提供完美的触觉反馈,甚至到像素级别。

因此,要在2D动画软件中实现与Maya中相同的功能:

  • 向左移动鼠标,动画后退1帧,通过发送Left箭头键,软件的键盘快捷键后退1帧
  • 向右移动鼠标,动画前进1帧,通过发送Right箭头键,软件的键盘快捷键前进1帧

问题是,我陷入了如何在AutoHotkey中实际实现这一普遍操作的困境,该操作可以绑定到任何键上,而且更加复杂,因为我还想利用XY轴。

例如,假设在按住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),但我无法弄清楚。

例如,我如何定期检查StartXCurrentX之间是否有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, % &quot;StartX: &quot; StartX &quot;`nStartY1: &quot; Starty          ;Temporary, for Debugging
KeyWait, Space
Sleep, 500                                                 ;Temporary sleep command for diffrentiating &quot;Start&quot; and &quot;current&quot; Tooltip
MouseGetPos, CurrentX, CurrentY
ToolTip, % &quot;CurrentX: &quot; CurrentX &quot;`nCurrentY: &quot; CurrentY   ;Temporary, for Debugging

If(CurrentX &gt; StartX)
	SendInput, {Right}

If(CurrentX &lt; StartX)
	SendInput, {Left}

If(CurrentY &gt; StartY)
	SendInput, {Up}

If(CurrentY &lt; 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 &lt; 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(&quot;space&quot;, &quot;p&quot;)
	{
	StartX := CurrentX
	StartY := CurrentY
	MouseGetPos, CurrentX, CurrentY
	
	Sleep, 555
	ToolTip, % &quot;StartX: &quot; StartX &quot;`nStartY1: &quot; StartY
	Sleep, 555
	If(CurrentX &gt; StartX)
		ToolTip, CurrentX &gt; StartX

	If(CurrentX &lt; StartX)
		ToolTip, CurrentX &lt; StartX

	If(CurrentY &gt; StartY)
		ToolTip, CurrentY &gt; StartY

	If(CurrentY &lt; StartY)
	Tooltip, CurrentY &lt; StartY
	}

Return
Esc::ExitApp

When I move 1 pixel to the Left, the message CurrentX &lt; StartX is printed
When I move 1 pixel to the Right, the message CurrentX &gt; StartX is printed

When I move 1 pixel to the Up, the message CurrentY &lt; StartY is printed
When I move 1 pixel to the Down , the message CurrentY &gt; 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(&quot;space&quot;, &quot;p&quot;)
	{
		MouseGetPos, X1, Y1
		Sleep, 500
		MouseGetPos, X2, Y2
		
		If (X2 &gt; X1+threshold)
			SendInput, {Right}
			
		If(X2 &lt; X1-threshold)
			SendInput, {Left}

		If(Y2 &gt; Y1+threshold)
			SendInput, {Down}

		If(Y2 &lt; Y1-threshold)
			SendInput, {Up}				
	}
return

EDIT:

Try also this:

#NoEnv
#SingleInstance Force

threshold = 10

space::
	X1 := &quot;&quot;
	Y1 := &quot;&quot;
	while GetKeyState(&quot;space&quot;, &quot;p&quot;)
	{
		X2 := X1
		Y2 := Y1
		MouseGetPos, X1, Y1
		dX := dX = &quot;&quot; ? X1 - X2 : dX + X1 - X2		
		dY := dY = &quot;&quot; ? Y1 - Y2 : dY + Y1 - Y2

		if (dX**2 &gt;= threshold**2)
		{
			SendInput % (dX &gt; 0 ? &quot;{Right}&quot; : &quot;{Left}&quot;)
			dX -= threshold * ((dX &gt; 0) * 2-1)
		}
		
	    if  (dY**2 &gt;= threshold**2)
		{
			SendInput % (dY &gt; 0 ? &quot;{Down}&quot; : &quot;{up}&quot;)
			dY -= threshold * ((dY &gt; 0) * 2-1)
		}
	}
return

huangapple
  • 本文由 发表于 2023年5月24日 22:06:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/76324425.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定