Jump to content


Photo

MGR v0.9.5


  • Please log in to reply
204 replies to this topic

#1 R3gX

R3gX
  • Members
  • 307 posts

Posted 08 May 2011 - 08:01 PM

Hi everyone!

Description :

MGR is a simple set of functions that helps you to use mouse, rocker, wheel and shake gestures.
I made it to be simple to use.

 

How to use :

• Mouse gestures

- Press the RButton

- Move the mouse in random directions
(A tooltip should display the command)

• Rocker gestures : ​LButton&RButton or RButton&LButton

• Wheel gestures : RButton&WheelUp or RButton&WheelDown

• Shake gestures 

- HShake : Horizontal Shake gesture (L-R-L, R-L-R, L-R-L-R...)

- VShake : Vertical Shake gesture (U-D-U, D-U-D, U-D-U-D...)

- DShake : Diagonal Shake gesture (UR-DL-UR, DR-UL-DR...)

Help about the configuration file will come later!

 

License :
Use in source, library and binary form is permitted.
Redistribution and modification must meet the following conditions:
- My nickname (R3gX) and the origin (link) must be reproduced by binaries, or attached in the documentation.
- If changes are made to my work, you are encouraged (yet not obliged) to post the changes for others to view, on the Autohotkey forum.
ALL MY SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESSED OR IMPLIED WARRANTIES
.


Thanks to :

- Carrozza, sumon & tsenlaw for their comments

- mright for his ideas and his work

 

Download (GitHub) https://github.com/R3gX/MGR
 

Change log :

v0.9.5 (09/May/2013)

- Fixed some bugs

- Modified : rocker & wheel gesture syntax XX & XX >> XX-XX (RB & LB >> RB-LB , RB & WU >> RB-WU...)

- Important modifications on 'gestures.ini'.

• The 'Global' section is now renamed in 'Default'.

This means that if a gesture is not set for the active application but is set in the 'Default' section,

the triggered command will be the command set in the 'Default' section.

If you don't want default gestures, simply delete the 'Default' section.

• A new section was added : 'Master'. This section has the priority over all others sections.

 

Here is a summary of priorities* for the sections : Master > Process:Title > Process:Class > Process > Default

For the gestures : Gesture@Area > Gesture

* :    > means 'has priority over'

 

Spoiler


Edited by R3gX, 10 May 2013 - 02:26 PM.


#2 Carrozza

Carrozza
  • Members
  • 200 posts

Posted 09 May 2011 - 06:35 AM

Well, another COOOL projects by R3gX!!! :D

Was FF5 so bad that you had to run out of the cinema back into coding stuff? Eheheh! :-p

Now to the coolness... I just tried it for a minute moving the mouse around like crazy and the recognization engine performs really well. It didn't miss a movement, actually (if it was long enough to be detected), and I like a lot the ability to use diagonal gestures in addition to the common perpendicular ones.

What's missing to move on to production environment:
1) timeout or "ESC" key to cancel wrong gestures;
2) the good old "right-button-still" action to launch task changer;
3) ...a real-world example with at least two actions, to better understand how add features.

Optional:
a) as the engine will be proved accurate I would get rid of the tooltip, as it just flickers around the screen messing the view;
B) ability to disable keyboard modifiers; with the endless combinations of eight directions I find it overwhelming to add also those, and I'm sure each GetKeyState request eats its slice of processing power.

I'm all for scripts with clean and efficient code.

Congratulations, way to go R3gX!!!

#3 R3gX

R3gX
  • Members
  • 307 posts

Posted 09 May 2011 - 09:34 AM

@Carrozza :

Well, another COOOL projects by R3gX!!!

It's not really a project, it's more a kind of library or an addon. You can use it (or not) within an existing script. This is a simple way to use mouse gestures that I wanted to share. Over time, I realize that mouse gestures with RingMenu are not natural. The advantage with this (new?) method is that you can do a mouse gesture with varying amplitude.

