Log In  

So I've started working on a pico8 U.I today. I'll be re-installing linux (switching to fedora) soon so I'm not only using this post as a backup, but also using this post as a sort of preview of things to come.

I wouldn't bother using this just yet, though. Its quite un-optimized so far and not yet finished, and its also not documented and the sample code used for the gif I generated was a bit sloppily thrown together, but if you want to take the code and tweak it to your own needs then by all means do so.
running code:

--s★ui
--shooting★

function s★ui_init()
    s★ui={frame={},mse={0,0}}
    --configure here
        --[1]=bg, [2]=border,
        --[3]=content color
        --[4] = scrollbar back color
        --[5] = scrollbar btn color
        --[6] = scrollbar btn hover
        --      color
        --[7] = content btn bg color
        --[8] = content btn border
        --      color
        --[9] = content btn fg color
        --[10]= content btn bg hover
        --[11]= content btn border
        --      hover
        --[12]= content btn text
        --      hover
    s★ui_wincol={
    6, --1
    5, --2
    1, --3
    1, --4
    6, --5
    9, --6
    2, --7
    1, --8
    6, --9
    1, --10
    8, --11
    6 --12
    }

    --mouse icon
    s★ui_msei = 1

    --content padding
    s★ui_padding=2

    --enable mouse
    poke(0x5f2d, 1)
end

--ui update function
function s★ui_upd()
    --ui mouse coords
    s★ui.mse[1] = stat(32)
    s★ui.mse[2] = stat(33)

    for i=1,#s★ui.frame do
        --draw the frame
        s★ui.frame[i].draw()
    end
    --draw mouse sprite
    spr(s★ui_msei, s★ui.mse[1], s★ui.mse[2])
end

