Quickie [was: Immediate Mode Gui]
Quickie [was: Immediate Mode Gui]
Inspired by the I hate myself editor gui and by "Sol on Immediate Mode GUIs", I wrote a little imgui implementation in Lua. Things are handled a bit different than described in the blog article. Check the comments in main.lua and button.lua for a (very brief) introduction how things work. I plan to implement keyboard support soon to enable implementing text-boxes and other widgets using the keyboard. Anyway, here it is:
Edit: Making the 2D slider do something.
- Attachments
-
- imgui.love
- (4.86 KiB) Downloaded 1931 times
Last edited by vrld on Tue Feb 07, 2012 10:27 pm, edited 1 time in total.
Re: Immediate Mode Gui
Very nice vrld! I haven't yet analyzed the code but I already loved this because of the theremin extra!
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: Immediate Mode Gui
That sound square needs to be bigger and allow a wider range of frequencies. Otherwise, you can't play the Star Trek theme with it! Such a shame!
Other than that, pretty nice. Pretty nice.
Other than that, pretty nice. Pretty nice.
When I write def I mean function.
Re: Immediate Mode Gui
But much earlier than some trekie give theremin treatment Delia Derbishire already themed original Dr.Who masterpiece!kikito wrote:That sound square needs to be bigger and allow a wider range of frequencies. Otherwise, you can't play the Star Trek theme with it! Such a shame!
http://www.youtube.com/watch?v=75V4ClJZME4
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: Immediate Mode Gui
That's no theremincoffee wrote:But much earlier than some trekie give theremin treatment Delia Derbishire already themed original Dr.Who masterpiece!
http://www.youtube.com/watch?v=75V4ClJZME4
When I write def I mean function.
Re: Immediate Mode Gui
But I didn't said that Delia used a theremin. She used basically pure oscillators devices (that is also VRLD demo concept basis) that is also the base of theremin (2 oscillators). Don't worry I know well enough Dr. Who theme and pioneer electronic music to say an incorrection like that.kikito wrote:That's no theremincoffee wrote:But much earlier than some trekie give theremin treatment Delia Derbishire already themed original Dr.Who masterpiece!
http://www.youtube.com/watch?v=75V4ClJZME4
Well let's not stay anymore off-topic in vrld nice library!
vrld, I think you need sort better intructions. There is need a lot of lecture jumping to understand things now.
Re: Immediate Mode Gui
Easy:kikito wrote:That sound square needs to be bigger and allow a wider range of frequencies. Otherwise, you can't play the Star Trek theme with it! Such a shame!
- Change (in main.lua) the sound base frequency (in love.load()) to something like 440:
Code: Select all
sd:setSample(i, math.sin(2 * math.pi * 440 * phase))
- Change min/max x-values of the `soundctl' table, e.g.
Code: Select all
local soundctl = {value = {x = 1, y = .5}, min = {x=.3,y=0}, max = {x=3,y=1}}
- Change the 2dslider dimensions and position (don't forget to update the labels as well), e.g
Code: Select all
if gui.Slider2D(soundctl, 360,10,400,400) then
Re: Immediate Mode Gui
Double post because there is now keyboard support (including tab ordering), and an input and checkbox widget. I also separated the widget style from the behavior code, so you can easily swap the global widget style. See quickie/style-default.lua for reference. You can also influence the colors by overwriting the gui.core.style.color and change the look of individual widgets by passing a custom draw function.
I will put this onto github and make a proper documentation soon-ish, but neither usage nor extension is really hard. You can probably grasp the basics of how to use the library by this snippet:
Implementing own widgets is also super easy. gui.core defines some functions to check mouse state, try grabing keyboard focus and more. This is the code to implement the button widget:
And the relevant drawing function is:
Code is here: https://github.com/vrld/Quickie.
I will put this onto github and make a proper documentation soon-ish, but neither usage nor extension is really hard. You can probably grasp the basics of how to use the library by this snippet:
Code: Select all
local gui = require 'quickie'
function love.load()
love.graphics.setFont(love.graphics.newFont(20))
end
-- widgets are "created" by calling their corresponding functions in love.update.
-- if you want to remove a widget, simply don't call the function (just like with
-- any other love drawable). widgets dont hold their own state - this is your job:
--
-- sliders have a value and optional a minimum (default = 0) and maximum (default = 1)
local slider = {value = 10, min = 0, max = 100}
-- input boxes have a text and a cursor position (defaults to end of string)
local input = {text = "Hello, World!", cursor = 0}
-- checkboxes have only a `checked' status
local checkbox = {checked = false}
function love.update(dt)
-- widgets are defined by simply calling them. usually a widget returns true if
-- if its value changed or if it was activated (click on button, ...)
if gui.Input(input, 10, 10, 300, 20) then
print('Text changed:', input.text)
end
-- tab order is determined by the order you call the widgets.
if gui.Button('Clear', 320,10,100,20) then
input.text = ""
end
-- add more widgets here
end
function love.draw()
-- draw the widgets which were "created" in love.update
gui.core.draw()
end
function love.keypressed(key,code)
-- forward keyboard events to the gui. If you don't want widget tabbing and
-- input widgets, skip this line
gui.core.keyboard.pressed(key, code)
end
Code: Select all
-- (...):match("^(.+)%.[^%.]+") extracts the require base, e.g. when required with
-- require 'quickie.button', the base is 'quickie.'
local core = require((...):match("^(.+)%.[^%.]+") .. '.core')
-- the widget
return function(title, x,y, w,h, draw)
-- Generate unique identifier for gui state update and querying.
local id = core.generateID()
-- The widget mouse-state can be:
-- hot (mouse over widget),
-- active (mouse pressed on widget) or
-- normal (mouse not on widget and not pressed on widget).
--
-- core.mouse.updateState(id, x,y,w,h) updates the state for this widget.
core.mouse.updateState(id, x,y,w,h)
-- core.makeTabable makes the item focus on tab. Tab order is determied
-- by the order you call the widget functions.
core.makeTabable(id)
-- core.registerDraw(id, drawfunction, drawfunction-arguments...)
-- shows widget when core.draw() is called.
core.registerDraw(id, draw or core.style.Button, title,x,y,w,h)
return core.mouse.releasedOn(id) or
(core.keyboard.key == 'return' and core.hasKeyFocus(id))
end
Code: Select all
function Button(state, title, x,y,w,h)
local c = color[state]
if state ~= 'normal' then -- draw drop shadow
love.graphics.setColor(c.fg)
love.graphics.rectangle('fill', x+3,y+3,w,h)
end
love.graphics.setColor(c.bg)
love.graphics.rectangle('fill', x,y,w,h)
love.graphics.setColor(c.fg)
local f = love.graphics.getFont()
love.graphics.print(title, x + (w-f:getWidth(title))/2, y + (h-f:getHeight(title))/2)
end
- Attachments
-
- quickie.love
- (10.09 KiB) Downloaded 681 times
Re: Quickie [was: Immediate Mode Gui]
Awesome stuff.
I whipped up an example yesterday. I extended the library with a hackish grid/table arranger. (Press "g" to see the grid outline.)
A newish (0.8.x) build of Love is required for the attached .love file.
I whipped up an example yesterday. I extended the library with a hackish grid/table arranger. (Press "g" to see the grid outline.)
A newish (0.8.x) build of Love is required for the attached .love file.
- Attachments
-
- quickie-example.love
- 0.8.0
- (91.95 KiB) Downloaded 987 times
Last edited by ncarlson on Thu Feb 09, 2012 4:31 pm, edited 1 time in total.
- kikito
- Inner party member
- Posts: 3153
- Joined: Sat Oct 03, 2009 5:22 pm
- Location: Madrid, Spain
- Contact:
Re: Quickie [was: Immediate Mode Gui]
I'm liking this project more and more every time I see it.
Recently I have been working on a small project which would have benefited from a "simple button drawing" function.
A couple comments;
I liked what you did on the init.lua file:
It is clever and elegant. But also a bit brittle. The code will stop working if someone requires the lib with require 'quickie.init' (small chance, but there is some).
In other files you have been using the most common "remove the filename from the path given by require approach":
This is slightly more verbose than necessary. The following pattern does the same and it's shorter:
I always thought that you had to use the first element of ... to get the path - ({...})[1] . I'm a bit surprised that it works without it.
EDIT: Now I understand why. Clever.
EDIT2: What are save_pack and save_unpack doing in core.lua? I don't quite get it.
I'm using 0.7.2 . Is your code only valid for 0.8.x?
Recently I have been working on a small project which would have benefited from a "simple button drawing" function.
A couple comments;
I liked what you did on the init.lua file:
Code: Select all
local BASE = (...) .. '.'
In other files you have been using the most common "remove the filename from the path given by require approach":
Code: Select all
local core = require((...):match("^(.+)%.[^%.]+") .. '.core')
Code: Select all
local core = require((...):match("(.-)[^%.]+$") .. '.core')
EDIT: Now I understand why. Clever.
EDIT2: What are save_pack and save_unpack doing in core.lua? I don't quite get it.
Your example gave me the following error:ncarlson wrote:Awesome stuff.
I whipped up an example yesterday. I extended the library with a hackish grid/table arranger. (Press "g" to see the grid outline.)
Code: Select all
main.lua: 35 attempt to call field 'getMode' (a nil value)
When I write def I mean function.
Who is online
Users browsing this forum: No registered users and 6 guests