Was FF5 so bad that you had to run out of the cinema back into coding stuff? Eheheh! :-p

IMO, FF5 is a good movie. There is action, good music, beautiful cars and ...beautiful women! The scenario is not so bad. It's just a kind of movie where you have to put your brain at the entrance of the cinema, that's all!

What's missing to move on to production environment:

1) During the night, I deleted the MButton hotkey to cancel a mouse gesture. If you want to cancel a mouse gesture, add some random movements and the script won't retrieve the associated command, so the gesture will be cancelled.
2) MG_R is not a complete script, it's more like a library. (In RingMenu I gave you a way to have this feature.)
3) OK! I will add them with the new version.

Optional:

a) & B) : See 2)

I'm all for scripts with clean and efficient code.

Me too! That's why I've done this lib. For the same reason, maybe the RingMenu project will be stopped!

Congratulations, way to go R3gX!!!

Thank you!

#4 Carrozza

Carrozza
  • Members
  • 200 posts

Posted 09 May 2011 - 09:52 AM

I'm also thinking that RingMenu and CoolGestures are overlapping.

Still have to make some tests, but for now if I had to choose I'd prefer the latter because it looks much tighter.

Will try out it extensively and report back soon.

Cheers!

#5 R3gX

R3gX
  • Members
  • 307 posts

Posted 09 May 2011 - 10:45 AM

@Carrozza :

CoolGestures

:?:

#6 Carrozza

Carrozza
  • Members
  • 200 posts

Posted 09 May 2011 - 11:17 AM

Well, it was an implicit suggestion. :lol:

You wouldn't call it "YAMGS" or something like that, would you?

* Yet Another Mouse Gesture Script

#7 R3gX

R3gX
  • Members
  • 307 posts

Posted 09 May 2011 - 12:09 PM

LOL :D
I thought you wanted to talk about another mouse gestures application on the forum!
I admit I searched if the name YAMGA(1) wasn't already taken. But as it is a library instead of a full script, I think I will keep the name MG_R(2). I don't know!

(1) Yet Another Mouse Gesture Application
(2) Mouse Gesture Recognizer


#8 Carrozza

Carrozza
  • Members
  • 200 posts

Posted 09 May 2011 - 02:38 PM

Mate, let me say that "MG_R by R3gX" doesn't sound sexy, no offence intended. :wink:

On the other hand I can understand that a man with your beautiful tight coding skills would love achronyms. If it's coherent and streamlined is OK.

Eheheh, please keep it up because I'm very interested!
Cheers!

#9 R3gX

R3gX
  • Members
  • 307 posts

Posted 09 May 2011 - 05:33 PM

@Carrozza :

Mate, let me say that "MG_R by R3gX" doesn't sound sexy, no offence intended.

You're absolutly right! My nickname itself is not sexy! Sorry if it doesn't sound italian (the language of love)! LOL

a man with your beautiful tight coding skills

It's so nice that it sounds fake!

Eheheh, please keep it up because I'm very interested!

I'll keep it as long as I don't have a better code!

#10 R3gX

R3gX
  • Members
  • 307 posts

Posted 10 May 2011 - 04:38 PM

New version : v0.2

I added a function to evaluate your ability, changed the way to display both gestures and commands.

#11 Carrozza

Carrozza
  • Members
  • 200 posts

Posted 11 May 2011 - 09:30 PM

Hello R3gX, after playing a bit with this new script I'm very happy.

The mouse gesture detection works perfectly, really.
Never missed one, always detected the correct sequence of movements.
As a side note, I messed up a little with the code and now I have this issue: if I perform a tiny movement like 3-4 pixels the gesture code is triggered, without being fed with direction tags (the letters U D L R).

About the GUI, well, I simply don't like it because I find it too intrusive.
That squarish words feel very DOS like, and that's not what I expect from a program in 2011.
I tried to remove GUI instructions from the script, and I guess it was successful.