--create a new frame
function s★ui_new(d)
    d = d or {}
    --frame can have custom cols,
    --bg,border and content
    d.bg=d.bg or s★ui_wincol[1]
    d.bdr=d.bdr or s★ui_wincol[2]
    d.cnt=d.cnt or s★ui_wincol[3]
    d.elm={}
    d.cs=0
    d.highest_cnt=0
    --close button, left as object
    --might add more btns later~
    d.btns={
        {
            title='x',
            x=117,
            y=2
        }
    }

    --if disabled close
    if d.dc == true then d.btns[1].disabled = true end
    --else, create close action
    d.btns[1].action=function()
    d.active=false
 end
 d.btns[1].draw=function()
    local col=5
    if s★ui.mse[1] > d.btns[1].x and s★ui.mse[1] < d.btns[1].x + 8 and s★ui.mse[2] > d.btns[1].y and s★ui.mse[2] < d.btns[1].y + 8 and d.dc != true then
        col=1
        if stat(34) == 1 then
            d.btns[1].action()
        end
    end
    print(d.btns[1].title, d.btns[1].x+3, d.btns[1].y, col)
 end
    d.active=true
    d.draw=function()
        if d.active == false then return end
        cls(d.bg)

        for i=1, #d.elm do
            d.elm[i].draw()
        end
        rect(2, 8, 125, 125, d.bdr)
        rectfill(0, 0, 127, 7, d.bg)
        rectfill(0, 126, 127, 127, d.bg)
        for i=1, #d.btns do
            d.btns[i].draw()
        end
        print(d.title, 2, 2, d.cnt)

        rectfill(116, 111, 124, 124, s★ui_wincol[4])
        local mainsc=s★ui_wincol[5]
        local hovcol={mainsc,mainsc}

        if s★ui.mse[1] > 116 and s★ui.mse[1]<124 and s★ui.mse[2]>112 and s★ui.mse[2]<118 then
            hovcol[1] = s★ui_wincol[6]
            if stat(34) == 1 then
                d.cs-=3
                d.cs=max(d.cs, 0)
            end
        end
        if s★ui.mse[1] > 116 and s★ui.mse[1]<124 and s★ui.mse[2]>118 and s★ui.mse[2]<124 then
            hovcol[2] = s★ui_wincol[6]
            if stat(34) == 1 then
                d.cs+=3
            end
        end
        print('⬆️',117, 112, hovcol[1])
        print('⬇️',117, 119, hovcol[2])
        rectfill(3, 118, 116, 124, 1)
         print(':'..d.cs/3, 4, 119, 6)
    end
    add(s★ui.frame, d)
    return s★ui.frame[#s★ui.frame]
end

--new element
function s★ui_newelem(f, d)
    d.type = d.type or 'text'
    d.clicked=0
    d.draw=function()
    local cy=d.y+8+s★ui_padding-f.cs
    local cx=d.x+2+s★ui_padding
        if d.type == 'text' then
            print(d.txt, cx, cy, d.col or f.cnt)
        end

        if d.type == 'hr' then
            line(4, cy, 123, cy, d.col or f.cnt)
        end

        if d.type == 'btn' then
            local cols={s★ui_wincol[7], s★ui_wincol[8], s★ui_wincol[9]}

            if s★ui.mse[1] >= cx and s★ui.mse[1] <= cx+(#d.txt*4)+2 and s★ui.mse[2] >= cy and s★ui.mse[2] <= cy+8 then
                cols={s★ui_wincol[10], s★ui_wincol[11], s★ui_wincol[12]}
                if stat(34) == 1 then
                    d.clicked+=1
                    if d.clicked==1 then
                        d.act()
                    end
                else
                    d.clicked=0
                end
            end
            d.clicked=stat(34)
            rectfill(cx, cy, cx+(#d.txt*4)+2, cy+8, cols[1])
            rect(cx, cy, cx+(#d.txt*4)+2, cy+8, cols[2])
            print(d.txt, cx+2, cy+2, cols[3])
        end

        if d.type == 'chk' then
            d.checked = d.checked or false
            print(d.txt, cx+8, cy+1, d.col or f.cnt)
            if s★ui.mse[1] >= cx and s★ui.mse[1] <= cx+(#d.txt*4)+6 and s★ui.mse[2] >= cy and s★ui.mse[2] <= cy+6 then
                cols={s★ui_wincol[10], s★ui_wincol[11], s★ui_wincol[12]}
                if stat(34) == 1 then
                    d.clicked+=1
                    if d.clicked==1 then
                        d.checked = not d.checked
                    end
                else
                    d.clicked=0
                end
            end
            d.clicked=stat(34)
            rect(cx, cy, cx+6, cy+6, d.col or f.cnt)
            if d.checked==true then
                line(cx+1, cy+3, cx+2, cy+6, d.col or f.cnt)
            line(cx+2, cy+6, cx+5, cy, d.col or f.cnt)
            end
        end
    end
    add(f.elm, d)
    return f.elm[#f.elm]
end

sample code used in gif above:

function _init()
    s★ui_init()

    wnd_main = s★ui_new({
        title='pico8-ui',
        dc=true
    })
    --wnd_main content
    s★ui_newelem(wnd_main, {
    x=0,
    y=0,
    txt='welcome to the pico-8 ui\ndemo!\n\nlicense:\nthis doesn\'t actually have\none, but i thought it would\nlook kinda cool to have\nsome kind of massive text\nwall here for this demo,\nso here it is. please use the\nbuttons on the bottom right\nhand corner to scroll this\npage!'})

    s★ui_newelem(wnd_main, {
    x=0,
    y=112,
    txt=[[oh, neat. you scrolled!
now that you have scrolled,
how about we get a little
more into it? if you want to
use this neat u.i, then be
prepared because it takes
929 tokens. however, as
you can tell its a fully
functional u.i system with
the ability to scroll content
and create buttons, checkboxes
and horizontal rules.

here's a sample setup!

function _init()
 s★ui_init()

 --setup main window
 wnd_main = s★ui_new({
        title='pico8-ui',
        dc=true --disable close
    })

    s★ui_newelem(wnd_main, {
    x=0,
    y=0,
    txt='this is some text'
 })

 wnd_checkbox = s★ui_newelem(
 wnd_main, {
    type='chk',
    x=80,
    y=86,
    txt='checkbox'
    })
end
]]})

    s★ui_newelem(wnd_main, {
    type='hr',
    x=0,
    y=13
    })

    --accept button
    s★ui_newelem(wnd_main, {
    type='btn',
    y=86,
    x=0,
    txt='i accept',
    act=function()
        sfx(0)
        if wnd_checkbox.checked == true then
            wnd_main.active=false
        end
    end
    })

    --fix close button
    s★ui_newelem(wnd_main, {
    type='btn',
    y=96,
    x=0,
    txt='enable win close',
    act=function()
        sfx(1)
        wnd_main.dc = false
    end
    })

    s★ui_newelem(wnd_main, {
    type='hr',
    x=0,
    y=106,
    col=13
    })

    wnd_checkbox = s★ui_newelem(wnd_main, {
    type='chk',
    x=80,
    y=86,
    txt='checkbox'
    })

 --end
end

function _draw()
    cls()
    s★ui_upd()
end
P#61854 2019-02-13 19:35 ( Edited 2019-02-13 20:59)

This is neat.

P#61899 2019-02-14 22:38

This is an interesting project. Do you plan to do line wrapping at some point?

P#61945 2019-02-16 11:06

Probably, though I haven't had much time to work on it since I've been working a lot. But yeah, I may include line-wrapping. Maybe even text-fields or something, depends. I'm trying to use a little tokens as possible so its already had a complete re-write at one point, and may have another soon.

P#61985 2019-02-17 17:35
1

version 1.0

early release

765 tokens

Cart [#ssui_sample-0#] | Code | 2019-02-17 | No License | Embed
1

Alright guys, so here it is. this is the first release~

Place this code somewhere:

--customization
ssui = {
    --config
        --colors
            --[frame background]--
        frm_bg=6,
                   --[frame border]--
        frm_bd=5,
                  --[frame content]--
        frm_cnt=1,
                --[normal icon clr]--
        icn_norm=1,
                 --[icon hover clr]--
        icn_hovr=2,
                  --[button bg clr]--
        btn_bg=1,
              --[button border clr]--
        btn_bd=12,
                --[button text clr]--
        btn_cnt=6,
            --same, but hover
                  --[button bg clr]--
        btnh_bg=13,
              --[button border clr]--
        btnh_bd=9,
                --[button text clr]--
        btnh_cnt=6,

     --icons/sprites
      --mouse (1=pointer,
      --2=clicker) refers to
      --sprite index
     mouse={1, 2},

     --frame-icon text symbols
     icn_scrollup='⬆️',
     icn_scrolldwn='⬇️',
     icn_closewin='❎',
    -----------------------------
    --arrays
    frames={},

    --other
    mousex=0,
    mousey=0,
    mousebtn=0,
    mousemode=1
}

--the code
function ssui_init() poke(0x5f2d, 1) end function ssui_frame(d) d = d or {} d.open = d.open or true d.active = d.active or true d.bg = d.bg or ssui.frm_bg d.bd = d.bd or ssui.frm_bd d.fg = d.fg or ssui.frm_cnt d.sy = 0 d.items={} d.draw = function() if d.open != true then return end cls(d.bg) for i=1,#d.items do local _bumpx=0 local _bumpy=0 local _x=3+d.items[i].x local _y=9+(d.items[i].y)-d.sy local _mx=ssui.mousex local _my=ssui.mousey local _col=d.items[i].tc or d.fg if d.items[i].type == 'hr' then line(_x, _y, 124, _y, _col) end if d.items[i].type == 'btn' then _bumpx = 2 _bumpy = 2 _col = ssui.btn_cnt local _w = (#d.items[i].txt*4)+1 local _bc1=ssui.btn_bg local _bc2=ssui.btn_bd if _mx>=_x and _mx<=_x+_w and _my>=_y and _my<=_y+8 then _col = ssui.btnh_col _bc1=ssui.btnh_bg _bc2=ssui.btnh_bd ssui.mousemode=2 if ssui.mousebtn==1 then d.items[i].clicker+=1 if d.items[i].clicker==1 then d.items[i].act() end else d.items[i].clicker = 0 end end rectfill(_x, _y, _x+_w,_y+8, _bc1) rect(_x, _y, _x+_w, _y+8, _bc2) end if d.items[i].type == 'chk' then _bumpx=7 rect(_x, _y, _x+4, _y+4, _col) if d.items[i].checked == true then print('x', _x+1, _y, _col) end if _mx>_x and _mx<_x+_bumpx+(#d.items[i].txt*4) and _my>_y and _my<_y+4 then if ssui.mousebtn == 1 then d.items[i].clicker+=1 if d.items[i].clicker==1 then d.items[i].checked = not d.items[i].checked end else d.items[i].clicker = 0 end end end print(d.items[i].txt or '', _bumpx+_x, _bumpy+_y, _col) end rect(1, 7, 126, 126, d.bd) rectfill(0, 0, 127, 6, d.bg) line(0, 127, 127, 127, d.bg) local _clscol=ssui.icn_norm local _mx=ssui.mousex local _my=ssui.mousey if _mx>117 and _mx<125 and _my>1 and _my<6 then if d.dc != true then _clscol=ssui.icn_hovr ssui.mousemode=2 if ssui.mousebtn==1 then d.open=false end end end print(d.title, 1, 1, d.fg) print(ssui.icn_closewin, 117, 1, _clscol) rectfill(3, 116, 124, 124, d.fg) print(':'..flr(d.sy), 4, 118, d.bg) _clscol = d.bg _clscol2= d.bg if _mx >=108 and _mx < 116 and _my >= 118 and _my < 124 then _clscol = ssui.icn_hovr if ssui.mousebtn==1 then d.sy-=1 end end if _mx >=116 and _mx < 124 and _my >= 118 and _my < 124 then _clscol2 = ssui.icn_hovr if ssui.mousebtn==1 then d.sy+=1 end end d.sy = max(d.sy, 0) print(ssui.icn_scrollup, 108, 118, _clscol) print(ssui.icn_scrolldwn, 116, 118, _clscol2) end d.add = function(d2) d2.clicker=0 add(d.items, d2) return d.items[#d.items] end add(ssui.frames, d) return ssui.frames[#ssui.frames] end function ssui_draw() ssui.mousemode=1 ssui.mousex=stat(32) ssui.mousey=stat(33) ssui.mousebtn=stat(34) for i=1, #ssui.frames do ssui.frames[i].draw() end spr(ssui.mouse[ssui.mousemode], ssui.mousex, ssui.mousey) end

phew, thats a lot of compressed code. Anyway, now here's how you can use it:
For starters, inside of _init() we're going to create a sample frame. First, we initialize SSUI (Shooting Start U.I)

--init ssui
ssui_init()

Next, we create the frame!

--create frame and disable close
frm_sample = ssui_frame({
    title='picoui - ssui demo',
    dc=true
})

by setting dc to true, we're disabling the ability to click the X at the top right corner. Now then, lets give this frame some content!

--simple text
frm_sample.add({
    x=0,
    y=0,
    txt='janky\n\nso this is what it means to\nhave a really neat u.i\nsystem that has scrolling\ncapabilities.'
})

--checkbox
frm_sample_chkbox = 
 frm_sample.add({
     x=0,
     y=48,
     txt='124 - lock y-scroll',
     type='chk'
})

--button
frm_sample_button = 
 frm_sample.add({
     x=0,
     y=60,
     txt='click me!',
     type='btn',
     act=function()
        sfx(0)
        frm_sample.dc = false
     end
})

--hr
frm_sample.add({
     x=0,
     y=74,
     type='hr',
})

All of these are commented so they should be readable. This code will create what you see in the gif. Clicking the button will play sfx 0 and also will give you the ability to close the frame.

To get everything drawing, lets put this inside _draw() (at the very bottom so it draws over everything else)

ssui_draw()

Finally, to get the checkbox to actually function, lets add something in _update60() (or non 60, up to you tbh)

if frm_sample_chkbox.checked == true then
    frm_sample.sy=0
end

Thats that. So far, this is all I'm capable of. Have fun creating multiple frames/content. Hope this helps some of you continue or start a project.

P#61987 2019-02-17 18:40 ( Edited 2019-02-17 18:50)

Very nice!

P#62856 2019-03-17 18:04

Thanks, tom

P#62863 2019-03-17 20:35

This is great! What do you think you'll use it for? I'm still brainstorming.

And do you have anywhere online I can follow more of your work? haha.

P#65226 2019-06-16 01:46

[Please log in to post a comment]

About | Contact | Updates | Terms of Use
Follow Lexaloffle:        
Generated 2019-06-25 20:36 | 0.027s | 4194k | Q:34