stuff YAY, xavier. work on the engine

This commit is contained in:
Jayden Khan 2026-06-04 23:53:15 -07:00
parent b46bfc32d6
commit 539ef72c81
4 changed files with 190 additions and 92 deletions

View File

@ -1,10 +1,13 @@
{
"Lua.workspace.library": [
"${addons}/love2d/module/library"
".vscode/love2d"
],
"Lua.runtime.version": "LuaJIT",
"Lua.runtime.special": {
"love.filesystem.load": "loadfile"
},
"Lua.workspace.checkThirdParty": false
"Lua.workspace.checkThirdParty": false,
"Lua.diagnostics.globals": [
"love"
]
}

10
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
"version": "2.0.0",
"tasks": [{
"label": "Run Love2D",
"type": "shell",
"command": "love .",
"options": { "cwd": "${workspaceFolder}" },
"group": { "kind": "build", "isDefault": true }
}]
}

View File

@ -3,119 +3,194 @@ local ui = {}
ui.theme = {
bg = {0.13, 0.13, 0.14},
panel = {0.17, 0.17, 0.19},
border = {0.28, 0.28, 0.30}, -- also known as outline
border = {0.28, 0.28, 0.30},
borderwidth = 3,
text = {0.90, 0.90, 0.90},
text_dim = {0.50, 0.50, 0.55}, -- low-key forgot
accent = {0.27, 0.52, 0.90}, -- low-key also forgot
text_dim = {0.50, 0.50, 0.55},
accent = {0.27, 0.52, 0.90},
hover = {0.22, 0.25, 0.35},
active = {0.20, 0.40, 0.75}, -- i low-key forgot again, probably made for when a toggle or something is turned on
active = {0.20, 0.40, 0.75},
}
ui.events = {}
ui._wasDown = false
ui._focused = nil
ui._inputs = {}
ui._claimedFocus = false
-- per-frame state (most/all gets reset if i remember)
ui._wasDown = false
ui._focused = nil
ui._inputs = {}
ui._claimedFocus = false
ui._clickConsumed = false
ui._elements = {} -- queue of UI elements, processed at end of frame
ui._hoverConsumed = false -- so it sets hovered to the correct thing
function ui.emit(event)
ui.events[event] = true -- should change to a custom ID soon to prevent conflicts.
end
function ui.on(event)
return ui.events[event] == true
end
function ui.flush() -- all issues is because of this btw (joke, kinda. bunch of bugs from it)
local isDown = love.mouse.isDown(1)
if isDown and not ui._wasDown and not ui._claimedFocus then
ui._focused = nil
end
ui._wasDown = isDown -- update AFTER using it
ui._claimedFocus = false
ui.events = {}
ui._clickConsumed = false
end
function ui.panel(x, y, w, h) -- this thingy magic panel creator makes a ui with outline. (x pos, y pos, width, height)
-- draws a basic bordered panel
function ui._draw_panel(e)
love.graphics.setColor(ui.theme.panel)
love.graphics.rectangle("fill", x, y, w, h)
love.graphics.rectangle("fill", e.x, e.y, e.w, e.h)
love.graphics.setColor(ui.theme.border)
love.graphics.setLineWidth(ui.theme.borderwidth)
love.graphics.rectangle("line", x, y, w, h)
love.graphics.rectangle("line", e.x, e.y, e.w, e.h)
end
function ui.button(x, y, w, h, text)
local mousex, mousey = love.mouse.getPosition()
local hovered = mousex > x and mousex < x + w and mousey > y and mousey < y + h -- calculaters if its touching the box
if hovered then
-- makes dimed panel then text ontop
love.graphics.setColor(ui.theme.hover)
love.graphics.rectangle("fill", x, y, w, h)
love.graphics.setColor(ui.theme.border)
love.graphics.setLineWidth(ui.theme.borderwidth)
love.graphics.rectangle("line", x, y, w, h)
ui.text(x, y, w, h, text)
else
ui.textPanel(x, y, w, h, text) -- just normal text with a background
end
if hovered and love.mouse.isDown(1) and not ui._wasDown and not ui._clickConsumed then
ui.emit(text)
ui._clickConsumed = true
end
return hovered -- returns hovered, this means hovered is returned. and hovered being returned means it returns what hovered is
end
function ui.textPanel(x, y, w, h, text) -- expand on this, havent fully read the text documentation so i dont know if i should have more
ui.panel(x, y, w, h)
ui.text(x, y, w, h, text)
end
function ui.text(x, y, w, h, text)
-- draws centered, wrapped, clipped text inside a box
function ui._draw_text(e)
local font = love.graphics.getFont()
local _, lines = font:getWrap(text, w)
local lineCount = #lines
local lineHeight = font:getHeight()
local totalHeight = lineCount * lineHeight
local startY = y + (h - totalHeight) / 2
local _, lines = font:getWrap(e.text, e.w)
local totalHeight = #lines * font:getHeight()
local startY = e.y + (e.h - totalHeight) / 2
love.graphics.setScissor(x, y, w, h)
love.graphics.setScissor(e.x, e.y, e.w, e.h) -- clip to box bounds
love.graphics.setColor(ui.theme.text)
love.graphics.printf(text, x, startY, w, "center")
love.graphics.setScissor() -- limits drawing space.
love.graphics.printf(e.text, e.x, startY, e.w, "center")
love.graphics.setScissor() -- reset clip
end
function ui.textInput(x, y, w, h, placeholder) -- two days for this to work...
local text = ui._inputs[placeholder] or ""
local focused = ui._focused == placeholder
local mousex, mousey = love.mouse.getPosition()
local clickedInside = mousex > x and mousex < x + w and mousey > y and mousey < y + h
-- draws a button, highlighted on hover
function ui._draw_button(e)
local mx, my = love.mouse.getPosition()
local hovered = not ui._hoverConsumed and mx > e.x and mx < e.x + e.w and my > e.y and my < e.y + e.h
if love.mouse.isDown(1) and not ui._wasDown and clickedInside then
ui._focused = placeholder
ui._claimedFocus = true
end
love.graphics.setColor(e._hovered and ui.theme.hover or ui.theme.panel)
love.graphics.rectangle("fill", e.x, e.y, e.w, e.h)
love.graphics.setColor(ui.theme.border)
love.graphics.setLineWidth(ui.theme.borderwidth)
love.graphics.rectangle("line", e.x, e.y, e.w, e.h)
ui._draw_text(e)
end
-- draws a text input, changes appearance based on focus state
function ui._draw_textInput(e)
local focused = ui._focused == e.placeholder
local text = ui._inputs[e.placeholder] or ""
if focused then
ui.panel(x, y, w, h)
love.graphics.setColor(ui.theme.panel)
love.graphics.rectangle("fill", e.x, e.y, e.w, e.h)
love.graphics.setColor(ui.theme.accent)
love.graphics.setLineWidth(ui.theme.borderwidth)
love.graphics.rectangle("line", e.x, e.y, e.w, e.h)
if text == "" then
-- show dimmed placeholder text when empty
local font = love.graphics.getFont()
local lineHeight = font:getHeight()
local startY = y + (h - lineHeight) / 2
local startY = e.y + (e.h - font:getHeight()) / 2
love.graphics.setColor(ui.theme.text_dim)
love.graphics.printf(placeholder, x + 4, startY, w - 8, "left")
love.graphics.printf(e.placeholder, e.x + 4, startY, e.w - 8, "left")
else
ui.text(x, y, w, h, text)
ui._draw_text({ x=e.x, y=e.y, w=e.w, h=e.h, text=text })
end
else
ui.button(x, y, w, h, text == "" and placeholder or text)
-- unfocused
local display = text == "" and e.placeholder or text
ui._draw_button({ x=e.x, y=e.y, w=e.w, h=e.h, text=display })
end
end
-- bordered panel, no interaction
function ui.panel(x, y, w, h)
table.insert(ui._elements, {
type = "panel",
x=x, y=y, w=w, h=h
})
end
-- centered text inside a box, no background
function ui.text(x, y, w, h, text)
table.insert(ui._elements, {
type = "text",
x=x, y=y, w=w, h=h, text=text
})
end
-- panel with centered text inside (justs draws a panel and puts text ontop, dependant on ui.text)
function ui.textPanel(x, y, w, h, text)
table.insert(ui._elements, {
type = "textPanel",
x=x, y=y, w=w, h=h, text=text
})
end
-- clickable button. callback is called when clicked (optional)
-- example: ui.button(x, y, w, h, "Click me", function() print("hi") end)
function ui.button(x, y, w, h, text, callback)
table.insert(ui._elements, {
type = "button",
x=x, y=y, w=w, h=h, text=text,
callback = callback
})
end
-- text input field. placeholder is also used as its unique ID
-- read typed text with: ui._inputs["placeholder"]
function ui.textInput(x, y, w, h, placeholder)
table.insert(ui._elements, {
type = "textInput",
x=x, y=y, w=w, h=h,
placeholder = placeholder
})
end
function ui.process()
local mx, my = love.mouse.getPosition()
local clicked = love.mouse.isDown(1) and not ui._wasDown
for i = #ui._elements, 1, -1 do
local e = ui._elements[i]
local inside = mx > e.x and mx < e.x + e.w and my > e.y and my < e.y + e.h
-- consume hover for top thing
if inside and not ui._hoverConsumed then
e._hovered = true
ui._hoverConsumed = true
else
e._hovered = false
end
end
-- reverse hit test so topmost element gets the click, similar to above but just for clicking
for i = #ui._elements, 1, -1 do
local e = ui._elements[i]
if clicked and not ui._clickConsumed then
local inside = mx > e.x and mx < e.x + e.w and my > e.y and my < e.y + e.h
if inside then
if e.type == "button" then
if e.callback then e.callback() end -- fire callback if provided
ui._clickConsumed = true
elseif e.type == "textInput" then
ui._focused = e.placeholder
ui._claimedFocus = true
ui._clickConsumed = true
end
end
end
end
-- clicked outside everything, clear focus
if clicked and not ui._claimedFocus then
ui._focused = nil
end
-- draw in order
for i = 1, #ui._elements do
local e = ui._elements[i]
if e.type == "panel" then ui._draw_panel(e)
elseif e.type == "text" then ui._draw_text(e)
elseif e.type == "textPanel" then ui._draw_panel(e) ui._draw_text(e)
elseif e.type == "button" then ui._draw_button(e)
elseif e.type == "textInput" then ui._draw_textInput(e)
end
end
-- clear queue/list for next frame (leave at end)
ui._elements = {}
end
function ui.flush()
ui._wasDown = love.mouse.isDown(1)
ui._claimedFocus = false
ui._clickConsumed = false
ui._hoverConsumed = false
end
-- text things, both used in the process of rendering text
function ui.textinput_char(t)
if ui._focused then
ui._inputs[ui._focused] = (ui._inputs[ui._focused] or "") .. t

View File

@ -1,3 +1,5 @@
-- ctrl+shift+b for launching game
local ui = require("editor.ui")
function love.load()
@ -19,12 +21,20 @@ function love.update(dt)
end
function love.draw()
ui.panel(50,50,50,50)
ui.button(100,200,100,100,"hello world")
if ui.on("hello world") then -- detect if the button is pressed.
ui.panel(250,250,100,100)
end
ui.textInput(50,400,100,100,"textInput")
ui.panel(50, 50, 50, 50)
ui.flush() -- KEEP AT END
ui.button(100, 200, 100, 100, "hello world", function()
print("clicked!")
end)
ui.textInput(50, 400, 100, 100, "textInput")
ui.button(200,200,100,100, "test", function ()
print("below")
end)
ui.button(200,250,100,100, "test2", function ()
print("on top")
end)
ui.process() -- hit test + draw
ui.flush() -- reset input state
end