Page 6 of 8
Re: Quickie [was: Immediate Mode Gui]
Posted: Wed Dec 11, 2013 3:05 pm
by vrld
Sorry it took so long to answer your posts
The bug in input.lua should
now be fixed, but I couldn't reproduce the slider2d.lua. I also added basic UTF-8 editing support (
this file could also be interesting for other projects) to support umlauts and the like. However, due to the way 0.8 handles text input, this will only work properly in LÖVE 0.9. For this keyboard.pressed(key, code) was split into keyboard.pressed(key) and keyboard.textinput(str). Porting for these changes is straigtforward:
LÖVE 0.8
Code: Select all
function love.keypressed(key, code)
gui.keyboard.pressed(key)
if code >= 32 and code < 127 then -- old behavior
gui.keyboard.textinput(string.char(code))
end
end
LÖVE 0.9
Code: Select all
function love.keypressed(key, code)
gui.keyboard.pressed(key)
end
function love.textinput(str)
gui.keyboard.textinput(str) -- yay, utf8!
end
That multiline textbox is nice by the way. I'll see how to integrate it into Quickie!
Re: Quickie [was: Immediate Mode Gui]
Posted: Wed Dec 11, 2013 4:49 pm
by kikito
Hi!
I did some utf8 manipulation a while back and it resulted in this utf-8 parsing thing:
https://github.com/kikito/utf8_validato ... or.lua#L35
Apparently, using string.find is faster than parsing the bytes one by one.
Full disclaimer: the original implementation was from
Michael Kulchenko, I just found a bug and adapted to my needs.
Re: Quickie [was: Immediate Mode Gui]
Posted: Wed Dec 11, 2013 5:21 pm
by vrld
kikito wrote:Apparently, using string.find is faster than parsing the bytes one by one.
Apparently not for iterating though (or am I missing something?):
Code: Select all
local function iter(s, i)
if i >= #s then return end
local b, nbytes = s:byte(i+1,i+1), 1
-- determine width of the codepoint by counting the number of set bits in the first byte
-- warning: there is no validation of the following bytes!
if b >= 0xc0 and b <= 0xdf then nbytes = 2 -- 1100 0000 to 1101 1111
elseif b >= 0xe0 and b <= 0xef then nbytes = 3 -- 1110 0000 to 1110 1111
elseif b >= 0xf0 and b <= 0xf7 then nbytes = 4 -- 1111 0000 to 1111 0111
elseif b >= 0xf8 and b <= 0xfb then nbytes = 5 -- 1111 1000 to 1111 1011
elseif b >= 0xfc and b <= 0xfd then nbytes = 6 -- 1111 1100 to 1111 1101
elseif b < 0x00 or b > 0x7f then error(("Invalid codepoint: 0x%02x"):format(b))
end
return i+nbytes, s:sub(i+1,i+nbytes), nbytes
end
function iter2(s, i)
if i >= #s then return end
i = i + 1
local nbytes = 0
if i == s:find("[%z\1-\127]", i) then nbytes = 1
elseif i == s:find("[\194-\223][\123-\191]", i) then nbytes = 2
elseif i == s:find( "\224[\160-\191][\128-\191]", i)
or i == s:find("[\225-\236][\128-\191][\128-\191]", i)
or i == s:find( "\237[\128-\159][\128-\191]", i)
or i == s:find("[\238-\239][\128-\191][\128-\191]", i) then nbytes = 3
elseif i == s:find( "\240[\144-\191][\128-\191][\128-\191]", i)
or i == s:find("[\241-\243][\128-\191][\128-\191][\128-\191]", i)
or i == s:find( "\244[\128-\143][\128-\191][\128-\191]", i) then nbytes = 4
end
assert(nbytes > 0, "Invalid UTF8")
return i+nbytes-1, s:sub(i, i+nbytes-1), nbytes
end
Code: Select all
function timeit(f, n)
local start = os.clock()
for i = 1,n do f() end
return os.clock() - start
end
print(timeit(function() for _ in iter, s, 0 do end end, 100000))
--> 0.99
print(timeit(function() for _ in iter2, s, 0 do end end, 100000))
--> 2.34
Re: Quickie [was: Immediate Mode Gui]
Posted: Wed Dec 11, 2013 10:27 pm
by kikito
Oh - hey, good to know
I will have to update *my* utf8 function then.
EDIT: well, maybe not. I see that you are skipping bytes, which I can't do when validating. Maybe when all the bytes are parsed it is worth it to use match. I didn't personally run any tests myself.
Re: Quickie [was: Immediate Mode Gui]
Posted: Tue Jun 03, 2014 4:54 pm
by murks
Now that I've found the actual Quickie thread instead of the ridiculous naming thing, here's the minor bug I want to report:
The example code in README.md doesn't execute:
Code: Select all
function love.keypressed(key, code)
gui.keyboard.pressed(key)
-- LÖVE 0.8: see if this code can be converted in a character
if pcall(string.char, code) code > 0 then
gui.keyboard.textinput(string.char(code))
end
end
I think it should be:
Code: Select all
function love.keypressed(key, code)
gui.keyboard.pressed(key)
-- LÖVE 0.8: see if this code can be converted in a character
if pcall(string.char, code) and code > 0 then
gui.keyboard.textinput(string.char(code))
end
end
I would also love some documentation, for example because I couldn't explain why cycling (using tab) didn't work in my code. It took me hours until I realised that I needed this particular function. The löve 0.8 compatibility thing obfuscated its function rather well, it suggests that this is about text input. Proper documentation would have helped.
I would even write some documentation but there's plenty I don't understand, for example push/pop, widgetHit, draw and so on.
Re: Quickie [was: Immediate Mode Gui]
Posted: Tue Jun 03, 2014 10:03 pm
by murks
I have another question regarding cycling.
Basically I switch between game states in love.update().
So far there's a main menu and an introduction, you can switch back and forth between them. This works fine if I click the button. However, if I use tab to highlight the introduction button and hit enter, there's no way to highlight the 'back' button using tab. Only if I click introduction the back button can be highlighted using tab. It seems as if the cycling thingy is left in a bad state or rather is stuck in the main menu.
Cycling remembers the position in the main menu, and if it's not on the first item in the main menu, it is impossible to cycle through the second menu. Is there a way to 'reset' the cycling thingy when switching between menus?
I may provide some code once I got the nerve to create a minimal working example.
EDIT: Attached is not a minimal example but all the code I have so far. I hope it's not too bad. Ways to reproduce:
A.
1. You are in the main menu, 'tab' to INTRODUCTION or EXIT.
2. Click on INTRODUCTION.
3. You are at the INTRODUCTION screen and there's no way to select BACK using 'tab'.
B.
1. You are in the main menu, 'tab' to EXIT.
2. Click on START.
3. Hit ESC.
4. You are at the retry screen now and there's no way to select buttons by 'tab'.
Re: Quickie [was: Immediate Mode Gui]
Posted: Mon Jun 09, 2014 11:20 am
by murks
I fixed my issue by calling
at the appropriate places. This resets the keyboard focus so that the first element in each menu is focused by default.
Re: Quickie [was: Immediate Mode Gui]
Posted: Sat Jun 14, 2014 11:45 pm
by murks
vrld wrote:Update!
Thanks to MarekkPie, you can now customize the keys that cycle widgets. The default binding is
Code: Select all
gui.core.keyboard.cycle.next = {key = 'tab'}
gui.core.keyboard.cycle.prev = {key = 'tab', 'lshift', 'rshift'}
... which means that 'tab' selects the next widget, while 'tab' + 'lshift'
or 'tab' + 'rshift' select the previous widgets. This scheme allows for any two-(but not three [nor four])-key combination to cycle widgets. For example,
Code: Select all
gui.core.keyboard.cycle = {
prev = {key = ' ', 'a'},
next = {key = ' ', 'd'},
}
cycles on `space + a' and `space + d'.
Cycle keys take precedence over remaining key actions, so if you set them to 'left' and 'right', you won't be able to move in a textbox anymore.
Updated code is at github:
https://github.com/vrld/Quickie
Is it somehow possible to cycle on more than one key? I'm looking something like left or up for previous and right or down for next.
Re: Quickie [was: Immediate Mode Gui]
Posted: Thu Jun 19, 2014 10:27 pm
by murks
Another question:
Is there a nice way to play a sound on:
a) mouse moves over a button? I found some isHot property in the Quickie code, but I don't understand how to use it and I'd need to only play the sound if the mouse was not already on this button.
b) same for keyboard, play the sound only when cycling through the buttons.
Re: Quickie [was: Immediate Mode Gui]
Posted: Tue Jun 24, 2014 8:30 pm
by murks
I was quite surprised to see that by default there's no way to display images. I wrote a very simple image widget in case anyone is interested.