mIRC Home    About    Download    Register    News    Help

Topic Options
#235221 - 30/11/11 12:59 PM Mouse events overhaul
FroggieDaFrog Online
Hoopy frood

Registered: 16/04/10
Posts: 910
Loc: USA
The Suggestion
It seems strange that for every other event, we use the format "on *:....", but with mouse events we have to use a menu definition. This is inconsistent, can be quite confusing, and is quite cumbersome(especially with picture windows) depending on what the user wishes to do. I am of the belief that if it is an event it should use the event syntax, and leave the menu definition syntax for defining menus.

So I now suggest a depreciation of using a menu definition to handle mouse events in exchange for:
Code:
on *:MOUSE:@Win:Event:x[-x2]:y[-y2]:{

  ; This triggers when a specified mouse event occurs within an area
  ;
  ;   @win  - the window inwhich the mouse event is to take place.
  ;
  ;   Event - the mouse event that is to take place. The events being:
  ;     enter     - the mouse entered the specified area
  ;     move      - the mouse moved within the specified area
  ;     sclick    - the left mouse button was pressed
  ;     dclick    - the left mouse button was pressed twice
  ;     rclick    - the right mouse button was pressed
  ;     uclick    - a mouse button was unpressed
  ;     lbclick   - an item in the listbox was selected.(This will trigger reguardless of the specified area)
  ;     drag      - the mouse moved while a mouse button was held
  ;     drop      - the mouse button was released after a drag took place
  ;     wheelup   - the mouse wheel was rotated upward
  ;     wheeldown - the mouse wheel was rotated downward
  ;     leave     - the mouse exited the specified area
  ;       You can specify multiple events by seperating them with a camma. You may specify * for all events
  ;
  ;   x[-x2] - the X range for which the event will trigger. * may be specified for the entire width of the window
  ;   y[-y2] - the Y range for which the event will trigger. * may be specified for the entire heighth of the window
}


With the previously stated format the $mouse identifier should be updated with the following additions:
Code:
$mouse.event   - The mouse event that took place
$mouse.dragx/y - the x,y position relative to the window inwhich the drag and/or drop originated.
$mouse.delta   - the number of units the mouse wheel moved. A negative delta signifies the wheel spun upward.



The Example
From the following example, you can see the required code is simpler and easier to read.

Scenerio: You want to fill a rectangle when the mouse enters it, then revert it's color back to the window background when it leaves while only (re)drawing when and what needs to be.
Code:
alias exp1 {
  window -aBCdfp @Exp1 0 0 250 250
  drawrect @Exp1 1 1 100 100 50 50
  exp1_color
}


;-----------------------;
;--    CURRENT WAY    --;
;--                   --;
menu @exp1 {
  mouse:exp1_color
}
alias exp1_color {
  if ($inrect($mouse.x,$mouse.y,100,100,50,50) != %exp1) {
    set %exp1 $v1
    drawfill @Exp1 $iif($v1,04,$color(background)) 1 125 125
  }
}
on *:CLOSE:@Exp1:unset %exp1


;-------------------------;
;--    SUGGESTED WAY    --;
;--                     --;
on *:MOUSE:@Exp1:Enter,Leave:100-150:100-150:{
  exp1_color
}
alias exp1_color {
  drawfill @Exp1 $iif($inrect($mouse.x,$mouse.y,100,100,50,50),04,$color(background)) 1 125 125
}



The Notes
If two scripted mouse-event-handlers with in the same script match the specific event, only the first within the script will trigger. This is normal mIRC behavior, but thought it should be mentioned
Code:
;If this triggers:
on *:MOUSE:@Win:sclick:1-50:1-50:echo -a $mouse.event on $mouse.win @ $mouse.x $mouse.y

;This will not:
on *:MOUSE:@Win:sclick:1-100:1-100:echo -a $mouse.event on $mouse.win @ $mouse.x $mouse.y


if my suggestion is implemented, the current way to do mouse events should remain viable but it's documentation removed from the helpfile and replaced with documentation of the a fore mentioned. This is to stem the use of the old format.



Comments/Questions/Additions/Flames are all welcome