My suggestion is - when a gesture is detected - just display a tooltip telling which command is being performed. Let it last one second and disappear, that's all.

Another thing I would change is the external file commands.ini; I think it could be integrated inside the main script, maybe just creating a commented caption to separate the section from others.

This is the stripped down version I just tested, mainly to understand how MGR works. Lacking all actual commands and actions right now...

AutoHotkey.ahk
;
; Begin auto-execute section
;

#Include %A_ScriptDir%\MGR.ahk
SetBatchLines, -1

#SingleInstance force
#NoEnv
SetTitleMatchMode, RegEx
CoordMode, Mouse, Screen
Process, Priority, , H
SendMode Input

SetTimer, RepeatingActions, 500

Return

;
; End auto-execute section
;


;======================================
;  R E P E A T I N G    A C T I O N S
;======================================

RepeatingActions:

   WinSet, Style, -0xC40000, ahk_class TTOTAL_CMD
   WinMove, ahk_class TTOTAL_CMD,,0,0,1535,900

   WinSet, Style, -0xC40000, ahk_class NOTES
   WinMove, ahk_class NOTES,,0,0,1535,900

   WinSet, Style, -0xC40000, ahk_class SAP_FRONTEND_SESSION
   WinMove, ahk_class SAP_FRONTEND_SESSION,,0,0,1535,900

   WinSet, Style, -0xC40000, ahk_class XmainClass
   WinMove, ahk_class XmainClass,,0,0,1535,900

   WinSet, Style, -0xC40000, ahk_class QWidget
   WinMove, ahk_class QWidget,,0,0,1535,900

   WinSet, Style, -0xC40000, ahk_class MRCC_Class
   WinMove, ahk_class MRCC_Class,,0,0,1535,900

   WinSet, Style, -0xC40000, ahk_class XTPMainFrame
   WinMove, ahk_class XTPMainFrame,,0,0,1535,900

   WinSet, Style, -0xC00000, ahk_class DSUI:PDFXCViewer

   WinSet, Style, -0xC00000, ahk_class Photo_Lightweight_Viewer

   WinSet, AlwaysOnTop, On, ahk_class CalcFrame


return


;=====================================
;  M O U S E    W H E E L    M O D S
;=====================================

WheelLeft::
   Send ^+{Tab}
return

WheelRight::
   Send ^{Tab}
return

~MButton::
   If (A_PriorHotkey = A_ThisHotkey AND A_TimeSincePriorHotkey < 400)
      WinClose A
Return


;====================================================
;  R I G H T    M O U S E    B U T T O N    M O D S
;====================================================

*RButton::
   MouseGetPos, mX1, mY1
   Loop
      {
      Sleep, 10
      MouseGetPos, mX2, mY2
      }
   Until (!GetKeyState("RButton", "P") || Abs(mX2-mX1)>3 || Abs(mY2-mY1)>3 || (A_TimeSinceThisHotkey > 350))
   if A_TimeSinceThisHotkey > 350
      {
      MouseMove, 650, 514
      Send ^!{Tab}
      KeyWait, RButton
      Send, {LButton}
      Return
      }
   If (Abs(mX2-mX1)<4 && Abs(mY2-mY1)<4)
      {
      Send, {RButton}
      Return
      }
   Else
      {
      Gesture := mgr_MonitorGesture()
      MsgBox,,,Gesture = %gesture%,1
      }
Return


;==================================
;  F U L L S C R E E N    M O D E
;==================================

^+F11:: ; Trigger is CTRL+SHIFT+F11

   WinSet, Style, -0xC40000, A
   WinMove, A,,0,0,1535,900

return


;================================
;  P R E C I S I O N    M O D E
;================================

;
; Activation keeping CapsLock pressed with left hand
;

CapsLock::
   Keywait, CapsLock, T0.75
   if ErrorLevel
      {
      DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 1, UInt, 0)
      Send #{NumpadAdd}
      KeyWait, CapsLock
      DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 15, UInt, 0)
      WinClose, ahk_class MagUIClass
      }
   else
      {
      SetCapsLockstate,% GetKeyState("CapsLock","T") ? "Off":"On"
      KeyWait, CapsLock
      }
Return

;
; Activation keeping ScrollLock pressed with right hand
;

ScrollLock::
   Keywait, ScrollLock, T0.75
   if ErrorLevel
      {
      DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 1, UInt, 0)
      Send #{NumpadAdd}
      KeyWait, ScrollLock
      DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 15, UInt, 0)
      WinClose, ahk_class MagUIClass
      }
   else
      {
      SetScrollLockState,% GetKeyState("ScrollLock","T") ? "Off":"On"
      KeyWait, ScrollLock
      }
Return


;============================================
;  A P P L I C A T I O N    S P E C I F I C
;============================================

;
; MOZILLA FIREFOX
;

#IfWinActive Google Reader
   PgDn::
      Send +{n}
      Send +{o}
   Return

   PgUp::
      Send +{p}
      Send +{o}
   Return
#IfWinActive

#IfWinActive ahk_class MozillaWindowClass
   Control::
      If (A_PriorHotkey = A_ThisHotkey AND A_TimeSincePriorHotkey < 350)
         Send ^{Tab}
   Return

   Shift::
      If (A_PriorHotkey = A_ThisHotkey AND A_TimeSincePriorHotkey < 350)
         Send ^+{Tab}
   Return

   ~MButton::
      If (A_PriorHotkey = A_ThisHotkey AND A_TimeSincePriorHotkey < 400)
         Send, ^w
   Return

#IfWinActive

;
; MICROSOFT PICTURE VIEWER
;

#IfWinActive ahk_class Photo_Lightweight_Viewer
   PgDn::
   WheelDown::
#IfWinActive ahk_class Photo_Slideshow_FrameWindow
   PgDn::
   WheelDown::
      Send {Right}
   Return

#IfWinActive ahk_class Photo_Lightweight_Viewer
   PgUp::
   WheelUp::
#IfWinActive ahk_class Photo_Slideshow_FrameWindow
   PgUp::
   WheelUp::
      Send {Left}
   Return

#IfWinActive ahk_class Photo_Lightweight_Viewer
   Esc::
#IfWinActive ahk_class Photo_Slideshow_FrameWindow
   Esc::
      Send !{F4}
   Return
#IfWinActive

MGR.ahk
mgr_GetModifiers()
{ ; Simple way to get hotkey modifiers
	Modifiers := ""
	Modifiers .= GetKeyState("Ctrl",		"P") ? "^" : ""
	Modifiers .= GetKeyState("Alt",		"P") ? "!" : ""
	Modifiers .= GetKeyState("Shift",	"P") ? "+" : ""
	Modifiers .= GetKeyState("LWin",		"P") ? "#" : ""
	Return, Modifiers
}

mgr_MonitorGesture()
{ ; Monitor the mouse directions to get the gesture
	While GetKeyState("RButton", "P")
	{
		MouseGetPos, x1, y1
		While GetKeyState("RButton", "P")
		{
			Sleep, 10
			MouseGetPos, x2, y2
			Module := Sqrt((x2-x1)**2+(y2-y1)**2)
			If (Module>=25)	; A minimal movement is needed
			{
				Direction := mgr_GetDirection(x2-x1, y2-y1)
				If (Direction && LastDirection && Direction<>LastDirection)	; If the direction has changed,
					Break																													;		get the next direction
				x1 := x2 , y1 := y2
			}
			LastDirection := Direction	; Usefull to know if the direction has changed
		}
		Directions .= "-" LastDirection ; Add the last movement to have a complete gesture
		LastDirection := Direction := ""
	}
	Directions .= Direction
	Return, mgr_RemoveDups(Directions, "-")
}

