keharriso / love-nuklear

Lightweight immediate mode GUI for LÖVE games
MIT License
350 stars 32 forks source link

What is the correct way to create a closable window? #29

Closed olivier-grech closed 5 years ago

olivier-grech commented 6 years ago

Using the following code:

local nk = require 'nuklear'

function love.load()
    nk.init()
end

function love.update(dt)
    nk.frameBegin()
    if nk.windowBegin('Simple Example', 100, 100, 200, 160, 'closable') then
    end
    nk.windowEnd()
    nk.frameEnd()
end

function love.draw()
    nk.draw()
end

function love.keypressed(key, scancode, isrepeat)
    nk.keypressed(key, scancode, isrepeat)
end

function love.keyreleased(key, scancode)
    nk.keyreleased(key, scancode)
end

function love.mousepressed(x, y, button, istouch)
    nk.mousepressed(x, y, button, istouch)
end

function love.mousereleased(x, y, button, istouch)
    nk.mousereleased(x, y, button, istouch)
end

function love.mousemoved(x, y, dx, dy, istouch)
    nk.mousemoved(x, y, dx, dy, istouch)
end

function love.textinput(text)
    nk.textinput(text)
end

function love.wheelmoved(x, y)
    nk.wheelmoved(x, y)
end

This creates a window that appears to be closable (there is a X in the top right corner), however, when clicking on said X, the window opens again in the next frame.

Is this an expected behavior? If yes, what is the correct way to create a window that can be closed?

keharriso commented 6 years ago

EDIT: The solution to this question has changed. See my answer further down the page.

This is a peculiarity of Nuklear. The way to solve it is to use the return value of nk.windowBegin. If it returns false, then the window has been closed. You can then call nk.windowHide in order to hide the closed window. There might be room here for improvement in the API.

function love.update(dt)
    nk.frameBegin()
    if nk.windowBegin('Simple Example', 100, 100, 200, 160, 'closable') then
    else
        nk.windowHide('Simple Example')
    end
    nk.windowEnd()
    nk.frameEnd()
end

Hopefully that solves your problem.

olivier-grech commented 5 years ago

Did the behavior change by chance?

I am having the same issue with the following code:

local nuklear = require "nuklear"

local ui1

function love.load()
    ui1 = nuklear.newUI()
end

function love.update(dt)
    ui1:frameBegin()
    if ui1:windowBegin("Chat", 50, 50, 400, 300, "border", "movable", "title", "closable") then
    else
        ui1:windowHide("Chat")
    end
    ui1:windowEnd()
    ui1:frameEnd()
end

function love.draw()
    ui1:draw()
end

local function input(name, ...)
    return ui1[name](ui1, ...)
end

function love.keypressed(key, scancode, isrepeat)
    input("keypressed", key, scancode, isrepeat)
end

function love.keyreleased(key, scancode)
    input("keyreleased", key, scancode)
end

function love.mousepressed(x, y, button, istouch, presses)
    input("mousepressed", x, y, button, istouch, presses)
end

function love.mousereleased(x, y, button, istouch, presses)
    input("mousereleased", x, y, button, istouch, presses)
end

function love.mousemoved(x, y, dx, dy, istouch)
    input("mousemoved", x, y, dx, dy, istouch)
end

function love.textinput(text)
    input("textinput", text)
end

function love.wheelmoved(x, y)
    input("wheelmoved", x, y)
end
keharriso commented 5 years ago

Somewhere between version 2.0 of LÖVE-Nuklear and the latest several versions of Nuklear itself, the old answer to this question doesn't work anymore (as you've noticed). You can get the same result by keeping track of whether or not to show the window in a variable (here titled "showChat"):

local showChat = true
function love.update(dt)
    ui1:frameBegin()
    if showChat then
        if ui1:windowBegin("Chat", 50, 50, 400, 300, "border", "movable", "title", "closable") then
        else
            showChat = false
        end
        ui1:windowEnd()
    end
    ui1:frameEnd()
end
olivier-grech commented 5 years ago

Thanks... again. :)

Might be worth mentioning it in the wiki maybe?