A quick & dirty guide on how to manage interactive display windows in G'MIC

There is not something like ‘scroll event’.
Events you can detect is key press, mouse button press, mouse button motion.
Even if you need a drag&drop, you have to code it by yourself, by :

  • Detecting mouse button press event.
  • Storing the location of the pointer as $x0,$y0
  • Detecting mouse button release event.
  • Get the new location as $x1,$y1
  • Then, do something with your $x0,$y0,$x1,$y1.

That’s really ‘low-level’ programming. It’s still possible to manage user interactions, but things are usually easier to code with a real GUI library.

@David_Tschumperle

A sneak peak of what I’m doing.

foo:
rm
tile_size=32

gw=512
gh=512

nw={floor($gw/$tile_size)*$tile_size}
nh={floor($gh/$tile_size)*$tile_size}

$gw,$gh,1,4,((x%$tile_size==0)||(y%$tile_size==0))||(x==(w-1)||y==(h-1))?1

n 0,255

i $1

l.
    xr={ceil(w#-1/(16*$tile_size))}
    yr={ceil(h#-1/(16*$tile_size))}
    split_tiles. {-16*$tile_size}
    mw=${-max_w}
    mh=${-max_h}
    ti=$!
endl

$tile_size,$tile_size,1,4,0

w[0] {w#0},{h#0},0,"Grid"
w1[1] {w#1},{h#1},0,"Tileset"
w2[-1] {w#-1*2},{h#-1*2},0,"Tile"

ci=0
lr=0
tb=0
tbc=0
ni=1

do
    x,y,b,ww,wh={*,x,y,b,w,h}
    x1,y1,b1,ww1,wh1={*1,x,y,b,w,h}
    
    if {*1,ARROWRIGHT}
        lr+=1
        lr={$lr%$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        w1[$ni]
    elif {*1,ARROWLEFT}
        lr-=1
        lr={$lr%$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        w1[$ni]
    elif {*1,ARROWDOWN}
        tbc+=1
        tbc={$tbc%$yr}
        tb={$tbc*$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        w1[$ni]
    elif {*1,ARROWUP}
        tbc-=1
        tbc={$tbc%$yr}
        tb={$tbc*$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        w1[$ni]
    fi
    if $b1" && "$x1>=0" && "$y1>=0
        f. i(#$ni,floor($x1/$tile_size)*$tile_size+x,floor($y1/$tile_size)*$tile_size+y,z,c)
        w2[-1]
    fi
    if $b" &&"$x>=0" && "$y>=0
        sh. 3
        j[0] [-2],{floor($x/$tile_size)*$tile_size},{floor($y/$tile_size)*$tile_size},0,0,1,[-1],255
        rm.
        w[0]
    fi
    wait
while {*}" && "!{*,ESC}
4 Likes

Makings of an RPG or rogue-like. :slight_smile::+1:
repeat
You wake up; slime attacks you for 10 points; you die.
done

1 Like

@David_Tschumperle Question, can window command be modified to have the option to inherently display alpha background as a option? The reason I’m asking is that it would be a lot of work just to enable alpha background.

Not sure what you are requesting here.
window can only display images with 1,2 or 3 channels. If you need some sort of ‘alpha’ support, then probably drgba could help to convert your RGBA image into a RGB representation to be displayed.

Well, dbrga command alone should make this a lot easier. Thanks though ideally, I would like for something like that to be built-in as a option within window so that less lines would be needed.

Not a good idea IMHO. There are probably thousands ways one wants to manage alpha-channel for a display window, so having an option for that (and for a built-in command as window) could not be “complete”.
Of course, you can always define your own custom_window command that manages the alpha-channel just as you want.

Okay, the more I work on the tile mini-program. I did found out that {,e} makes the command switch mode. So, I have to ask you what keys are not available in use for {,?}? I used {*,s} and the mode flickering is gone.

So you mean {*,S} ?
Testing a key is always done with a syntax involving a capital letter.

There’s another thing I might make with more knowledge on interactive filter scripting. I think I can actually theoretically make a MS Paint clone or something like amiga painting softwares. In fact, it would be exciting to make such a entire program with gmic scripting.

A bit like command x_paint ? :stuck_out_tongue:

Yes. But more on the direction of Grafx2 with a more modern interface.

@David_Tschumperle How to hide windows at a code level? After fixing bugs, I realized I wanted to create two different mode of operations. One mode should only have one window.

w[] 0
(or w0[] 0, etc…).

1 Like

If you went in the direction of Mario Gmicky Paint, that would be something. Would elevate G’MIC to another level.

It definitely would. Now to come to think of it, it’s actually easier to make than the interactive RPG tiling tool I’m working on. That one is exhausting.

1 Like

I think I want to leave a tip. For interactive window project. It’s great to use command or m to create functions. It makes work a lot easier to understand.

For example from snippets (This code doesn’t work, but they’re part of a working code I’m working on now):

if narg($7)||narg($8)||narg($9)
    if narg($7) __r_col={min(abs($7),255)} else __r_col=0 fi
    if narg($8) __g_col={min(abs($8),255)} else __g_col=0 fi
    if narg($9) __b_col={min(abs($9),255)} else __b_col=0 fi

    m "xalp : drgba $__r_col,$__g_col,$__b_col"
else
    m "xalp : drgba"
fi

m "out2display : skip ${""2=},${""3=},${""4=1},${""5=1},${""6=},${""7=} if $""1 $__bg rv blend alpha fi xalp if narg($""6)||narg($""7) if narg($""2)&&narg($""3)&&narg($""4)&&narg($""5) f. begin(xc=$""2;yc=$""3;tw=$""4;th=$""5;psx=floor(xc/tw)*$2;psy=floor(yc/$2)*$2;border=2;border_left=psx+border;border_right=psx+$2-border;border_up=psy+border;border_down=psy+$2-border;boundx=psx+$2;boundy=psy+$2;);if(narg($""6),tracker=(x>psx&&x<boundx)&&(y>psy&&y<boundy)?((x<=border_left||x>=border_right)||(y<=border_up||y>=border_down)?$""6:i):i;,tracker=i;);grid=!(((x%$2)==0||(y%$2)==0)||(x==(w-1)||y==(h-1)))?tracker:(narg($""7)?$""7:i); fi fi"

m "pass2tile : pass$""1 f[0] i(#-1,$""2+x,$""3+y) rm."

    if $b1" && "$x1>=0" && "$y1>=0" && "$x1<w#1" && "$y1<h#1
        select_from_tileset=1
        tsx={floor($x1/$min_tile)*$min_tile} tsy={floor($y1/$min_tile)*$min_tile}
        pass2tile[-1] [1],$tsx,$tsy
        +out2display. 0
        w2[-1] 
        rm.
        
        if $tileset_gridmode
            +out2display[$ni] $tileset_background,$tsx,$tsy,$tile_width,$tile_height,$trackpadcol,$gridcol
        else
            +out2display[$ni] $tileset_background,$tsx,$tsy,$tile_width,$tile_height,$trackpadcol
        fi
        w1[-1]
        rm.
        
        wait 400

    fi

Note how the out2display is quite long. Now, imagine what I had to do without using command and debugging it. Quite painful, right?

This windowing business requires many lines of code (just look at David’s code in stdlib – wow), so breaking it down into manageable chunks is wise.

command used in this way is equivalent to a macro function in the math interpreter. I haven’t done this because I tend to make standalone commands that can be accessed everywhere.

@David_Tschumperle is there a simple way to check for an event such as “the mouse has moved over the display”?

Must we compare window coordinates to do that?

This code demonstrates that a move event is indeed generated:
gmic run "400,400 w0 do v + e {u(1)} v - wait while {*}&&\!{*,ESC}"

Not directly, you have to store old mouse coordinates and compare with the current to check the mouse has moved.