mgr_GetDirection(X_Offset, Y_Offset)
{ ; Get the direction of the mouse movement depending on polar coordinates
	Directions	:= 8
	Deg					:= (360/Directions)																	; Degree value that "cuts" RingMenu in equal slices
	Module			:= Sqrt((X_Offset**2)+(Y_Offset**2))							; Distance between the center and the mouse cursor
	Argument		:= ACos(X_Offset/Module)*(180/(4*ATan(1)))			; Angle between the mouse and the X-axis from the center
	Argument		:= (Y_Offset<0 ? 360-Argument : Argument)						; (Screen Y-axis is inverted)
	Argument		-= Mod(Directions, 2) ? 0 : Deg/2										; Allows vertical/horizontal movement from the first slice
	Direction		:= Directions-Mod(Floor(Argument/Deg), Directions)	; Converts the argument into a slice number
	Direction		:= Direction>Directions ? 1 : Direction
	Direction		:=	Direction=1	? "R"
							:		Direction=2	? "UR"
							:		Direction=3	? "U"
							:		Direction=4	? "UL"
							:		Direction=5	? "L"
							:		Direction=6	? "DL"
							:		Direction=7	? "D"
							:		Direction=8	? "DR"
							:		""
	Return, Direction
}

mgr_RemoveDups(list1, separator="")
{	; Remove duplicated follwing values
	Loop, Parse, list1, % separator
	{
		list2 .= (A_LoopField<>Last_LoopField) ? separator A_LoopField : ""
		Last_LoopField := A_LoopField
	}
	Return % Trim(list2, separator)
}


#12 Carrozza

Carrozza
  • Members
  • 200 posts

Posted 12 May 2011 - 07:38 AM

I'm keeping on with gesture detection tests, using just MsgBox, I can definitely say that this script doesn't miss a shot!

Now, before starting the real customization adding some actions, I'd love to hear from the father if I did the right changes to remove the UI, or if I left something behind.

Here is the scripts combination I'm using right now: pretty stable and performing well in my opinion.

AutoHotkey.ahk
;
; Begin auto-execute section
;

#Include %A_ScriptDir%\MGR.ahk
SetBatchLines, -1

#SingleInstance force
#NoEnv
SetTitleMatchMode, RegEx
CoordMode, Mouse, Screen
Process, Priority, , H
SendMode Input

SetTimer, RepeatingActions, 500

Return

;
; End auto-execute section
;


;======================================
;  R E P E A T I N G    A C T I O N S
;======================================

RepeatingActions:

   WinSet, Style, -0xC40000, ahk_class TTOTAL_CMD
   WinMove, ahk_class TTOTAL_CMD,,0,0,1535,900

   WinSet, Style, -0xC40000, ahk_class NOTES
   WinMove, ahk_class NOTES,,0,0,1535,900

   WinSet, Style, -0xC40000, ahk_class SAP_FRONTEND_SESSION
   WinMove, ahk_class SAP_FRONTEND_SESSION,,0,0,1535,900

   WinSet, Style, -0xC40000, ahk_class XmainClass
   WinMove, ahk_class XmainClass,,0,0,1535,900

   WinSet, Style, -0xC40000, ahk_class QWidget
   WinMove, ahk_class QWidget,,0,0,1535,900

   WinSet, Style, -0xC40000, ahk_class MRCC_Class
   WinMove, ahk_class MRCC_Class,,0,0,1535,900

   WinSet, Style, -0xC40000, ahk_class XTPMainFrame
   WinMove, ahk_class XTPMainFrame,,0,0,1535,900

   WinSet, Style, -0xC00000, ahk_class DSUI:PDFXCViewer

   WinSet, Style, -0xC00000, ahk_class Photo_Lightweight_Viewer

   WinSet, AlwaysOnTop, On, ahk_class CalcFrame

return


;=====================================
;  M O U S E    W H E E L    M O D S
;=====================================

WheelLeft::
   Send ^+{Tab}
return

WheelRight::
   Send ^{Tab}
return

