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
12


This is neat.


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


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.


2

version 1.0

early release

765 tokens

Cart #ssui_sample-0 | 2019-02-17 | Code ▽ | Embed ▽ | No License
2

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.


Very nice!


Thanks, tom


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.



[Please log in to post a comment]