Working on a Tile Placing tool for G'MIC-QT

Since this is going to take a while to develop on. I’m going to share this on a separate thread. This thread is basically going to be about a upgrade to this tool over the Paint.NET forum (see picture below).

Right now, here’s what I have

Features it supports right now:

  • Erasing. If you click on the tile window, Grid Window becomes Grid - Eraser Mode.
  • Placing Tiles.
  • Selection box over tileset. You can see what you selected.
  • Add tile rotation support
  • Backdrop support. While this may erase your image as a whole, it enables users to have different layers making it very useful in conjunction with Krita or GIMP. From those end of things, they support merging layer from the g’mic interface side of thing, so it’s very useful.
  • Selection enlarging/decreasing.

TODO:

  • Grid support for Tileset
  • Release
foo:
tile_size=32
if !$!
    gw=512
    gh=512
    nw={ceil($gw/$tile_size)*$tile_size}
    nh={ceil($gh/$tile_size)*$tile_size}
    $nw,$nh,1,4
    include_image=0
elif $!==1
    gw={w#0}
    gh={h#0}
    nw={ceil($gw/$tile_size)*$tile_size}
    nh={ceil($gh/$tile_size)*$tile_size}
    r $nw,$nh,100%,100%,0,0,.5,.5 to_a
    include_image=1
    +store[0] bg
    f 0
else
    error "Only one or less image is acceptable!"
fi

i $1

echo {s#-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
fti={$!}

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
pb=1

do
    x,y,b,ww,wh={*,x,y,b,w,h}
    x1,y1,b1,ww1,wh1={*1,x,y,b,w,h}
    x2,y2,b2,ww2,wh2={*2,x,y,b,w,h}
    
    if {*1,ARROWRIGHT}
        lr+=1
        lr={$lr%$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        w1[$ni] {w#$ni},{h#$ni}
    elif {*1,ARROWLEFT}
        lr-=1
        lr={$lr%$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        w1[$ni] {w#$ni},{h#$ni}
    elif {*1,ARROWDOWN}
        tbc+=1
        tbc={$tbc%$yr}
        tb={$tbc*$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        w1[$ni] {w#$ni},{h#$ni}
    elif {*1,ARROWUP}
        tbc-=1
        tbc={$tbc%$yr}
        tb={$tbc*$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        w1[$ni] {w#$ni},{h#$ni}
    fi
    if $b1" && "$x1>=0" && "$y1>=0
        pb=0
        f. i(#$ni,floor($x1/$tile_size)*$tile_size+x,floor($y1/$tile_size)*$tile_size+y,z,c)
        w2[-1]
        +f[-1] (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255-i:i
        +j[$ni] [-1],{floor($x1/$tile_size)*$tile_size},{floor($y1/$tile_size)*$tile_size} 
        w1[-1]
        rm[-2,-1]
        w[0] {w#0},{h#0},0,"Grid-Place Tileset"
    fi
    if $b" &&"$x>=0" && "$y>=0
        if !$pb
            sh[-1] {s#-1-1}
            j[0] [-2],{floor($x/$tile_size)*$tile_size},{floor($y/$tile_size)*$tile_size},0,0,1,[-1],255
            rm.
        else
            $tile_size,$tile_size,1,4
            j[0] [-1],{floor($x/$tile_size)*$tile_size},{floor($y/$tile_size)*$tile_size}
            rm.
        fi
        if $include_image
            sh[0] 0,{s#0-2}
            sh[0] {s#0-1}
            $bg
            j[-1] [-3],{floor($x/$tile_size)*$tile_size},{floor($y/$tile_size)*$tile_size},0,0,1,[-2],255
            w[-1]
            rm[-3--1]
        else
            w[0]
        fi
    fi
    if $b2" &&"$x2>=0" && "$y2>=0
        pb=1
        f. 0
        w2[-1]
        w1[$ni]
        w[0] {w#0},{h#0},0,"Grid-Eraser Mode"
    fi
    wait
while {*}" && "!{*,ESC}
k[0]
2 Likes

That’s very ambitious. I’ll follow it with interest :slight_smile:

@afre I don’t want to pester David, so I’m asking you. Why is it nothing is showing up when I try to paint tiles on a empty image? Run $ gmic 512,512,1,4 foo tile.png in cmd, and you’d see what I mean. Then try $ gmic sp dog foo tile.png. You can see that it doesn’t paint on a empty image. But, at least the final [0] image does show tile is being painted on.

foo:
min_tile=32
increment=32
icx=0
icy=0
max_tile=64
max_increment={floor($max_tile/$min_tile)-1}
tile_width=$min_tile
tile_height=$min_tile
twmul=1
mhmul=1

r_col=255
g_col=0
b_col=255

if $!==1
    gw={w#0}
    gh={h#0}
    nw={ceil($gw/$min_tile)*$min_tile}
    nh={ceil($gh/$min_tile)*$min_tile}
    r $nw,$nh,100%,100%,0,0,.5,.5 to_a
    cs={s#-1}
    include_image=1
    +store[0] bg
    +store[0] cbg
    +f ((x%$min_tile)==0||(y%$min_tile)==0)||(x==(w-1)||y==(h-1))?255-i:i
    +store. tbg
    rm.
    f 0
    echo "Creating Image from Tileset!"
else
    error "$!==1=F"
fi

i $1

echo {s#-1}

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

$min_tile,$min_tile,1,4,0
fti={$!}

if $include_image
    $bg
    +drgba. $r_col,$g_col,$b_col
    w[-1] {w#0},{h#0},0,"Canvas"
    rm[-2,-1]
else
    +drgba[0] $r_col,$g_col,$b_col
    w[-1] {w#0},{h#0},0,"Canvas"
    rm.
fi

+drgba[1] $r_col,$g_col,$b_col w1[-1] {w#1},{h#1},0,"Tileset" rm.
w2[-1] 196,196,0,"Tile"

ci=0
lr=0
tb=0
tbc=0
ni=1
erase_mode=1
rotval=0
gridmode=0

selection=0
sx=0
sy=0

activate_edit=0

do
    x,y,b,ww,wh={*,x,y,b,w,h}
    x1,y1,b1,ww1,wh1={*1,x,y,b,w,h}
    x2,y2,b2,ww2,wh2={*2,x,y,b,w,h}
    
    if {*,g} 
        echo "gridmode"
    fi
    
    
    if   {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWLEFT}}" &&"$selection      
        icx-=1
        icx={max($icx,0)}
        tile_width={$min_tile+($icx*$increment)}
        
        f. 0
        r. $tile_width,$tile_height
        f. i(#$ni,$sx+x,$sy+y)
        +drgba. $r_col,$g_col,$b_col
        w2[-1] {($icx+1)*196},{($icy+1)*196},0,"Tile"
        rm.
        +f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255-i:i
        +j[$ni] [-1],$sx,$sy
        drgba. $r_col,$g_col,$b_col
        w1[-1]
        rm[-2,-1]
    elif {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWRIGHT}}" &&"$selection   
        icx+=1
        icx={min($icx,$max_increment)}
        tile_width={$min_tile+($icx*$increment)}

        f. 0
        r. $tile_width,$tile_height
        f. i(#$ni,$sx+x,$sy+y)
        +drgba. $r_col,$g_col,$b_col
        w2[-1] {($icx+1)*196},{($icy+1)*196},0,"Tile"
        rm.
        +f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255-i:i
        +j[$ni] [-1],$sx,$sy
        drgba. $r_col,$g_col,$b_col
        w1[-1]
        rm[-2,-1]
    elif {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWDOWN}}" &&"$selection
        icy+=1
        icy={min($icy,$max_increment)}
        tile_height={$min_tile+($icy*$increment)}

        f. 0
        r. $tile_width,$tile_height
        f. i(#$ni,$sx+x,$sy+y)
        +drgba. $r_col,$g_col,$b_col
        w2[-1] {($icx+1)*196},{($icy+1)*196},0,"Tile"
        rm.
        +f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255-i:i
        +j[$ni] [-1],$sx,$sy
        drgba. $r_col,$g_col,$b_col
        w1[-1]
        rm[-2,-1]
    elif {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWUP}}" &&"$selection
        icy-=1
        icy={max($icy,0)}
        tile_height={$min_tile+($icy*$increment)}
        
        f. 0
        r. $tile_width,$tile_height
        f. i(#$ni,$sx+x,$sy+y)
        +drgba. $r_col,$g_col,$b_col
        w2[-1] {($icx+1)*196},{($icy+1)*196},0,"Tile"
        rm.
        +f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255-i:i
        +j[$ni] [-1],$sx,$sy
        drgba. $r_col,$g_col,$b_col
        w1[-1]
        rm[-2,-1]
    elif {*1,ARROWRIGHT}
        selection=0
        lr+=1
        lr={$lr%$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        +drgba[$ni] $r_col,$g_col,$b_col
        w1[-1] {w#$ni},{h#$ni}
        rm.
    elif {*1,ARROWLEFT}
        selection=0
        lr-=1
        lr={$lr%$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        +drgba[$ni] $r_col,$g_col,$b_col
        w1[-1] {w#$ni},{h#$ni}
        rm.
    elif {*1,ARROWDOWN}
        selection=0
        tbc+=1
        tbc={$tbc%$yr}
        tb={$tbc*$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        +drgba[$ni] $r_col,$g_col,$b_col
        w1[-1] {w#$ni},{h#$ni}
        rm.
    elif {*1,ARROWUP}
        selection=0
        tbc-=1
        tbc={$tbc%$yr}
        tb={$tbc*$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        +drgba[$ni] $r_col,$g_col,$b_col
        w1[-1] {w#$ni},{h#$ni}
        rm.
    fi
    
    if   {*2,ARROWLEFT}
        rotate[-1] -90
        w2[-1]
    elif {*2,ARROWRIGHT}
        rotate[-1] 90
        w2[-1]
    fi
    
    if $b1" && "$x1>=0" && "$y1>=0
        if !$selection selection=1 fi
        if !$activate_edit activate_edit=1 fi
        erase_mode=0
        
        sx={floor($x1/$min_tile)*$min_tile}
        sy={floor($y1/$min_tile)*$min_tile}
        f. i(#$ni,$sx+x,$sy+y,z,c)
        +drgba. $r_col,$g_col,$b_col
        w2[-1] 
        rm.
        
        +f[-1] (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255-i:i
        +j[$ni] [-1],$sx,$sy
        drgba. $r_col,$g_col,$b_col
        w1[-1]
        rm[-2,-1]
        if $gridmode
            w[] {w#0},{h#0},0,"Canvas - Place Tileset (Gridmode ON)"
        else
            w[] {w#0},{h#0},0,"Canvas - Place Tileset"
        fi
    fi
    
    if $b" &&"$x>=0" && "$y>=0
        psx={floor($x/$min_tile)*$min_tile}
        psy={floor($y/$min_tile)*$min_tile}
        sh. 0,{s-2}
        sh.. {s}
        j[0] [-2],$psx,$psy,0,0,1,[-1],255
        $cbg
        j[-1] [-3],$psx,$psy,0,0,1,[-2],255
        +store. cbg
        drgba. $r_col,$g_col,$b_col
        w[-1]
        rm[-3--1]
    fi
    
    if $b2" &&"$x2>=0" && "$y2>=0
        erase_mode=1
        f. 0
        w2[-1]
        +drgba[$ni] $r_col,$g_col,$b_col
        w1[-1]
        rm.
        if $gridmode
            w[] {w#0},{h#0},0,"Canvas - Eraser Mode (Gridmode ON)"
        else
            w[] {w#0},{h#0},0,"Canvas - Eraser Mode"
        fi
    fi
    
    wait
while {*}" && "!{*,ESC}
k[0]
1 Like

Insomnia has given me time. The best way to figure it out is to step through the process methodically and see where it fails to draw the image. It likely has to do with your management of alpha, which to be honest almost no one uses the way you do. Sure enough if I make the sample image rgba, tiles don’t appear on the canvas when drawn.

gmic sp tiger to_rgba foo_r tile.png

I don’t have your tile set, so I retrieved one from https://rpgtileset.com/tileset/ancient-civilization-ruins/. Here is my experience. To begin, here is what I get visually.

Immediately, there are several differences from your screenshot above.

The relative window sizes are different. Could be due to my screen size. With a command like this, controlling and standardizing window size might be important to the user.

Starting with the most obvious, the tile window is much larger than yours. Tileset is smaller than tile.png, which is okay because I can go left, right, up and down; but scrolling by key stroke doesn’t always work as expected and the refresh flickers a lot. The selection box is off in size, aspect ratio and position likely because of your defaults.

Another difference is the alpha only spots are magenta, while yours is white in the tileset window and black in the canvas. As you can see, the magenta also around the tiger: why is there an extra transparent padding around the tiger? It doesn’t seem to belong to the canvas.

One last issue is the final window that pops up. The image has dimensions larger than the input image, which isn’t expected and likely wrong. The tiger is nowhere to be seen and the padding is gone. Only the drawn tiles are there. Early days. :slight_smile:

PS On second thought, the larger dimensions are due to the padding. I guess it has to do with the input image and the tile grid not matching but even so the image should probably be cropped rather than have an odd border around it…

@David_Tschumperle @bazza @afre

I’m on the near-release phase. Right now, I’m working on the GUI side of thing. The CLI side of thing is done though ideally I could have made symmetry mode and row/column shifting mode, but it’s very difficult as it is to work with this code.

#@cli rep_rpgtiler_noniso: { filename | [tile] },min_tile>=3,increment>=0,_tileset_iw_width>=1,_tileset_ih_width>=1,_preserve_bgout={ 0=eliminate_bg | 1=preserve_bg },_drgba_r>=0,_drgba_g>=0,_drgba_b>=0,_gridcol>=0,_trackpadcol>=0 
#@cli : Launch the interactive non-isometric RPG Tiling toolkit.
#@cli : More info: The interactive RPG Tiling toolkit is a early version. More features will be added such as symmetry mode and row/column shifting.\n
#@cli : Note: This is meant to enable artists to make artwork based on non-isometric RPG games or even world. It is not meant to be a tool to aid into making RPG games. If you want that, then you need to look into other solutions. Of course, there might be the off-chance that this tool is suitable for you.\n 
#@cli : '{ filename | [tile] }' can be either location of the tile in text form, or as a image argument. If using image argument, you must do rep_rpgtiler[target] [tile] to make it work.
#@cli : 'min_tile' defines the size of tiles.
#@cli : 'increment' defines the maximum possible selection length by number of tiles added by 1. 0 means maximum possible selection length by tile within axis is exactly 1.
#@cli : '_tileset_iw_width' defines the width of tileset visible within interactive window.
#@cli : '_tileset_ih_width' defines the width of tileset visible within interactive window.
#@cli : '_preserve_bgout' can be used to keep or erase image after painting tiles.
#@cli : '_dbrga_r' is the color of transparent background. If a value is assigned to this, then transparent areas are replaced with colored background instead of a checkerboard.
#@cli : '_dbrga_g' is the color of transparent background. If a value is assigned to this, then transparent areas are replaced with colored background instead of a checkerboard.
#@cli : '_dbrga_b' is the color of transparent background. If a value is assigned to this, then transparent areas are replaced with colored background instead of a checkerboard.
#@cli : '_gridcol' defines the color of grid within interactive window. Only grayscale value.
#@cli : '_trackpadcol' defines the color of tracker pad within interactive window. Only grayscale value.\n
#@cli : Default values: '_tileset_iw_width=16','_tileset_ih_width=16','_preserve_bgout=0','_drgba_r=','_drgba_g=','_drgba_b=','_gridcol=0','_trackpadcol=0'
rep_rpgtiler_noniso:
skip ${4=16},${5=16},${6=0},${7=},${8=},${9=},${10=0},${11=255}
include_image=${"is_image_arg $1"}

min_tile={abs($2)}
if $min_tile<3 error "$"2>=3==F"" fi
max_increment={abs($3)}

tile_width=$min_tile
tile_height=$min_tile

gridcol={abs($10)}
trackpadcol={abs($11)}

if narg($_drgba_r)||narg($_drgba_g)||narg($_drgba_b)
    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 "xalpa: xalp to_a"

if $!==1
    gw={w#0}
    gh={h#0}
    nw={ceil($gw/$min_tile)*$min_tile}
    nh={ceil($gh/$min_tile)*$min_tile}
    r $nw,$nh,100%,100%,0,0,.5,.5 to_a 
    +store[0] ogb
    xalpa
    cs={s#-1}
    +store[0] bg
    +store[0] cbg
    +f (((x%$min_tile)==0||(y%$min_tile)==0)||(x==(w-1)||y==(h-1)))?255-i:i
    rm.
    f 0
    +store[0] current_image
    e[] "\nEntering non-isometric RPG Tiling Tool!"
else
    error "$!==1=F"
fi

e[] "\n Instruction on how to work with interactive windows.\n
 \ ---------------------------------------------------------\n\n
 \ - On any window - \n
 \   * Q: Remove/Restore Background\n
 \   * G: Activate Canvas Grid Mode ON/OFF\n
 \   * Z: Activate Copy Mode On/OFF\n
 \   * D: Switch between Place/Eraser Mode\n
 \   * W: Restore ALL windows\n\n
 \ - On Canvas window - \n
 \   * F: Activate/Deactivate Background Tile Layering Mode\n
 \   * A: Enable/Disable Tracker\n\n
 \ - On Tileset window - \n
 \   * CTRL+ARROWKEY: Resize Tile Selection Box\n
 \   * ARROWKEY: Scroll through tileset\n\n
 \ - On Tile window - \n
 \   * CTRL+ARROWKEY: Mirror alongside axis\n
 \   * ARROWKEY: Rotate Tile\n
 \   * MOUSE BUTTON: Switch between Place/Eraser Mode\n\n
 \ ---------------------------------------------------------\n"\n

if $include_image
    pass$1 0
else
    i $1
fi

l.
    xr={ceil(w#-1/(abs($4)*$min_tile))}
    yr={ceil(h#-1/(abs($5)*$min_tile))}
    split_tiles. {-abs($4)*$min_tile},{-abs($5)*$min_tile}
    mw=${-max_w}
    mh=${-max_h}
    ti={$!}
endl

$min_tile,$min_tile,1,4,0
fti={$!}

$bg
+xalp.
w[-1] {w#0},{h#0},0,"Canvas"
rm[-2,-1]

+xalp[1] w1[-1] {w#1},{h#1},0,"Tileset" rm.
w2[-1] 196,196,0,"Tile"

fti={$!}

icx=0
icy=0
ci=0
lr=0
tb=0
tbc=0
ni=1
erasemode=0
rotval=0
background_mode=0
gridmode=0
optinsert=1
start=0
copymode=0
trackermode=1
canvas_background=1
current_canvas_background=1
current_erase_mode=0
selection=0
sx=0
sy=0
cx=-1
cy=-1

activate_edit=0
do
    if {*,W}" || "{*1,W}" || "{*2,W} w[] w1[] w2[] fi
    
    if $erasemode
        +f. 0 w2[-1] rm.
        optinsert=1
    fi
    
    if $current_erase_mode!=$erasemode
        if $current_erase_mode==1&&$erasemode==0
            $tile f.. i#-1 rm.
            +xalpa.
            w2[-1] rm.        
        fi
        current_erase_mode=$erasemode
    fi
    
    if $current_canvas_background!=$canvas_background
        if $canvas_background
            $cbg store. bg
            current_canvas_background=$canvas_background
        else
            $bg f. 0 xalpa. store. bg
            current_canvas_background=$canvas_background           
        fi
    fi
    
    if {*,Q}" || "{*1,Q}" || "{*2,Q}
        canvas_background+=1
        canvas_background={$canvas_background%2}
        wait 500
    fi
    
    x,y,b,ww,wh={*,x,y,b,w,h}
    x1,y1,b1,ww1,wh1={*1,x,y,b,w,h}
    x2,y2,b2,ww2,wh2={*2,x,y,b,w,h}
    
    if {*,G}" || "{*1,G}" || "{*2,G}
        gridmode+=1
        gridmode={$gridmode%2}
    fi
    
    if {*,Z}" || "{*1,Z}" || "{*2,Z}
        erasemode=0
        copymode+=1
        copymode={$copymode%2}
    fi
    
    if {*,F}
        background_mode+=1
        background_mode={$background_mode%2}
    fi
    
    if {*,A}
        trackermode+=1
        trackermode={$trackermode%2}
    fi
    
    if $start
        if $copymode
            if $trackermode
                $bg [0] blend[-2,-1] alpha
                psx={floor($x/$min_tile)*$min_tile}
                psy={floor($y/$min_tile)*$min_tile}
                $tile_width,$tile_height,1,{$cs-1},(x<=2||x>=(w-3))||(y<=2||y>=(h-3))?$trackpadcol:0
                sh. 0 f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255:0
                j[-3] [-2],$psx,$psy,0,0,1,[-1],255
                rm[-2--1]
                xalp.
                w[-1] {w#0},{h#0},0,"Canvas - (Copy Mode)"
                rm.
            else w[] {w#0},{h#0},0,"Canvas - (Copy Mode)"
            fi
        else
            if $background_mode
                if !$erasemode
                    if !$gridmode
                        $bg [0] blend[-2,-1] alpha
                        if $trackermode" && "$x>=0" && "$y>=0" && "$x<=(w#0-1)" && "$y<=(h#0-1)
                            psx={floor($x/$min_tile)*$min_tile}
                            psy={floor($y/$min_tile)*$min_tile}
                            $tile_width,$tile_height,1,{$cs-1},(x<=2||x>=(w-3))||(y<=2||y>=(h-3))?$trackpadcol:0
                            sh. 0 f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255:0
                            j[-3] [-2],$psx,$psy,0,0,1,[-1],255
                            rm[-2--1]
                        fi
                        xalp.
                        w[-1] {w#0},{h#0},0,"Canvas - Place Tileset (Background Mode)"
                        rm.
                    else
                        $bg [0] blend[-2,-1] alpha f. !(((x%$min_tile)==0||(y%$min_tile)==0)||(x==(w-1)||y==(h-1)))?i:$gridcol
                        if $trackermode" && "$x>=0" && "$y>=0" && "$x<=(w#0-1)" && "$y<=(h#0-1)
                            psx={floor($x/$min_tile)*$min_tile}
                            psy={floor($y/$min_tile)*$min_tile}
                            $tile_width,$tile_height,1,{$cs-1},(x<=2||x>=(w-3))||(y<=2||y>=(h-3))?$trackpadcol:0
                            sh. 0 f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255:0
                            j[-3] [-2],$psx,$psy,0,0,1,[-1],255
                            rm[-2--1]
                        fi
                        xalp. f. !(((x%$min_tile)==0||(y%$min_tile)==0)||(x==(w-1)||y==(h-1)))?i:$gridcol
                        w[-1] {w#0},{h#0},0,"Canvas - Place Tileset (Background Mode) (Gridmode ON)"
                        rm.
                    fi
                else
                    if !$gridmode
                        $bg [0] blend[-2,-1] alpha
                        if $trackermode" && "$x>=0" && "$y>=0" && "$x<=(w#0-1)" && "$y<=(h#0-1)
                            psx={floor($x/$min_tile)*$min_tile}
                            psy={floor($y/$min_tile)*$min_tile}
                            $tile_width,$tile_height,1,{$cs-1},(x<=2||x>=(w-3))||(y<=2||y>=(h-3))?$trackpadcol:0
                            sh. 0 f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255:0
                            j[-3] [-2],$psx,$psy,0,0,1,[-1],255
                            rm[-2--1]
                        fi
                        xalp.
                        w[-1] {w#0},{h#0},0,"Canvas - Eraser Mode"
                        rm.
                    else
                        $bg [0] blend[-2,-1] alpha f. !(((x%$min_tile)==0||(y%$min_tile)==0)||(x==(w-1)||y==(h-1)))?i:$gridcol
                        if $trackermode" && "$x>=0" && "$y>=0" && "$x<=(w#0-1)" && "$y<=(h#0-1)
                            psx={floor($x/$min_tile)*$min_tile}
                            psy={floor($y/$min_tile)*$min_tile}
                            $tile_width,$tile_height,1,{$cs-1},(x<=2||x>=(w-3))||(y<=2||y>=(h-3))?$trackpadcol:0
                            sh. 0 f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255:0
                            j[-3] [-2],$psx,$psy,0,0,1,[-1],255
                            rm[-2--1]
                        fi
                        xalp. f. !(((x%$min_tile)==0||(y%$min_tile)==0)||(x==(w-1)||y==(h-1)))?i:$gridcol
                        w[-1] {w#0},{h#0},0,"Canvas - Eraser Mode (Gridmode ON)"
                        rm.
                    fi
                fi
            else
                if !$erasemode
                    if !$gridmode
                        $bg [0] blend[-2,-1] alpha
                        if $trackermode" && "$x>=0" && "$y>=0" && "$x<=(w#0-1)" && "$y<=(h#0-1)
                            psx={floor($x/$min_tile)*$min_tile}
                            psy={floor($y/$min_tile)*$min_tile}
                            $tile_width,$tile_height,1,{$cs-1},(x<=2||x>=(w-3))||(y<=2||y>=(h-3))?$trackpadcol:0
                            sh. 0 f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255:0
                            j[-3] [-2],$psx,$psy,0,0,1,[-1],255
                            rm[-2--1]
                        fi
                        xalp.
                        w[-1] {w#0},{h#0},0,"Canvas - Place Tileset"
                        rm.
                    else
                        $bg [0] blend[-2,-1] alpha f. !(((x%$min_tile)==0||(y%$min_tile)==0)||(x==(w-1)||y==(h-1)))?i:$gridcol
                        if $trackermode" && "$x>=0" && "$y>=0" && "$x<=(w#0-1)" && "$y<=(h#0-1)
                            psx={floor($x/$min_tile)*$min_tile}
                            psy={floor($y/$min_tile)*$min_tile}
                            $tile_width,$tile_height,1,{$cs-1},(x<=2||x>=(w-3))||(y<=2||y>=(h-3))?$trackpadcol:0
                            sh. 0 f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255:0
                            j[-3] [-2],$psx,$psy,0,0,1,[-1],255
                            rm[-2--1]
                        fi
                        xalp. f. !(((x%$min_tile)==0||(y%$min_tile)==0)||(x==(w-1)||y==(h-1)))?i:$gridcol
                        w[-1] {w#0},{h#0},0,"Canvas - Place Tileset (Gridmode ON)"
                        rm.
                    fi
                else
                    if !$gridmode
                        $bg [0] blend[-2,-1] alpha
                        if $trackermode" && "$x>=0" && "$y>=0" && "$x<=(w#0-1)" && "$y<=(h#0-1)
                            psx={floor($x/$min_tile)*$min_tile}
                            psy={floor($y/$min_tile)*$min_tile}
                            $tile_width,$tile_height,1,{$cs-1},(x<=2||x>=(w-3))||(y<=2||y>=(h-3))?$trackpadcol:0
                            sh. 0 f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255:0
                            j[-3] [-2],$psx,$psy,0,0,1,[-1],255
                            rm[-2--1]
                        fi
                        xalp.
                        w[-1] {w#0},{h#0},0,"Canvas - Eraser Mode"
                        rm.
                    else
                        $bg [0] blend[-2,-1] alpha f. !(((x%$min_tile)==0||(y%$min_tile)==0)||(x==(w-1)||y==(h-1)))?i:$gridcol
                        if $trackermode" && "$x>=0" && "$y>=0" && "$x<=(w#0-1)" && "$y<=(h#0-1)
                            psx={floor($x/$min_tile)*$min_tile}
                            psy={floor($y/$min_tile)*$min_tile}
                            $tile_width,$tile_height,1,{$cs-1},(x<=2||x>=(w-3))||(y<=2||y>=(h-3))?$trackpadcol:0
                            sh. 0 f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255:0
                            j[-3] [-2],$psx,$psy,0,0,1,[-1],255
                            rm[-2--1]
                        fi
                        xalp. f. !(((x%$min_tile)==0||(y%$min_tile)==0)||(x==(w-1)||y==(h-1)))?i:$gridcol
                        w[-1] {w#0},{h#0},0,"Canvas - Eraser Mode (Gridmode ON)"
                        rm.
                    fi
                fi
            fi
        fi
    else
        if $gridmode
            $bg xalp. f. !(((x%$min_tile)==0||(y%$min_tile)==0)||(x==(w-1)||y==(h-1)))?i:$gridcol
            f. !(((x%$min_tile)==0||(y%$min_tile)==0)||(x==(w-1)||y==(h-1)))?i:$gridcol
            w[-1] {w#0},{h#0},0,"Canvas - (Gridmode ON)"
            rm.
        else
            $bg xalp.
            w[-1] {w#0},{h#0},0,"Canvas"
            rm.
        fi
        
    fi
    
    if   {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWLEFT}}" &&"$selection      
        icx-=1
        icx={max($icx,0)}
        tile_width={$min_tile+($icx*$min_tile)}
        
        f. 0
        r. $tile_width,$tile_height
        f. i(#$ni,$sx+x,$sy+y)
        +xalp.
        w2[-1] {($icx+1)*196},{($icy+1)*196},0,"Tile"
        rm.
        +f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255-i:i
        +j[$ni] [-1],$sx,$sy
        xalp.
        w1[-1]
        rm[-2,-1]
    elif {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWRIGHT}}" &&"$selection   
        icx+=1
        icx={min($icx,$max_increment)}
        tile_width={$min_tile+($icx*$min_tile)}

        f. 0
        r. $tile_width,$tile_height
        f. i(#$ni,$sx+x,$sy+y)
        +xalp.
        w2[-1] {($icx+1)*196},{($icy+1)*196},0,"Tile"
        rm.
        +f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255-i:i
        +j[$ni] [-1],$sx,$sy
        xalp.
        w1[-1]
        rm[-2,-1]
    elif {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWDOWN}}" &&"$selection
        icy+=1
        icy={min($icy,$max_increment)}
        tile_height={$min_tile+($icy*$min_tile)}

        f. 0
        r. $tile_width,$tile_height
        f. i(#$ni,$sx+x,$sy+y)
        +xalp.
        w2[-1] {($icx+1)*196},{($icy+1)*196},0,"Tile"
        rm.
        +f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255-i:i
        +j[$ni] [-1],$sx,$sy
        xalp.
        w1[-1]
        rm[-2,-1]
    elif {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWUP}}" &&"$selection
        icy-=1
        icy={max($icy,0)}
        tile_height={$min_tile+($icy*$min_tile)}
        
        f. 0
        r. $tile_width,$tile_height
        f. i(#$ni,$sx+x,$sy+y)
        +xalp.
        w2[-1] {($icx+1)*196},{($icy+1)*196},0,"Tile"
        rm.
        +f. (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255-i:i
        +j[$ni] [-1],$sx,$sy
        xalp.
        w1[-1]
        rm[-2,-1]
    elif {*1,ARROWRIGHT}
        selection=0
        lr+=1
        lr={$lr%$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        +xalp[$ni]
        w1[-1] {w#$ni},{h#$ni}
        rm.
        wait 625
    elif {*1,ARROWLEFT}
        selection=0
        lr-=1
        lr={$lr%$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        +xalp[$ni]
        w1[-1] {w#$ni},{h#$ni}
        rm.
        wait 625
    elif {*1,ARROWDOWN}
        selection=0
        tbc+=1
        tbc={$tbc%$yr}
        tb={$tbc*$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        +xalp[$ni]
        w1[-1] {w#$ni},{h#$ni}
        rm.
        wait 625
    elif {*1,ARROWUP}
        selection=0
        tbc-=1
        tbc={$tbc%$yr}
        tb={$tbc*$xr}
        ci={($lr+$tb)%$ti}
        ni={$ci+1}
        +xalp[$ni]
        w1[-1] {w#$ni},{h#$ni}
        rm.
        wait 625
    fi
    
    if   {{*2,CTRLLEFT}" || "{*2,CTRLRIGHT}}" && "{{*2,ARROWLEFT}" || "{*2,ARROWRIGHT}}
        mirror[-1] x
        +xalp.
        w2[-1]  {($icx+1)*196},{($icy+1)*196},0,"Tile"
        rm.
        optinsert=1
        wait 100
    elif {{*2,CTRLLEFT}" || "{*2,CTRLRIGHT}}" && "{{*2,ARROWUP}" || "{*2,ARROWDOWN}}
        mirror[-1] y
        +xalp.
        w2[-1]  {($icx+1)*196},{($icy+1)*196},0,"Tile"
        rm.
        optinsert=1
        wait 100
    elif {*2,ARROWLEFT}
        temp_tile_width=$tile_width
        temp_tile_height=$tile_height
        temp_icx=$icx
        temp_icy=$icy
        icx=$temp_icy
        icy=$temp_icx
        rotate[-1] -90
        +xalp.
        w2[-1]  {($icx+1)*196},{($icy+1)*196},0,"Tile"
        rm.
        optinsert=1
        tile_width=$temp_tile_height
        tile_height=$temp_tile_width
        wait 100
    elif {*2,ARROWRIGHT}
        temp_tile_width=$tile_width
        temp_tile_height=$tile_height
        temp_icx=$icx
        temp_icy=$icy
        icx=$temp_icy
        icy=$temp_icx
        rotate[-1] 90
        +xalp.
        w2[-1]  {($icx+1)*196},{($icy+1)*196},0,"Tile"
        rm.
        optinsert=1
        tile_width=$temp_tile_height
        tile_height=$temp_tile_width
        wait 100
    fi
    
    if $b" && "$x>=0" && "$y>=0
        psx={floor($x/$min_tile)*$min_tile}
        psy={floor($y/$min_tile)*$min_tile}
        if !$erasemode&&!$copymode
            if $psx!=$cx||$psy!=$cy||$optinsert
                $tile_width,$tile_height,1,{s#0},i(#0,x+$psx,y+$psy)
                [-2]
                if $background_mode rv[-2,-1] fi
                blend[-2,-1] alpha
                j[0] [-1],$psx,$psy
                rm.
                +store[0] current_image
                $bg
                $current_image
                blend[-2,-1] alpha
                xalp.
                if !$gridmode w[-1]
                else
                    f. !(((x%$min_tile)==0||(y%$min_tile)==0)||(x==(w-1)||y==(h-1)))?i:$gridcol
                    w[-1]
                fi
                rm.
                optinsert=0
            fi
        elif !$copymode
            $tile_width,$tile_height,1,{s#0}
            j[0] [-1],$psx,$psy
            rm.
            +store[0] current_image
            $bg
            $current_image
            blend[-2,-1] alpha
            xalp.
            if !$gridmode w[-1]
            else
                f. !(((x%$min_tile)==0||(y%$min_tile)==0)||(x==(w-1)||y==(h-1)))?i:$gridcol
                w[-1]
            fi
            rm.
        else
            f[-1] i(#0,$psx+x,$psy+y)
            +store. tile
            +xalp.
            w2[-1]
            rm.
            copymode=0
            erasemode=0
        fi
        cx=$psx
        cy=$psy
    fi
    
    if $b1" && "$x1>=0" && "$y1>=0
        copymode=0
        if !$selection selection=1 fi
        erasemode=0
        
        sx={floor($x1/$min_tile)*$min_tile}
        sy={floor($y1/$min_tile)*$min_tile}
        f. i(#$ni,$sx+x,$sy+y,z,c)
        +store. tile
        +xalp.
        w2[-1] 
        rm.
        
        +f[-1] (x<=2||x>=(w-3))||(y<=2||y>=(h-3))?255-i:i
        +j[$ni] [-1],$sx,$sy
        xalp.
        w1[-1]
        rm[-2,-1]
        if $gridmode
            if $background_mode w[] {w#0},{h#0},0,"Canvas - Place Tileset (Background Mode) (Gridmode ON)"
            else  w[] {w#0},{h#0},0,"Canvas - Place Tileset (Gridmode ON)"
            fi
        else
            if $background_mode w[] {w#0},{h#0},0,"Canvas - Place Tileset"
            else w[] {w#0},{h#0},0,"Canvas - Place Tileset"
            fi
        fi
        optinsert=1
        start=1
    fi
    
    if {*,D}" || "{*1,D}" || "{*2,D}
        erasemode+=1
        erasemode={$erasemode%2}
        if $erasemode
            +store. tile
            f. 0
            w2[-1]
        fi
        wait 400
    fi
    
    if {$b2" && "$x2>=0" && "$y2>=0}
        erasemode+=1
        erasemode={$erasemode%2}
        copymode=0
        if !$erasemode
            +store. tile
            f. 0
            w2[-1]
            +xalp[$ni]
            w1[-1]
            rm.
            if $gridmode
                w[] {w#0},{h#0},0,"Canvas - Eraser Mode (Gridmode ON)"
            else
                w[] {w#0},{h#0},0,"Canvas - Eraser Mode"
            fi
            optinsert=1
        fi
    fi
    
    wait
while {*}" && "!{*,ESC}
uncommand xalp,xalpa
w1[] 0
w2[] 0
k[0]
if $6 $obg rv blend alpha fi

Now it has been published. Keep in mind that this is a early version. I do realized that I could have reduced so much codes after looking at the f block within the command used by the gui filter, and learning of the =. technique to merge text string. So, I mentioned refactoring is planned. Right now, it’s just incredibly difficult to read and write on.

I’m almost done refactoring the code (I’m still missing in features for now, but it’s not so far off from being finished. It’s about to be finished, and the refactoring mode makes it easier for me to figure out how to do symmetry mode.). Compare this with the branch. The code is less than 3/4 of the original one after refactoring. Also, easier to understand as you can see. I might just move some lines to have the code with less lines.

EDIT: Successfully have remade the interactive window tool to something far more maintainable. There’s new features such as cutting/copying to tile. Still no symmetry mode or row/column shifting mode yet. That’s going to be a separate mode entirely from the main mode. But those are next after the replace tool. This code is 2/3 as big as the original one.

EDIT 2: I finished implementing replace mode. j[m] [n] didn’t work, so I had to find a working macro command to make it work. Now it’s time for me to finish symmetry mode. After that, I will do row/column shifting which is way easier to figure out.

EDIT 3: I have figured out how to implement symmetry mode. The code is sure coming to completion with every features I"d like into it. Right now, symmetry mode only works with periodic setting and only on place tile mode and only along x axis and only based on half-x. I’ll add it to cut and erase mode. After that, I’ll be inserting a new mode to enhance tile placement tool and a option to allow users to import original image as placed tiles. That way, with the new mode that allows row/column shifting and bigger cut/copy and paste, it’ll be incredibly easy to make a rpg world art.

#@cli rep_rpgtiler_noniso: { filename | [tile] },__min_tile>=3,increment>=0,_tileset_iw_width>=1,_tileset_ih_width>=1,_preserve_bgout={ 0=eliminate_bg | 1=preserve_bg },_drgba_r>=0,_drgba_g>=0,_drgba_b>=0,_gridcol>=0,_trackpadcol>=0 
#@cli : Launch the interactive non-isometric RPG Tiling toolkit.
#@cli : More info: The interactive RPG Tiling toolkit is a early version. More features will be added such as symmetry mode and row/column shifting.\n
#@cli : Note: This is meant to enable artists to make artwork based on non-isometric RPG games or even world. It is not meant to be a tool to aid into making RPG games. If you want that, then you need to look into other solutions. Of course, there might be the off-chance that this tool is suitable for you.\n 
#@cli : '{ filename | [tile] }' can be either location of the tile in text form, or as a image argument. If using image argument, you must do rep_rpgtiler[target] [tile] to make it work.
#@cli : '__min_tile' defines the size of tiles.
#@cli : 'increment' defines the maximum possible selection length by number of tiles added by 1. 0 means maximum possible selection length by tile within axis is exactly 1.
#@cli : '_tileset_iw_width' defines the width of tileset visible within interactive window.
#@cli : '_tileset_ih_width' defines the width of tileset visible within interactive window.
#@cli : '_preserve_bgout' can be used to keep or erase image after painting tiles.
#@cli : '_dbrga_r' is the color of transparent background. If a value is assigned to this, then transparent areas are replaced with colored background instead of a checkerboard.
#@cli : '_dbrga_g' is the color of transparent background. If a value is assigned to this, then transparent areas are replaced with colored background instead of a checkerboard.
#@cli : '_dbrga_b' is the color of transparent background. If a value is assigned to this, then transparent areas are replaced with colored background instead of a checkerboard.
#@cli : '_gridcol' defines the color of grid within interactive window. Only grayscale value.
#@cli : '_trackpadcol' defines the color of tracker pad within interactive window. Only grayscale value.\n
#@cli : Default values: '_tileset_iw_width=16','_tileset_ih_width=16','_preserve_bgout=0','_drgba_r=','_drgba_g=','_drgba_b=','_gridcol=0','_trackpadcol=0'
rep_rpgtiler_noniso:
skip ${4=16},${5=16},${6=0},${7=},${8=},${9=},${10=128},${11=128}
include_image=${"is_image_arg $1"}

__min_tile={abs($2)}
if $__min_tile<3 error "$"2>=3==F"" fi
max_increment={abs($3)}

tile_width=$__min_tile
tile_height=$__min_tile

gridcol={abs($10)}
trackpadcol={abs($11)}

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 "xalpa: xalp to_a"

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

m "tile2canvas : pass$""1 0 +f. i(#0,$""2+x,$""3+y) if !$""4 rv[-2,-1] fi blend[-2,-1] alpha j[0] [-1],$""2,$""3 rm."

m "tile2canvas_r : +f. 0 j[0] [-1],$""1,$""2 rm. tile2canvas[0] [-1],$""1,$""2,$""3"

if $!==1
    gw={w#0}
    gh={h#0}
    __nw={ceil($gw/$__min_tile)*$__min_tile}
    __nh={ceil($gh/$__min_tile)*$__min_tile}
    r $__nw,$__nh,100%,100%,0,0,.5,.5 to_a 
    +store[0] ogb
    xalpa
    cs={s#-1}
    +store[0] __bg
    +store[0] cbg
    +f (((x%$__min_tile)==0||(y%$__min_tile)==0)||(x==(w-1)||y==(h-1)))?255-i:i
    rm.
    f 0
    +store[0] current_image
    +store[0] undo_image
    e[] "\nEntering non-isometric RPG Tiling Tool!"
else
    error "$!==1=F"
fi

m "tile2canvas_sym : pass$""1 0 +f. i(#0,$""2+x,$""3+y) if !$""5 rv[-2,-1] fi blend[-2,-1] alpha j[0] [-1],$""2,$""3 j[0] [-1],{($__nw-$""4)-$""2},$""3 rm."

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


e[] "\n Instruction on how to work with interactive windows.\n
 \ ---------------------------------------------------------\n\n
 \ - On any window - \n
 \   * Q: Remove/Restore Background\n
 \   * G: Activate Canvas Grid Mode On/Off\n
 \   * C: Activate Copy Mode On/Off\n
 \   * X: Activate Cut Mode On/Off\n
 \   * D: Switch between Place/Eraser Mode\n
 \   * Z: Undo Changes\n
 \   * R: Activate Replace Mode\n
 \   * S: Activate Symmetry Mode\n
 \   * M: Switch Axis in Symmetry Mode\n
 \   * B: Switch between Periodic/Mirror mode in Symmetry Mode\n
 \   * W: Restore All Windows\n\n
 \ - On Canvas window - \n
 \   * F: Activate/Deactivate Background Tile Layering Mode\n
 \   * A: Enable/Disable Tracker\n\n
 \ - On Tileset window - \n
 \   * CTRL+ARROWKEY: Resize Tile Selection Box\n
 \   * ARROWKEY: Scroll through tileset\n\n
 \ - On Tile window - \n
 \   * CTRL+ARROWKEY: Mirror alongside axis\n
 \   * ARROWKEY: Rotate Tile\n
 \   * MOUSE BUTTON: Switch between Place/Eraser Mode\n\n
 \ ---------------------------------------------------------\n"\n

if $include_image
    pass$1 0
else
    i $1
fi

l.
    xr={ceil(w#-1/(abs($4)*$__min_tile))}
    yr={ceil(h#-1/(abs($5)*$__min_tile))}
    split_tiles. {-abs($4)*$__min_tile},{-abs($5)*$__min_tile}
    mw=${-max_w}
    mh=${-max_h}
    ti={$!}
endl

$__min_tile,$__min_tile,1,4,0
fti={$!}

$__bg
+xalp.

dw0c={w#0}
dh0c={h#0}

dwm0=0
dwm1=0
dwm2=0

d2rw=162

w[-1] {w#0},{h#0},0,"Canvas"
rm[-2,-1]
+xalp[1] w1[-1] 

{w#1},{h#1},0,"Tileset" rm.
w2[-1] $d2rw,$d2rw,0,"Tile"

fti={$!}

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

cutcopymode=0
erasemode=0
replacemode=0

symmetrymode=0
symmetryaxis=0
symmetrybound=0

canvas_background=1
canvas_gridmode=0
canvas_tracker=1

tileset_gridmode=0

select_from_tileset=0
select_from_canvas=0
select_from_tile=0

resize_tile_from_tileset=0
resize_tile_from_canvas=0
transform_tile=0
switch_tile_set=0

tile_placement_mode=0

start=0
current_csx=-1
current_csy=-1
optinsert=1

do
    undo_state=0
    main_w_title="Canvas"
    canvas_set=""
    
    if {*,W}" || "{*1,W}" || "{*2,W} w[] w1[] w2[] fi
    
    if {*,Z} undo_state=1 fi
    
    if {*,G} canvas_gridmode+=1   canvas_gridmode={$canvas_gridmode%2} fi
    if {*,Q} canvas_background+=1 canvas_background={$canvas_background%2} fi
    if {*,A} canvas_tracker+=1 canvas_tracker={$canvas_tracker%2} fi
    
    if {*,F} tile_placement_mode+=1 tile_placement_mode={$tile_placement_mode%2} fi
    if {*,R} replacemode+=1 replacemode={$replacemode%2} optinsert=1 fi
    
    if {*,S} symmetrymode+=1 symmetrymode={$symmetrymode%2} fi
    
    if $symmetrymode
        if {*,B} symmetryaxis+=1 symmetryaxis={$symmetryaxis%4} fi
        if {*,M} symmetrybound+1 symmetrybound{$symmetrybound%2} fi
    fi
    
    if $canvas_gridmode
        if $canvas_tracker canvas_endset=,$trackpadcol,$gridcol
        else canvas_endset=,,$gridcol
        fi
    else
        if $canvas_tracker canvas_endset=,$trackpadcol
        else canvas_endset=""
        fi
    fi
    if {*,C}" || "{*,X}
        if {*,X} cutcopymode=1
        else cutcopymode=2
        fi
    fi
    
    if {*,D} 
        erasemode+=1 
        erasemode={$erasemode%2} 
        if $erasemode  +f. 0 w2[-1] {$d2rw+($d2rw*$icx)},{$d2rw+($d2rw*$icy)} rm. 
        else +out2display. , w2[-1] {$d2rw+($d2rw*$icx)},{$d2rw+($d2rw*$icy)} rm.
        fi
        optinsert=1
    fi
    
    x,y,b,ww,wh={*,x,y,b,w,h}
    x1,y1,b1,ww1,wh1={*1,x,y,b,w,h}
    x2,y2,b2,ww2,wh2={*2,x,y,b,w,h}
    
    if $start
        if $undo_state
            +store[0] temp_undo
            $undo_image
            rv[0,-1]
            rm.
            $temp_undo
            store. undo_image
        fi
        
        if {{*2,CTRLLEFT}" || "{*2,CTRLRIGHT}}" && "{{*2,ARROWLEFT}" || "{*2,ARROWRIGHT}}
            mirror. x transform_tile=1
            wait 100
        elif {{*2,CTRLLEFT}" || "{*2,CTRLRIGHT}}" && "{{*2,ARROWUP}" || "{*2,ARROWDOWN}}
            mirror. y transform_tile=1
            wait 100
        elif {*2,ARROWLEFT}||{*2,ARROWRIGHT}
            temp_tile_width=$tile_width
            temp_tile_height=$tile_height
            temp_icx=$icx
            temp_icy=$icy
            icx=$temp_icy
            icy=$temp_icx
            tile_width=$temp_tile_height
            tile_height=$temp_tile_width
            
            if {*2,ARROWRIGHT} rotate. 90 else rotate. -90 fi
            transform_tile=1
            
            wait 100
        fi
        
        if $transform_tile
            +out2display[$ni] , w1[-1] rm.
            +out2display. , w2[-1] {$d2rw+($d2rw*$icx)},{$d2rw+($d2rw*$icy)} rm.
            transform_tile=0
            optinsert=1
        fi
        
        if {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWRIGHT}}
            if $select_from_tileset
                icx+=1
                icx={min($icx,$max_increment)}
                tile_width={$__min_tile+($icx*$__min_tile)}
            fi
                    
            if $select_from_tileset resize_tile_from_tileset=1 fi
            
            wait 500
        elif {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWLEFT}}
            if $select_from_tileset
                icx-=1
                icx={max($icx,0)}
                tile_width={$__min_tile+($icx*$__min_tile)}
            fi
                    
            if $select_from_tileset resize_tile_from_tileset=1 fi
            
            wait 500
        elif {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWDOWN}}
            if $select_from_tileset
                icy+=1
                icy={min($icy,$max_increment)}
                tile_height={$__min_tile+($icy*$__min_tile)}
            fi
                    
            if $select_from_tileset resize_tile_from_tileset=1 fi
            
            wait 500
        elif {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWUP}}
            if $select_from_tileset
                icy-=1
                icy={max($icy,0)}
                tile_height={$__min_tile+($icy*$__min_tile)}
            fi
                    
            if $select_from_tileset resize_tile_from_tileset=1 fi
            
            wait 500
        elif {*1,ARROWRIGHT}
            select_from_tileset=0
            lr+=1
            lr={$lr%$xr}
            ci={($lr+$tb)%$ti}
            ni={$ci+1}
            switch_tile_set=1
            wait 625
        elif {*1,ARROWLEFT}
            select_from_tileset=0
            lr-=1
            lr={$lr%$xr}
            ci={($lr+$tb)%$ti}
            ni={$ci+1}
            switch_tile_set=1
            wait 625
        elif {*1,ARROWDOWN}
            select_from_tileset=0
            tbc+=1
            tbc={$tbc%$yr}
            tb={$tbc*$xr}
            ci={($lr+$tb)%$ti}
            ni={$ci+1}
            switch_tile_set=1
            wait 625
        elif {*1,ARROWUP}
            select_from_tileset=0
            tbc-=1
            tbc={$tbc%$yr}
            tb={$tbc*$xr}
            ci={($lr+$tb)%$ti}
            ni={$ci+1}
            switch_tile_set=1
            wait 625
        fi
        
        if $switch_tile_set
            +out2display[$ni] , w1[-1] {w#$ni+$dwm1*w#$ni},{h#$ni+$dwm1*h#$ni} rm.
            switch_tile_set=0
        fi
        
        if $resize_tile_from_tileset
                r. $tile_width,$tile_height,100%,100%,0
                pass2tile. [$ni],$tsx,$tsy
                +out2display. , w2[-1] {$d2rw+($d2rw*$icx)},{$d2rw+($d2rw*$icy)} rm.
                if $tileset_gridmode
                    +out2display[$ni] 0,$tsx,$tsy,$tile_width,$tile_height,$trackpadcol,$gridcol
                else
                    +out2display[$ni] 0,$tsx,$tsy,$tile_width,$tile_height,$trackpadcol
                fi
                w1[-1] rm.
                resize_tile_from_tileset=0
        fi
        
        if $b" && "$x>=0" && "$y>=0" && "$x<w#0" && "$y<h#0
            csx={floor($x/$__min_tile)*$__min_tile} csy={floor($y/$__min_tile)*$__min_tile}
            if !$cutcopymode&&!$erasemode
                if (($current_csx!=$csx)||($current_csy!=$csy))||$optinsert
                    +store[0] undo_image
                    if $replacemode 
                        tile2canvas_r[0,-1] $csx,$csy,$tile_placement_mode
                    else
                        if $symmetrymode 
                            tile2canvas_sym[0] [-1],$csx,$csy,$tile_width,$tile_placement_mode
                        else 
                            tile2canvas[0] [-1],$csx,$csy,$tile_placement_mode
                        fi
                    fi
                fi
                optinsert=0
            elif $cutcopymode&&!$erasemode
                if $cutcopymode==1 
                    +store[0] undo_image
                    pass2tile. [0],$cx,$cy {w#-1},{h#-1},1,{s#-1} j[0] [-1],$cx,$cy rm.
                else 
                    pass2tile. [0],$csx,$csy optinsert=0
                fi
                +out2display. , w2[-1] {$d2rw+($d2rw*$icx)},{$d2rw+($d2rw*$icy)} rm. 
                cutcopymode=0
                optinsert=1
            else
                +store[0] undo_image
                cutcopymode=0
                if (($current_csx!=$csx)||($current_csy!=$csy))||$optinsert
                    $tile_width,$tile_height,1,{s#0} j[0] [-1],$csx,$csy rm.
                fi
            fi
            current_csx=$csx current_csy=$csy
        fi
    
    fi
    
    if $b1" && "$x1>=0" && "$y1>=0" && "$x1<w#1" && "$y1<h#1
        start=1
        optinsert=1
        select_from_canvas=0
        select_from_tileset=1
        select_from_tile=0
        tsx={floor($x1/$__min_tile)*$__min_tile} tsy={floor($y1/$__min_tile)*$__min_tile}
        pass2tile. [$ni],$tsx,$tsy
        +out2display. , w2[-1] rm.
        
        if $tileset_gridmode
            +out2display[$ni] 0,$tsx,$tsy,$tile_width,$tile_height,$trackpadcol,$gridcol
        else
            +out2display[$ni] 0,$tsx,$tsy,$tile_width,$tile_height,$trackpadcol
        fi
        w1[-1] rm.
        
        wait 50
    fi
    
    if !$start
        if $canvas_gridmode
            +out2display[0] $canvas_background,0,0,1,1,,$gridcol
        else
            +out2display[0] $canvas_background
        fi
        w[-1] rm.
    else
        if $x>=0" && "$y>=0" && "$x<w#0" && "$y<h#0
            cx={floor($x/$__min_tile)*$__min_tile} cy={floor($y/$__min_tile)*$__min_tile}
            canvas_set=$canvas_background,$cx,$cy,$tile_width,$tile_height
            canvas_set.=$canvas_endset
            +out2display[0] $canvas_set
            w[-1]
            rm.
        else
            if $canvas_gridmode
                +out2display[0] $canvas_background,0,0,1,1,,$gridcol
            else
                +out2display[0] $canvas_background
            fi
            w[-1] rm.
        fi
        wait 50
    fi
    wait
while {*}" && "!{*,ESC}
uncommand xalp,xalpa,out2display,pass2tile,tile2canvas,tile2canvas_r
w1[] 0
w2[] 0
k[0]
if $6 $obg rv blend alpha fi

I’m having a hard time combining these two

EDIT: Symmetry mode is finished for tile placement!

On the picture, you see some use periodic placement and other use mirror placement. As well as foreground/background placement.

I am now preparing to finish up version 2 of the tiling tool. It’ll be released in 24 hours from now or 48 hours. After that, I think I’ll be on a break.

Version 2 will have (To finish and release soon):
1 - Symmetrical editing with offset option(Overlay tiles, replace tiles, and erase tiles all can be done symmetrically).
2 - Fully functional one stop undo
3 - Cut and Copy
4 - Tile Replace
5 - Preserve Base Image. So you can work on more areas by deleting existing tiles, then shifting them.
6 - Tile Resize from canvas and tile window. Periodic mode only.

Version 3 will have a separate special mode to address limitation of version 2:
1 - Row/Column Shifting
2 - Unlimited Selection.

Version 3 will be final.

Tiler has been updated to version 2. I’m not sure why the option to merge with background image don’t work, but oh well, I’ll look into that after the break or maybe even after version 3. Could be soon as it’s just few lines.

Earlier I was poking fun at the idea of making a game. While a full-blown RPG or rogue-like is unlikely, I do see the potential of a board game or D&D planner coming out of this. Think about it: it is just a matter of shuffling tiles around. :wink:

Actually, I think full blown RPG is possible out of this. It’s just a matter of adding more codes to create tile id, location, and other data with a side of nongmic programming. Someone else can do that though.

Still on a break. However, I’ll share this. This is what I made with my own filter.

5 Likes

What fun. Reminds me of Harvest Moon. :sunny: Has 2-3 missing edges though. :stuck_out_tongue:

1 Like

Looks great!

1 Like

Back to working on this.

EDIT: I went to use images and store route to solve the vector problem. Now it works! Row and column shifting feature will come soon.

EDIT: I’m figuring out how to pass selected column/row into tile window. Critical for placing tile en masse.

EDIT: Above problem was just solved. Some more work to do such as previewing selected row/column as well as adding row/column selection tracker.

EDIT: @afre I actually realized that in theory, adding a image with 2 channels (x,y channel), and z can be used to represent data of placed tiles from tileset, so with this as a option, you can make a full-blown rpg using this filter as an aid, but that comes after the final version of the filter. This doesn’t seem so hard to do actually though it would take time.

#@cli rep_rpgtiler_noniso: { filename | [tileset] },__min_tile>=3,increment>=0,_tileset_iw_width>=1,_tileset_ih_width>=1,{ filename | [premade_tiled] },_preserve_bgout={ 0=eliminate_bg | 1=preserve_bg },_drgba_r>=0,_drgba_g>=0,_drgba_b>=0,_gridcol>=0,_trackpadcol>=0 
#@cli : Launch the interactive non-isometric RPG Tiling toolkit.
#@cli : More info: The interactive RPG Tiling toolkit is a intermediate version. Final version of this filter will have row/column shifting,symmetrized tracker and option to import existing tile.\n
#@cli : Note: This is meant to enable artists to make artwork based on non-isometric RPG games or even world. It is not meant to be a tool to aid into making RPG games. If you want that, then you need to look into other solutions. Of course, there might be the off-chance that this tool is suitable for you.\n 
#@cli : '{ filename | [tile] }' can be either location of the tile in text form, or as a image argument. If using image argument, you must do rep_rpgtiler[target] [tile] to make it work.
#@cli : '__min_tile' defines the size of tiles.
#@cli : 'increment' defines the maximum possible selection length by number of tiles added by 1. 0 means maximum possible selection length by tile within axis is exactly 1.
#@cli : '_tileset_iw_width' defines the width of tileset visible within interactive window.
#@cli : '_tileset_ih_width' defines the width of tileset visible within interactive window.
#@cli : '_preserve_bgout' can be used to keep or erase image after painting tiles.
#@cli : '_dbrga_r' is the color of transparent background. If a value is assigned to this, then transparent areas are replaced with colored background instead of a checkerboard.
#@cli : '_dbrga_g' is the color of transparent background. If a value is assigned to this, then transparent areas are replaced with colored background instead of a checkerboard.
#@cli : '_dbrga_b' is the color of transparent background. If a value is assigned to this, then transparent areas are replaced with colored background instead of a checkerboard.
#@cli : '_gridcol' defines the color of grid within interactive window. Only grayscale value.
#@cli : '_trackpadcol' defines the color of tracker pad within interactive window. Only grayscale value.\n
#@cli : Default values: '_tileset_iw_width=16','_tileset_ih_width=16','_preserve_bgout=0','_drgba_r=','_drgba_g=','_drgba_b=','_gridcol=0','_trackpadcol=0'
rep_rpgtiler_noniso:
skip ${4=16},${5=16},${6=},${7=0},${8=},${9=},${10=},${11=0},${12=50}
include_background_image=${"is_image_arg $1"}
include_tile_img=${"is_image_arg $6"}
include_tile_loc={!isint($6)||!isnum($6)} 

__min_tile={abs($2)}
if $__min_tile<3 error "$"2>=3==F"" fi
max_increment={abs($3)}

tile_width=$__min_tile
tile_height=$__min_tile

gridcol={abs($11)}
trackpadcol={abs($12)}

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

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

m "xalpa: xalp to_a"

m "out2display : skip ${""1=},${""2=},${""3=},${""4=1},${""5=1},${""6=},${""7=},${""8=},${""9=},${""10=} if narg($""1) if $""1 $__bg rv blend alpha fi fi xalp if narg($""6) if narg($""2)&&narg($""3)&&narg($""4)&&narg($""5) {$""4},{$""5},1,{s#0},i(#-1,$""2+x,$""3+y) f. begin(ww=w-1;hh=h-1;);(x<(2+narg($""7))||x>ww-2)||(y<(2+narg($""7))||y>hh-2)?(xor($""6,i)>128?0:255):i j[0] [-1],$""2,$""3 rm. if narg($""8)&&narg($""9)&&narg($""10) if $""8==0||$""8>2 {$""4},{$""5},1,{s#0},i(#0,$__nw+($__min_tile*$""9)-$""2+x-$""4,$""3+y) f. begin(ww=w-1;hh=h-1;);(x<(2+narg($""7))||x>ww-2)||(y<(2+narg($""7))||y>hh-2)?(xor($""6,i)>128?0:255):i j[0] [-1],{$__nw+($__min_tile*$""9)-$""2-$""4},$""3 rm. fi if $""8==1||$""8>2 {$""4},{$""5},1,{s#0},i(#0,$""2+x,$__nh+($__min_tile*$""10)-$""3+y-$""5) f. begin(ww=w-1;hh=h-1;);(x<(2+narg($""7))||x>ww-2)||(y<(2+narg($""7))||y>hh-2)?(xor($""6,i)>128?0:255):i j[0] [-1],$""2,{$__nh+($__min_tile*$""10)-$""3-$""5} rm. fi if $""8==2||$""8>2 {$""4},{$""5},1,{s#0},i(#0,$__nw+($__min_tile*$""9)-$""2+x-$""4,$__nh+($__min_tile*$""10)-$""3+y-$""5) f. begin(ww=w-1;hh=h-1;);(x<(2+narg($""7))||x>ww-2)||(y<(2+narg($""7))||y>hh-2)?(xor($""6,i)>128?0:255):i j[0] [-1],{$__nw+($__min_tile*$""9)-$""2-$""4},{$__nh+($__min_tile*$""10)-$""3-$""5} rm. fi fi fi fi if narg($""7) f[0] begin(ww=w-1;hh=h-1;);(x%$__min_tile==0||y%$__min_tile==0)||(x==ww||y==hh)?$""7:i fi"

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

m "tile2canvas : skip ${""4=0} pass$""1 0 +f. i(#0,$""2+x,$""3+y) if !$""4 rv[-2,-1] fi blend[-2,-1] alpha j[0] [-1],$""2,$""3 rm."

m "tile2canvas_r : +f. 0 j[0] [-1],$""1,$""2 rm. tile2canvas[0] [-1],$""1,$""2,$""3"

if $!==1
    ttw={ceil(w#0/$__min_tile)}
    tth={ceil(h#0/$__min_tile)}
    $ttw,1,1,1 iscl={$ttw-1} store. __isc
    $tth,1,1,1 isrl={$tth-1} store. __isr
    __nw={$ttw*$__min_tile}
    __nh={$tth*$__min_tile}
    ttw-=2
    tth-=2
    r $__nw,$__nh,100%,100%,0,0,.5,.5 to_a 
    +store[0] obg
    xalpa
    cs={s#-1}
    +store[0] __bg
    if narg($6)
        if include_tile_img pass$6
        else include_tile_loc i $6
        fi
        rm[0]
        if ((w#-1!=$__nw)||(h#-1!=$__nw))||(s#-1!=$cs)
            error "Invalid Tile Image!"
        fi
        start=1
    else
        f 0
        start=0
    fi
    +store[0] current_image
    +store[0] undo_image
    e[] "\nEntering non-isometric RPG Tiling Tool!"
else
    error "$!==1=F"
fi

m "tile2canvas_sym : pass$""1 0 +f. i(#0,$""2+x,$""3+y) if $""8==0||$""8==3 [1] if $""7 mirror. x fi +f. i(#0,$__nw+($__min_tile*$""9)-$""4-$""2+x,$""3+y) fi if $""8==1||$""8==3 [1] if $""7 mirror. y fi +f. i(#0,$""2+x,$__nh+($__min_tile*$""10)-$""5-$""3+y) fi if $""8==2||$""8==3 [1] if $""7 rotate. 180 fi +f. i(#0,$__nw+($__min_tile*$""9)-$""4-$""2+x,$__nh+($__min_tile*$""10)-$""5-$""3+y) fi if $""8==3 if !$""6 rv[-8,-7] rv[-6,-5] fi blend[-8,-7] alpha blend[-6,-5] alpha fi if !$""6 rv[-4,-3] rv[-2,-1] fi blend[-4,-3] alpha blend[-2,-1] alpha if $""8==3 j[0] [-4],$""2,$""3 j[0] [-3],{$__nw+($__min_tile*$""9)-$""4-$""2},$""3 j[0] [-2],$""2,{$__nh+($__min_tile*$""10)-$""5-$""3} j[0] [-1],{$__nw+($__min_tile*$""9)-$""4-$""2},{$__nh+($__min_tile*$""10)-$""5-$""3} k[0] else j[0] [-2],$""2,$""3 if $""8==0 j[0] [-1],{$__nw+($__min_tile*$""9)-$""4-$""2},$""3 elif $""8==1 j[0] [-1],$""2,{$__nh+($__min_tile*$""10)-$""5-$""3} elif $""8==2 j[0] [-1],{$__nw+($__min_tile*$""9)-$""4-$""2},{$__nh+($__min_tile*$""10)-$""5-$""3} fi rm[-2,-1] fi"

m "tile2canvas_r_sym : +f. 0 j[0] [-1],$""1,$""2 if $""6==3||$""6==0 j[0] [-1],{$__nw+($__min_tile*$""7)-$""3-$""1},$""2 fi if $""6==3||$""6==1 j[0] [-1],$""1,{$__nh+($__min_tile*$""8)-$""4-$""2} fi if $""6==3||$""6==2 j[0] [-1],{$__nw+($__min_tile*$""7)-$""3-$""1},{$__nh+($__min_tile*$""8)-$""4-$""2} fi rm. if $""5&&($""6==3||$""6==0) +mirror[1] x fi if $""5&&($""6==3||$""6==1) +mirror[1] y fi if $""5&&($""6==3||$""6==2) +rotate[1] 180 fi if $""6==3 tile2canvas[0] [{$""5?-4:1}],$""1,$""2 tile2canvas[0] [{$""5?-3:1}],{$__nw+($__min_tile*$""7)-$""3-$""1},$""2 tile2canvas[0] [{$""5?-2:1}],$""1,{$__nh+($__min_tile*$""8)-$""4-$""2} tile2canvas[0] [{$""5?-1:1}],{$__nw+($__min_tile*$""7)-$""3-$""1},{$__nh+($__min_tile*$""8)-$""4-$""2} k[0,1] else tile2canvas[0] [1],$""1,$""2 if $""6==0 tile2canvas[0] [{$""5?2:1}],{$__nw+($__min_tile*$""7)-$""3-$""1},$""2 elif $""6==1 tile2canvas[0] [{$""5?2:1}],$""1,{$__nh+($__min_tile*$""8)-$""4-$""2} elif $""6==2 tile2canvas[0] [{$""5?2:1}],{$__nw+($__min_tile*$""7)-$""3-$""1},{$__nh+($__min_tile*$""8)-$""4-$""2} fi k[0,1] fi"

m "addsym2display : tlx={w#0/2+($""2/2)*$""3-2} tly={h#0/2+($""2/2)*$""4-2} px={w#0/2-2} py={h#0/2-2} if $""1<2 if $""1==0 4,{h#0},1,{s#0},begin(ww=w-1;dp=$""1<2?0:1;lp=dp+1;);x==0||x==ww?dp:lp elif $""1==1 {w#0},4,1,{s#0},begin(hh=h-1;dp=$""1<2?0:1;lp=dp+1;);y==0||y==hh?dp:lp fi *. 255 if $""1==0 j[0] [-1],$tlx,0 else j[0] [-1],0,$tly fi k[0] else ntlx={$tlx+3} ntly={$tly+3} f[0] ((x>=$tlx&&x<=$ntlx)||(y>=$tly&&y<=$tly+3))?((x==$tlx||x==$ntlx)||(y==$tly||y==$ntly)?0:255):i fi"

__pmin=0
__mode_one_orientation=0
m "filter_to_selected_row_column: if $__mode_one_orientation $__isr f[0] i(#-1,floor((y+$__pmin*$__min_tile)/$__min_tile),0,0,0)?i:0 else $__isc f[0] i(#-1,floor((x+$__pmin*$__min_tile)/$__min_tile),0,0,0)?i:0 fi k[0]"


e[] "\n Instruction on how to work with interactive windows.\n
 \ ---------------------------------------------------------\n\n
 \ - On any window - \n
 \   * D: Switch between Place/Eraser Mode\n
 \   * R: Activate Replace Mode\n
 \   * W: Restore All Windows\n
 \   * SPACEBAR: Switch Mode\n\n
 \ - On Canvas window - \n
 \   * C: Activate Copy Mode On/Off\n
 \   * X: Activate Cut Mode On/Off\n
 \   * Z: Undo Canvas Changes\n
 \   * F: Activate/Deactivate Background Tile Layering Mode\n
 \   * G: Activate Canvas Grid Mode On/Off\n
 \   * Q: Remove/Restore Background\n
 \   * A: Enable/Disable Tracker\n
 \   * S: Activate Symmetry Mode\n\n
 \   -- On Canvas [Symmetry Mode] --\n
 \     * B: Switch Axis in Symmetry Mode\n
 \     * M: Switch between Periodic/Mirror mode in Symmetry Mode\n
 \     * J: Symmetry Line to Center\n
 \     * ARROWKEY: Move Symmetry Line\n\n
 \ - On Tileset window - \n
 \   * CTRL+ARROWKEY: Resize Tile Selection Box\n
 \   * ARROWKEY: Scroll through tileset\n\n
 \ - On Tile window - \n
 \   * CTRL+ARROWKEY: Mirror alongside axis\n
 \   * ARROWKEY: Rotate Tile\n
 \   * MOUSE BUTTON: Switch between Place/Eraser Mode\n\n
 \ ---------------------------------------------------------\n"\n

if $include_background_image
    pass$1 0
else
    i $1
fi

l.
    xr={ceil(w#-1/(abs($4)*$__min_tile))}
    yr={ceil(h#-1/(abs($5)*$__min_tile))}
    split_tiles. {-abs($4)*$__min_tile},{-abs($5)*$__min_tile}
    mw=${-max_w}
    mh=${-max_h}
    ti={$!}
endl

$__min_tile,$__min_tile,1,4,0
fti={$!}

$__bg
+xalp.

dw0c={w#0}
dh0c={h#0}

dwm0=0
dwm1=0
dwm2=0

d2rw=162

w[-1] {w#0},{h#0},0,"Canvas"
rm[-2,-1]
+xalp[1] w1[-1] 

{w#1},{h#1},0,"Tileset" rm.
w2[-1] $d2rw,$d2rw,0,"Tile"

fti={$!}

mode=0

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

    cutcopymode=0
    erasemode=0
    replacemode=0
    editmode=0

    symmetrymode=0
    symmetryaxis=0
    symmetrybound=0
    symmetry_posx=0
    symmetry_posy=0

    canvas_background=1
    canvas_gridmode=0
    canvas_tracker=1

    tileset_gridmode=0

    select_from_tileset=0

    resize_tile_from_tileset=0
    resize_tile_from_canvas=0
    transform_tile=0
    switch_tile_set=0

    tile_placement_mode=0

    current_csx=-1
    current_csy=-1
    optinsert=1

#mode=1#

    activated_switched_twice=0
    modeswitched=0
    changeselectionmode=0
    deselectmode=0
    movemode=0
    delmode=0
    rowcolumnshiftmode=0
    placemove=0
    transfermode=0
    
    current_acsx=-1
    current_acsy=-1

    vmax=0
    pmax=0
    pdiff=0

do
    main_w_title="Canvas"
    if {*,SPACE}" || "{*1,SPACE}" || "{*2,SPACE} 
        if !$mode +store. tile_id1 
        else +store. tile_id2 
        fi 
        mode+=1 mode={$mode%2} 
        wait 200 
    fi
    if $start&&$mode
        if {*,S} changeselectionmode+=1 changeselectionmode={$changeselectionmode%2} fi
        if {*,D} deselectmode+=1 deselectmode={$deselectmode%2} fi
        if $changeselectionmode
            if {*,ARROWLEFT}||{*,ARROWRIGHT} __mode_one_orientation+=1 __mode_one_orientation={$__mode_one_orientation%2} fi
        fi
        
        if $changeselectionmode&&($deselectmode==1) main_w_title.="- [Deselection]"
        elif $changeselectionmode&&($deselectmode==0) main_w_title.="- [Selection]"
        fi
        
        x,y,b,ww,wh={*,x,y,b,w,h}
        
        if $b" && "$x>=0" && "$y>=0" && "$x<w#0" && "$y<h#0
            acsx={floor($x/$__min_tile)} acsy={floor($y/$__min_tile)}
            if $changeselectionmode
                if (($current_acsx!=$acsx)||($current_acsy!=$acsy))
                    if !$deselectmode
                        if !$__mode_one_orientation
                            $__isc
                            f. x==$acsx?1:i
                            vmax={iM#-1}
                            __pmin={find([crop(#-1)],1,0,1)}
                            pmax={find([crop(#-1)],1,$iscl,-1)}
                            pdiff={$pmax-$__pmin+1}
                            store. __isc
                        else
                            $__isr
                            f. x==$acsy?1:i
                            vmax={iM#-1}
                            __pmin={find([crop(#-1)],1,0,1)}
                            pmax={find([crop(#-1)],1,$isrl,-1)}
                            pdiff={$pmax-$__pmin+1}
                            store. __isr
                        fi
                    else
                        if !$__mode_one_orientation
                            $__isc
                            f. x==$acsx?0:i
                            vmax={iM#-1}
                            __pmin={find([crop(#-1)],1,0,1)}
                            pmax={find([crop(#-1)],1,$iscl,-1)}
                            pdiff={$pmax-$__pmin+1}
                            store. __isc
                        else
                            $__isr
                            f. x==$acsy?0:i
                            vmax={iM#-1}
                            __pmin={find([crop(#-1)],1,0,1)}
                            pmax={find([crop(#-1)],1,$isrl,-1)}
                            pdiff={$pmax-$__pmin+1}
                            store. __isr
                        fi
                    fi
                    if $vmax
                        if !$__mode_one_orientation
                            r. {$pdiff*$__min_tile},{h#0}
                            pass2tile. [0],{$__pmin*$__min_tile},0
                        else
                            r. {w#0},{$pdiff*$__min_tile}
                            pass2tile. [0],0,{$__pmin*$__min_tile}

                        fi
                        filter_to_selected_row_column.
                        +out2display. , w2[-1] {w#-1},{h#-1},-1,-1,"Tile" rm. 
                    else
                        r. 1,1
                        f. 0
                        +out2display. , w2[-1] {$d2rw},{$d2rw} rm. 
                    fi
                fi                
            fi
            current_acsx=$acsx current_acsy=$acsy
        fi
        w[] -1,-1,-1,-1,$main_w_title
    else
        undo_state=0
        canvas_set=""
        
        if {*,W}" || "{*1,W}" || "{*2,W} w[] w1[] w2[] fi
        
        if {*,Z} undo_state=1 fi
        
        if {*,G} canvas_gridmode+=1   canvas_gridmode={$canvas_gridmode%2} fi
        if {*,Q} canvas_background+=1 canvas_background={$canvas_background%2} fi
        if {*,A} canvas_tracker+=1 canvas_tracker={$canvas_tracker%2} fi
        
        if {*,F} tile_placement_mode+=1 tile_placement_mode={$tile_placement_mode%2} fi
        if {*,R}" || "{*1,R}" || "{*2,R} 
            replacemode+=1 replacemode={$replacemode%2} optinsert=1 
        fi
        
        if {*,S} symmetrymode+=1 symmetrymode={$symmetrymode%2} fi
        
        if $symmetrymode
            if {*,B} symmetryaxis+=1 symmetryaxis={$symmetryaxis%4} wait 200 fi
            if {*,M} symmetrybound+=1 symmetrybound={$symmetrybound%2} wait 200  fi
            if {*,J} symmetry_posx=0 symmetry_posy=0 wait 200 fi
            if {*,ARROWLEFT} symmetry_posx-=1 wait 200 fi
            if {*,ARROWRIGHT} symmetry_posx+=1 wait 200 fi
            if {*,ARROWUP} symmetry_posy-=1 wait 200 fi
            if {*,ARROWDOWN} symmetry_posy+=1 wait 200 fi
            symmetry_posx={$symmetry_posx>=0?min($ttw,$symmetry_posx):max(-$ttw,$symmetry_posx)}
            symmetry_posy={$symmetry_posy>=0?min($tth,$symmetry_posy):max(-$tth,$symmetry_posy)}
        fi
        
        if $canvas_gridmode
            if $canvas_tracker canvas_endset=,$trackpadcol,$gridcol,
            else canvas_endset=,,$gridcol,
            fi
        else
            if $canvas_tracker canvas_endset=,$trackpadcol,
            else canvas_endset=",,"
            fi
        fi
        if {*,C}" || "{*,X}
            if {*,X} cutcopymode=1
            else cutcopymode=2
            fi
        fi
        
        if {*,D}" || "{*1,D}" || "{*2,D}
            erasemode+=1 
            erasemode={$erasemode%2} 
            if $erasemode  +f. 0 w2[-1] {$d2rw+($d2rw*$icx)},{$d2rw+($d2rw*$icy)} rm. 
            else +out2display. , w2[-1] {$d2rw+($d2rw*$icx)},{$d2rw+($d2rw*$icy)} rm.
            fi
            optinsert=1
        fi
        
        x,y,b,ww,wh={*,x,y,b,w,h}
        x1,y1,b1,ww1,wh1={*1,x,y,b,w,h}
        x2,y2,b2,ww2,wh2={*2,x,y,b,w,h}
        
        if $start
            if $undo_state
                +store[0] temp_undo
                $undo_image
                rv[0,-1]
                rm.
                $temp_undo
                store. undo_image
            fi
            
            if {{*2,CTRLLEFT}" || "{*2,CTRLRIGHT}}" && "{{*2,ARROWLEFT}" || "{*2,ARROWRIGHT}}
                mirror. x transform_tile=1
                wait 100
            elif {{*2,CTRLLEFT}" || "{*2,CTRLRIGHT}}" && "{{*2,ARROWUP}" || "{*2,ARROWDOWN}}
                mirror. y transform_tile=1
                wait 100
            elif {*2,ARROWLEFT}||{*2,ARROWRIGHT}
                temp_tile_width=$tile_width
                temp_tile_height=$tile_height
                temp_icx=$icx
                temp_icy=$icy
                icx=$temp_icy
                icy=$temp_icx
                tile_width=$temp_tile_height
                tile_height=$temp_tile_width
                
                if {*2,ARROWRIGHT} rotate. 90 else rotate. -90 fi
                transform_tile=1
                
                wait 100
            fi
            
            if $transform_tile
                +out2display[$ni] , w1[-1] rm.
                +out2display. , w2[-1] {$d2rw+($d2rw*$icx)},{$d2rw+($d2rw*$icy)} rm.
                transform_tile=0
                optinsert=1
            fi
            
            if {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWRIGHT}}
                if $select_from_tileset
                    icx+=1
                    icx={min($icx,$max_increment)}
                    tile_width={$__min_tile+($icx*$__min_tile)}
                fi
                        
                if $select_from_tileset resize_tile_from_tileset=1 fi
                
                wait 500
            elif {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWLEFT}}
                if $select_from_tileset
                    icx-=1
                    icx={max($icx,0)}
                    tile_width={$__min_tile+($icx*$__min_tile)}
                fi
                        
                if $select_from_tileset resize_tile_from_tileset=1 fi
                
                wait 500
            elif {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWDOWN}}
                if $select_from_tileset
                    icy+=1
                    icy={min($icy,$max_increment)}
                    tile_height={$__min_tile+($icy*$__min_tile)}
                fi
                        
                if $select_from_tileset resize_tile_from_tileset=1 fi
                
                wait 500
            elif {{{*1,CTRLLEFT}" || "{*1,CTRLRIGHT}}" && "{*1,ARROWUP}}
                if $select_from_tileset
                    icy-=1
                    icy={max($icy,0)}
                    tile_height={$__min_tile+($icy*$__min_tile)}
                fi
                        
                if $select_from_tileset resize_tile_from_tileset=1 fi
                
                wait 500
            elif {*1,ARROWRIGHT}
                select_from_tileset=0
                lr+=1
                lr={$lr%$xr}
                ci={($lr+$tb)%$ti}
                ni={$ci+1}
                switch_tile_set=1
                wait 625
            elif {*1,ARROWLEFT}
                select_from_tileset=0
                lr-=1
                lr={$lr%$xr}
                ci={($lr+$tb)%$ti}
                ni={$ci+1}
                switch_tile_set=1
                wait 625
            elif {*1,ARROWDOWN}
                select_from_tileset=0
                tbc+=1
                tbc={$tbc%$yr}
                tb={$tbc*$xr}
                ci={($lr+$tb)%$ti}
                ni={$ci+1}
                switch_tile_set=1
                wait 625
            elif {*1,ARROWUP}
                select_from_tileset=0
                tbc-=1
                tbc={$tbc%$yr}
                tb={$tbc*$xr}
                ci={($lr+$tb)%$ti}
                ni={$ci+1}
                switch_tile_set=1
                wait 625
            fi
            
            if $switch_tile_set
                +out2display[$ni] , w1[-1] {w#$ni+$dwm1*w#$ni},{h#$ni+$dwm1*h#$ni} rm.
                switch_tile_set=0
            fi
            
            if $resize_tile_from_tileset
                    r. $tile_width,$tile_height,100%,100%,0
                    pass2tile. [$ni],$tsx,$tsy
                    +out2display. , w2[-1] {$d2rw+($d2rw*$icx)},{$d2rw+($d2rw*$icy)} rm.
                    if $tileset_gridmode
                        +out2display[$ni] 0,$tsx,$tsy,$tile_width,$tile_height,$trackpadcol,$gridcol
                    else
                        +out2display[$ni] 0,$tsx,$tsy,$tile_width,$tile_height,$trackpadcol
                    fi
                    w1[-1] rm.
                    resize_tile_from_tileset=0
            fi
            
            if $b" && "$x>=0" && "$y>=0" && "$x<w#0" && "$y<h#0
                csx={floor($x/$__min_tile)*$__min_tile} csy={floor($y/$__min_tile)*$__min_tile}
                if !$cutcopymode&&!$erasemode
                    if (($current_csx!=$csx)||($current_csy!=$csy))||$optinsert
                        +store[0] undo_image
                        if $replacemode 
                            if $symmetrymode
                                tile2canvas_r_sym[0,-1] $csx,$csy,$tile_width,$tile_height,$symmetrybound,$symmetryaxis,$symmetry_posx,$symmetry_posy
                            else
                                tile2canvas_r[0,-1] $csx,$csy,$tile_placement_mode
                            fi
                        else
                            if $symmetrymode 
                                tile2canvas_sym[0] [-1],$csx,$csy,$tile_width,$tile_height,$tile_placement_mode,$symmetrybound,$symmetryaxis,$symmetry_posx,$symmetry_posy
                            else 
                                tile2canvas[0] [-1],$csx,$csy,$tile_placement_mode
                            fi
                        fi
                    fi
                    optinsert=0
                elif $cutcopymode&&!$erasemode
                    if $cutcopymode==1 
                        +store[0] undo_image
                        pass2tile. [0],$cx,$cy {w#-1},{h#-1},1,{s#-1} j[0] [-1],$cx,$cy rm.
                    else 
                        pass2tile. [0],$csx,$csy optinsert=0
                    fi
                    +out2display. , w2[-1] {$d2rw+($d2rw*$icx)},{$d2rw+($d2rw*$icy)} rm. 
                    cutcopymode=0
                    optinsert=1
                else
                    +store[0] undo_image
                    cutcopymode=0
                    if (($current_csx!=$csx)||($current_csy!=$csy))||$optinsert
                        if $symmetrymode
                            $tile_width,$tile_height,1,{s#0}
                            j[0] [-1],$csx,$csy 
                            if $symmetryaxis==3||$symmetryaxis==0 j[0] [-1],{$__nw+($__min_tile*$symmetry_posx)-$tile_width-$csx},$csy fi 
                            if $symmetryaxis==3||$symmetryaxis==1 j[0] [-1],$csx,{$__nh+($__min_tile*$symmetry_posy)-$tile_height-$csy} fi 
                            if $symmetryaxis==3||$symmetryaxis==2 j[0] [-1],{$__nw+($__min_tile*$symmetry_posx)-$tile_width-$csx},{$__nh+($__min_tile*$symmetry_posy)-$tile_height-$csy} fi 
                            rm.
                        else
                            $tile_width,$tile_height,1,{s#0} j[0] [-1],$csx,$csy rm.
                        fi
                    fi
                fi
                current_csx=$csx current_csy=$csy
            fi
        
        fi
        
        if $b1" && "$x1>=0" && "$y1>=0" && "$x1<w#1" && "$y1<h#1
            cutcopymode=0
            start=1
            optinsert=1
            select_from_tileset=1
            erasemode=0
            tsx={floor($x1/$__min_tile)*$__min_tile} tsy={floor($y1/$__min_tile)*$__min_tile}
            pass2tile. [$ni],$tsx,$tsy
            +out2display. , w2[-1] rm.
            
            if $tileset_gridmode
                +out2display[$ni] 0,$tsx,$tsy,$tile_width,$tile_height,$trackpadcol,$gridcol
            else
                +out2display[$ni] 0,$tsx,$tsy,$tile_width,$tile_height,$trackpadcol
            fi
            w1[-1] rm.
            
            wait 50
        fi
        
        if !$start
            if $canvas_gridmode
                +out2display[0] $canvas_background,0,0,1,1,,$gridcol
            else
                +out2display[0] $canvas_background
            fi
            if $symmetrymode addsym2display. $symmetryaxis,$__min_tile,$symmetry_posx,$symmetry_posy fi
            w[-1] rm.
        else
            if $x>=0" && "$y>=0" && "$x<w#0" && "$y<h#0
                cx={floor($x/$__min_tile)*$__min_tile} cy={floor($y/$__min_tile)*$__min_tile}
                canvas_set=$canvas_background,$cx,$cy,$tile_width,$tile_height
                canvas_set.=$canvas_endset
                if $symmetrymode
                    if $canvas_gridmode canvas_set.=$symmetryaxis,$symmetry_posx,$symmetry_posy
                    else canvas_set.=,$symmetryaxis,$symmetry_posx,$symmetry_posy
                    fi
                fi
                +out2display[0] $canvas_set
                if $symmetrymode addsym2display. $symmetryaxis,$__min_tile,$symmetry_posx,$symmetry_posy fi
                w[-1]
                rm.
            else
                if $canvas_gridmode
                    +out2display[0] $canvas_background,0,0,1,1,,$gridcol
                else
                    +out2display[0] $canvas_background
                fi
                if $symmetrymode addsym2display. $symmetryaxis,$__min_tile,$symmetry_posx,$symmetry_posy fi
                w[-1] rm.
            fi
        fi
        
        if $start
            if $erasemode main_w_title.=" (Eraser Mode) - " 
            else 
                if $cutcopymode
                    if $cutcopymode==2 main_w_title.=" (Copy Mode) - " 
                    else main_w_title.=" (Cut Mode) - " 
                    fi
                else
                    if $replacemode main_w_title.=" (Replacement Mode) - " 
                    else 
                        if $tile_placement_mode main_w_title.=" (Place Tile [Background]) - " 
                        else main_w_title.=" (Place Tile [Foreground]) - " 
                        fi
                    fi
                fi
            fi

            if $canvas_tracker main_w_title.="(Tracker)" fi
            if $canvas_gridmode main_w_title.="(Grid)" fi
            if $symmetrymode 
                if $symmetryaxis==0  
                    if $symmetrybound main_w_title.="(Symmetry-X (Mirror))"
                    else main_w_title.="(Symmetry-X (Periodic))"
                    fi
                elif $symmetryaxis==1 
                    if $symmetrybound main_w_title.="(Symmetry-Y (Mirror))"
                    else main_w_title.="(Symmetry-Y (Periodic))"
                    fi
                elif $symmetryaxis==2 
                    if $symmetrybound main_w_title.="(Symmetry-XY (Corner) (Mirror))"
                    else main_w_title.="(Symmetry-XY (Corner)(Periodic))"
                    fi
                else                  
                    if $symmetrybound main_w_title.="(Symmetry-XY (Reflected) (Mirror))"
                    else main_w_title.="(Symmetry-XY (Reflected) (Periodic))"
                    fi
                fi
            fi
        fi    
        w[] -1,-1,-1,-1,$main_w_title
    fi
    wait
while {*}" && "!{*,ESC}
uncommand xalp,xalpa,out2display,pass2tile,tile2canvas,tile2canvas_r,tile2canvas_sym,tile2canvas_r_sym,addsym2display,filter_to_selected_row_column
w1[] 0
w2[] 0
k[0]
if $7 $obg rv blend alpha fi

With so many edits, it is hard to keep track. If by x,y,z you mean, xy-location and z-height for character and object sprites, then yes, that would be necessary for an RPG or any game for that matter. Another consideration is boundaries. You wouldn’t want to walk through walls or off cliffs unless your character wants bloody wounds or death.

Ok, that means 3-channel with z depth to it. The third channel being boundary condition.

By the way, @David_Tschumperle, I mentioned you at the PDN forum. This can be ignored as it about a future discussion on adding preset tileset.

When have a bit of time want to arm something with this:
https://corax89.github.io/esp8266Game/index.html

Game examples here: https://corax89.github.io/esp8266Game/gamelist/index.html.

@bazza Of all the game that is on the list, tank city is literally the most feasible with this tool. Basically, only requires extracting the alpha channel of the walls and then simplifying the boxes into 0,1 then rescale to nearest. The rest is done with programming which is out of scope for the purpose of this tool.