~MButton::
   MouseGetPos, mX1, mY1
   While GetKeyState("MButton", "P")
      {
      Sleep, 10
      MouseGetPos, mX2, mY2
      If (Abs(mx2-mx1) || Abs(my2-my1))
         Return
      If A_TimeSinceThisHotkey > 500
         {
         IfWinActive ahk_class MozillaWindowClass
            {
            Send, ^w
            Sleep, 750
            }
         Else
            {
            WinClose A
            Sleep, 750
            }
         }
      }
Return


;====================================================
;  R I G H T    M O U S E    B U T T O N    M O D S
;====================================================

*RButton::
   MouseGetPos, mX1, mY1
   Loop
      {
      Sleep, 10
      MouseGetPos, mX2, mY2
      }
   Until (!GetKeyState("RButton", "P") || Abs(mX2-mX1)>3 || Abs(mY2-mY1)>3 || (A_TimeSinceThisHotkey > 350))
   if A_TimeSinceThisHotkey > 350
      {
      MouseMove, 650, 514
      Send ^!{Tab}
      KeyWait, RButton
      Send, {LButton}
      Return
      }
   If (Abs(mX2-mX1)<4 && Abs(mY2-mY1)<4)
      {
      Send, {RButton}
      Return
      }
   Else
      {
      Gesture := mgr_MonitorGesture()
      MsgBox,,,Gesture = %gesture%,1
      }
Return


;==================================
;  F U L L S C R E E N    M O D E
;==================================

^+F11:: ; Trigger is CTRL+SHIFT+F11

   WinSet, Style, -0xC40000, A
   WinMove, A,,0,0,1535,900

return


;================================
;  P R E C I S I O N    M O D E
;================================

;
; Activation keeping CapsLock pressed with left hand
;

CapsLock::
   Keywait, CapsLock, T0.75
   if ErrorLevel
      {
      DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 1, UInt, 0)
      Send #{NumpadAdd}
      KeyWait, CapsLock
      DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 15, UInt, 0)
      WinClose, ahk_class MagUIClass
      }
   else
      {
      SetCapsLockstate,% GetKeyState("CapsLock","T") ? "Off":"On"
      KeyWait, CapsLock
      }
Return

;
; Activation keeping ScrollLock pressed with right hand
;

ScrollLock::
   Keywait, ScrollLock, T0.75
   if ErrorLevel
      {
      DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 1, UInt, 0)
      Send #{NumpadAdd}
      KeyWait, ScrollLock
      DllCall("SystemParametersInfo", UInt, 0x71, UInt, 0, UInt, 15, UInt, 0)
      WinClose, ahk_class MagUIClass
      }
   else
      {
      SetScrollLockState,% GetKeyState("ScrollLock","T") ? "Off":"On"
      KeyWait, ScrollLock
      }
Return


;============================================
;  A P P L I C A T I O N    S P E C I F I C
;============================================

;
; MOZILLA FIREFOX
;

#IfWinActive Google Reader
   PgDn::
      Send +{n}
      Send +{o}
   Return

   PgUp::
      Send +{p}
      Send +{o}
   Return
#IfWinActive

#IfWinActive ahk_class MozillaWindowClass
   Control::
      If (A_PriorHotkey = A_ThisHotkey AND A_TimeSincePriorHotkey < 350)
         Send ^{Tab}
   Return

   Shift::
      If (A_PriorHotkey = A_ThisHotkey AND A_TimeSincePriorHotkey < 350)
         Send ^+{Tab}
   Return

#IfWinActive

;
; MICROSOFT PICTURE VIEWER
;

#IfWinActive ahk_class Photo_Lightweight_Viewer
   PgDn::
   WheelDown::
#IfWinActive ahk_class Photo_Slideshow_FrameWindow
   PgDn::
   WheelDown::
      Send {Right}
   Return

#IfWinActive ahk_class Photo_Lightweight_Viewer
   PgUp::
   WheelUp::