Edited by FroggieDaFrog (30/11/11 01:12 PM)
_________________________
I am SReject
My Stuff

Top
#235224 - 30/11/11 04:59 PM Re: Mouse events overhaul [Re: FroggieDaFrog]
Wiz126 Offline
Babel fish

Registered: 22/03/10
Posts: 57
I can see where mouse event is useful and the drag and drop would be nice. I don't like the addition of 12 individual events as it is too cumbersome and inconsistent. First of all, I would start by noting that almost every option in the on event idea has a one-to-one corresponding menu option - turning them into individual events would be nothing but cosmetics. You could easily turn it into an event dispatch to perform 90% of what you asked.

Lastly, I think the drag/drop events would be nice as a general event (i.e. can be used with #channels as well, I can see nice application for that), so @win should actually be 'target' in that case.

Here is some basic code: (supports mouse enter, leave, move, drag, drop, click, and double click)

Code:
;        on mouse enter event in @window
;
;    - triggers when the mouse is within a specified square in a custom window
;    - Multiple on mouse_event are allowed by cannot overlap.
;
; Params:
;    - %%window -> @window that triggered the event
;    - %%mouse.x -> mouse current x coordinate
;    - %%mouse.x -> mouse current y coordinate
;
on *:signal:$($mouse_enter(50, 50, 100, 100)):{
  echo -s Mouse is in window %%window within the square area (50, 50) and (150, 150)! $&
    At ( $+ %%mouse.x $+ , %%mouse.y $+ ).
}
on *:signal:$($mouse_enter(200, 200, 100, 100)):{
  echo -s Mouse is in window %%window within the square area (200, 200) and (300, 300)! $&
    At ( $+ %%mouse.x $+ , %%mouse.y $+ ).
}

;        on mouse move event in @window
;
;    - triggers when the mouse moves in a custom window
;
; Params:
;    - %%window -> @window that triggered the event
;    - %%mouse.x -> mouse current x coordinate
;    - %%mouse.x -> mouse current y coordinate
;
on *:signal:mouse,move:{
  echo -s Mouse moved in window %%window at ( $+ %%mouse.x $+ , %%mouse.y $+ ).
}

;        on mouse leave event in @window
;
;    - triggers when the mouse leaves a custom window
;
; Params:
;    - %%window -> @window that triggered the event
;
on *:signal:mouse,leave:{
  echo -s Mouse left window %%window $+ .
}

;        on mouse drag event in @window
;
;    - triggers when the mouse is dragging in a custom window
;
; Params:
;    - %%window -> @window that triggered the event
;    - %%mouse.x -> mouse current x coordinate
;    - %%mouse.x -> mouse current y coordinate
;
on *:signal:mouse,drag:{
  echo -s Mouse is dragging in window %%window at ( $+ %%mouse.x $+ , %%mouse.y $+ ).
}

;        on mouse drop event in @window
;
;    - triggers when a mouse has dropped/done dragging in a custom window
;
; Params:
;    - %%window -> @window that triggered the event
;    - %%mouse.x -> mouse current x coordinate
;    - %%mouse.x -> mouse current y coordinate
;    - %%mouse.origin.x -> mouse drag origin x coordinate
;    - %%mouse.origin.x -> mouse drag origin y coordinate
;
on *:signal:mouse,drop:{
  echo -s Mouse is dropped in window %%window at ( $+ %%mouse.x $+ , %%mouse.y $+ ). $&
    Mouse was dragged from:  ( $+ %%mouse.origin.x $+ , %%mouse.origin.y $+ ).
}

;        on mouse click event in @window
;
;    - triggers when a mouse click occures in a custom window
;
; Params:
;    - %%window -> @window that triggered the event
;    - %%mouse.x -> mouse current x coordinate
;    - %%mouse.x -> mouse current y coordinate
;
on *:signal:mouse,click:{
  echo -s Mouse clicked in window %%window at ( $+ %%mouse.x $+ , %%mouse.y $+ ).
}

;        on mouse double-click event in @window
;
;    - triggers when a double click occures in a custom window
;
; Params:
;    - %%window -> @window that triggered the event
;    - %%mouse.x -> mouse current x coordinate
;    - %%mouse.x -> mouse current y coordinate
;
on *:signal:mouse,dclick:{
  echo -s Mouse double-clicked in window %%window at ( $+ %%mouse.x $+ , %%mouse.y $+ ).
}








/* event dispatcher
*/
menu @* {
  mouse:setcoords | if ($isdragged) .signal -n mouse,drag | else .signal -n mouse,move | .signal -n __enter_event
  sclick:setcoords | .signal -n mouse,click
  dclick:setcoords | .signal -n mouse,dclick
  rclick:setcoords | .signal -n mouse,rclick
  leave:setcoords | .signal -n mouse,leave
}
/*
** set some cross-alias local variables
** This is needed because $mouse.x/y from signal can differ (or not
** exists at all) from the actual window (taken from global pos).
*/
alias setcoords {
  ; mouse x/y
  set -u0 %%mouse.x $mouse.x
  set -u0 %%mouse.y $mouse.y
  ; event/window
  set -u0 %%event $active
  set -u0 %%window $active
}
/*
** check if the mouse is being dragged
*/
alias isdragged {
  if ($mouse.key & 1) {
    .timer $+ %%window -m 0 0 checkdrop $ltimer
    set -u1 %%_x_ $+ %%window $mouse.x
    set -u1 %%_y_ $+ %%window $mouse.y
    return 1
  }
  return 0
}
/*
** check if the mouse is dropped
*/
alias checkdrop {
  if (!$mouse.key) {
    timer $+ $1 off
    set -u0 %%mouse.x $($+(%, %, _x_, $1), 2)
    set -u0 %%mouse.y $($+(%, %, _y_, $1), 2)
    set -u0 %%mouse.origin.x $click($1, $click($1, 0)).x
    set -u0 %%mouse.origin.y $click($1, $click($1, 0)).y
    .signal -n mouse,drop
  }
}
/*
** check if we are within a certain area
*/
alias mouse_enter {
  if ($0 != 4) { echo -sc info * on mouse_enter: syntax error! | halt }
  if ($inrect(%%mouse.x, %%mouse.y, $1, $2, $3, $4)) {
    return __enter_event
  }
  return __enter_nop
}

The example above is very clean (keeps no global variables or data of any kind) and uses a single self-terminating timer per window for the drag/drop event.

Note, my code does not reflect exactly what you want because itís just a simple example. The same thing done using my custom mouse_enter event can be done to another mouse_leave event without much trouble.


Edited by Wiz126 (30/11/11 05:13 PM)

Top
#235225 - 30/11/11 06:28 PM Re: Mouse events overhaul [Re: Wiz126]
FroggieDaFrog Online
Hoopy frood

Registered: 16/04/10
Posts: 910
Loc: USA
No offense, but you have gracefully stepped over the main two reasons I make this suggestion:

1: The current way of doing mouse events is inconsistent with the rest of how mIRC handles events. An event happens in a dialog onDialog is triggered, someone says something in a channel onText is triggered. To me it would only make sense that if the a mouse event occurs, onMouse would be called.

2: Using the current method, checking if a specific mouse event occurred for a specified area is quite cumbersome. Checking if $mouse.key equals a specific value, check if $mouse.x/y are with a specific range, keeping track of where the mouse is and whether or not the mouse moved into, moved while inside, or moved to the outside of the area. My suggested method handles all of this and more with ease


I understand that all but the suggested mousewheel event(which can be done with a dll) can be scripted, but doing so is quite unwieldy compared to what I have purposed.

Purpose you have a @picwin inwhich you want to script a button for that changes color when hovered over, clicked over, or revert back.

The current way:
Code:
menu @Win {
  move:{
    if (mouse isin buttonA) {
      if (mouse button ispressed) {
        if (mouse wasn't in buttonA) || (mousebutton wasn't pressed) {
          draw ButtonA pressed
        }
      }
      elseif (mouse wasn't in buttonA) || (mousebutton was pressed) {
        draw ButtonA hovered
      }
    }
    elseif (mouse wasin ButtonA) {
      draw ButtonA as normal 
    }
  }
  sclick:{
    if (mouse isin ButtonA) {
      draw ButtonA pressed
    }
  }
  uclick:{
    if (mouse isin ButtonA) {
      draw ButtonA Hover
    }
  }
}


The purposed way:
Code:
on *:MOUSE:@Win:Enter,SClick,UClick:X-X2:Y-Y2:{
  if (mouse button is pressed) {
    draw ButtonA pressed
  }
  else {
    draw ButtonA hovered
  }
}
on *:MOUSE:@Win:Leave:X-X2:Y-Y2:{
  draw ButtonA Normal
}


Edited by FroggieDaFrog (30/11/11 06:33 PM)
_________________________
I am SReject
My Stuff

Top
#235227 - 30/11/11 11:14 PM Re: Mouse events overhaul [Re: FroggieDaFrog]
argv0 Offline
Planetary brain

Registered: 13/10/03
Posts: 3918
Loc: Montreal, QC, Canada
Personally I'm dubious about the addition of the hardcoded x/y coords in an event like this. I can only imagine a few very simplistic scenarios where these values would be useful to a script. Most scripts will quickly outgrow hardcoded values and require dynamic hitbox testing-- specifically, any window that supported resizing would not benefit from hardcoded x/y values. I think depending on $inrect inside of a mouse event makes much more sense than providing two extra parameters that most users won't use.

You say that adding the x/y makes it easier, but again, only for your simplified example. By using pseudocode for your example, you make it seem like your checks for "if mouse isin buttonA" is a simple hardcoded check, but in most cases it is not. You will more often than not see something like

Code:
if ($inrect($mouse.x,$mouse.y,$calc($window(@win).w - 200), 10, $calc($window(@win).w - 20), 20)) ..... 


As another example, if I were using a @window to draw the equivalent of a channel window (with buffer, nicklist and editbox areas), hardcoding x/y would not be possible. And this is a very simple custom window drawing exercise. The other examples I can think of are games, where hitbox testing are very much dependent on game state, not hardcoded values.

So I would suggest dropping the x/y params. But then you're just left with:

Code:
on *:MOUSE:@win:move:...


As opposed to:

Code:
menu @win {
  move:...
}


Which seems like a shallow aesthetic change. Yes, I agree that, syntactically speaking, mouse events are inconsistent with other events-- but only syntactically. You can view the menu definitions as just another way to write an event. Conceptually, they are the same as other events. The two samples I showed above are completely equivalent. The difference really is just syntax. And I personally don't see aesthetics as a reason in itself to deprecate over a decade of code.
_________________________
- argv[0] on EFnet #mIRC
- "Life is a pointer to an integer without a cast"

Top
#235230 - 01/12/11 11:55 AM Re: Mouse events overhaul [Re: argv0]
hixxy Offline
Hoopy frood

Registered: 06/09/05
Posts: 2876
I love the idea of mouse events being events rather than menu definitions, but I'm not keen on the idea of putting coordinates in the event definition itself.

The event definition should just contain the target and the type of event, eg:

On *:mouse:@win:move:{

}

Then you can carry on using $inrect etc as we do now. Would make existing code easier to copy/paste over to the new style too.

Nice idea.

Edit:

Sorry should've replied to the op.


Edited by hixxy (01/12/11 11:57 AM)

Top
#235232 - 01/12/11 01:38 PM Re: Mouse events overhaul [Re: hixxy]
Riamus2 Offline
Planetary brain

Registered: 13/10/04
Posts: 8327
Loc: MA, USA
Agreed. The point of this feature suggestion is to make it more like the existing syntax for other events. Coordinates are not part of other events, so including them here doesn't do what the OP was wanting. The event should be done as hixxy showed. Everything else should be in the event, just like with any other kind of event.

I'm all for changing the unusual events to work like the rest of the events. Mouse and CTCP are two of these that really would be nice to see changed.
_________________________
Invision Support
#Invision on irc.irchighway.net

Top
#235235 - 01/12/11 02:57 PM Re: Mouse events overhaul [Re: Riamus2]
hixxy Offline
Hoopy frood

Registered: 06/09/05
Posts: 2876
Agreed, and dcc events.

Top