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": [ "Lua.workspace.library": [
"${addons}/love2d/module/library" ".vscode/love2d"
], ],
"Lua.runtime.version": "LuaJIT", "Lua.runtime.version": "LuaJIT",
"Lua.runtime.special": { "Lua.runtime.special": {
"love.filesystem.load": "loadfile" "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 = { ui.theme = {
bg = {0.13, 0.13, 0.14}, bg = {0.13, 0.13, 0.14},
panel = {0.17, 0.17, 0.19}, 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, borderwidth = 3,
text = {0.90, 0.90, 0.90}, text = {0.90, 0.90, 0.90},
text_dim = {0.50, 0.50, 0.55}, -- low-key forgot text_dim = {0.50, 0.50, 0.55},
accent = {0.27, 0.52, 0.90}, -- low-key also forgot accent = {0.27, 0.52, 0.90},
hover = {0.22, 0.25, 0.35}, 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 = {} -- per-frame state (most/all gets reset if i remember)
ui._wasDown = false ui._wasDown = false
ui._focused = nil ui._focused = nil
ui._inputs = {} ui._inputs = {}
ui._claimedFocus = false ui._claimedFocus = false
ui._clickConsumed = 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) -- draws a basic bordered panel
ui.events[event] = true -- should change to a custom ID soon to prevent conflicts. function ui._draw_panel(e)
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)
love.graphics.setColor(ui.theme.panel) 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.setColor(ui.theme.border)
love.graphics.setLineWidth(ui.theme.borderwidth) 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 end
function ui.button(x, y, w, h, text) -- draws centered, wrapped, clipped text inside a box
local mousex, mousey = love.mouse.getPosition() function ui._draw_text(e)
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)
local font = love.graphics.getFont() local font = love.graphics.getFont()
local _, lines = font:getWrap(text, w) local _, lines = font:getWrap(e.text, e.w)
local lineCount = #lines local totalHeight = #lines * font:getHeight()
local lineHeight = font:getHeight() local startY = e.y + (e.h - totalHeight) / 2
local totalHeight = lineCount * lineHeight
local startY = y + (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.setColor(ui.theme.text)
love.graphics.printf(text, x, startY, w, "center") love.graphics.printf(e.text, e.x, startY, e.w, "center")
love.graphics.setScissor() -- limits drawing space. love.graphics.setScissor() -- reset clip
end end
function ui.textInput(x, y, w, h, placeholder) -- two days for this to work... -- draws a button, highlighted on hover
local text = ui._inputs[placeholder] or "" function ui._draw_button(e)
local focused = ui._focused == placeholder local mx, my = love.mouse.getPosition()
local mousex, mousey = 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
local clickedInside = mousex > x and mousex < x + w and mousey > y and mousey < y + h
if love.mouse.isDown(1) and not ui._wasDown and clickedInside then love.graphics.setColor(e._hovered and ui.theme.hover or ui.theme.panel)
ui._focused = placeholder love.graphics.rectangle("fill", e.x, e.y, e.w, e.h)
ui._claimedFocus = true love.graphics.setColor(ui.theme.border)
end 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 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 if text == "" then
-- show dimmed placeholder text when empty
local font = love.graphics.getFont() local font = love.graphics.getFont()
local lineHeight = font:getHeight() local startY = e.y + (e.h - font:getHeight()) / 2
local startY = y + (h - lineHeight) / 2
love.graphics.setColor(ui.theme.text_dim) 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 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 end
else 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
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) function ui.textinput_char(t)
if ui._focused then if ui._focused then
ui._inputs[ui._focused] = (ui._inputs[ui._focused] or "") .. t 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") local ui = require("editor.ui")
function love.load() function love.load()
@ -19,12 +21,20 @@ function love.update(dt)
end end
function love.draw() function love.draw()
ui.panel(50,50,50,50) 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.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 end