#IfWinActive ahk_class Photo_Slideshow_FrameWindow
   PgUp::
   WheelUp::
      Send {Left}
   Return

#IfWinActive ahk_class Photo_Lightweight_Viewer
   Esc::
#IfWinActive ahk_class Photo_Slideshow_FrameWindow
   Esc::
      Send !{F4}
   Return
#IfWinActive

MGR.AHK
mgr_GetModifiers()
{ ; Simple way to get hotkey modifiers
	Modifiers := ""
	Modifiers .= GetKeyState("Ctrl",		"P") ? "^" : ""
	Modifiers .= GetKeyState("Alt",		"P") ? "!" : ""
	Modifiers .= GetKeyState("Shift",	"P") ? "+" : ""
	Modifiers .= GetKeyState("LWin",		"P") ? "#" : ""
	Return, Modifiers
}

mgr_MonitorGesture()
{ ; Monitor the mouse directions to get the gesture
	While GetKeyState("RButton", "P")
	{
		MouseGetPos, x1, y1
		While GetKeyState("RButton", "P")
		{
			Sleep, 10
			MouseGetPos, x2, y2
			Module := Sqrt((x2-x1)**2+(y2-y1)**2)
			If (Module>=25)	; A minimal movement is needed
			{
				Direction := mgr_GetDirection(x2-x1, y2-y1)
				If (Direction && LastDirection && Direction<>LastDirection)	; If the direction has changed,
					Break																													;		get the next direction
				x1 := x2 , y1 := y2
			}
			LastDirection := Direction	; Usefull to know if the direction has changed
		}
		Directions .= "-" LastDirection ; Add the last movement to have a complete gesture
		LastDirection := Direction := ""
	}
	Directions .= Direction
	Return, mgr_RemoveDups(Directions, "-")
}

mgr_GetDirection(X_Offset, Y_Offset)
{ ; Get the direction of the mouse movement depending on polar coordinates
	Directions	:= 8
	Deg					:= (360/Directions)																	; Degree value that "cuts" RingMenu in equal slices
	Module			:= Sqrt((X_Offset**2)+(Y_Offset**2))							; Distance between the center and the mouse cursor
	Argument		:= ACos(X_Offset/Module)*(180/(4*ATan(1)))			; Angle between the mouse and the X-axis from the center
	Argument		:= (Y_Offset<0 ? 360-Argument : Argument)						; (Screen Y-axis is inverted)
	Argument		-= Mod(Directions, 2) ? 0 : Deg/2										; Allows vertical/horizontal movement from the first slice
	Direction		:= Directions-Mod(Floor(Argument/Deg), Directions)	; Converts the argument into a slice number
	Direction		:= Direction>Directions ? 1 : Direction
	Direction		:=	Direction=1	? "R"
							:		Direction=2	? "UR"
							:		Direction=3	? "U"
							:		Direction=4	? "UL"
							:		Direction=5	? "L"
							:		Direction=6	? "DL"
							:		Direction=7	? "D"
							:		Direction=8	? "DR"
							:		""
	Return, Direction
}

mgr_RemoveDups(list1, separator="")
{	; Remove duplicated follwing values
	Loop, Parse, list1, % separator
	{
		list2 .= (A_LoopField<>Last_LoopField) ? separator A_LoopField : ""
		Last_LoopField := A_LoopField
	}
	Return % Trim(list2, separator)
}

Cheers!

#13 sumon

sumon
  • Moderators
  • 1310 posts

Posted 12 May 2011 - 08:32 AM

Some quick ones:
1) To me, the rightbutton original mouseclick is not left intact - sometimes I get the MGR menu instead, when I just want to mouseclick. It's the same problem I had with RingMenu.

2) The actions aren't really actions right? Because nothing trigger. They're more examples of how to integrate MGR into an existing script, or?

