Created
September 21, 2022 00:21
-
-
Save x4fx77x4f/d9e3e9b43e9ff2d7725acfc122c32543 to your computer and use it in GitHub Desktop.
Work-in-progress on-screen keyboard for StarfallEx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--@client | |
local osk | |
do | |
osk = {} | |
local function enum(t_in) | |
local n = #t_in | |
local bits = 0 | |
repeat | |
bits = bits+1 | |
until n <= 2^bits | |
assert(bits <= 32, "bit count for enum cannot exceed 32") | |
local t_out = {} | |
t_out._BITS = bits | |
for i=1, #t_in do | |
t_out[t_in[i]] = i-1 | |
end | |
return t_out | |
end | |
local function bitfield(t_in) | |
local bits = #t_in | |
assert(bits <= 31, "bit count for bitfield cannot exceed 31") | |
local t_out = {} | |
t_out._BITS = bits | |
local all = 0 | |
for i=1, #t_in do | |
local b = bit.lshift(1, i-1) | |
t_out[t_in[i]] = b | |
all = bit.bor(all, b) | |
end | |
t_out._ALL = all | |
return t_out | |
end | |
osk.F = enum({ | |
'BACKSPACE', | |
'TAB', | |
'CAPSLOCK', | |
'RETURN', | |
'SHIFT', | |
'CTRL', | |
'SUPER', | |
'ALT', | |
'MENU', | |
'OSK_HIDE', | |
'OSK_LOCK', | |
}) | |
local labels = { | |
[osk.F.BACKSPACE] = "Backspace", | |
[osk.F.TAB] = "Tab", | |
[osk.F.CAPSLOCK] = "Caps Lock", | |
[osk.F.RETURN] = "Return", | |
[osk.F.SHIFT] = "Shift", | |
[osk.F.CTRL] = "Ctrl", | |
[osk.F.SUPER] = "Super", | |
[osk.F.ALT] = "Alt", | |
[osk.F.MENU] = "Menu", | |
[osk.F.OSK_HIDE] = "Hide", | |
[osk.F.OSK_LOCK] = "Lock", | |
} | |
osk.INPUTMODE = enum({ | |
'TEXT', | |
'DECIMAL', | |
'NUMERIC', | |
'TEL', | |
'SEARCH', | |
'EMAIL', | |
'URL', | |
}) | |
osk.FLAGS = bitfield({ | |
'LETTERS', | |
'DIGITS', -- Digits and "!@#$%^&*()" | |
'PUNCTUATION', -- "`-=[]\\;',./~_+{}|:\"<>?" | |
'SHIFT', -- Shift and caps lock | |
'CTRL', | |
'SYSTEM', -- Tab, shift, ctrl, alt, super, and menu | |
}) | |
local p = 4 | |
local rc = 5 | |
local e = {} | |
osk._e = e | |
e.w = 512 | |
e.h = 170 | |
e.x = 0 | |
e.y = 512-e.h | |
local eiw, eih = e.w-p-p, (e.h-p)/rc-p | |
for i=1, 5 do | |
local ei = {} | |
e[i] = ei | |
ei.w = eiw | |
ei.h = eih | |
ei.x = p | |
ei.y = (i-1)*(eih+p)+p | |
end | |
local e1 = e[1] | |
local e1jw = (e1.w+p)/15 | |
for j=1, 14 do | |
local e1j = {} | |
e1[j] = e1j | |
e1j.w = e1jw-p | |
e1j.h = e1.h | |
e1j.x = (j-1)*e1jw | |
e1j.y = 0 | |
end | |
local s, s_shift, s_caps = '`1234567890-=', '~!@#$%^&*()_+' | |
for i=1, 13 do | |
local e1i = e1[i] | |
e1i.s = string.sub(s, i, i) | |
e1i.s_shift = string.sub(s_shift, i, i) | |
e1i.flags = osk.FLAGS.DIGITS | |
end | |
e1[1].flags = osk.FLAGS.PUNCTUATION | |
e1[12].flags = osk.FLAGS.PUNCTUATION | |
e1[13].flags = osk.FLAGS.PUNCTUATION | |
e1[14].f = osk.F.BACKSPACE | |
e1[14].flags = osk.FLAGS._ALL | |
e1[14].w = e1[14].w+e1jw | |
local e2 = e[2] | |
local e2_1w = e1jw*1.5 | |
for j=2, 14 do | |
local e2j = {} | |
e2[j] = e2j | |
e2j.w = e1jw-p | |
e2j.h = e2.h | |
e2j.x = (j-2)*e1jw+e2_1w+p | |
e2j.y = 0 | |
end | |
s, s_caps = '\x00qwertyuiop', '\x00QWERTYUIOP' | |
for i=2, 11 do | |
local e2i = e2[i] | |
e2i.s = string.sub(s, i, i) | |
e2i.s_caps = string.sub(s_caps, i, i) | |
e2i.flags = osk.FLAGS.LETTERS | |
end | |
local e2_1 = {} | |
e2[1] = e2_1 | |
e2_1.f = osk.F.TAB | |
e2_1.flags = osk.FLAGS.SYSTEM | |
e2_1.w = e2_1w | |
e2_1.h = e2.h | |
e2_1.x = 0 | |
e2_1.y = 0 | |
e2[12].s = '[' | |
e2[12].s_shift = '{' | |
e2[12].flags = osk.FLAGS.PUNCTUATION | |
e2[13].s = ']' | |
e2[13].s_shift = '}' | |
e2[13].flags = osk.FLAGS.PUNCTUATION | |
e2[14].s = '\\' | |
e2[14].s_shift = '|' | |
e2[14].flags = osk.FLAGS.PUNCTUATION | |
e2[14].w = e2.w-e2[14].x | |
local e3 = e[3] | |
local e3_1w = e1jw*1.8 | |
for j=2, 13 do | |
local e3j = {} | |
e3[j] = e3j | |
e3j.w = e1jw-p | |
e3j.h = e3.h | |
e3j.x = (j-2)*e1jw+e3_1w+p | |
e3j.y = 0 | |
end | |
s, s_caps = '\x00asdfghjkl', '\x00ASDFGHJKL' | |
for i=2, 12 do | |
local e3i = e3[i] | |
e3i.s = string.sub(s, i, i) | |
e3i.s_caps = string.sub(s_caps, i, i) | |
e3i.flags = osk.FLAGS.LETTERS | |
end | |
local e3_1 = {} | |
e3[1] = e3_1 | |
e3_1.f = osk.F.CAPSLOCK | |
e3_1.flags = bit.bor(osk.FLAGS.SYSTEM, osk.FLAGS.SHIFT) | |
e3_1.w = e3_1w | |
e3_1.h = e3.h | |
e3_1.x = 0 | |
e3_1.y = 0 | |
e3[11].s = ';' | |
e3[11].s_shift = ':' | |
e3[11].flags = osk.FLAGS.PUNCTUATION | |
e3[12].s = '\'' | |
e3[12].s_shift = '"' | |
e3[12].flags = osk.FLAGS.PUNCTUATION | |
e3[13].f = osk.F.RETURN | |
e3[13].flags = osk.FLAGS._ALL | |
e3[13].w = e3.w-e3[13].x | |
local e4 = e[4] | |
local e4_1w = e1jw*2.4 | |
for j=2, 12 do | |
local e4j = {} | |
e4[j] = e4j | |
e4j.w = e1jw-p | |
e4j.h = e4.h | |
e4j.x = (j-2)*e1jw+e4_1w+p | |
e4j.y = 0 | |
end | |
s, s_caps = '\x00zxcvbnm', '\x00ZXCVBNM' | |
for i=2, 9 do | |
local e4i = e4[i] | |
e4i.s = string.sub(s, i, i) | |
e4i.s_caps = string.sub(s_caps, i, i) | |
e4i.flags = osk.FLAGS.LETTERS | |
end | |
local e4_1 = {} | |
e4[1] = e4_1 | |
e4_1.f = osk.F.SHIFT | |
e4_1.flags = bit.bor(osk.FLAGS.SYSTEM, osk.FLAGS.SHIFT) | |
e4_1.w = e4_1w | |
e4_1.h = e4.h | |
e4_1.x = 0 | |
e4_1.y = 0 | |
e4[9].s = ',' | |
e4[9].s_shift = '<' | |
e4[9].flags = osk.FLAGS.PUNCTUATION | |
e4[10].s = '.' | |
e4[10].s_shift = '>' | |
e4[10].flags = osk.FLAGS.PUNCTUATION | |
e4[11].s = '/' | |
e4[11].s_shift = '?' | |
e4[11].flags = osk.FLAGS.PUNCTUATION | |
e4[12].f = osk.F.SHIFT | |
e4[12].flags = bit.bor(osk.FLAGS.SYSTEM, osk.FLAGS.SHIFT) | |
e4[12].w = e4.w-e4[12].x | |
local e5 = e[5] | |
local e5_4w = e1jw*5.5 | |
local e5jw = (e5.w-e5_4w)/7 | |
for j=1, 8 do | |
local e5j = {} | |
e5[j] = e5j | |
e5j.w = e5jw-p | |
e5j.h = e5.h | |
e5j.x = (j-1)*e5jw+(j > 4 and e5_4w-e5jw+p or 0) | |
e5j.y = 0 | |
end | |
e5[1].f = osk.F.CTRL | |
e5[1].flags = bit.bor(osk.FLAGS.SYSTEM, osk.FLAGS.CTRL) | |
e5[2].f = osk.F.SUPER | |
e5[2].flags = osk.FLAGS.SYSTEM | |
e5[3].f = osk.F.ALT | |
e5[3].flags = osk.FLAGS.SYSTEM | |
e5[4].s = ' ' | |
e5[4].flags = osk.FLAGS._ALL | |
e5[4].w = e5_4w | |
e5[5].f = osk.F.ALT | |
e5[5].flags = osk.FLAGS.SYSTEM | |
e5[6].f = osk.F.SUPER | |
e5[5].flags = osk.FLAGS.SYSTEM | |
e5[7].f = osk.F.MENU | |
e5[5].flags = osk.FLAGS.SYSTEM | |
e5[8].f = osk.F.CTRL | |
e5[5].flags = bit.bor(osk.FLAGS.SYSTEM, osk.FLAGS.CTRL) | |
osk.bg = Color(0, 0, 0) | |
osk.bg_k = Color('#474747') | |
osk.bg_k_special = Color('#222222') | |
osk.fg = Color('#ffffff') | |
osk.fg_outline = Color(255, 255, 255, 15) | |
osk.fg_off = Color(0, 0, 0) | |
osk.fg_on = Color('#44afd6') | |
osk.fg_on_alt = Color('#fcae00') | |
local function draw_outline(x, y, w, h, r) | |
render.drawRect(x, y, w, r) | |
render.drawRect(x, y+h-r, w, r) | |
render.drawRect(x, y, r, h) | |
render.drawRect(x+w-r, y, r, h) | |
end | |
local function draw_box(x, y, e) | |
local w, h = e.w, e.h | |
x, y = x+e.x, y+e.y | |
render.drawRect(x, y, w, h) | |
end | |
local function draw_box_outlined(x, y, e) | |
local w, h = e.w, e.h | |
x, y = x+e.x, y+e.y | |
render.drawRect(x, y, w, h) | |
render.setColor(osk.fg_outline) | |
draw_outline(x, y, w, h, 1) | |
end | |
local id = 'osk' | |
render.createRenderTarget(id) | |
hook.add('renderoffscreen', id, function() | |
hook.remove('renderoffscreen', id) | |
render.selectRenderTarget(id) | |
render.clear(Color(255, 255, 255, 0), true) | |
local x, y = 0, 0 | |
render.setColor(osk.bg) | |
draw_box(x, y, e) | |
x, y = x+e.x, y+e.y | |
for i=1, #e do | |
local ei = e[i] | |
local x, y = x+ei.x, y+ei.y | |
for j=1, #ei do | |
local eij = ei[j] | |
render.setColor(eij.f ~= nil and osk.bg_k_special or osk.bg_k) | |
draw_box_outlined(x, y, eij) | |
local label = eij.s | |
if label == nil then | |
label = labels[eij.f] | |
end | |
if label ~= nil then | |
render.setColor(osk.fg) | |
render.setFont('DermaDefault') | |
render.drawSimpleText(x+eij.x+eij.w/2, y+eij.y+eij.h/2, label, TEXT_ALIGN.CENTER ,TEXT_ALIGN.CENTER) | |
end | |
end | |
end | |
end) | |
local color_white = Color(255, 255, 255) | |
function osk.draw_osk() | |
render.setColor(color_white) | |
render.setRenderTargetTexture(id) | |
render.drawTexturedRectUV(0, 0, 512, 512, 0, 0, 0.5, 0.5) | |
end | |
end | |
local color_bg = Color(63, 63, 63) | |
local color_fg = Color(255, 255, 255) | |
local color_outline = Color(127, 127, 127) | |
local function draw_outline(x, y, w, h, r) | |
--return render.drawRectOutline(x, y, w, h, r) | |
render.drawRect(x, y, w, r) | |
render.drawRect(x, y+h-r, w, r) | |
render.drawRect(x, y, r, h) | |
render.drawRect(x+w-r, y, r, h) | |
end | |
local function draw_box(x, y, e) | |
local w, h = e.w, e.h | |
x, y = x+e.x, y+e.y | |
render.setColor(color_bg) | |
render.drawRect(x, y, w, h) | |
render.setColor(color_outline) | |
draw_outline(x, y, w, h, 2) | |
end | |
hook.add('render', '', function() | |
render.setBackgroundColor(color_bg) | |
local p = 8 | |
local x, y = p, p | |
render.setFont('DermaLarge') | |
local ew, eh = render.drawSimpleText(x, y, "On-screen keyboard demo") | |
y = y+eh+p | |
render.setFont('DermaDefault') | |
ew, eh = render.drawSimpleText(x, y, "Click by looking at element and pressing Use or Primary Fire.") | |
y = y+eh+p | |
osk.draw_osk() | |
end) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment