mirror of
https://github.com/Insality/druid.git
synced 2025-06-27 02:17:52 +02:00
Add more widgets
This commit is contained in:
parent
6cb2c9ca9a
commit
37190684c4
222
druid/color.lua
Normal file
222
druid/color.lua
Normal file
@ -0,0 +1,222 @@
|
||||
---@type table<string, table<string, vector4>>
|
||||
local PALETTE_DATA
|
||||
local CURRENT_PALETTE = "default"
|
||||
local DEFAULT_COLOR = vmath.vector4(1, 1, 1, 1)
|
||||
local COLOR_X = hash("color.x")
|
||||
local COLOR_Y = hash("color.y")
|
||||
local COLOR_Z = hash("color.z")
|
||||
|
||||
local M = {}
|
||||
|
||||
|
||||
---Get color color by id
|
||||
---@param color_id string
|
||||
---@return vector4
|
||||
function M.get(color_id)
|
||||
return PALETTE_DATA[CURRENT_PALETTE] and PALETTE_DATA[CURRENT_PALETTE][color_id] or DEFAULT_COLOR
|
||||
end
|
||||
|
||||
|
||||
---Add palette to palette data
|
||||
---@param palette_name string
|
||||
---@param palette_data table<string, vector4>
|
||||
function M.add_palette(palette_name, palette_data)
|
||||
PALETTE_DATA[palette_name] = PALETTE_DATA[palette_name] or {}
|
||||
local palette = PALETTE_DATA[palette_name]
|
||||
|
||||
for color_id, color in pairs(palette_data) do
|
||||
if type(color) == "string" then
|
||||
palette[color_id] = M.hex2vector4(color)
|
||||
else
|
||||
palette[color_id] = color
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function M.set_palette(palette_name)
|
||||
if PALETTE_DATA[palette_name] then
|
||||
CURRENT_PALETTE = palette_name
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function M.get_palette()
|
||||
return CURRENT_PALETTE
|
||||
end
|
||||
|
||||
|
||||
---Set color of gui node without changing alpha
|
||||
---@param gui_node node
|
||||
---@param color vector4|vector3|string Color in vector4, vector3 or color id from palette
|
||||
function M.set_color(gui_node, color)
|
||||
if type(color) == "string" then
|
||||
color = M.get(color)
|
||||
end
|
||||
|
||||
gui.set(gui_node, COLOR_X, color.x)
|
||||
gui.set(gui_node, COLOR_Y, color.y)
|
||||
gui.set(gui_node, COLOR_Z, color.z)
|
||||
end
|
||||
|
||||
|
||||
function M.get_random_color()
|
||||
return vmath.vector4(math.random(), math.random(), math.random(), 1)
|
||||
end
|
||||
|
||||
|
||||
---Lerp colors via color HSB values
|
||||
function M.lerp(t, color1, color2)
|
||||
local h1, s1, v1 = M.rgb2hsb(color1.x, color1.y, color1.z)
|
||||
local h2, s2, v2 = M.rgb2hsb(color2.x, color2.y, color2.z)
|
||||
|
||||
local h = h1 + (h2 - h1) * t
|
||||
local s = s1 + (s2 - s1) * t
|
||||
local v = v1 + (v2 - v1) * t
|
||||
|
||||
local r, g, b, a = M.hsb2rgb(h, s, v)
|
||||
a = a or 1
|
||||
return vmath.vector4(r, g, b, a)
|
||||
end
|
||||
|
||||
|
||||
---@param hex string
|
||||
---@param alpha number|nil
|
||||
---@return number, number, number, number
|
||||
function M.hex2rgb(hex, alpha)
|
||||
alpha = alpha or 1
|
||||
if alpha > 1 then
|
||||
alpha = alpha / 100
|
||||
end
|
||||
|
||||
-- Remove leading #
|
||||
if string.sub(hex, 1, 1) == "#" then
|
||||
hex = string.sub(hex, 2)
|
||||
end
|
||||
|
||||
-- Expand 3-digit hex codes to 6 digits
|
||||
if #hex == 3 then
|
||||
hex = string.rep(string.sub(hex, 1, 1), 2) ..
|
||||
string.rep(string.sub(hex, 2, 2), 2) ..
|
||||
string.rep(string.sub(hex, 3, 3), 2)
|
||||
end
|
||||
|
||||
local r = tonumber("0x" .. string.sub(hex, 1, 2)) / 255
|
||||
local g = tonumber("0x" .. string.sub(hex, 3, 4)) / 255
|
||||
local b = tonumber("0x" .. string.sub(hex, 5, 6)) / 255
|
||||
return r, g, b, alpha
|
||||
end
|
||||
|
||||
|
||||
---@param hex string
|
||||
---@param alpha number|nil
|
||||
---@return vector4
|
||||
function M.hex2vector4(hex, alpha)
|
||||
local r, g, b, a = M.hex2rgb(hex, alpha)
|
||||
return vmath.vector4(r, g, b, a)
|
||||
end
|
||||
|
||||
|
||||
---Convert hsb color to rgb color
|
||||
---@param r number @Red value
|
||||
---@param g number @Green value
|
||||
---@param b number @Blue value
|
||||
---@param alpha number|nil @Alpha value. Default is 1
|
||||
function M.rgb2hsb(r, g, b, alpha)
|
||||
alpha = alpha or 1
|
||||
local min, max = math.min(r, g, b), math.max(r, g, b)
|
||||
local delta = max - min
|
||||
local h, s, v = 0, max, max
|
||||
|
||||
s = max ~= 0 and delta / max or 0
|
||||
|
||||
if delta ~= 0 then
|
||||
if r == max then
|
||||
h = (g - b) / delta
|
||||
elseif g == max then
|
||||
h = 2 + (b - r) / delta
|
||||
else
|
||||
h = 4 + (r - g) / delta
|
||||
end
|
||||
h = (h / 6) % 1
|
||||
end
|
||||
|
||||
alpha = alpha > 1 and alpha / 100 or alpha
|
||||
|
||||
return h, s, v, alpha
|
||||
end
|
||||
|
||||
|
||||
---Convert hsb color to rgb color
|
||||
---@param h number @Hue
|
||||
---@param s number @Saturation
|
||||
---@param v number @Value
|
||||
---@param alpha number|nil @Alpha value. Default is 1
|
||||
function M.hsb2rgb(h, s, v, alpha)
|
||||
local r, g, b
|
||||
local i = math.floor(h * 6)
|
||||
local f = h * 6 - i
|
||||
local p = v * (1 - s)
|
||||
local q = v * (1 - f * s)
|
||||
local t = v * (1 - (1 - f) * s)
|
||||
|
||||
i = i % 6
|
||||
|
||||
if i == 0 then r, g, b = v, t, p
|
||||
elseif i == 1 then r, g, b = q, v, p
|
||||
elseif i == 2 then r, g, b = p, v, t
|
||||
elseif i == 3 then r, g, b = p, q, v
|
||||
elseif i == 4 then r, g, b = t, p, v
|
||||
elseif i == 5 then r, g, b = v, p, q
|
||||
end
|
||||
|
||||
return r, g, b, alpha
|
||||
end
|
||||
|
||||
|
||||
---Convert rgb color to hex color
|
||||
---@param red number @Red value
|
||||
---@param green number @Green value
|
||||
---@param blue number @Blue value
|
||||
function M.rgb2hex(red, green, blue)
|
||||
local r = string.format("%x", math.floor(red * 255))
|
||||
local g = string.format("%x", math.floor(green * 255))
|
||||
local b = string.format("%x", math.floor(blue * 255))
|
||||
return string.upper((#r == 1 and "0" or "") .. r .. (#g == 1 and "0" or "") .. g .. (#b == 1 and "0" or "") .. b)
|
||||
end
|
||||
|
||||
|
||||
function M.load_palette()
|
||||
local PALETTE_PATH = sys.get_config_string("fluid.palette")
|
||||
if PALETTE_PATH then
|
||||
PALETTE_DATA = M.load_json(PALETTE_PATH) --[[@as table<string, table<string, vector4>>]]
|
||||
end
|
||||
PALETTE_DATA = PALETTE_DATA or {}
|
||||
|
||||
for _, palette_data in pairs(PALETTE_DATA) do
|
||||
for color_id, color in pairs(palette_data) do
|
||||
if type(color) == "string" then
|
||||
palette_data[color_id] = M.hex2vector4(color)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---Load JSON file from game resources folder (by relative path to game.project)
|
||||
---Return nil if file not found or error
|
||||
---@param json_path string
|
||||
---@return table|nil
|
||||
function M.load_json(json_path)
|
||||
local resource, is_error = sys.load_resource(json_path)
|
||||
if is_error or not resource then
|
||||
return nil
|
||||
end
|
||||
|
||||
return json.decode(resource)
|
||||
end
|
||||
|
||||
|
||||
M.load_palette()
|
||||
|
||||
return M
|
@ -80,10 +80,16 @@ function M:set_margin(margin_x, margin_y)
|
||||
end
|
||||
|
||||
|
||||
---@param padding vector4 The vector4 with padding values, where x - left, y - top, z - right, w - bottom
|
||||
---@param padding_x number|nil
|
||||
---@param padding_y number|nil
|
||||
---@param padding_z number|nil
|
||||
---@param padding_w number|nil
|
||||
---@return druid.layout
|
||||
function M:set_padding(padding)
|
||||
self.padding = padding
|
||||
function M:set_padding(padding_x, padding_y, padding_z, padding_w)
|
||||
self.padding.x = padding_x or self.padding.x
|
||||
self.padding.y = padding_y or self.padding.y
|
||||
self.padding.z = padding_z or padding_x or self.padding.z
|
||||
self.padding.w = padding_w or padding_y or self.padding.w
|
||||
self.is_dirty = true
|
||||
|
||||
return self
|
||||
|
58
druid/widget/memory_panel/memory_panel.gui
Normal file
58
druid/widget/memory_panel/memory_panel.gui
Normal file
@ -0,0 +1,58 @@
|
||||
nodes {
|
||||
size {
|
||||
x: 200.0
|
||||
y: 100.0
|
||||
}
|
||||
type: TYPE_BOX
|
||||
id: "root"
|
||||
inherit_alpha: true
|
||||
size_mode: SIZE_MODE_AUTO
|
||||
visible: false
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_TEMPLATE
|
||||
id: "mini_graph"
|
||||
parent: "root"
|
||||
inherit_alpha: true
|
||||
template: "/druid/widget/mini_graph/mini_graph.gui"
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "mini_graph/root"
|
||||
parent: "mini_graph"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_TEXT
|
||||
text: "Memory Panel"
|
||||
id: "mini_graph/text_header"
|
||||
parent: "mini_graph/root"
|
||||
overridden_fields: 8
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "mini_graph/icon_drag"
|
||||
parent: "mini_graph/root"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "mini_graph/panel_diagram"
|
||||
parent: "mini_graph/root"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "mini_graph/prefab_line"
|
||||
parent: "mini_graph/panel_diagram"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_TEXT
|
||||
id: "mini_graph/text_value"
|
||||
parent: "mini_graph/root"
|
||||
template_node_child: true
|
||||
}
|
||||
material: "/builtins/materials/gui.material"
|
||||
adjust_reference: ADJUST_REFERENCE_PARENT
|
22
druid/widget/memory_panel/memory_panel.lua
Normal file
22
druid/widget/memory_panel/memory_panel.lua
Normal file
@ -0,0 +1,22 @@
|
||||
local mini_graph = require("druid.widget.mini_graph.mini_graph")
|
||||
|
||||
---@class widget.memory_panel: druid.widget
|
||||
---@field root node
|
||||
local M = {}
|
||||
|
||||
|
||||
function M:init()
|
||||
self.druid = self:get_druid()
|
||||
self.mini_graph = self.druid:new_widget(mini_graph, "mini_graph")
|
||||
|
||||
--for index = 1, 32 do
|
||||
-- self.mini_graph:set_line_value(index, 0)
|
||||
--end
|
||||
|
||||
timer.delay(0.1, true, function()
|
||||
self.mini_graph:push_line_value(math.random())
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
return M
|
171
druid/widget/mini_graph/mini_graph.gui
Normal file
171
druid/widget/mini_graph/mini_graph.gui
Normal file
@ -0,0 +1,171 @@
|
||||
fonts {
|
||||
name: "text_regular"
|
||||
font: "/druid/fonts/text_regular.font"
|
||||
}
|
||||
fonts {
|
||||
name: "text_bold"
|
||||
font: "/druid/fonts/text_bold.font"
|
||||
}
|
||||
textures {
|
||||
name: "druid"
|
||||
texture: "/druid/druid.atlas"
|
||||
}
|
||||
nodes {
|
||||
size {
|
||||
x: 200.0
|
||||
y: 140.0
|
||||
}
|
||||
color {
|
||||
x: 0.173
|
||||
y: 0.184
|
||||
z: 0.204
|
||||
}
|
||||
type: TYPE_BOX
|
||||
texture: "druid/ui_circle_16"
|
||||
id: "root"
|
||||
inherit_alpha: true
|
||||
slice9 {
|
||||
x: 8.0
|
||||
y: 8.0
|
||||
z: 8.0
|
||||
w: 8.0
|
||||
}
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
x: -92.0
|
||||
y: 63.0
|
||||
}
|
||||
scale {
|
||||
x: 0.5
|
||||
y: 0.5
|
||||
}
|
||||
size {
|
||||
x: 260.0
|
||||
y: 50.0
|
||||
}
|
||||
color {
|
||||
x: 0.463
|
||||
y: 0.475
|
||||
z: 0.49
|
||||
}
|
||||
type: TYPE_TEXT
|
||||
text: "Mini Graph"
|
||||
font: "text_regular"
|
||||
id: "text_header"
|
||||
pivot: PIVOT_NW
|
||||
outline {
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
z: 1.0
|
||||
}
|
||||
shadow {
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
z: 1.0
|
||||
}
|
||||
parent: "root"
|
||||
inherit_alpha: true
|
||||
outline_alpha: 0.0
|
||||
shadow_alpha: 0.0
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
x: 92.0
|
||||
y: 67.0
|
||||
}
|
||||
color {
|
||||
x: 0.129
|
||||
y: 0.141
|
||||
z: 0.157
|
||||
}
|
||||
type: TYPE_BOX
|
||||
texture: "druid/ui_circle_32"
|
||||
id: "icon_drag"
|
||||
pivot: PIVOT_NE
|
||||
parent: "root"
|
||||
inherit_alpha: true
|
||||
size_mode: SIZE_MODE_AUTO
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
y: -70.0
|
||||
}
|
||||
size {
|
||||
x: 200.0
|
||||
y: 100.0
|
||||
}
|
||||
color {
|
||||
x: 0.129
|
||||
y: 0.141
|
||||
z: 0.157
|
||||
}
|
||||
type: TYPE_BOX
|
||||
texture: "druid/ui_circle_16"
|
||||
id: "panel_diagram"
|
||||
pivot: PIVOT_S
|
||||
parent: "root"
|
||||
inherit_alpha: true
|
||||
slice9 {
|
||||
x: 8.0
|
||||
y: 8.0
|
||||
z: 8.0
|
||||
w: 8.0
|
||||
}
|
||||
clipping_mode: CLIPPING_MODE_STENCIL
|
||||
}
|
||||
nodes {
|
||||
size {
|
||||
x: 8.0
|
||||
y: 70.0
|
||||
}
|
||||
color {
|
||||
x: 0.957
|
||||
y: 0.608
|
||||
z: 0.608
|
||||
}
|
||||
type: TYPE_BOX
|
||||
texture: "druid/pixel"
|
||||
id: "prefab_line"
|
||||
pivot: PIVOT_S
|
||||
parent: "panel_diagram"
|
||||
inherit_alpha: true
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
y: 12.0
|
||||
}
|
||||
scale {
|
||||
x: 0.7
|
||||
y: 0.7
|
||||
}
|
||||
size {
|
||||
x: 260.0
|
||||
y: 40.0
|
||||
}
|
||||
color {
|
||||
x: 0.463
|
||||
y: 0.475
|
||||
z: 0.49
|
||||
}
|
||||
type: TYPE_TEXT
|
||||
text: "120.23 KB"
|
||||
font: "text_bold"
|
||||
id: "text_value"
|
||||
outline {
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
z: 1.0
|
||||
}
|
||||
shadow {
|
||||
x: 1.0
|
||||
y: 1.0
|
||||
z: 1.0
|
||||
}
|
||||
parent: "root"
|
||||
inherit_alpha: true
|
||||
outline_alpha: 0.0
|
||||
shadow_alpha: 0.0
|
||||
}
|
||||
material: "/builtins/materials/gui.material"
|
||||
adjust_reference: ADJUST_REFERENCE_PARENT
|
88
druid/widget/mini_graph/mini_graph.lua
Normal file
88
druid/widget/mini_graph/mini_graph.lua
Normal file
@ -0,0 +1,88 @@
|
||||
local color = require("druid.color")
|
||||
|
||||
---@class widget.mini_graph: druid.widget
|
||||
local M = {}
|
||||
|
||||
local SIZE_Y = hash("size.y")
|
||||
|
||||
|
||||
function M:init()
|
||||
self.druid = self:get_druid()
|
||||
self.root = self:get_node("root")
|
||||
self.container = self.druid:new_container(self.root)
|
||||
self.text_header = self.druid:new_text("text_header")
|
||||
self.text_value = self.druid:new_text("text_value")
|
||||
self.drag_corner = self.druid:new_drag("icon_drag", self.on_drag_corner)
|
||||
self.layout = self.druid:new_layout("panel_diagram", "horizontal")
|
||||
:set_margin(0, 0)
|
||||
:set_padding(0, 0, 0, 0)
|
||||
|
||||
self.prefab_line = self:get_node("prefab_line")
|
||||
gui.set_enabled(self.prefab_line, false)
|
||||
|
||||
self.color_zero = color.hex2vector4("#8ED59E")
|
||||
self.color_one = color.hex2vector4("#F49B9B")
|
||||
|
||||
self.lines = {}
|
||||
self.values = {}
|
||||
self.samples = 64
|
||||
local line_width = self.layout:get_size().x / self.samples
|
||||
for index = 1, self.samples do
|
||||
local line = gui.clone(self.prefab_line)
|
||||
gui.set_enabled(line, true)
|
||||
gui.set(line, "size.x", line_width)
|
||||
self.layout:add(line)
|
||||
table.insert(self.lines, line)
|
||||
end
|
||||
|
||||
for index = 1, self.samples do
|
||||
local outsine = index/self.samples
|
||||
self:set_line_value(index, outsine)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---@param index number
|
||||
---@param value number The normalized value from 0 to 1
|
||||
function M:set_line_value(index, value)
|
||||
local line = self.lines[index]
|
||||
if not line then
|
||||
return
|
||||
end
|
||||
|
||||
local target_color = color.lerp(value * value, self.color_zero, self.color_one)
|
||||
gui.set(line, SIZE_Y, value * 70)
|
||||
gui.set_color(line, target_color)
|
||||
|
||||
self.values[index] = value
|
||||
end
|
||||
|
||||
|
||||
---@return number
|
||||
function M:get_line_value(index)
|
||||
return self.values[index]
|
||||
end
|
||||
|
||||
|
||||
function M:push_line_value(value)
|
||||
for index = 1, self.samples - 1 do
|
||||
self:set_line_value(index, self:get_line_value(index + 1), true)
|
||||
end
|
||||
|
||||
self:set_line_value(self.samples, value, true)
|
||||
end
|
||||
|
||||
|
||||
---@param text string
|
||||
function M:set_text(text)
|
||||
self.text_value:set_to(text)
|
||||
end
|
||||
|
||||
|
||||
function M:on_drag_corner(dx, dy)
|
||||
local position = self.container:get_position()
|
||||
self.container:set_position(position.x + dx, position.y + dy)
|
||||
end
|
||||
|
||||
|
||||
return M
|
Loading…
x
Reference in New Issue
Block a user