3) Speaking of integration in existing scripts, I would like you to state your claims of licensing for this one. That is, what is required from me to use it in one of my scripts - must I refer to you, if so how, etc. If you want it 100% free, do like Nimda, claim it to be WTFPL (Do what the **** you want, public license). Not that I would step on your toes regardless, but it's just nice knowing beforehand, so I don't forget f.ex. refering to you.

4) Nice job!

#14 Carrozza

Carrozza
  • Members
  • 200 posts

Posted 12 May 2011 - 11:34 AM

Yep, Sumon, that's more or less what I meant with: "...if I perform a tiny movement like 3-4 pixels the gesture code is triggered, without being fed with direction tags (the letters U D L R)."

#15 R3gX

R3gX
  • Members
  • 307 posts

Posted 12 May 2011 - 01:07 PM

@Carrozza :

About the GUI, well, I simply don't like it because I find it too intrusive.
That squarish words feel very DOS like, and that's not what I expect from a program in 2011.

I admit that you're totally right! I'm ok for the Tooltip feature.

Another thing I would change is the external file commands.ini; I think it could be integrated inside the main script, maybe just creating a commented caption to separate the section from others.

IMO, it's not a good thing. I explain, in my case I have about 40 general commands and 20 contextual commands. Too much lines to add! But if you really want this for your script, do it that way :
- Put the commands inside the /* ... */
- Change fCommands := A_ScriptDir "\Commands.ini" by fCommands := A_ScriptFullPath
That's all!

I'm keeping on with gesture detection tests, using just MsgBox, I can definitely say that this script doesn't miss a shot!

Great! I'm happy that the script works well!

Now, before starting the real customization adding some actions, I'd love to hear from the father if I did the right changes to remove the UI, or if I left something behind.

I'll really appreciate if you leave this on the script : :!:
/*
Name		: Mouse Gesture Recognizer v0.2
Author	: R3gX
Link		: http://www.autohotkey.com/forum/viewtopic.php?t=71666
*/
By the way, you've deleted the good lines to remove the GUI feature.

@Carrozza & sumon : For the issue about the RButton actions, here is a solution :
*RButton:: ; * Allows different modifiers
MouseGetPos, mX1, mY1
Loop {
	Sleep, 10
	MouseGetPos, mX2, mY2
} Until (		!GetKeyState("RButton", "P") || Abs(mX2-mX1)>=5 || Abs(mY2-mY1)>=5
					|| (Abs(mX2-mX1)<5 && Abs(mY2-mY1)<5 && A_TimeSinceThisHotkey>=150)  )
If ( Abs(mX2-mX1)<5 && Abs(mY2-mY1)<5 && A_TimeSinceThisHotkey<150 )
	SendInput, % mgr_GetModifiers() "{RButton}"
Else If ( Abs(mX2-mX1)<5 && Abs(mY2-mY1)<5 && A_TimeSinceThisHotkey>=150 )
{
	SendInput, ^!{Tab}
	; ...
	; ...
}
Else 
{
	Gesture := mgr_MonitorGesture()
	;Result := mgr_EvaluateMyGestures(Gesture, "D-DR")
	ToolTip
	; ADD YOUR CODE
}
Return
This part of code is important!
Abs(mX2-mX1)<5 && Abs(mY2-mY1)<5

@sumon :

2) The actions aren't really actions right? Because nothing trigger. They're more examples of how to integrate MGR into an existing script, or?

The given script is a sample to let you know how the script works. That's why I don't gave you a full code. It's more a quick tutorial. BTW, I use the RM_Execute() function (RingMenu) for my script (renamed in mgr_Execute() ).

About the licencing, I don't know anything about it! For all of my scripts, libs or functions posted in "Scripts and functions" I just want that users mention my nickname and the link of the original topic.
If changes are made to my work, I would appreciate they are posted on the AutoHotkey forum.
I really make scripts for pleasure. The only thing that is important to me is the exchange: exchange of opinions, knowledge ...
I do not like to lose my head for protection, laws, lawyers issues! At least not for scripts.