Update example with new brand one

This commit is contained in:
Insality
2024-10-17 01:24:15 +03:00
parent 2c762716bb
commit 91879509a0
197 changed files with 36779 additions and 7 deletions

View File

@@ -0,0 +1,40 @@
images {
image: "/example/assets/images/empty.png"
}
images {
image: "/example/assets/images/icon_cross.png"
}
images {
image: "/example/assets/images/pixel.png"
}
images {
image: "/example/assets/images/ui_circle_8.png"
}
images {
image: "/example/assets/images/ui_circle_16.png"
}
images {
image: "/example/assets/images/ui_circle_32.png"
}
images {
image: "/example/assets/images/ui_circle_64.png"
}
images {
image: "/example/assets/images/ui_rounded_top_32.png"
}
images {
image: "/example/assets/images/icon_arrow.png"
}
images {
image: "/example/assets/images/icon_check.png"
}
images {
image: "/example/assets/images/rect_round2_width1.png"
}
images {
image: "/example/assets/images/ui_circle_64_blur_8.png"
}
images {
image: "/example/assets/images/icon_heart.png"
}
extrude_borders: 2

View File

@@ -0,0 +1,16 @@
images {
image: "/example/assets/images/icon_druid.png"
}
images {
image: "/example/assets/images/logo_druid.png"
}
images {
image: "/example/assets/images/sponsor_coffee.png"
}
images {
image: "/example/assets/images/sponsor_github.png"
}
images {
image: "/example/assets/images/sponsor_kofi.png"
}
extrude_borders: 2

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

BIN
example/assets/images/empty.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 432 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
example/assets/images/pixel.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 787 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

View File

@@ -0,0 +1,528 @@
--- Container component
-- Container setup in GUI
-- parent container - container that contains this container. If not, then it's a window default container
-- container pivot - the point of the parent container that will be used as a pivot point for positioning
-- node_offset - position offset from parent container pivot point (vector4 - offset in pixels from each side)
-- adjust mode FIT - container will keep it's size and will be positioned inside parent container
-- adjust mode STRETCH - container will have percentage of parent container size
-- adjust mode STRETCH_X - container will have percentage of parent container size (only x side)
-- adjust mode STRETCH_Y - container will have percentage of parent container size (only y side)
-- Adjust Stretch and x_anchor == None: container will be positioned by pivot point with one side fixed margin, stretched to pivot side by percentage
-- Adjust stretch and x_anchor ~= None: container will be positioned by pivot point, stretched to pivot side by percentage, but with fixed margins
-- Inner container should be inside other container
local const = require("druid.const")
local helper = require("druid.helper")
local component = require("druid.component")
local Event = require("druid.event")
---@class druid.container: druid.base_component
---@field node node
---@field druid druid_instance
---@field node_offset vector4
---@field origin_size vector3
---@field size vector3
---@field origin_position vector3
---@field position vector3
---@field pivot_offset vector3
---@field center_offset vector3
---@field mode string
---@field fit_size vector3
---@field min_size_x number|nil
---@field min_size_y number|nil
---@field on_size_changed druid.event @function on_size_changed(size)
---@field _parent_container druid.container
---@field _containers table
---@field _draggable_corners table
local Container = component.create("container")
local abs = math.abs
local min = math.min
local max = math.max
local CORNER_PIVOTS = {
gui.PIVOT_NE,
gui.PIVOT_NW,
gui.PIVOT_SE,
gui.PIVOT_SW,
}
--- The Container init
---@param node node Gui node
---@param mode string Layout mode
---@param callback fun(self: druid.container, size: vector3) Callback on size changed
function Container:init(node, mode, callback)
self.node = self:get_node(node)
self.druid = self:get_druid()
self.min_size_x = 0
self.min_size_y = 0
self._containers = {}
self._draggable_corners = {}
self.node_offset = vmath.vector4(0)
self.node_fill_x = nil
self.node_fill_y = nil
self._position = gui.get_position(self.node)
local x_koef, y_koef = helper.get_screen_aspect_koef()
self.x_koef = x_koef
self.y_koef = y_koef
self.x_anchor = gui.get_xanchor(self.node)
self.y_anchor = gui.get_yanchor(self.node)
-- Can be changed
self.origin_size = gui.get_size(self.node)
self.size = gui.get_size(self.node)
self.position = gui.get_position(self.node)
self.origin_position = gui.get_position(self.node)
local adjust_mode = gui.get_adjust_mode(self.node)
self.mode = mode or (adjust_mode == gui.ADJUST_FIT) and const.LAYOUT_MODE.FIT or const.LAYOUT_MODE.STRETCH
gui.set_size_mode(self.node, gui.SIZE_MODE_MANUAL)
gui.set_adjust_mode(self.node, gui.ADJUST_FIT)
self.on_size_changed = Event(callback)
self.pivot_offset = helper.get_pivot_offset(gui.get_pivot(self.node))
self.center_offset = -vmath.vector3(self.size.x * self.pivot_offset.x, self.size.y * self.pivot_offset.y, 0)
self:set_size(self.size.x, self.size.y)
end
function Container:on_late_init()
if not gui.get_parent(self.node) then
-- TODO: Scale issue here, in fit into window!
self:fit_into_window()
end
end
function Container:on_remove()
self:clear_draggable_corners()
end
function Container:refresh_origins()
self.origin_size = gui.get_size(self.node)
self.origin_position = gui.get_position(self.node)
self:set_pivot(gui.get_pivot(self.node))
end
---@param pivot constant
function Container:set_pivot(pivot)
gui.set_pivot(self.node, pivot)
self.pivot_offset = helper.get_pivot_offset(pivot)
self.center_offset = -vmath.vector3(self.size.x * self.pivot_offset.x, self.size.y * self.pivot_offset.y, 0)
end
--- Component style params.
-- You can override this component styles params in Druid styles table
-- or create your own style
-- @table style
-- @tfield[opt=vector3(24, 24, 0)] vector3 DRAGGABLE_CORNER_SIZE Size of box node for debug draggable corners
-- @tfield[opt=vector4(1)] vector4 DRAGGABLE_CORNER_COLOR Color of debug draggable corners
function Container:on_style_change(style)
self.style = {}
self.style.DRAGGABLE_CORNER_SIZE = style.DRAGGABLE_CORNER_SIZE or vmath.vector3(24, 24, 0)
self.style.DRAGGABLE_CORNER_COLOR = style.DRAGGABLE_CORNER_COLOR or vmath.vector4(10)
end
--- Set new size of layout node
---@param width number|nil
---@param height number|nil
---@return druid.container @{Container}
function Container:set_size(width, height)
width = width or self.size.x
height = height or self.size.y
if self.min_size_x then
width = max(width, self.min_size_x)
end
if self.min_size_y then
height = max(height, self.min_size_y)
end
if (width and width ~= self.size.x) or (height and height ~= self.size.y) then
self.center_offset.x = -width * self.pivot_offset.x
self.center_offset.y = -height * self.pivot_offset.y
self.size.x = width
self.size.y = height
self.size.z = 0
gui.set_size(self.node, self.size)
self:update_child_containers()
self.on_size_changed:trigger(self:get_context(), self.size)
end
return self
end
---@param pos_x number
---@param pos_y number
function Container:set_position(pos_x, pos_y)
if self._position.x == pos_x and self._position.y == pos_y then
return
end
self._position.x = pos_x
self._position.y = pos_y
gui.set_position(self.node, self._position)
end
---Get current size of layout node
---@return vector3 size
function Container:get_size()
return self.size
end
---Get current scale of layout node
---@return vector3 scale
function Container:get_scale()
return helper.get_scene_scale(self.node, true) --[[@as vector3]]
end
--- Set size for layout node to fit inside it
---@param target_size vector3
---@return druid.container @{Container}
function Container:fit_into_size(target_size)
self.fit_size = target_size
self:refresh()
return self
end
--- Set current size for layout node to fit inside it
---@return druid.container @{Container}
function Container:fit_into_window()
return self:fit_into_size(vmath.vector3(gui.get_width(), gui.get_height(), 0))
end
---@param self druid.container
function Container:on_window_resized()
local x_koef, y_koef = helper.get_screen_aspect_koef()
self.x_koef = x_koef
self.y_koef = y_koef
if not self._parent_container then
self:refresh()
end
end
---@param node_or_container node|string|druid.container|table
---@param mode string|nil stretch, fit, stretch_x, stretch_y. Default: Pick from node, "fit" or "stretch"
---@param on_resize_callback fun(self: userdata, size: vector3)|nil
---@return druid.container @{Container} New created layout instance
function Container:add_container(node_or_container, mode, on_resize_callback)
local container = nil
local node = node_or_container
-- Check it's a container components instead of node
if type(node_or_container) == "table" and node_or_container._component then
node = node_or_container.node
container = node_or_container
mode = mode or container.mode
end
-- Covert node_id to node if needed
node = self:get_node(node)
container = container or self.druid:new(Container, node, mode)
container:set_parent_container(self)
if on_resize_callback then
container.on_size_changed:subscribe(on_resize_callback)
end
table.insert(self._containers, container)
return container
end
---@return druid.container|nil
function Container:remove_container_by_node(node)
for index = 1, #self._containers do
local container = self._containers[index]
if container.node == node then
table.remove(self._containers, index)
self.druid:remove(container)
return container
end
end
return nil
end
---@param parent_container druid.container|nil
function Container:set_parent_container(parent_container)
if not parent_container then
self._parent_container = nil
gui.set_parent(self.node, nil)
self:refresh()
return
end
-- TODO: Just check it's already parent
gui.set_parent(self.node, parent_container.node, true)
-- Node offset - fixed distance from parent side to the child side
local parent_left = parent_container.center_offset.x - parent_container.origin_size.x * 0.5
local parent_right = parent_container.center_offset.x + parent_container.origin_size.x * 0.5
local parent_top = parent_container.center_offset.y + parent_container.origin_size.y * 0.5
local parent_bottom = parent_container.center_offset.y - parent_container.origin_size.y * 0.5
local node_left = self.origin_position.x + self.center_offset.x - self.origin_size.x * 0.5
local node_right = self.origin_position.x + self.center_offset.x + self.origin_size.x * 0.5
local node_top = self.origin_position.y + self.center_offset.y + self.origin_size.y * 0.5
local node_bottom = self.origin_position.y + self.center_offset.y - self.origin_size.y * 0.5
self.node_offset.x = node_left - parent_left
self.node_offset.y = node_top - parent_top
self.node_offset.z = node_right - parent_right
self.node_offset.w = node_bottom - parent_bottom
self._parent_container = parent_container
local offset_x = (self.node_offset.x + self.node_offset.z)/2
local offset_y = (self.node_offset.y + self.node_offset.w)/2
if self.pivot_offset.x < 0 then
offset_x = self.node_offset.x
end
if self.pivot_offset.x > 0 then
offset_x = self.node_offset.z
end
if self.pivot_offset.y < 0 then
offset_y = self.node_offset.w
end
if self.pivot_offset.y > 0 then
offset_y = self.node_offset.y
end
local koef_x = (parent_container.origin_size.x - abs(offset_x))
self.node_fill_x = koef_x ~= 0 and self.origin_size.x / koef_x or 1
local x_anchor = gui.get_xanchor(self.node)
if x_anchor ~= gui.ANCHOR_NONE then
self.node_fill_x = 1
end
local koef_y = (parent_container.origin_size.y - abs(offset_y))
self.node_fill_y = koef_y ~= 0 and self.origin_size.y / koef_y or 1
local y_anchor = gui.get_yanchor(self.node)
if y_anchor ~= gui.ANCHOR_NONE then
self.node_fill_y = 1
end
self:refresh()
end
-- Glossary
-- Center Offset - vector from node position to visual center of node
function Container:refresh()
local x_koef, y_koef = self.x_koef, self.y_koef
self:refresh_scale()
if self._parent_container then
local parent = self._parent_container
local offset_x = (self.node_offset.x + self.node_offset.z) / 2
local offset_y = (self.node_offset.y + self.node_offset.w) / 2
if self.pivot_offset.x < 0 then
offset_x = self.node_offset.x
end
if self.pivot_offset.x > 0 then
offset_x = self.node_offset.z
end
if self.pivot_offset.y < 0 then
offset_y = self.node_offset.w
end
if self.pivot_offset.y > 0 then
offset_y = self.node_offset.y
end
local stretch_side_x = parent.size.x - abs(offset_x)
local stretch_side_y = parent.size.y - abs(offset_y)
do
local parent_pivot_x = parent.center_offset.x + (parent.size.x * self.pivot_offset.x)
local parent_pivot_y = parent.center_offset.y + (parent.size.y * self.pivot_offset.y)
local pos_x = parent_pivot_x + offset_x
local pos_y = parent_pivot_y + offset_y
self:set_position(pos_x, pos_y)
end
do
if self.x_anchor ~= gui.ANCHOR_NONE then
stretch_side_x = parent.size.x - (abs(self.node_offset.x) + abs(self.node_offset.z))
end
if self.y_anchor ~= gui.ANCHOR_NONE then
stretch_side_y = parent.size.y - (abs(self.node_offset.y) + abs(self.node_offset.w))
end
---- Size Update (for stretch)
if self.mode == const.LAYOUT_MODE.STRETCH then
self:set_size(
abs(stretch_side_x * self.node_fill_x),
abs(stretch_side_y * self.node_fill_y))
end
if self.mode == const.LAYOUT_MODE.STRETCH_X then
self:set_size(abs(stretch_side_x * self.node_fill_x), nil)
end
if self.mode == const.LAYOUT_MODE.STRETCH_Y then
self:set_size(nil, abs(stretch_side_y * self.node_fill_y))
end
end
else
if self.fit_size then
x_koef = self.fit_size.x / self.origin_size.x * x_koef
y_koef = self.fit_size.y / self.origin_size.y * y_koef
if self.mode == const.LAYOUT_MODE.STRETCH then
self:set_size(self.origin_size.x * x_koef, self.origin_size.y * y_koef)
end
end
end
self:update_child_containers()
end
function Container:refresh_scale()
if self._fit_node then
local fit_node_size = gui.get_size(self._fit_node)
local scale = vmath.vector3(1)
scale.x = min(fit_node_size.x / self.size.x, 1)
scale.y = min(fit_node_size.y / self.size.y, 1)
scale.x = min(scale.x, scale.y)
scale.y = min(scale.x, scale.y)
gui.set_scale(self.node, scale)
end
end
function Container:update_child_containers()
for index = 1, #self._containers do
self._containers[index]:refresh()
end
end
---@return druid.container @{Container}
function Container:create_draggable_corners()
self:clear_draggable_corners()
for _, corner_pivot in pairs(CORNER_PIVOTS) do
local corner_offset = helper.get_pivot_offset(corner_pivot)
local anchor_position = vmath.vector3(
self.center_offset.x + (self.size.x) * corner_offset.x,
self.center_offset.y + (self.size.y) * corner_offset.y,
0)
local new_draggable_node = gui.new_box_node(anchor_position, self.style.DRAGGABLE_CORNER_SIZE)
gui.set_color(new_draggable_node, self.style.DRAGGABLE_CORNER_COLOR)
gui.set_pivot(new_draggable_node, corner_pivot)
gui.set_parent(new_draggable_node, self.node)
self:add_container(new_draggable_node)
---@type druid.drag
local drag = self.druid:new_drag(new_draggable_node, function(_, x, y)
self:_on_corner_drag(x, y, corner_offset)
end)
table.insert(self._draggable_corners, drag)
drag.style.DRAG_DEADZONE = 0
end
return self
end
---@return druid.container @{Container}
function Container:clear_draggable_corners()
for index = 1, #self._draggable_corners do
local drag_component = self._draggable_corners[index]
self.druid:remove(drag_component)
self:remove_container_by_node(drag_component.node)
gui.delete_node(drag_component.node)
end
self._draggable_corners = {}
return self
end
function Container:_on_corner_drag(x, y, corner_offset)
x = corner_offset.x >= 0 and x or -x
y = corner_offset.y >= 0 and y or -y
local size = self:get_size()
if self.min_size_x and size.x + x < self.min_size_x then
x = self.min_size_x - size.x
end
if self.min_size_y and size.y + y < self.min_size_y then
y = self.min_size_y - size.y
end
if corner_offset.x < 0 then
self.node_offset.x = self.node_offset.x - x
end
if corner_offset.x > 0 then
self.node_offset.z = self.node_offset.z - x
end
if corner_offset.y < 0 then
self.node_offset.w = self.node_offset.w - y
end
if corner_offset.y > 0 then
self.node_offset.y = self.node_offset.y - y
end
local pivot = gui.get_pivot(self.node)
local pivot_offset = helper.get_pivot_offset(pivot)
local center_pos_x = self._position.x + (x * (pivot_offset.x + corner_offset.x))
local center_pos_y = self._position.y + (y * (pivot_offset.y + corner_offset.y))
self:set_position(center_pos_x, center_pos_y)
self:set_size(size.x + x, size.y + y)
end
--- Set node for layout node to fit inside it. Pass nil to reset
---@param node string|node The node_id or gui.get_node(node_id)
---@return druid.container @{Layout}
function Container:fit_into_node(node)
self._fit_node = self:get_node(node)
self:refresh_scale()
return self
end
---@param min_size_x number|nil
---@param min_size_y number|nil
function Container:set_min_size(min_size_x, min_size_y)
self.min_size_x = min_size_x or self.min_size_x
self.min_size_y = min_size_y or self.min_size_y
self:refresh()
return self
end
return Container

View File

@@ -0,0 +1,451 @@
script: ""
fonts {
name: "text_regular"
font: "/example/assets/fonts/text_regular.font"
}
textures {
name: "druid_logo"
texture: "/example/assets/druid_logo.atlas"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 170.0
z: 0.0
w: 1.0
}
color {
x: 0.129
y: 0.141
z: 0.157
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/pixel"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_STENCIL
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 200.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 16.0
y: 16.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "E_Anchor"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_E
adjust_mode: ADJUST_MODE_STRETCH
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 10.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid_logo/icon_druid"
id: "icon_druid_right"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "E_Anchor"
layer: "druid_logo"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 0.5
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -200.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 16.0
y: 16.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "W_Anchor"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
adjust_mode: ADJUST_MODE_STRETCH
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: -10.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid_logo/icon_druid"
id: "icon_druid_left"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "W_Anchor"
layer: "druid_logo"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 0.5
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid_logo/logo_druid"
id: "icon_logo"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: "druid_logo"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: -50.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.6
y: 0.6
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Defold UI Framework"
font: "text_regular"
id: "text_description"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: "text_regular"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
layers {
name: "druid"
}
layers {
name: "druid_logo"
}
layers {
name: "text_regular"
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,48 @@
local panthera = require("panthera.panthera")
local component = require("druid.component")
local druid_logo_panthera = require("example.components.druid_logo.druid_logo_panthera")
local container = require("example.components.container.container")
---@class druid_logo: druid.base_component
---@field root druid.container
---@field text_description druid.text
---@field druid druid_instance
local DruidLogo = component.create("druid_logo")
---@param template string
---@param nodes table<hash, node>
function DruidLogo:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.root = self.druid:new(container, "root") --[[@as druid.container]]
self.root:add_container("E_Anchor")
self.root:add_container("W_Anchor")
self.druid:new_button("root", self.on_click):set_style(nil)
self.animation = panthera.create_gui(druid_logo_panthera, self:get_template(), nodes)
panthera.play(self.animation, "idle", { is_loop = true })
self.animation_hover = panthera.clone_state(self.animation)
self.hover = self.druid:new_hover("root")
self.hover.on_mouse_hover:subscribe(self.on_mouse_hover)
end
function DruidLogo:on_click()
sys.open_url("https://github.com/Insality/druid", { target = "_blank" })
end
function DruidLogo:on_mouse_hover(is_hover)
if is_hover then
panthera.play(self.animation_hover, "on_hover_in")
else
panthera.play(self.animation_hover, "on_hover_out", { is_skip_init = true })
end
end
return DruidLogo

View File

@@ -0,0 +1,268 @@
return {
version = 1,
format = "json",
data = {
animations = {
{
duration = 12,
animation_id = "idle",
animation_keys = {
{
node_id = "icon_druid_left",
duration = 3,
end_value = -5,
easing = "outsine",
key_type = "tween",
property_id = "position_y",
},
{
node_id = "icon_druid_right",
duration = 3,
end_value = -5,
easing = "outsine",
key_type = "tween",
property_id = "position_y",
},
{
node_id = "icon_logo",
duration = 4,
end_value = 5,
easing = "outsine",
key_type = "tween",
property_id = "position_y",
},
{
start_time = 3,
duration = 3,
start_value = -5,
easing = "outsine",
key_type = "tween",
node_id = "icon_druid_left",
end_value = 5,
property_id = "position_y",
},
{
start_time = 3,
duration = 3,
start_value = -5,
easing = "outsine",
key_type = "tween",
node_id = "icon_druid_right",
end_value = 5,
property_id = "position_y",
},
{
start_time = 4,
duration = 8,
start_value = 5,
easing = "insine",
key_type = "tween",
node_id = "icon_logo",
property_id = "position_y",
},
{
start_time = 6,
duration = 6,
start_value = 5,
easing = "outsine",
key_type = "tween",
node_id = "icon_druid_left",
property_id = "position_y",
},
{
start_time = 6,
duration = 6,
start_value = 5,
easing = "outsine",
key_type = "tween",
node_id = "icon_druid_right",
property_id = "position_y",
},
},
},
{
duration = 0.6,
animation_id = "on_hover_in",
animation_keys = {
{
node_id = "W_Anchor",
duration = 0.6,
end_value = -220,
easing = "outsine",
key_type = "tween",
start_value = -200,
property_id = "position_x",
},
{
node_id = "text_description",
duration = 0.6,
end_value = -60,
easing = "outsine",
key_type = "tween",
start_value = -50,
property_id = "position_y",
},
{
node_id = "icon_druid_left",
duration = 0.6,
end_value = 0.7,
easing = "outsine",
key_type = "tween",
start_value = 0.5,
property_id = "color_a",
},
{
node_id = "icon_druid_right",
duration = 0.6,
end_value = 0.7,
easing = "outsine",
key_type = "tween",
start_value = 0.5,
property_id = "color_a",
},
{
node_id = "icon_logo",
duration = 0.6,
end_value = 1.1,
easing = "outsine",
key_type = "tween",
start_value = 1,
property_id = "scale_x",
},
{
node_id = "icon_logo",
duration = 0.6,
end_value = 1.1,
easing = "outsine",
key_type = "tween",
start_value = 1,
property_id = "scale_y",
},
{
node_id = "icon_logo",
duration = 0.6,
end_value = 1.7,
easing = "outsine",
key_type = "tween",
start_value = 1,
property_id = "color_a",
},
{
node_id = "E_Anchor",
duration = 0.6,
end_value = 220,
easing = "outsine",
key_type = "tween",
start_value = 200,
property_id = "position_x",
},
},
},
{
duration = 0.3,
animation_id = "on_hover_out",
animation_keys = {
{
node_id = "W_Anchor",
duration = 0.3,
end_value = -200,
easing = "outback",
key_type = "tween",
start_value = -200,
property_id = "position_x",
},
{
node_id = "text_description",
duration = 0.3,
end_value = -50,
easing = "outback",
key_type = "tween",
start_value = -50,
property_id = "position_y",
},
{
node_id = "icon_druid_left",
duration = 0.3,
end_value = 0.5,
easing = "outsine",
key_type = "tween",
start_value = 0.5,
property_id = "color_a",
},
{
node_id = "icon_druid_right",
duration = 0.3,
end_value = 0.5,
easing = "outsine",
key_type = "tween",
start_value = 0.5,
property_id = "color_a",
},
{
node_id = "icon_logo",
duration = 0.3,
end_value = 1,
easing = "outsine",
key_type = "tween",
start_value = 1,
property_id = "color_a",
},
{
node_id = "icon_logo",
duration = 0.3,
end_value = 1,
easing = "outback",
key_type = "tween",
start_value = 1,
property_id = "scale_x",
},
{
node_id = "icon_logo",
duration = 0.3,
end_value = 1,
easing = "outback",
key_type = "tween",
start_value = 1,
property_id = "scale_y",
},
{
node_id = "E_Anchor",
duration = 0.3,
end_value = 200,
easing = "outback",
key_type = "tween",
start_value = 200,
property_id = "position_x",
},
},
},
},
metadata = {
gui_path = "/example/components/druid_logo/druid_logo.gui",
settings = {
font_size = 40,
},
gizmo_steps = {
time = 0.1,
},
layers = {
{
name = "druid",
color = "73E84C",
},
{
name = "druid_logo",
color = "90D2F6",
},
{
name = "text_regular",
color = "C379F0",
},
},
fps = 60,
},
nodes = {
},
},
type = "animation_editor",
}

View File

@@ -0,0 +1,146 @@
script: ""
fonts {
name: "text_regular"
font: "/example/assets/fonts/text_regular.font"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1080.0
y: 1030.0
z: 0.0
w: 1.0
}
color {
x: 0.129
y: 0.141
z: 0.157
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_STRETCH
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -530.0
y: 505.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.5
y: 0.5
z: 1.0
w: 1.0
}
size {
x: 1080.0
y: 520.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Entities: 8\n"
"Top Index: 1\n"
"Bottom Index: 10\n"
"Scroll Size: 200x400\n"
"Grid Size: 400x800"
font: "text_regular"
id: "text_debug_info"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: "text_regular"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
layers {
name: "text_regular"
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,29 @@
local component = require("druid.component")
local container = require("example.components.container.container")
---@class example_scene: druid.base_component
---@field root druid.container
---@field text_debug_info druid.text
---@field druid druid_instance
local M = component.create("example_scene")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.root = self.druid:new(container, "root") --[[@as druid.container]]
self.root:add_container("text_debug_info")
self.text_debug_info = self.druid:new_text("text_debug_info")
end
---@param info string
function M:set_debug_info(info)
self.text_debug_info:set_to(info)
end
return M

View File

@@ -0,0 +1,612 @@
script: ""
fonts {
name: "text_regular"
font: "/example/assets/fonts/text_regular.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 910.0
z: 0.0
w: 1.0
}
color {
x: 0.173
y: 0.184
z: 0.204
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/pixel"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_STRETCH
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -190.0
y: 445.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.9
y: 0.9
z: 1.0
w: 1.0
}
size {
x: 250.0
y: 60.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Examples"
font: "text_regular"
id: "text_header"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: "text_regular"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -200.0
y: 395.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 850.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "scroll_view"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
adjust_mode: ADJUST_MODE_STRETCH
parent: "root"
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_STENCIL
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 850.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "scroll_content"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
adjust_mode: ADJUST_MODE_STRETCH
parent: "scroll_view"
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: -52.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "examples_list_view_item"
parent: "scroll_content"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/components/examples_list_view/examples_list_view_item.gui"
template_node_child: false
custom_type: 0
enabled: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.173
y: 0.184
z: 0.204
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "examples_list_view_item/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
adjust_mode: ADJUST_MODE_STRETCH
parent: "examples_list_view_item"
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/pixel"
id: "examples_list_view_item/panel_highlight"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
adjust_mode: ADJUST_MODE_FIT
parent: "examples_list_view_item/root"
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 0.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 4.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.894
y: 0.506
z: 0.333
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/pixel"
id: "examples_list_view_item/panel_selected"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
adjust_mode: ADJUST_MODE_FIT
parent: "examples_list_view_item/root"
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: false
visible: true
material: ""
}
nodes {
position {
x: 18.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.6
y: 0.6
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 0.851
y: 0.851
z: 0.851
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/icon_arrow"
id: "examples_list_view_item/icon"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "examples_list_view_item/root"
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_AUTO
custom_type: 0
enabled: false
visible: true
material: ""
}
nodes {
position {
x: 36.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.7
y: 0.7
z: 1.0
w: 1.0
}
size {
x: 500.0
y: 60.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Basic"
font: "text_bold"
id: "examples_list_view_item/text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
outline {
x: 0.941
y: 0.984
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "examples_list_view_item/root"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
layers {
name: "druid"
}
layers {
name: "text_regular"
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,172 @@
local event = require("druid.event")
local component = require("druid.component")
local container = require("example.components.container.container")
local lang_text = require("druid.extended.lang_text")
local storage = require("saver.storage")
local examples_list_view_item = require("example.components.examples_list_view.examples_list_view_item")
---@class examples_list_view: druid.base_component
---@field root druid.container
---@field druid druid_instance
---@field scroll druid.scroll
---@field grid druid.static_grid
local M = component.create("examples_list_view")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.root = self.druid:new(container, "root") --[[@as druid.container]]
self.root:add_container("text_header")
self.druid:new(lang_text, "text_header", "ui_examples")
self.druid:new(examples_list_view_item, "examples_list_view_item")
self.prefab = self:get_node("examples_list_view_item/root")
gui.set_enabled(self.prefab, false)
self.scroll = self.druid:new_scroll("scroll_view", "scroll_content")
self.grid = self.druid:new_static_grid("scroll_content", self.prefab, 1)
self.scroll:bind_grid(self.grid)
self.root:add_container("scroll_view", nil, function(_, size)
self.scroll:set_view_size(size)
self.scroll:set_size(self.grid:get_size())
end)
self.selected_example = nil
self.examples = {}
self.on_debug_info = event()
self.on_set_information = event()
self.add_log_text = event()
timer.delay(0.1, true, function()
self:update_debug_info()
end)
end
---@param examples druid.examples
---@param druid_example druid.example @The main GUI component
function M:add_example(examples, druid_example)
local example_name_id = examples.example_name_id
local examples_list = examples.examples_list
if false then
do -- Add section name
local nodes = gui.clone_tree(self.prefab)
local item = self.druid:new(examples_list_view_item, "examples_list_view_item", nodes) --[[@as examples_list_view_item]]
gui.set_enabled(item.root.node, true)
item.text:translate(example_name_id)
item:set_fold_icon_enabled(true)
item.on_click:subscribe(function()
item:set_fold_status(not item:is_folded())
end)
self.grid:add(item.root.node)
end
end
for index = 1, #examples_list do
local example_data = examples_list[index]
local nodes = gui.clone_tree(self.prefab)
local item = self.druid:new(examples_list_view_item, "examples_list_view_item", nodes) --[[@as examples_list_view_item]]
gui.set_enabled(item.root.node, true)
item.text:translate(example_data.name_id)
item:set_fold_icon_enabled(false)
item.on_click:subscribe(function()
if self.selected_example then
self.selected_example.list_item:set_selected(false)
druid_example.druid:remove(self.selected_example.instance)
gui.set_enabled(self.selected_example.root, false)
self.selected_example = nil
end
local root = gui.get_node(example_data.root)
gui.set_enabled(root, true)
local instance = druid_example.druid:new(example_data.component_class, example_data.template)
self.selected_example = {
data = example_data,
list_item = item,
instance = instance,
root = root
}
item:set_selected(true)
druid_example.output_list:clear()
if example_data.on_create then
example_data.on_create(instance, druid_example.output_list)
end
if example_data.information_text_id then
self.on_set_information(example_data.information_text_id)
else
self.on_set_information("")
end
druid_example.properties_panel:clear()
if example_data.properties_control then
example_data.properties_control(instance, druid_example.properties_panel)
end
storage.set("last_selected_example", example_data.name_id)
if html5 then
local command = string.format('window.history.replaceState(null, null, "?example=%s")', example_data.name_id)
html5.run(command)
end
end)
self.grid:add(item.root.node)
table.insert(self.examples, {
data = example_data,
list_item = item
})
end
end
---@param name_id string
---@return boolean @true if example was found and selected
function M:select_example_by_name_id(name_id)
for index = 1, #self.examples do
local example = self.examples[index]
-- Scroll to the element
self.scroll:scroll_to(gui.get_position(example.list_item.root.node), true)
-- Select the element
if example.data.name_id == name_id then
example.list_item.on_click:trigger()
return true
end
end
return false
end
function M:update_debug_info()
if not self.selected_example then
self.on_debug_info:trigger("")
return
end
local data = self.selected_example.data
if data.get_debug_info then
local info = data.get_debug_info(self.selected_example.instance)
self.on_debug_info:trigger(info)
return
end
self.on_debug_info:trigger("")
end
return M

View File

@@ -0,0 +1,326 @@
script: ""
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.173
y: 0.184
z: 0.204
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
adjust_mode: ADJUST_MODE_STRETCH
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/pixel"
id: "panel_highlight"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 0.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 4.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.894
y: 0.506
z: 0.333
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/pixel"
id: "panel_selected"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: false
visible: true
material: ""
}
nodes {
position {
x: 18.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.6
y: 0.6
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 0.851
y: 0.851
z: 0.851
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/icon_arrow"
id: "icon"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
enabled: false
visible: true
material: ""
}
nodes {
position {
x: 36.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.7
y: 0.7
z: 1.0
w: 1.0
}
size {
x: 500.0
y: 60.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Basic"
font: "text_bold"
id: "text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
outline {
x: 0.941
y: 0.984
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
layers {
name: "druid"
}
layers {
name: "text_bold"
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,74 @@
local component = require("druid.component")
local container = require("example.components.container.container")
local lang_text = require("druid.extended.lang_text")
---@class examples_list_view_item: druid.base_component
---@field root druid.container
---@field text druid.lang_text
---@field druid druid_instance
---@field on_click druid.event
local M = component.create("examples_list_view_item")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.root = self.druid:new(container, "root") --[[@as druid.container]]
self.text = self.druid:new(lang_text, "text") --[[ @as druid.lang_text]]
self.icon = self:get_node("icon")
self.selected = self:get_node("panel_selected")
self.highlight = self:get_node("panel_highlight")
self.color_not_selected = gui.get_color(self.text.node)
self.color_selected = gui.get_outline(self.text.node)
self.color_selected.w = 1
self._is_folded = true
self.button = self.druid:new_button("root")
self.button:set_style(nil)
local hover = self.druid:new_hover("root")
hover.on_mouse_hover:subscribe(self.on_hover)
-- External Events
self.on_click = self.button.on_click
end
---@param is_enabled boolean
function M:set_fold_icon_enabled(is_enabled)
gui.set_enabled(self.icon, is_enabled)
end
---@param is_folded boolean
function M:set_fold_status(is_folded)
self._is_folded = is_folded
gui.animate(self.icon, "euler.z", is_folded and 0 or -90, gui.EASING_OUTQUAD, 0.2)
end
function M:is_folded()
return self._is_folded
end
function M:set_selected(is_selected)
gui.set_enabled(self.selected, is_selected)
local color = is_selected and self.color_selected or self.color_not_selected
gui.set_color(self.text.node, color)
end
function M:on_hover(is_hover)
if is_hover then
gui.animate(self.highlight, "color.w", 1, gui.EASING_OUTQUAD, 0.2)
else
gui.animate(self.highlight, "color.w", 0, gui.EASING_OUTQUAD, 0.1)
end
end
return M

View File

@@ -0,0 +1,397 @@
script: ""
fonts {
name: "text_regular"
font: "/example/assets/fonts/text_regular.font"
}
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 440.0
y: 280.0
z: 0.0
w: 1.0
}
color {
x: 0.173
y: 0.184
z: 0.204
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/pixel"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_STRETCH
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -210.0
y: 130.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.9
y: 0.9
z: 1.0
w: 1.0
}
size {
x: 245.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Output"
font: "text_regular"
id: "text_header"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: "text_regular"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -200.0
y: 80.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 220.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "scroll_view"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
adjust_mode: ADJUST_MODE_STRETCH
parent: "root"
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_STENCIL
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 220.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "scroll_content"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
adjust_mode: ADJUST_MODE_STRETCH
parent: "scroll_view"
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: -20.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.7
y: 0.7
z: 1.0
w: 1.0
}
size {
x: 571.4286
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 0.941
y: 0.984
z: 1.0
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Log text"
font: "text_bold"
id: "text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "scroll_content"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 140.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 440.0
y: 4.0
z: 0.0
w: 1.0
}
color {
x: 0.129
y: 0.141
z: 0.157
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/pixel"
id: "separator"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_N
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: "druid"
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
layers {
name: "druid"
}
layers {
name: "text_regular"
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,68 @@
local component = require("druid.component")
local container = require("example.components.container.container")
local lang_text = require("druid.extended.lang_text")
---@class output_list: druid.base_component
---@field root druid.container
---@field text_header druid.text
---@field scroll druid.scroll
---@field druid druid_instance
local M = component.create("output_list")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.root = self.druid:new(container, "root") --[[@as druid.container]]
self.root:add_container("text_header")
self.root:add_container("separator")
self.created_texts = {}
self.prefab = self:get_node("text")
gui.set_enabled(self.prefab, false)
self.grid = self.druid:new_static_grid("scroll_content", "text", 1)
self.scroll = self.druid:new_scroll("scroll_view", "scroll_content")
self.scroll:bind_grid(self.grid)
self.scroll:set_horizontal_scroll(false)
self.druid:new(lang_text, "text_header", "ui_output")
end
---@param text string
function M:add_log_text(text)
local text_node = gui.clone(self.prefab)
gui.set_enabled(text_node, true)
local text_instance = self.druid:new_text(text_node, text)
self.grid:add(text_instance.node)
table.insert(self.created_texts, text_instance)
self.scroll:scroll_to_percent(vmath.vector3(0, 0, 0))
if #self.created_texts > 64 then
self.grid:remove(1)
self.druid:remove(self.created_texts[1])
gui.delete_node(self.created_texts[1].node)
table.remove(self.created_texts, 1)
end
end
function M:clear()
for index = 1, #self.created_texts do
self.druid:remove(self.created_texts[index])
end
local nodes = self.grid.nodes
for index = 1, #nodes do
gui.delete_node(nodes[index])
end
self.created_texts = {}
self.grid:clear()
end
return M

View File

@@ -0,0 +1,988 @@
script: ""
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1080.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.129
y: 0.141
z: 0.157
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_STRETCH
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -530.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 16.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "group_memory"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 89.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.8
y: 0.8
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.306
y: 0.31
z: 0.314
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Memory"
font: "text_bold"
id: "text_memory"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "group_memory"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 199.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.8
y: 0.8
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "2048"
font: "text_bold"
id: "text_memory_amount"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "group_memory"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 273.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.8
y: 0.8
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.306
y: 0.31
z: 0.314
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "KB"
font: "text_bold"
id: "text_memory_kb"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "group_memory"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -130.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 16.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "group_fps"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: -50.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.8
y: 0.8
z: 1.0
w: 1.0
}
size {
x: 120.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.306
y: 0.31
z: 0.314
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "FPS"
font: "text_bold"
id: "text_fps"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "group_fps"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 17.0
y: -20.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.8
y: 0.8
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "60"
font: "text_bold"
id: "text_fps_amount"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_S
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "group_fps"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 65.0
y: -17.5
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.6
y: 0.6
z: 1.0
w: 1.0
}
size {
x: 100.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "/60"
font: "text_bold"
id: "text_fps_min"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_S
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "group_fps"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 130.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 16.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "group_components"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: -50.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.8
y: 0.8
z: 1.0
w: 1.0
}
size {
x: 350.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.306
y: 0.31
z: 0.314
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Components"
font: "text_bold"
id: "text_components"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "group_components"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 90.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.8
y: 0.8
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "2004"
font: "text_bold"
id: "text_components_amount"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "group_components"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 530.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 16.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "group_events"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_E
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: -163.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.8
y: 0.8
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.306
y: 0.31
z: 0.314
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Events"
font: "text_bold"
id: "text_events"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "group_events"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -59.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.8
y: 0.8
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "6000"
font: "text_bold"
id: "text_events_amount"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "group_events"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
layers {
name: "druid"
}
layers {
name: "text_bold"
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,180 @@
local event = require("druid.event")
local helper = require("druid.helper")
local component = require("druid.component")
local container = require("example.components.container.container")
local lang_text = require("druid.extended.lang_text")
---@class panel_druid_profiler: druid.base_component
---@field root druid.container
---@field druid druid_instance
local M = component.create("panel_druid_profiler")
local FPS_SAMPLES = 60
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.root = self.druid:new(container, "root") --[[@as druid.container]]
self.group_memory = self.root:add_container("group_memory")
self.group_fps = self.root:add_container("group_fps")
self.group_components = self.root:add_container("group_components")
self.group_events = self.root:add_container("group_events")
self.druid:new_button("group_memory", self.run_collectgarbage)
self.group_memory:set_min_size(270, nil)
self.group_fps:set_min_size(270, nil)
self.group_components:set_min_size(270, nil)
self.group_events:set_min_size(270, nil)
self.text_memory_amount = self.druid:new_text("text_memory_amount")
self.text_fps_amount = self.druid:new_text("text_fps_amount")
self.text_fps_min = self.druid:new_text("text_fps_min")
self.text_components_amount = self.druid:new_text("text_components_amount")
self.text_events_amount = self.druid:new_text("text_events_amount")
self.druid:new(lang_text, "text_memory", "ui_profiler_memory")
self.druid:new(lang_text, "text_fps", "ui_profiler_fps")
self.druid:new(lang_text, "text_components", "ui_profiler_components")
self.druid:new(lang_text, "text_events", "ui_profiler_events")
self.previous_time = nil
self.fps_samples = {}
self.nodes_memory = {
self:get_node("text_memory"),
self:get_node("text_memory_amount"),
self:get_node("text_memory_kb"),
}
self.nodes_fps = {
self:get_node("text_fps"),
self:get_node("text_fps_amount"),
self:get_node("text_fps_min"),
}
self.nodes_components = {
self:get_node("text_components"),
self:get_node("text_components_amount"),
}
self.nodes_events = {
self:get_node("text_events"),
self:get_node("text_events_amount"),
}
timer.delay(0.16, true, function()
self:update_memory()
self:update_fps()
self:update_components()
self:update_events()
self:align_fps_components()
end)
end
function M:on_language_change()
self:update_memory()
self:update_fps()
self:update_components()
self:update_events()
self:align_fps_components()
end
function M:update_memory()
local memory = collectgarbage("count")
self.text_memory_amount:set_to(tostring(math.ceil(memory)))
local width = helper.centrate_nodes(2, unpack(self.nodes_memory))
for index = 1, #self.nodes_memory do
local node = self.nodes_memory[index]
local position_x = gui.get(node, "position.x")
gui.set(node, "position.x", position_x + width/2)
end
self.group_memory:set_size(width, nil)
end
function M:update_fps()
local average_frame_time = 0
local max_frame_time = 0
for index = 1, #self.fps_samples do
average_frame_time = average_frame_time + self.fps_samples[index]
max_frame_time = math.max(max_frame_time, self.fps_samples[index])
end
average_frame_time = average_frame_time / #self.fps_samples
self.text_fps_amount:set_to(tostring(math.ceil(1 / average_frame_time)))
self.text_fps_min:set_to("/ " .. tostring(math.ceil(1 / max_frame_time)))
local width = helper.centrate_nodes(2, unpack(self.nodes_fps))
self.group_fps:set_size(width, nil)
end
function M:update_components()
---@diagnostic disable-next-line: undefined-field
local components = #self.druid.components_all
self.text_components_amount:set_to(tostring(components))
local width = helper.centrate_nodes(2, unpack(self.nodes_components))
self.group_components:set_size(width, nil)
end
function M:update_events()
self.text_events_amount:set_to(tostring(event.COUNTER))
local width = helper.centrate_nodes(2, unpack(self.nodes_events))
for index = 1, #self.nodes_events do
local node = self.nodes_events[index]
local position_x = gui.get(node, "position.x")
gui.set(node, "position.x", position_x - width/2)
end
self.group_events:set_size(width, nil)
end
function M:align_fps_components()
local pos_x_memory = gui.get(self.group_memory.node, "position.x") + gui.get(self.group_memory.node, "size.x")
local pos_x_events = gui.get(self.group_events.node, "position.x") - gui.get(self.group_events.node, "size.x")
local width = pos_x_events - pos_x_memory
-- Align FPS and Components
local fps_size = gui.get(self.group_fps.node, "size.x")
local components_size = gui.get(self.group_components.node, "size.x")
local free_width = width - fps_size - components_size
gui.set(self.group_fps.node, "position.x", pos_x_memory + fps_size/2 + free_width/3)
gui.set(self.group_components.node, "position.x", pos_x_events - components_size/2 - free_width/3)
end
function M:update()
self:sample_fps()
end
function M:sample_fps()
if not self.previous_time then
self.previous_time = socket.gettime()
return
end
local current_time = socket.gettime()
local delta_time = current_time - self.previous_time
self.previous_time = current_time
table.insert(self.fps_samples, delta_time)
if #self.fps_samples > FPS_SAMPLES then
table.remove(self.fps_samples, 1)
end
end
function M:run_collectgarbage()
collectgarbage("collect")
end
return M

View File

@@ -0,0 +1,259 @@
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
fonts {
name: "text_regular"
font: "/example/assets/fonts/text_regular.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
nodes {
size {
x: 440.0
y: 450.0
}
color {
x: 0.173
y: 0.184
z: 0.204
}
type: TYPE_BOX
texture: "druid/pixel"
id: "root"
adjust_mode: ADJUST_MODE_STRETCH
layer: "druid"
inherit_alpha: true
}
nodes {
position {
x: -210.0
y: 215.0
}
scale {
x: 0.9
y: 0.9
}
size {
x: 245.0
y: 50.0
}
color {
x: 0.463
y: 0.475
z: 0.49
}
type: TYPE_TEXT
text: "Information"
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"
layer: "text_regular"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
nodes {
position {
y: -225.0
}
size {
x: 16.0
y: 16.0
}
type: TYPE_BOX
id: "S_Anchor"
pivot: PIVOT_S
parent: "root"
inherit_alpha: true
visible: false
}
nodes {
position {
y: 60.0
}
type: TYPE_TEMPLATE
id: "button_view_code"
parent: "S_Anchor"
inherit_alpha: true
template: "/example/templates/button_text_blue.gui"
}
nodes {
size {
x: 240.0
y: 80.0
}
type: TYPE_BOX
id: "button_view_code/root"
parent: "button_view_code"
overridden_fields: 4
template_node_child: true
}
nodes {
scale {
x: 0.75
y: 0.75
}
type: TYPE_TEXT
text: "View code"
id: "button_view_code/text"
parent: "button_view_code/root"
overridden_fields: 3
overridden_fields: 8
template_node_child: true
}
nodes {
position {
x: 220.0
y: 225.0
}
size {
x: 16.0
y: 16.0
}
type: TYPE_BOX
id: "NE_Anchor"
pivot: PIVOT_NE
parent: "root"
inherit_alpha: true
visible: false
}
nodes {
position {
x: -85.0
y: -32.5
}
type: TYPE_TEMPLATE
id: "button_profiler"
parent: "NE_Anchor"
inherit_alpha: true
template: "/example/templates/button_text_yellow.gui"
}
nodes {
size {
x: 130.0
y: 35.0
}
type: TYPE_BOX
texture: "druid/ui_circle_8"
id: "button_profiler/root"
parent: "button_profiler"
slice9 {
x: 4.0
y: 4.0
z: 4.0
w: 4.0
}
overridden_fields: 4
overridden_fields: 9
overridden_fields: 22
template_node_child: true
}
nodes {
scale {
x: 0.6
y: 0.6
}
size {
x: 190.0
y: 50.0
}
type: TYPE_TEXT
text: "Profiler"
id: "button_profiler/text"
parent: "button_profiler/root"
overridden_fields: 3
overridden_fields: 4
overridden_fields: 8
template_node_child: true
}
nodes {
position {
x: -200.0
y: 150.0
}
size {
x: 400.0
y: 250.0
}
type: TYPE_BOX
texture: "druid/empty"
id: "scroll_view"
pivot: PIVOT_NW
parent: "root"
inherit_alpha: true
visible: false
}
nodes {
size {
x: 400.0
y: 250.0
}
type: TYPE_BOX
texture: "druid/empty"
id: "scroll_content"
pivot: PIVOT_NW
parent: "scroll_view"
inherit_alpha: true
visible: false
}
nodes {
scale {
x: 0.75
y: 0.75
}
size {
x: 535.0
y: 270.0
}
color {
x: 0.463
y: 0.475
z: 0.49
}
type: TYPE_TEXT
text: "The default example how to use the button and bind the callbacks on them"
font: "text_regular"
id: "text_description"
pivot: PIVOT_NW
outline {
x: 1.0
y: 1.0
z: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
}
line_break: true
parent: "scroll_content"
layer: "text_bold"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
layers {
name: "druid"
}
layers {
name: "text_bold"
}
layers {
name: "text_regular"
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT

View File

@@ -0,0 +1,62 @@
local lang = require("lang.lang")
local component = require("druid.component")
local container = require("example.components.container.container")
local lang_text = require("druid.extended.lang_text")
local rich_text = require("druid.custom.rich_text.rich_text")
---@class panel_information: druid.base_component
---@field root druid.container
---@field text_header druid.lang_text
---@field rich_text druid.rich_text
---@field druid druid_instance
local PanelInformation = component.create("panel_information")
---@param template string
---@param nodes table<hash, node>
function PanelInformation:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.root = self.druid:new(container, "root") --[[@as druid.container]]
self.root:add_container("text_header")
self.root:add_container("scroll_view")
self.root:add_container("S_Anchor")
self.root:add_container("NE_Anchor")
self.druid:new(lang_text, "text_header", "ui_information")
self.druid:new(lang_text, "button_profiler/text", "ui_profiler")
--self.text_description = self.druid:new(lang_text, "text_description", "") --[[@as druid.lang_text]]
self.rich_text = self.druid:new(rich_text, "text_description")
self.button_profiler = self.druid:new_button("button_profiler/root", self.on_profiler_click)
self.button_profiler:set_key_trigger("key_p")
self.button_view_code = self.druid:new_button("button_view_code/root")
-- Disable profiler button for HTML5
gui.set_enabled(self.button_profiler.node, not html5)
end
function PanelInformation:set_text(text_id)
local text = lang.txt(text_id)
self.rich_text:set_text(text)
end
function PanelInformation:on_profiler_click()
if self._profiler_mode == nil then
self._profiler_mode = profiler.VIEW_MODE_MINIMIZED
profiler.enable_ui(true)
profiler.set_ui_view_mode(self._profiler_mode)
elseif self._profiler_mode == profiler.VIEW_MODE_MINIMIZED then
self._profiler_mode = profiler.VIEW_MODE_FULL
profiler.enable_ui(true)
profiler.set_ui_view_mode(self._profiler_mode)
else
self._profiler_mode = nil
profiler.enable_ui(false)
end
end
return PanelInformation

View File

@@ -0,0 +1,328 @@
script: ""
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
adjust_mode: ADJUST_MODE_STRETCH
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: -20.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.65
y: 0.65
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Button"
font: "text_bold"
id: "text_name"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 267.0
y: -20.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 226.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/rect_round2_width1"
id: "button"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 4.0
y: 4.0
z: 4.0
w: 4.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: -20.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 226.0
y: 4.0
z: 0.0
w: 1.0
}
color {
x: 0.894
y: 0.506
z: 0.333
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/pixel"
id: "selected"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_S
adjust_mode: ADJUST_MODE_STRETCH
parent: "button"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.65
y: 0.65
z: 1.0
w: 1.0
}
size {
x: 250.0
y: 30.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Button"
font: "text_bold"
id: "text_button"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "button"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,33 @@
local component = require("druid.component")
local lang_text = require("druid.extended.lang_text")
---@class property_button: druid.base_component
---@field root node
---@field text_name druid.lang_text
---@field button druid.button
---@field text_button druid.text
---@field druid druid_instance
local M = component.create("property_button")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.root = self:get_node("root")
self.text_name = self.druid:new(lang_text, "text_name") --[[@as druid.lang_text]]
self.selected = self:get_node("selected")
gui.set_alpha(self.selected, 0)
self.button = self.druid:new_button("button", self.on_click)
self.text_button = self.druid:new_text("text_button")
end
function M:on_click()
gui.set_alpha(self.selected, 1)
gui.animate(self.selected, "color.w", 0, gui.EASING_INSINE, 0.16)
end
return M

View File

@@ -0,0 +1,320 @@
script: ""
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
adjust_mode: ADJUST_MODE_STRETCH
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: -20.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.65
y: 0.65
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Checkbox"
font: "text_bold"
id: "text_name"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 174.0
y: -20.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 40.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/rect_round2_width1"
id: "button"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 4.0
y: 4.0
z: 4.0
w: 4.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/icon_check"
id: "icon"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "button"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: -20.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 40.0
y: 4.0
z: 0.0
w: 1.0
}
color {
x: 0.894
y: 0.506
z: 0.333
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/pixel"
id: "selected"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_S
adjust_mode: ADJUST_MODE_STRETCH
parent: "button"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,54 @@
local component = require("druid.component")
local container = require("example.components.container.container")
local lang_text = require("druid.extended.lang_text")
---@class property_checkbox: druid.base_component
---@field druid druid_instance
---@field root druid.container
---@field text_name druid.lang_text
---@field button druid.button
---@field selected node
local M = component.create("property_checkbox")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.root = self.druid:new(container, "root") --[[@as druid.container]]
self.icon = self:get_node("icon")
gui.set_enabled(self.icon, false)
self.selected = self:get_node("selected")
gui.set_alpha(self.selected, 0)
self.text_name = self.druid:new(lang_text, "text_name") --[[@as druid.lang_text]]
self.button = self.druid:new_button("button")
end
---@param value boolean
function M:set_value(value, is_instant)
if self._value == value then
return
end
self._value = value
gui.set_enabled(self.icon, value)
if not is_instant then
gui.set_alpha(self.selected, 1)
gui.animate(self.selected, "color.w", 0, gui.EASING_INSINE, 0.16)
end
end
---@return boolean
function M:get_value()
return self._value
end
return M

View File

@@ -0,0 +1,564 @@
script: ""
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
adjust_mode: ADJUST_MODE_STRETCH
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: -20.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.65
y: 0.65
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Checkbox"
font: "text_bold"
id: "text_name"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 400.0
y: -20.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "E_Anchor"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_E
adjust_mode: ADJUST_MODE_STRETCH
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: -20.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 60.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/rect_round2_width1"
id: "button"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_E
adjust_mode: ADJUST_MODE_FIT
parent: "E_Anchor"
layer: ""
inherit_alpha: true
slice9 {
x: 4.0
y: 4.0
z: 4.0
w: 4.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: -20.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 60.0
y: 4.0
z: 0.0
w: 1.0
}
color {
x: 0.894
y: 0.506
z: 0.333
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/pixel"
id: "selected"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_SE
adjust_mode: ADJUST_MODE_STRETCH
parent: "button"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -30.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.55
y: 0.55
z: 1.0
w: 1.0
}
size {
x: 100.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "25 %"
font: "text_bold"
id: "text_value"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "button"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 234.0
y: -20.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 160.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 0.129
y: 0.141
z: 0.157
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "slider"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 160.0
y: 8.0
z: 0.0
w: 1.0
}
color {
x: 0.129
y: 0.141
z: 0.157
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_8"
id: "slider_back"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "slider"
layer: ""
inherit_alpha: true
slice9 {
x: 4.0
y: 4.0
z: 4.0
w: 4.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -68.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 24.0
y: 24.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_8"
id: "slider_pin"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "slider"
layer: ""
inherit_alpha: true
slice9 {
x: 4.0
y: 4.0
z: 4.0
w: 4.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,75 @@
local component = require("druid.component")
local container = require("example.components.container.container")
local lang_text = require("druid.extended.lang_text")
local slider = require("druid.extended.slider")
---@class property_slider: druid.base_component
---@field druid druid_instance
---@field root druid.container
---@field text_name druid.lang_text
---@field text_value druid.text
---@field slider druid.slider
local M = component.create("property_slider")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.root = self.druid:new(container, "root") --[[@as druid.container]]
self.selected = self:get_node("selected")
gui.set_alpha(self.selected, 0)
self._value = 0
self.text_name = self.druid:new(lang_text, "text_name") --[[@as druid.lang_text]]
self.text_value = self.druid:new_text("text_value")
self.slider = self.druid:new(slider, "slider_pin", vmath.vector3(68, 0, 0), self._on_slider_change_by_user) --[[@as druid.slider]]
self.slider:set_input_node("slider")
self:set_text_function(function(value)
return math.floor(value * 100) .. "%"
end)
end
---@param callback fun(value:number):string
function M:set_text_function(callback)
self._text_function = callback
self.text_value:set_to(self._text_function(self._value))
end
---@param value number
function M:set_value(value, is_instant)
if self._value == value then
return
end
self._value = value
self.slider:set(value, true)
self.text_value:set_to(self._text_function(value))
if not is_instant then
gui.set_alpha(self.selected, 1)
gui.animate(self.selected, "color.w", 0, gui.EASING_INSINE, 0.16)
end
end
---@return number
function M:get_value()
return self._value
end
function M:_on_slider_change_by_user(value)
self._value = value
self.text_value:set_to(self._text_function(value))
gui.set_alpha(self.selected, 1)
gui.animate(self.selected, "color.w", 0, gui.EASING_INSINE, 0.16)
end
return M

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,128 @@
local component = require("druid.component")
local container = require("example.components.container.container")
local lang_text = require("druid.extended.lang_text")
local property_checkbox = require("example.components.properties_panel.properties.property_checkbox")
local property_slider = require("example.components.properties_panel.properties.property_slider")
local property_button = require("example.components.properties_panel.properties.property_button")
---@class properties_panel: druid.base_component
---@field root druid.container
---@field text_no_properties druid.lang_text
---@field scroll druid.scroll
---@field druid druid_instance
local M = component.create("properties_panel")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.root = self.druid:new(container, "root") --[[@as druid.container]]
self.root:add_container("text_header")
self.root:add_container("separator")
--self.root:add_container("scroll_view", nil, function()
-- self.scroll:update_view_size()
--end)
self.properties = {}
self.druid:new(lang_text, "text_header", "ui_properties_panel")
self.text_no_properties = self.druid:new(lang_text, "text_no_properties", "ui_no_properties") --[[@as druid.lang_text]]
self.scroll = self.druid:new_scroll("scroll_view", "scroll_content")
self.grid = self.druid:new_static_grid("scroll_content", "item_size", 1)
self.scroll:bind_grid(self.grid)
self.property_checkbox_prefab = self:get_node("property_checkbox/root")
gui.set_enabled(self.property_checkbox_prefab, false)
self.property_slider_prefab = self:get_node("property_slider/root")
gui.set_enabled(self.property_slider_prefab, false)
self.property_button_prefab = self:get_node("property_button/root")
gui.set_enabled(self.property_button_prefab, false)
end
function M:clear()
for index = 1, #self.properties do
self.druid:remove(self.properties[index])
end
self.properties = {}
local nodes = self.grid.nodes
for index = 1, #nodes do
gui.delete_node(nodes[index])
end
self.grid:clear()
gui.set_enabled(self.text_no_properties.text.node, true)
end
---@param text_id string
---@param initial_value boolean
---@param on_change_callback function
---@return property_checkbox
function M:add_checkbox(text_id, initial_value, on_change_callback)
local nodes = gui.clone_tree(self.property_checkbox_prefab)
local instance = self.druid:new(property_checkbox, "property_checkbox", nodes) --[[@as property_checkbox]]
instance.text_name:translate(text_id)
instance:set_value(initial_value, true)
instance.button.on_click:subscribe(function()
instance:set_value(not instance:get_value())
on_change_callback(instance:get_value())
end)
gui.set_enabled(instance.root.node, true)
self.grid:add(instance.root.node)
table.insert(self.properties, instance)
gui.set_enabled(self.text_no_properties.text.node, false)
return instance
end
---@param text_id string
---@param initial_value number
---@param on_change_callback function
---@return property_slider
function M:add_slider(text_id, initial_value, on_change_callback)
local nodes = gui.clone_tree(self.property_slider_prefab)
local instance = self.druid:new(property_slider, "property_slider", nodes) --[[@as property_slider]]
instance.text_name:translate(text_id)
instance:set_value(initial_value, true)
gui.set_enabled(instance.root.node, true)
self.grid:add(instance.root.node)
table.insert(self.properties, instance)
gui.set_enabled(self.text_no_properties.text.node, false)
instance.slider.on_change_value:subscribe(function(_, value)
on_change_callback(value)
end)
return instance
end
---@param text_id string
---@param on_click_callback function
function M:add_button(text_id, on_click_callback)
local nodes = gui.clone_tree(self.property_button_prefab)
local instance = self.druid:new(property_button, "property_button", nodes) --[[@as property_button]]
instance.text_name:translate(text_id)
gui.set_enabled(instance.root, true)
self.grid:add(instance.root)
table.insert(self.properties, instance)
gui.set_enabled(self.text_no_properties.text.node, false)
instance.button.on_click:subscribe(on_click_callback)
return instance
end
return M

39
example/druid.collection Normal file
View File

@@ -0,0 +1,39 @@
name: "example"
scale_along_z: 0
embedded_instances {
id: "go"
data: "components {\n"
" id: \"druid\"\n"
" component: \"/example/druid.gui\"\n"
" position {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" }\n"
" rotation {\n"
" x: 0.0\n"
" y: 0.0\n"
" z: 0.0\n"
" w: 1.0\n"
" }\n"
" property_decls {\n"
" }\n"
"}\n"
""
position {
x: 0.0
y: 0.0
z: 0.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale3 {
x: 1.0
y: 1.0
z: 1.0
}
}

3610
example/druid.gui Normal file

File diff suppressed because it is too large Load Diff

210
example/druid.gui_script Normal file
View File

@@ -0,0 +1,210 @@
local lang = require("lang.lang")
local saver = require("saver.saver")
local storage = require("saver.storage")
local druid = require("druid.druid")
local container = require("example.components.container.container")
local druid_logo = require("example.components.druid_logo.druid_logo")
local panel_information = require("example.components.panel_information.panel_information")
local example_scene = require("example.components.example_scene.example_scene")
local panel_druid_profiler = require("example.components.panel_druid_profiler.panel_druid_profiler")
local examples_list_view = require("example.components.examples_list_view.examples_list_view")
local properties_panel = require("example.components.properties_panel.properties_panel")
local output_list = require("example.components.output_list.output_list")
local druid_examples = require("example.examples.druid_examples")
---@class druid.example
---@field druid druid_instance
---@field container_root druid.container
---@field container_left druid.container
---@field container_logo druid.container
---@field container_examples druid.container
---@field container_right druid.container
---@field container_info druid.container
---@field container_group_settings_output druid.container
---@field container_settings druid.container
---@field container_output druid.container
---@field container_center druid.container
---@field container_status druid.container
---@field druid_logo druid_logo
---@field panel_information panel_information
---@field example_scene example_scene
---@field panel_druid_profiler panel_druid_profiler
---@field examples_list_view examples_list_view
---@field properties_panel properties_panel
---@field output_list output_list
--- Generic setup that should be done once per application
---@param self druid.example
local function setup_druid(self)
saver.init()
saver.bind_save_state("lang", lang.state)
lang.init()
lang.set_lang("en") -- Force default start language to EN, switch through the UI to check
druid.set_text_function(lang.txp)
window.set_listener(function(_, event)
druid.on_window_callback(event)
end)
end
--- Containers is a layout of the GUI scene. Inside this containers I will place a logic components
--- This allow easily move components in the GUI scene and change the size of each section
---@param self druid.example
local function setup_layout(self)
self.container_root = self.druid:new(container, "root") --[[@as druid.container]]
self.container_left = self.container_root:add_container("container_left", "stretch_y")
self.container_logo = self.container_left:add_container("container_logo")
self.container_examples = self.container_left:add_container("container_examples")
self.container_right = self.container_root:add_container("container_right", "stretch_y")
self.container_info = self.container_right:add_container("container_info")
self.container_group_settings_output = self.container_right:add_container("container_group_settings_output")
self.container_settings = self.container_group_settings_output:add_container("container_settings")
self.container_output = self.container_group_settings_output:add_container("container_output")
self.container_center = self.container_root:add_container("container_center")
self.container_status = self.container_root:add_container("container_status", "stretch_x")
end
---@param self druid.example
local function setup_components(self)
self.druid_logo = self.druid:new(druid_logo, "druid_logo") --[[@as druid_logo]]
self.container_logo:add_container(self.druid_logo.root)
self.panel_information = self.druid:new(panel_information, "panel_information") --[[@as panel_information]]
self.container_info:add_container(self.panel_information.root)
self.example_scene = self.druid:new(example_scene, "example_scene") --[[@as example_scene]]
self.container_center:add_container(self.example_scene.root)
self.panel_druid_profiler = self.druid:new(panel_druid_profiler, "panel_druid_profiler") --[[@as panel_druid_profiler]]
self.container_status:add_container(self.panel_druid_profiler.root)
self.examples_list_view = self.druid:new(examples_list_view, "examples_list_view") --[[@as examples_list_view]]
self.container_examples:add_container(self.examples_list_view.root)
self.properties_panel = self.druid:new(properties_panel, "properties_panel") --[[@as properties_panel]]
self.container_settings:add_container(self.properties_panel.root)
self.output_list = self.druid:new(output_list, "output_list") --[[@as output_list]]
self.container_output:add_container(self.output_list.root)
do -- Component bindings
self.examples_list_view.on_debug_info:subscribe(function(info)
self.example_scene:set_debug_info(info)
end)
self.examples_list_view.add_log_text:subscribe(function(log)
self.output_list:add_log_text(log)
end)
self.examples_list_view.on_set_information:subscribe(function(text_id)
self.panel_information:set_text(text_id)
end)
self.panel_information.button_view_code.on_click:subscribe(function()
local selected_example = self.examples_list_view.selected_example
if not selected_example then
return
end
local code_url = selected_example.data.code_url
if not code_url then
return
end
local url_prefix = "https://github.com/Insality/druid/blob/master/"
sys.open_url(url_prefix .. code_url, { target = "_blank" })
end)
end
end
---@param self druid.example
local function select_start_example(self)
if html5 then
-- Try load example from URL
local example_name = html5.run("new URLSearchParams(window.location.search).get('example')")
if example_name then
local is_selected self.examples_list_view:select_example_by_name_id(example_name)
if is_selected then
return
end
end
end
-- If we have last selected example in cache, select it again
local last_selected_example_name = storage.get_string("last_selected_example", "")
if last_selected_example_name ~= "" then
self.examples_list_view:select_example_by_name_id(last_selected_example_name)
end
end
---@param self druid.example
local function setup_examples(self)
local examples = druid_examples.get_examples()
do -- Disable all examples by default
for index = 1, #examples do
local example = examples[index]
local examples_list = example.examples_list
for example_index = 1, #examples_list do
gui.set_enabled(gui.get_node(examples_list[example_index].root), false)
end
end
end
for index = 1, #examples do
local example = examples[index]
self.examples_list_view:add_example(example, self)
end
select_start_example(self)
end
---@param self druid.example
function init(self)
setup_druid(self)
self.druid = druid.new(self)
setup_layout(self)
setup_components(self)
setup_examples(self)
end
---@param self druid.example
function final(self)
self.druid:final()
end
---@param self druid.example
---@param dt number
function update(self, dt)
self.druid:update(dt)
end
---@param self druid.example
---@param message_id hash
---@param message table
---@param sender url
function on_message(self, message_id, message, sender)
self.druid:on_message(message_id, message, sender)
end
---@param self druid.example
---@param action_id hash
---@param action action
function on_input(self, action_id, action)
return self.druid:on_input(action_id, action)
end

View File

@@ -0,0 +1,50 @@
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
nodes {
size {
x: 1000.0
y: 1000.0
}
color {
x: 0.173
y: 0.184
z: 0.204
}
type: TYPE_BOX
texture: "druid/ui_circle_64"
id: "root"
inherit_alpha: true
slice9 {
x: 32.0
y: 32.0
z: 32.0
w: 32.0
}
}
nodes {
size {
x: 700.0
y: 100.0
}
color {
x: 0.522
y: 0.522
z: 0.522
}
type: TYPE_TEXT
text: "Press \"back\" to trigger a callback"
font: "text_bold"
id: "text"
parent: "root"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT

View File

@@ -0,0 +1,24 @@
local component = require("druid.component")
---@class basic_back_handler: druid.base_component
---@field druid druid_instance
local M = component.create("basic_back_handler")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.druid:new_back_handler(self.on_back)
end
function M:on_back()
local node = self:get_node("text")
gui.animate(node, gui.PROP_SCALE, vmath.vector3(1.2), gui.EASING_OUTELASTIC, 0.5, 0, function()
gui.animate(node, gui.PROP_SCALE, vmath.vector3(1), gui.EASING_OUTELASTIC, 0.5)
end)
end
return M

View File

@@ -0,0 +1,91 @@
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
nodes {
size {
x: 1000.0
y: 1000.0
}
color {
x: 0.173
y: 0.184
z: 0.204
}
type: TYPE_BOX
texture: "druid/ui_circle_64"
id: "root"
inherit_alpha: true
slice9 {
x: 32.0
y: 32.0
z: 32.0
w: 32.0
}
}
nodes {
size {
x: 512.0
y: 512.0
}
color {
x: 0.31
y: 0.318
z: 0.322
}
type: TYPE_BOX
texture: "druid/ui_circle_32"
id: "blocker"
parent: "root"
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
}
nodes {
type: TYPE_TEMPLATE
id: "button"
parent: "blocker"
inherit_alpha: true
template: "/example/templates/button_text_green.gui"
}
nodes {
type: TYPE_BOX
id: "button/root"
parent: "button"
template_node_child: true
}
nodes {
type: TYPE_TEXT
id: "button/text"
parent: "button/root"
template_node_child: true
}
nodes {
position {
x: -246.0
y: 246.0
}
size {
x: 300.0
y: 50.0
}
type: TYPE_TEXT
text: "Blocker"
font: "text_bold"
id: "text"
pivot: PIVOT_NW
parent: "blocker"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT

View File

@@ -0,0 +1,34 @@
local component = require("druid.component")
---@class basic_blocker: druid.component
---@field druid druid_instance
---@field root node
---@field blocker druid.blocker
local M = component.create("basic_blocker")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.root = self:get_node("root")
self.button_root = self.druid:new_button(self.root, self.on_root_click)
-- This blocker forbid input to all previous nodes in node zone
self.blocker = self.druid:new_blocker("blocker")
self.button = self.druid:new_button("button/root", self.on_button_click)
end
function M:on_root_click()
print("Root click")
end
function M:on_button_click()
print("Button click")
end
return M

View File

@@ -0,0 +1,236 @@
script: ""
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "button"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/templates/button_text_green.gui"
template_node_child: false
custom_type: 0
enabled: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 280.0
y: 90.0
z: 0.0
w: 1.0
}
color {
x: 0.557
y: 0.835
z: 0.62
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_32"
id: "button/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "button"
layer: "druid"
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 245.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Confirm"
font: "text_bold"
id: "button/text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "button/root"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,19 @@
local component = require("druid.component")
---@class basic_button: druid.base_component
---@field druid druid_instance
---@field button druid.button
local M = component.create("basic_button")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.button = self.druid:new_button("button/root", function()
print("Button pressed")
end)
end
return M

View File

@@ -0,0 +1,236 @@
script: ""
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "button"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/templates/button_text_green.gui"
template_node_child: false
custom_type: 0
enabled: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 280.0
y: 90.0
z: 0.0
w: 1.0
}
color {
x: 0.557
y: 0.835
z: 0.62
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_32"
id: "button/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "button"
layer: "druid"
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 245.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Confirm"
font: "text_bold"
id: "button/text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "button/root"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,23 @@
local component = require("druid.component")
---@class basic_button_double_click: druid.base_component
---@field druid druid_instance
---@field button druid.button
local M = component.create("basic_button_double_click")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.button = self.druid:new_button("button/root", function()
print("Click")
end)
self.button.on_double_click:subscribe(function()
print("Double click")
end)
end
return M

View File

@@ -0,0 +1,107 @@
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
nodes {
size {
x: 200.0
y: 100.0
}
type: TYPE_BOX
id: "root"
inherit_alpha: true
size_mode: SIZE_MODE_AUTO
visible: false
}
nodes {
size {
x: 280.0
y: 90.0
}
color {
x: 0.902
y: 0.875
z: 0.624
}
type: TYPE_BOX
texture: "druid/ui_circle_32"
id: "button"
parent: "root"
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
}
nodes {
size {
x: 400.0
y: 400.0
}
type: TYPE_PIE
id: "mask"
parent: "button"
inherit_alpha: true
clipping_mode: CLIPPING_MODE_STENCIL
clipping_visible: false
size_mode: SIZE_MODE_AUTO
}
nodes {
size {
x: 280.0
y: 90.0
}
color {
x: 0.557
y: 0.835
z: 0.62
}
type: TYPE_BOX
texture: "druid/ui_circle_32"
id: "button_image"
parent: "mask"
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
}
nodes {
size {
x: 245.0
y: 50.0
}
color {
x: 0.31
y: 0.318
z: 0.322
}
type: TYPE_TEXT
text: "Confirm"
font: "text_bold"
id: "text"
outline {
x: 1.0
y: 1.0
z: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
}
parent: "button"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT

View File

@@ -0,0 +1,49 @@
local component = require("druid.component")
local panthera = require("panthera.panthera")
local animation = require("example.examples.basic.button.basic_button_hold_panthera")
---@class basic_button_hold: druid.base_component
---@field druid druid_instance
---@field button druid.button
local M = component.create("basic_button_hold")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.animation = panthera.create_gui(animation, self:get_template(), nodes)
self.button = self.druid:new_button("button", function()
print("Click")
end)
self.button:set_style({})
self.button.style.AUTOHOLD_TRIGGER = 2
self.button.style.LONGTAP_TIME = 0
self.button.on_hold_callback:subscribe(function(_, _, _, time)
local start_time = self.button.style.LONGTAP_TIME
local max_time = self.button.style.AUTOHOLD_TRIGGER
local progress = (time - start_time) / (max_time - start_time)
panthera.set_time(self.animation, "hold", progress)
end)
self.button.on_long_click:subscribe(function()
panthera.play(self.animation, "complete")
end)
self.button.hover.on_mouse_hover:subscribe(function(_, state)
if not state then
panthera.set_time(self.animation, "hold", 0)
end
end)
self.button.on_click_outside:subscribe(function()
panthera.set_time(self.animation, "hold", 0)
end)
end
return M

View File

@@ -0,0 +1,266 @@
return {
type = "animation_editor",
format = "json",
data = {
nodes = {
},
animations = {
{
animation_id = "default",
duration = 1,
animation_keys = {
},
},
{
animation_id = "hold",
duration = 1,
animation_keys = {
{
end_value = -90,
easing = "outsine",
property_id = "rotation_z",
node_id = "button_image",
key_type = "tween",
},
{
end_value = 90,
easing = "outsine",
property_id = "rotation_z",
node_id = "mask",
key_type = "tween",
},
{
end_value = 1.1,
easing = "outsine",
property_id = "scale_x",
duration = 0.15,
key_type = "tween",
node_id = "button",
start_value = 1,
},
{
end_value = 1.1,
easing = "outsine",
property_id = "scale_y",
duration = 0.15,
key_type = "tween",
node_id = "button",
start_value = 1,
},
{
end_value = 1.3,
easing = "outsine",
property_id = "scale_x",
duration = 0.15,
key_type = "tween",
node_id = "text",
start_value = 1,
},
{
end_value = 1.3,
easing = "outsine",
property_id = "scale_y",
duration = 0.15,
key_type = "tween",
node_id = "text",
start_value = 1,
},
{
start_value = 360,
easing = "outsine",
property_id = "fill_angle",
duration = 1,
node_id = "mask",
key_type = "tween",
},
{
end_value = 1,
easing = "incirc",
property_id = "scale_x",
duration = 0.85,
start_value = 1.1,
key_type = "tween",
node_id = "button",
start_time = 0.15,
},
{
end_value = 1,
easing = "incirc",
property_id = "scale_y",
duration = 0.85,
start_value = 1.1,
key_type = "tween",
node_id = "button",
start_time = 0.15,
},
{
end_value = 1,
easing = "outsine",
property_id = "scale_x",
duration = 0.51,
start_value = 1.3,
key_type = "tween",
node_id = "text",
start_time = 0.49,
},
{
end_value = 1,
easing = "outsine",
property_id = "scale_y",
duration = 0.51,
start_value = 1.3,
key_type = "tween",
node_id = "text",
start_time = 0.49,
},
},
},
{
animation_id = "complete",
duration = 0.4,
animation_keys = {
{
easing = "linear",
property_id = "inherit_alpha",
data = "false",
key_type = "trigger",
node_id = "text",
start_data = "true",
},
{
end_value = 0.624,
easing = "outsine",
property_id = "color_b",
key_type = "tween",
node_id = "button_image",
start_value = 0.62,
},
{
end_value = 0.875,
easing = "outsine",
property_id = "color_g",
key_type = "tween",
node_id = "button_image",
start_value = 0.835,
},
{
end_value = 0.902,
easing = "outsine",
property_id = "color_r",
key_type = "tween",
node_id = "button_image",
start_value = 0.557,
},
{
end_value = 1.1,
easing = "outsine",
property_id = "color_a",
duration = 0.17,
key_type = "tween",
node_id = "root",
start_value = 1,
},
{
end_value = 1.2,
easing = "outsine",
property_id = "scale_x",
duration = 0.17,
key_type = "tween",
node_id = "root",
start_value = 1,
},
{
end_value = 1.2,
easing = "outsine",
property_id = "scale_y",
duration = 0.17,
key_type = "tween",
node_id = "root",
start_value = 1,
},
{
end_value = 0.557,
easing = "outsine",
property_id = "color_r",
duration = 0.38,
start_value = 0.902,
key_type = "tween",
node_id = "button_image",
start_time = 0.02,
},
{
end_value = 0.62,
easing = "outsine",
property_id = "color_b",
duration = 0.38,
start_value = 0.624,
key_type = "tween",
node_id = "button_image",
start_time = 0.02,
},
{
end_value = 0.835,
easing = "outsine",
property_id = "color_g",
duration = 0.38,
start_value = 0.875,
key_type = "tween",
node_id = "button_image",
start_time = 0.02,
},
{
end_value = 1,
easing = "outsine",
property_id = "color_a",
duration = 0.22,
start_value = 1.1,
key_type = "tween",
node_id = "root",
start_time = 0.17,
},
{
end_value = 1,
easing = "outsine",
property_id = "scale_x",
duration = 0.22,
start_value = 1.2,
key_type = "tween",
node_id = "root",
start_time = 0.17,
},
{
end_value = 1,
easing = "outsine",
property_id = "scale_y",
duration = 0.22,
start_value = 1.2,
key_type = "tween",
node_id = "root",
start_time = 0.17,
},
{
easing = "linear",
property_id = "inherit_alpha",
start_data = "false",
data = "true",
key_type = "trigger",
node_id = "text",
start_time = 0.39,
},
},
},
},
metadata = {
layers = {
},
gui_path = "/example/examples/basic/button/basic_button_hold.gui",
gizmo_steps = {
},
settings = {
font_size = 40,
},
fps = 60,
},
},
version = 1,
}

View File

@@ -0,0 +1,77 @@
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
nodes {
size {
x: 200.0
y: 100.0
}
type: TYPE_BOX
id: "root"
inherit_alpha: true
size_mode: SIZE_MODE_AUTO
visible: false
}
nodes {
size {
x: 40.0
y: 40.0
}
color {
x: 0.463
y: 0.475
z: 0.49
}
type: TYPE_BOX
texture: "druid/rect_round2_width1"
id: "button"
parent: "root"
inherit_alpha: true
slice9 {
x: 4.0
y: 4.0
z: 4.0
w: 4.0
}
}
nodes {
color {
x: 0.722
y: 0.741
z: 0.761
}
type: TYPE_BOX
texture: "druid/icon_check"
id: "icon"
parent: "button"
inherit_alpha: true
size_mode: SIZE_MODE_AUTO
}
nodes {
position {
y: -20.0
}
size {
x: 40.0
y: 4.0
}
color {
x: 0.894
y: 0.506
z: 0.333
}
type: TYPE_BOX
texture: "druid/pixel"
id: "selected"
pivot: PIVOT_S
adjust_mode: ADJUST_MODE_STRETCH
parent: "button"
inherit_alpha: true
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT

View File

@@ -0,0 +1,41 @@
local component = require("druid.component")
---@class basic_checkbox: druid.base_component
---@field druid druid_instance
---@field button druid.button
local M = component.create("basic_checkbox")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.button = self.druid:new_button("button", self.on_checkbox_click) -- Button to handle checkbox
self.icon = self:get_node("icon") -- Checkbox icon to hide/show
self.selected = self:get_node("selected") -- Selected effect to show when checkbox is changed
gui.set_alpha(self.selected, 0)
self:set_state(false)
end
function M:on_checkbox_click()
self:set_state(not self.is_enabled)
end
function M:set_state(is_enabled)
if self.is_enabled == is_enabled then
return
end
self.is_enabled = is_enabled
gui.set_enabled(self.icon, self.is_enabled)
gui.set_alpha(self.selected, 1)
gui.animate(self.selected, "color.w", 0, gui.EASING_INSINE, 0.16)
end
return M

View File

@@ -0,0 +1,241 @@
script: ""
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1000.0
y: 1000.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "drag"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/templates/button_text_blue.gui"
template_node_child: false
custom_type: 0
enabled: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 280.0
y: 90.0
z: 0.0
w: 1.0
}
color {
x: 0.631
y: 0.843
z: 0.961
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_32"
id: "drag/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "drag"
layer: "druid"
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 245.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Drag Me"
font: "text_bold"
id: "drag/text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "drag/root"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
overridden_fields: 8
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,29 @@
local component = require("druid.component")
---@class drag: druid.base_component
---@field druid druid_instance
local M = component.create("drag")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
-- Init drag and move the drag node on drag callback
self.drag = self.druid:new_drag("drag/root", function(_, dx, dy)
local position_x = gui.get(self.drag.node, "position.x")
local position_y = gui.get(self.drag.node, "position.y")
gui.set(self.drag.node, "position.x", position_x + dx)
gui.set(self.drag.node, "position.y", position_y + dy)
end)
-- Save start position for animation
self.start_position = gui.get_position(self.drag.node)
self.drag.on_drag_end:subscribe(function()
gui.animate(self.drag.node, "position", self.start_position, gui.EASING_OUTBACK, 0.3)
end)
end
return M

View File

@@ -0,0 +1,124 @@
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
nodes {
size {
x: 1000.0
y: 1000.0
}
type: TYPE_BOX
id: "root"
inherit_alpha: true
visible: false
}
nodes {
type: TYPE_TEMPLATE
id: "drag"
parent: "root"
inherit_alpha: true
template: "/example/templates/button_text_blue.gui"
}
nodes {
type: TYPE_BOX
id: "drag/root"
parent: "drag"
template_node_child: true
}
nodes {
type: TYPE_TEXT
text: "Drag Me"
id: "drag/text"
parent: "drag/root"
overridden_fields: 8
template_node_child: true
}
nodes {
position {
y: 300.0
}
size {
x: 300.0
y: 300.0
}
color {
x: 0.173
y: 0.184
z: 0.204
}
type: TYPE_BOX
texture: "druid/ui_circle_64"
id: "zone"
parent: "root"
inherit_alpha: true
slice9 {
x: 32.0
y: 32.0
z: 32.0
w: 32.0
}
}
nodes {
position {
y: 100.0
}
size {
x: 300.0
y: 100.0
}
color {
x: 0.31
y: 0.318
z: 0.322
}
type: TYPE_TEXT
text: "Drop Item Here"
font: "text_bold"
id: "text_hint"
outline {
x: 1.0
y: 1.0
z: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
}
parent: "zone"
outline_alpha: 0.0
shadow_alpha: 0.0
}
nodes {
scale {
x: 2.0
y: 2.0
}
size {
x: 100.0
y: 100.0
}
type: TYPE_TEXT
text: "0"
font: "text_bold"
id: "text_counter"
outline {
x: 1.0
y: 1.0
z: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
}
parent: "zone"
outline_alpha: 0.0
shadow_alpha: 0.0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT

View File

@@ -0,0 +1,62 @@
local component = require("druid.component")
---@class drag_to_node: druid.base_component
---@field druid druid_instance
local M = component.create("drag_to_node")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.zone = self:get_node("zone")
self.counter = 0
self.text_counter = self:get_node("text_counter")
gui.set_text(self.text_counter, self.counter)
-- Init drag and move the drag node on drag callback
self.drag = self.druid:new_drag("drag/root", self.on_drag_start)
self.drag.on_drag_end:subscribe(self.on_drag_end)
-- Save start position for animation
self.start_position = gui.get_position(self.drag.node)
end
function M:on_drag_start(dx, dy, x, y, touch)
local position_x = gui.get(self.drag.node, "position.x")
local position_y = gui.get(self.drag.node, "position.y")
gui.set(self.drag.node, "position.x", position_x + dx)
gui.set(self.drag.node, "position.y", position_y + dy)
local is_pick_zone = gui.pick_node(self.zone, touch.x, touch.y)
self:on_hover_pick_zone(is_pick_zone)
end
function M:on_drag_end(x, y, touch)
gui.animate(self.drag.node, "position", self.start_position, gui.EASING_OUTBACK, 0.3)
local is_pick_zone = gui.pick_node(self.zone, touch.x, touch.y)
if is_pick_zone then
self.counter = self.counter + 1
gui.set_text(self.text_counter, self.counter)
self:on_drop_to_zone()
end
self:on_hover_pick_zone(false)
end
function M:on_hover_pick_zone(is_pick_zone)
local target_alpha = is_pick_zone and 1.5 or 1
gui.animate(self.zone, "color.w", target_alpha, gui.EASING_OUTSINE, 0.3)
end
function M:on_drop_to_zone()
gui.set_scale(self.zone, vmath.vector3(1.2))
gui.animate(self.zone, "scale", vmath.vector3(1), gui.EASING_OUTBACK, 0.3)
end
return M

View File

@@ -0,0 +1,721 @@
local const = require("druid.const")
local helper = require("druid.helper")
local M = {}
function M.get_examples()
---@type druid.example.data[]
return {
{
name_id = "ui_example_basic_button",
information_text_id = "ui_example_basic_button_description",
template = "basic_button",
root = "basic_button/root",
code_url = "example/examples/basic/button/basic_button.lua",
component_class = require("example.examples.basic.button.basic_button"),
properties_control = function(instance, properties_panel)
---@cast instance basic_button
local checkbox = properties_panel:add_checkbox("ui_enabled", false, function(value)
instance.button:set_enabled(value)
end)
checkbox:set_value(true)
end,
on_create = function(instance, output_log)
---@cast instance basic_button
instance.button.on_click:subscribe(function()
output_log:add_log_text("Button Clicked")
end)
end,
},
{
name_id = "ui_example_basic_button_double_click",
information_text_id = "ui_example_basic_button_double_click_description",
template = "basic_button_double_click",
root = "basic_button_double_click/root",
code_url = "example/examples/basic/button/basic_button_double_click.lua",
component_class = require("example.examples.basic.button.basic_button_double_click"),
on_create = function(instance, output_log)
---@cast instance basic_button_double_click
instance.button.on_click:subscribe(function()
output_log:add_log_text("Clicked")
end)
instance.button.on_double_click:subscribe(function()
output_log:add_log_text("Double Clicked")
end)
end,
},
{
name_id = "ui_example_basic_button_hold",
information_text_id = "ui_example_basic_button_hold_description",
template = "basic_button_hold",
root = "basic_button_hold/root",
code_url = "example/examples/basic/button/basic_button_hold.lua",
component_class = require("example.examples.basic.button.basic_button_hold"),
on_create = function(instance, output_log)
---@cast instance basic_button_hold
instance.button.on_click:subscribe(function()
output_log:add_log_text("Clicked")
end)
instance.button.on_long_click:subscribe(function()
output_log:add_log_text("On long click")
end)
end,
},
{
name_id = "ui_example_basic_text",
information_text_id = "ui_example_basic_text_description",
template = "basic_text",
root = "basic_text/root",
code_url = "example/examples/basic/text/basic_text.lua",
component_class = require("example.examples.basic.text.basic_text"),
properties_control = function(instance, properties_panel)
---@cast instance basic_text
local adjust_index = 1
local adjust_types = {
const.TEXT_ADJUST.DOWNSCALE,
const.TEXT_ADJUST.DOWNSCALE_LIMITED,
--const.TEXT_ADJUST.SCALE_THEN_SCROLL, -- works bad with container for some reason
--const.TEXT_ADJUST.SCROLL, -- works bad with container for some reason
const.TEXT_ADJUST.TRIM,
}
properties_panel:add_button("ui_adjust_next", function()
adjust_index = adjust_index + 1
if adjust_index > #adjust_types then
adjust_index = 1
end
instance.text:set_text_adjust(adjust_types[adjust_index], 0.5)
end)
local pivot_index = 1
local pivot_list = {
gui.PIVOT_CENTER,
gui.PIVOT_W,
gui.PIVOT_SW,
gui.PIVOT_S,
gui.PIVOT_SE,
gui.PIVOT_E,
gui.PIVOT_NE,
gui.PIVOT_N,
gui.PIVOT_NW,
}
---@cast instance rich_text_tags
properties_panel:add_button("ui_pivot_next", function()
pivot_index = pivot_index + 1
if pivot_index > #pivot_list then
pivot_index = 1
end
instance:set_pivot(pivot_list[pivot_index])
end)
end,
get_debug_info = function(instance)
---@cast instance multiline_text
local info = ""
info = info .. "Text Adjust: " .. instance.text.adjust_type .. "\n"
info = info .. "Pivot: " .. gui.get_pivot(instance.text.node) .. "\n"
return info
end
},
{
name_id = "ui_example_basic_multiline_text",
information_text_id = "ui_example_basic_multiline_text_description",
template = "multiline_text",
root = "multiline_text/root",
code_url = "example/examples/basic/text/multiline_text.lua",
component_class = require("example.examples.basic.text.multiline_text"),
properties_control = function(instance, properties_panel)
---@cast instance multiline_text
local adjust_index = 1
local adjust_types = {
const.TEXT_ADJUST.DOWNSCALE,
const.TEXT_ADJUST.DOWNSCALE_LIMITED,
--const.TEXT_ADJUST.SCALE_THEN_SCROLL, -- works bad with container for some reason
--const.TEXT_ADJUST.SCROLL, -- works bad with container for some reason
const.TEXT_ADJUST.TRIM,
}
properties_panel:add_button("ui_adjust_next", function()
adjust_index = adjust_index + 1
if adjust_index > #adjust_types then
adjust_index = 1
end
instance.text:set_text_adjust(adjust_types[adjust_index], 0.8)
end)
end,
get_debug_info = function(instance)
---@cast instance multiline_text
local info = ""
info = info .. "Text Adjust: " .. instance.text.adjust_type .. "\n"
info = info .. "Pivot: " .. gui.get_pivot(instance.text.node) .. "\n"
return info
end
},
{
name_id = "ui_example_basic_hover",
information_text_id = "ui_example_basic_hover_description",
template = "hover",
root = "hover/root",
code_url = "example/examples/basic/hover/hover.lua",
component_class = require("example.examples.basic.hover.hover"),
},
{
name_id = "ui_example_basic_drag",
information_text_id = "ui_example_basic_drag_description",
template = "drag",
root = "drag/root",
code_url = "example/examples/basic/drag/drag.lua",
component_class = require("example.examples.basic.drag.drag"),
},
{
name_id = "ui_example_basic_drag_to_node",
information_text_id = "ui_example_basic_drag_to_node_description",
template = "drag_to_node",
root = "drag_to_node/root",
code_url = "example/examples/basic/drag/drag_to_node.lua",
component_class = require("example.examples.basic.drag.drag_to_node"),
},
{
name_id = "ui_example_basic_slider",
information_text_id = "ui_example_basic_slider_description",
template = "basic_slider",
root = "basic_slider/root",
code_url = "example/examples/basic/slider/basic_slider.lua",
component_class = require("example.examples.basic.slider.basic_slider"),
on_create = function(instance, output_log)
---@cast instance basic_slider
instance.slider.on_change_value:subscribe(function(_, value)
local value = helper.round(value, 2)
output_log:add_log_text("Slider Value: " .. value)
end)
end,
},
{
name_id = "ui_example_basic_slider_vertical",
information_text_id = "ui_example_basic_slider_vertical_description",
template = "basic_slider_vertical",
root = "basic_slider_vertical/root",
code_url = "example/examples/basic/slider/basic_slider_vertical.lua",
component_class = require("example.examples.basic.slider.basic_slider_vertical"),
on_create = function(instance, output_log)
---@cast instance basic_slider_vertical
instance.slider.on_change_value:subscribe(function(_, value)
local value = helper.round(value, 2)
output_log:add_log_text("Slider Value: " .. value)
end)
end,
},
{
name_id = "ui_example_basic_slider_stepped",
information_text_id = "ui_example_basic_slider_stepped_description",
template = "basic_slider_stepped",
root = "basic_slider_stepped/root",
code_url = "example/examples/basic/slider/basic_slider_stepped.lua",
component_class = require("example.examples.basic.slider.basic_slider_stepped"),
on_create = function(instance, output_log)
---@cast instance basic_slider
instance.slider.on_change_value:subscribe(function(_, value)
local value = helper.round(value, 2)
output_log:add_log_text("Slider Value: " .. value)
end)
end,
},
{
name_id = "ui_example_basic_progress_bar",
information_text_id = "ui_example_basic_progress_bar_description",
template = "basic_progress_bar",
root = "basic_progress_bar/root",
code_url = "example/examples/basic/progress_bar/basic_progress_bar.lua",
component_class = require("example.examples.basic.progress_bar.basic_progress_bar"),
properties_control = function(instance, properties_panel)
---@cast instance basic_progress_bar
properties_panel:add_slider("ui_value", 1, function(value)
instance:set_value(value)
end)
end,
},
{
name_id = "ui_example_basic_progress_bar_slice9",
information_text_id = "ui_example_basic_progress_bar_slice9_description",
template = "basic_progress_bar_slice9",
root = "basic_progress_bar_slice9/root",
code_url = "example/examples/basic/progress_bar/basic_progress_bar_slice9.lua",
component_class = require("example.examples.basic.progress_bar.basic_progress_bar_slice9"),
properties_control = function(instance, properties_panel)
---@cast instance basic_progress_bar_slice9
properties_panel:add_slider("ui_value", 1, function(value)
instance:set_value(value)
end)
end,
},
{
name_id = "ui_example_basic_blocker",
information_text_id = "ui_example_basic_blocker_description",
template = "basic_blocker",
root = "basic_blocker/root",
code_url = "example/examples/basic/blocker/basic_blocker.lua",
component_class = require("example.examples.basic.blocker.basic_blocker"),
on_create = function(instance, output_log)
---@cast instance basic_blocker
instance.button_root.on_click:subscribe(function()
output_log:add_log_text("Root Clicked")
end)
instance.button.on_click:subscribe(function()
output_log:add_log_text("Button Clicked")
end)
end,
},
{
name_id = "ui_example_basic_back_handler",
information_text_id = "ui_example_basic_back_handler_description",
template = "basic_back_handler",
root = "basic_back_handler/root",
code_url = "example/examples/basic/back_handler/basic_back_handler.lua",
component_class = require("example.examples.basic.back_handler.basic_back_handler"),
},
{
name_id = "ui_example_basic_timer",
information_text_id = "ui_example_basic_timer_description",
template = "basic_timer",
root = "basic_timer/root",
code_url = "example/examples/basic/timer/basic_timer.lua",
component_class = require("example.examples.basic.timer.basic_timer"),
on_create = function(instance, output_log)
---@cast instance basic_timer
instance.on_cycle_end:subscribe(function()
output_log:add_log_text("Timer Cycle End")
end)
end,
},
{
name_id = "ui_example_basic_hotkey",
information_text_id = "ui_example_basic_hotkey_description",
template = "basic_hotkey",
root = "basic_hotkey/root",
code_url = "example/examples/basic/hotkey/basic_hotkey.lua",
component_class = require("example.examples.basic.hotkey.basic_hotkey"),
on_create = function(instance, output_log)
---@cast instance basic_hotkey
instance.hotkey.on_hotkey_released:subscribe(function()
output_log:add_log_text("Hotkey Released")
end)
end,
},
{
name_id = "ui_example_basic_scroll",
information_text_id = "ui_example_basic_scroll_description",
template = "scroll",
root = "scroll/root",
code_url = "example/examples/basic/scroll/scroll.lua",
component_class = require("example.examples.basic.scroll.scroll"),
on_create = function(instance, output_log)
---@cast instance scroll
instance.button_tutorial.on_click:subscribe(function()
output_log:add_log_text("Button Tutorial Clicked")
end)
instance.button_stencil.on_click:subscribe(function()
output_log:add_log_text("Button Stencil Clicked")
end)
end,
properties_control = function(instance, properties_panel)
---@cast instance scroll
local is_stretch = instance.scroll.style.EXTRA_STRETCH_SIZE > 0
properties_panel:add_checkbox("ui_elastic_scroll", is_stretch, function(value)
instance.scroll:set_extra_stretch_size(value and 100 or 0)
end)
local view_node = instance.scroll.view_node
local is_stencil = gui.get_clipping_mode(view_node) == gui.CLIPPING_MODE_STENCIL
properties_panel:add_checkbox("ui_clipping", is_stencil, function(value)
gui.set_clipping_mode(view_node, value and gui.CLIPPING_MODE_STENCIL or gui.CLIPPING_MODE_NONE)
end)
end,
get_debug_info = function(instance)
---@cast instance scroll
local info = ""
local s = instance.scroll
info = info .. "View Size Y: " .. gui.get(s.view_node, "size.y") .. "\n"
info = info .. "Content Size Y: " .. gui.get(s.content_node, "size.y") .. "\n"
info = info .. "Content position Y: " .. math.ceil(s.position.y) .. "\n"
info = info .. "Content Range Y: " .. s.available_pos.y .. " - " .. s.available_pos.w .. "\n"
return info
end
},
{
name_id = "ui_example_basic_scroll_slider",
information_text_id = "ui_example_basic_scroll_slider_description",
template = "scroll_slider",
root = "scroll_slider/root",
code_url = "example/examples/basic/scroll_slider/scroll_slider.lua",
component_class = require("example.examples.basic.scroll_slider.scroll_slider"),
get_debug_info = function(instance)
---@cast instance scroll_slider
local info = ""
local s = instance.scroll
info = info .. "View Size Y: " .. gui.get(s.view_node, "size.y") .. "\n"
info = info .. "Content Size Y: " .. gui.get(s.content_node, "size.y") .. "\n"
info = info .. "Content position Y: " .. math.ceil(s.position.y) .. "\n"
info = info .. "Content Range Y: " .. s.available_pos.y .. " - " .. s.available_pos.w .. "\n"
return info
end
},
{
name_id = "ui_example_basic_grid",
information_text_id = "ui_example_basic_grid_description",
template = "grid",
root = "grid/root",
code_url = "example/examples/basic/grid/grid.lua",
component_class = require("example.examples.basic.grid.grid"),
properties_control = function(instance, properties_panel)
---@cast instance grid
local slider = properties_panel:add_slider("ui_grid_in_row", 0.3, function(value)
local in_row_amount = math.ceil(value * 10)
in_row_amount = math.max(1, in_row_amount)
instance.grid:set_in_row(in_row_amount)
end)
slider:set_text_function(function(value)
return tostring(math.ceil(value * 10))
end)
properties_panel:add_button("ui_add_element", function()
if #instance.created_nodes >= 36 then
return
end
instance:add_element()
end)
properties_panel:add_button("ui_remove_element", function()
instance:remove_element()
end)
properties_panel:add_button("ui_clear_elements", function()
instance:clear()
end)
end,
},
{
name_id = "ui_example_basic_scroll_bind_grid",
information_text_id = "ui_example_basic_scroll_bind_grid_description",
template = "scroll_bind_grid",
root = "scroll_bind_grid/root",
code_url = "example/examples/basic/scroll_bind_grid/scroll_bind_grid.lua",
component_class = require("example.examples.basic.scroll_bind_grid.scroll_bind_grid"),
properties_control = function(instance, properties_panel)
---@cast instance scroll_bind_grid
local view_node = instance.scroll.view_node
local is_stencil = gui.get_clipping_mode(view_node) == gui.CLIPPING_MODE_STENCIL
properties_panel:add_checkbox("ui_clipping", is_stencil, function(value)
gui.set_clipping_mode(view_node, value and gui.CLIPPING_MODE_STENCIL or gui.CLIPPING_MODE_NONE)
end)
properties_panel:add_button("ui_add_element", function()
if #instance.created_nodes >= 100 then
return
end
instance:add_element()
end)
properties_panel:add_button("ui_remove_element", function()
instance:remove_element()
end)
properties_panel:add_button("ui_clear_elements", function()
instance:clear()
end)
end,
get_debug_info = function(instance)
---@cast instance scroll_bind_grid
local info = ""
local s = instance.scroll
local view_node_size = gui.get(s.view_node, "size.y")
local scroll_position = -s.position
local scroll_bottom_position = vmath.vector3(scroll_position.x, scroll_position.y - view_node_size, scroll_position.z)
info = info .. "View Size Y: " .. gui.get(s.view_node, "size.y") .. "\n"
info = info .. "Content Size Y: " .. gui.get(s.content_node, "size.y") .. "\n"
info = info .. "Content position Y: " .. math.ceil(s.position.y) .. "\n"
info = info .. "Content Range Y: " .. s.available_pos.y .. " - " .. s.available_pos.w .. "\n"
info = info .. "Grid Items: " .. #instance.grid.nodes .. "\n"
info = info .. "Grid Item Size: " .. instance.grid.node_size.x .. " x " .. instance.grid.node_size.y .. "\n"
info = info .. "Top Scroll Pos Grid Index: " .. instance.grid:get_index(scroll_position) .. "\n"
info = info .. "Bottm Scroll Pos Grid Index: " .. instance.grid:get_index(scroll_bottom_position) .. "\n"
return info
end
},
{
name_id = "ui_example_basic_scroll_bind_grid_horizontal",
information_text_id = "ui_example_basic_scroll_bind_grid_horizontal_description",
template = "scroll_bind_grid_horizontal",
root = "scroll_bind_grid_horizontal/root",
code_url = "example/examples/basic/scroll_bind_grid/scroll_bind_grid_horizontal.lua",
component_class = require("example.examples.basic.scroll_bind_grid.scroll_bind_grid_horizontal"),
properties_control = function(instance, properties_panel)
---@cast instance scroll_bind_grid_horizontal
local view_node = instance.scroll.view_node
local is_stencil = gui.get_clipping_mode(view_node) == gui.CLIPPING_MODE_STENCIL
properties_panel:add_checkbox("ui_clipping", is_stencil, function(value)
gui.set_clipping_mode(view_node, value and gui.CLIPPING_MODE_STENCIL or gui.CLIPPING_MODE_NONE)
end)
properties_panel:add_button("ui_add_element", function()
if #instance.created_nodes >= 100 then
return
end
instance:add_element()
end)
properties_panel:add_button("ui_remove_element", function()
instance:remove_element()
end)
properties_panel:add_button("ui_clear_elements", function()
instance:clear()
end)
end,
get_debug_info = function(instance)
---@cast instance scroll_bind_grid_horizontal
local info = ""
local s = instance.scroll
local view_node_size = gui.get(s.view_node, "size.x")
local scroll_position = -s.position
local scroll_bottom_position = vmath.vector3(scroll_position.x + view_node_size, scroll_position.y, scroll_position.z)
info = info .. "View Size X: " .. gui.get(s.view_node, "size.x") .. "\n"
info = info .. "Content Size X: " .. gui.get(s.content_node, "size.x") .. "\n"
info = info .. "Content position X: " .. math.ceil(s.position.x) .. "\n"
info = info .. "Content Range X: " .. s.available_pos.x .. " - " .. s.available_pos.z .. "\n"
info = info .. "Grid Items: " .. #instance.grid.nodes .. "\n"
info = info .. "Grid Item Size: " .. instance.grid.node_size.x .. " x " .. instance.grid.node_size.y .. "\n"
info = info .. "Left Scroll Pos Grid Index: " .. instance.grid:get_index(scroll_position) .. "\n"
info = info .. "Right Scroll Pos Grid Index: " .. instance.grid:get_index(scroll_bottom_position) .. "\n"
return info
end
},
{
name_id = "ui_example_basic_scroll_bind_grid_points",
information_text_id = "ui_example_basic_scroll_bind_grid_points_description",
template = "scroll_bind_grid_points",
root = "scroll_bind_grid_points/root",
code_url = "example/examples/basic/scroll_bind_grid/scroll_bind_grid_points.lua",
component_class = require("example.examples.basic.scroll_bind_grid.scroll_bind_grid_points"),
properties_control = function(instance, properties_panel)
---@cast instance scroll_bind_grid_points
local view_node = instance.scroll.view_node
local is_stencil = gui.get_clipping_mode(view_node) == gui.CLIPPING_MODE_STENCIL
properties_panel:add_checkbox("ui_clipping", is_stencil, function(value)
gui.set_clipping_mode(view_node, value and gui.CLIPPING_MODE_STENCIL or gui.CLIPPING_MODE_NONE)
end)
properties_panel:add_button("ui_add_element", function()
if #instance.created_nodes >= 100 then
return
end
instance:add_element()
end)
properties_panel:add_button("ui_remove_element", function()
instance:remove_element()
end)
properties_panel:add_button("ui_clear_elements", function()
instance:clear()
end)
end,
get_debug_info = function(instance)
---@cast instance scroll_bind_grid_points
local info = ""
local s = instance.scroll
local view_node_size = gui.get(s.view_node, "size.y")
local scroll_position = -s.position
local scroll_bottom_position = vmath.vector3(scroll_position.x, scroll_position.y - view_node_size, scroll_position.z)
info = info .. "View Size Y: " .. gui.get(s.view_node, "size.y") .. "\n"
info = info .. "Content Size Y: " .. gui.get(s.content_node, "size.y") .. "\n"
info = info .. "Content position Y: " .. math.ceil(s.position.y) .. "\n"
info = info .. "Content Range Y: " .. s.available_pos.y .. " - " .. s.available_pos.w .. "\n"
info = info .. "Grid Items: " .. #instance.grid.nodes .. "\n"
info = info .. "Grid Item Size: " .. instance.grid.node_size.x .. " x " .. instance.grid.node_size.y .. "\n"
info = info .. "Top Scroll Pos Grid Index: " .. instance.grid:get_index(scroll_position) .. "\n"
info = info .. "Bottm Scroll Pos Grid Index: " .. instance.grid:get_index(scroll_bottom_position) .. "\n"
return info
end
},
{
name_id = "ui_example_basic_input",
information_text_id = "ui_example_basic_input_description",
template = "basic_input",
root = "basic_input/root",
code_url = "example/examples/basic/input/basic_input.lua",
component_class = require("example.examples.basic.input.basic_input"),
on_create = function(instance, output_log)
---@cast instance basic_input
instance.input.on_input_unselect:subscribe(function(_, text)
output_log:add_log_text("Input: " .. text)
end)
instance.input_2.on_input_unselect:subscribe(function(_, text)
output_log:add_log_text("Input 2: " .. text)
end)
end,
},
{
name_id = "ui_example_input_password",
information_text_id = "ui_example_input_password_description",
template = "input_password",
root = "input_password/root",
code_url = "example/examples/basic/input/input_password.lua",
component_class = require("example.examples.basic.input.input_password"),
on_create = function(instance, output_log)
---@cast instance input_password
instance.input.on_input_unselect:subscribe(function(_, text)
output_log:add_log_text("Input: " .. text)
end)
end,
},
{
name_id = "ui_example_basic_rich_input",
information_text_id = "ui_example_basic_rich_input_description",
template = "basic_rich_input",
root = "basic_rich_input/root",
code_url = "example/examples/basic/input/rich_input.lua",
component_class = require("example.examples.basic.input.rich_input"),
on_create = function(instance, output_log)
---@cast instance rich_input
instance.rich_input.input.on_input_unselect:subscribe(function(_, text)
output_log:add_log_text("Input: " .. text)
end)
instance.rich_input_2.input.on_input_unselect:subscribe(function(_, text)
output_log:add_log_text("Input 2: " .. text)
end)
end,
},
{
name_id = "ui_example_basic_rich_text",
information_text_id = "ui_example_basic_rich_text_description",
template = "basic_rich_text",
root = "basic_rich_text/root",
code_url = "example/examples/basic/rich_text/basic_rich_text.lua",
component_class = require("example.examples.basic.rich_text.basic_rich_text"),
},
{
name_id = "ui_example_rich_text_tags",
information_text_id = "ui_example_rich_text_tags_description",
template = "rich_text_tags",
root = "rich_text_tags/root",
code_url = "example/examples/basic/rich_text/rich_text_tags.lua",
component_class = require("example.examples.basic.rich_text.rich_text_tags"),
properties_control = function(instance, properties_panel)
local pivot_index = 1
local pivot_list = {
gui.PIVOT_CENTER,
gui.PIVOT_W,
gui.PIVOT_SW,
gui.PIVOT_S,
gui.PIVOT_SE,
gui.PIVOT_E,
gui.PIVOT_NE,
gui.PIVOT_N,
gui.PIVOT_NW,
}
---@cast instance rich_text_tags
properties_panel:add_button("ui_pivot_next", function()
pivot_index = pivot_index + 1
if pivot_index > #pivot_list then
pivot_index = 1
end
instance:set_pivot(pivot_list[pivot_index])
end)
end
},
--{
-- name_id = "ui_example_rich_text_tags_custom",
-- information_text_id = "ui_example_rich_text_tags_custom_description",
-- template = "rich_text_tags_custom",
-- root = "rich_text_tags_custom/root",
-- code_url = "example/examples/basic/rich_text/rich_text_tags_custom.lua",
-- component_class = require("example.examples.basic.rich_text.rich_text_tags_custom"),
-- properties_control = function(instance, properties_panel)
-- local pivot_index = 1
-- local pivot_list = {
-- gui.PIVOT_CENTER,
-- gui.PIVOT_W,
-- gui.PIVOT_SW,
-- gui.PIVOT_S,
-- gui.PIVOT_SE,
-- gui.PIVOT_E,
-- gui.PIVOT_NE,
-- gui.PIVOT_N,
-- gui.PIVOT_NW,
-- }
-- ---@cast instance rich_text_tags_custom
-- properties_panel:add_button("ui_pivot_next", function()
-- pivot_index = pivot_index + 1
-- if pivot_index > #pivot_list then
-- pivot_index = 1
-- end
-- instance:set_pivot(pivot_list[pivot_index])
-- end)
-- end,
-- on_create = function(instance, output_log)
-- ---@cast instance rich_text_tags_custom
-- instance.on_link_click:subscribe(function(text)
-- output_log:add_log_text("Custom Link: " .. text)
-- end)
-- end
--},
{
name_id = "ui_example_basic_swipe",
information_text_id = "ui_example_basic_swipe_description",
template = "basic_swipe",
root = "basic_swipe/root",
code_url = "example/examples/basic/swipe/basic_swipe.lua",
component_class = require("example.examples.basic.swipe.basic_swipe"),
on_create = function(instance, output_log)
---@cast instance basic_swipe
instance.swipe.on_swipe:subscribe(function(_, side, dist, delta_time)
output_log:add_log_text("Swipe Side: " .. side)
end)
end,
},
{
name_id = "ui_example_basic_checkbox",
information_text_id = "ui_example_basic_checkbox_description",
template = "basic_checkbox",
root = "basic_checkbox/root",
code_url = "example/examples/basic/checkbox/basic_checkbox.lua",
component_class = require("example.examples.basic.checkbox.basic_checkbox"),
on_create = function(instance, output_log)
---@cast instance basic_checkbox
instance.button.on_click:subscribe(function()
output_log:add_log_text("Checkbox Clicked: " .. tostring(instance.is_enabled))
end)
end,
},
}
end
return M

View File

@@ -0,0 +1,320 @@
script: ""
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1000.0
y: 1000.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 300.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 600.0
y: 600.0
z: 0.0
w: 1.0
}
color {
x: 0.173
y: 0.184
z: 0.204
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_32"
id: "grid"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_N
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 100.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "prefab"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "grid"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 90.0
y: 90.0
z: 0.0
w: 1.0
}
color {
x: 0.631
y: 0.843
z: 0.961
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_32"
id: "panel"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "prefab"
layer: ""
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.5
y: 1.5
z: 1.0
w: 1.0
}
size {
x: 50.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "1"
font: "text_bold"
id: "text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "prefab"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,66 @@
local component = require("druid.component")
---@class grid: druid.base_component
---@field grid druid.static_grid
---@field text druid.text
---@field druid druid_instance
local M = component.create("grid")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.created_nodes = {}
self.prefab = self:get_node("prefab")
gui.set_enabled(self.prefab, false)
self.grid = self.druid:new_static_grid("grid", "prefab", 3)
for index = 1, 9 do
self:add_element()
end
end
function M:on_remove()
self:clear()
end
function M:add_element()
local prefab_nodes = gui.clone_tree(self.prefab)
local root = prefab_nodes[self:get_template() .. "/prefab"]
local text = prefab_nodes[self:get_template() .. "/text"]
table.insert(self.created_nodes, root)
gui.set_text(text, #self.created_nodes)
gui.set_enabled(root, true)
self.grid:add(root)
end
function M:remove_element()
local last_node = table.remove(self.created_nodes)
if last_node == nil then
return
end
gui.delete_node(last_node)
local grid_index = self.grid:get_index_by_node(last_node)
self.grid:remove(grid_index)
end
function M:clear()
for _, node in ipairs(self.created_nodes) do
gui.delete_node(node)
end
self.created_nodes = {}
self.grid:clear()
end
return M

View File

@@ -0,0 +1,36 @@
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
nodes {
size {
x: 200.0
y: 100.0
}
type: TYPE_BOX
id: "root"
inherit_alpha: true
size_mode: SIZE_MODE_AUTO
visible: false
}
nodes {
size {
x: 700.0
y: 100.0
}
color {
x: 0.522
y: 0.522
z: 0.522
}
type: TYPE_TEXT
text: "Press \"SHIFT\" + \"X\" to trigger hotkey"
font: "text_bold"
id: "text"
parent: "root"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT

View File

@@ -0,0 +1,29 @@
local hotkey = require("druid.extended.hotkey")
local component = require("druid.component")
---@class basic_hotkey: druid.base_component
---@field druid druid_instance
---@field root node
---@field text druid.text
local M = component.create("basic_hotkey")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.root = self:get_node("root")
self.hotkey = self.druid:new(hotkey, { "key_lshift", "key_x" }, self.on_hotkey)
end
function M:on_hotkey()
gui.animate(self.root, gui.PROP_SCALE, vmath.vector3(1.2), gui.EASING_OUTELASTIC, 0.5, 0, function()
gui.animate(self.root, gui.PROP_SCALE, vmath.vector3(1), gui.EASING_OUTELASTIC, 0.5)
end)
end
return M

View File

@@ -0,0 +1,410 @@
script: ""
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1000.0
y: 1000.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 100.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "button_mouse_hover"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/templates/button_text_green.gui"
template_node_child: false
custom_type: 0
enabled: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 280.0
y: 90.0
z: 0.0
w: 1.0
}
color {
x: 0.557
y: 0.835
z: 0.62
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_32"
id: "button_mouse_hover/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "button_mouse_hover"
layer: "druid"
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 245.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Mouse Hover"
font: "text_bold"
id: "button_mouse_hover/text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "button_mouse_hover/root"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
overridden_fields: 8
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: -100.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "button_mobile_hover"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/templates/button_text_green.gui"
template_node_child: false
custom_type: 0
enabled: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 280.0
y: 90.0
z: 0.0
w: 1.0
}
color {
x: 0.557
y: 0.835
z: 0.62
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_32"
id: "button_mobile_hover/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "button_mobile_hover"
layer: "druid"
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 245.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Mobile Hover"
font: "text_bold"
id: "button_mobile_hover/text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "button_mobile_hover/root"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
overridden_fields: 8
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,34 @@
local component = require("druid.component")
---@class hover: druid.base_component
---@field druid druid_instance
---@field hover druid.hover
---@field hover_pressed druid.hover
local M = component.create("hover")
---Color: #E6DF9F
local HOVERED_COLOR = vmath.vector4(230/255, 223/255, 159/255, 1.0)
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
-- Default hover callback is `on_hover`, designed for mobile devices
-- It's only hover if touch action is above the node
self.hover_default = self.druid:new_hover("button_mobile_hover/root", self.on_hover)
-- If you wan't to use mouse hover, you can use `on_mouse_hover` callback
-- It's checks the `action_id` == nil (mouse events)
self.hover = self.druid:new_hover("button_mouse_hover/root", nil, self.on_hover)
self.default_color = gui.get_color(self.hover.node)
end
function M:on_hover(is_hover, hover_instance)
gui.animate(hover_instance.node, "color", is_hover and HOVERED_COLOR or self.default_color, gui.EASING_LINEAR, 0.2)
end
return M

View File

@@ -0,0 +1,406 @@
script: ""
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1000.0
y: 1000.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "input"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/templates/input.gui"
template_node_child: false
custom_type: 0
enabled: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 500.0
y: 80.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/rect_round2_width1"
id: "input/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "input"
layer: ""
inherit_alpha: true
slice9 {
x: 4.0
y: 4.0
z: 4.0
w: 4.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -240.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 480.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Tap me to input"
font: "text_bold"
id: "input/text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "input/root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: -150.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "input_2"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/templates/input.gui"
template_node_child: false
custom_type: 0
enabled: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 500.0
y: 80.0
z: 0.0
w: 1.0
}
color {
x: 0.463
y: 0.475
z: 0.49
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/rect_round2_width1"
id: "input_2/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "input_2"
layer: ""
inherit_alpha: true
slice9 {
x: 4.0
y: 4.0
z: 4.0
w: 4.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 480.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Tap me to input"
font: "text_bold"
id: "input_2/text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "input_2/root"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
overridden_fields: 1
overridden_fields: 14
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,26 @@
local component = require("druid.component")
local input = require("druid.extended.input")
---@class basic_input: druid.base_component
---@field druid druid_instance
---@field input druid.input
local M = component.create("basic_input")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.input = self.druid:new(input, "input/root", "input/text")
self.input_2 = self.druid:new(input, "input_2/root", "input_2/text") --[[@as druid.input]]
-- you can set custom style for input and their components
-- Check in the example, how long tap on bottom input will erase text
self.input_2.style.IS_LONGTAP_ERASE = true
self.input_2.button.style.AUTOHOLD_TRIGGER = 1.5
end
return M

View File

@@ -0,0 +1,33 @@
nodes {
size {
x: 1000.0
y: 1000.0
}
type: TYPE_BOX
id: "root"
inherit_alpha: true
visible: false
}
nodes {
type: TYPE_TEMPLATE
id: "input"
parent: "root"
inherit_alpha: true
template: "/example/templates/input.gui"
}
nodes {
type: TYPE_BOX
id: "input/root"
parent: "input"
template_node_child: true
}
nodes {
type: TYPE_TEXT
id: "input/text"
parent: "input/root"
overridden_fields: 1
overridden_fields: 14
template_node_child: true
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT

View File

@@ -0,0 +1,25 @@
local component = require("druid.component")
local input = require("druid.extended.input")
---@class input_password: druid.component
---@field druid druid_instance
---@field root node
local M = component.create("input_password")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.root = self:get_node("root")
self.input = self.druid:new(input, "input/root", "input/text", gui.KEYBOARD_TYPE_PASSWORD)
self.input:set_text("")
self.input.on_input_unselect:subscribe(function(_, text)
print(text)
end)
end
return M

View File

@@ -0,0 +1,918 @@
script: ""
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1000.0
y: 1000.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "rich_input"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/templates/rich_input.gui"
template_node_child: false
custom_type: 0
enabled: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 500.0
y: 80.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "rich_input/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "rich_input"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 500.0
y: 80.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/rect_round2_width1"
id: "rich_input/button"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "rich_input/root"
layer: ""
inherit_alpha: true
slice9 {
x: 4.0
y: 4.0
z: 4.0
w: 4.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -240.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 480.0
y: 60.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Placeholder"
font: "text_bold"
id: "rich_input/placeholder_text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
outline {
x: 0.4
y: 0.4
z: 0.4
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "rich_input/button"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
overridden_fields: 1
overridden_fields: 14
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -240.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 480.0
y: 60.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "User input"
font: "text_bold"
id: "rich_input/input_text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "rich_input/button"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
overridden_fields: 1
overridden_fields: 14
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 16.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.631
y: 0.843
z: 0.961
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_16"
id: "rich_input/cursor_node"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "rich_input/button"
layer: ""
inherit_alpha: true
slice9 {
x: 8.0
y: 8.0
z: 8.0
w: 8.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 0.5
overridden_fields: 1
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 4.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.2
y: 1.2
z: 1.0
w: 1.0
}
size {
x: 20.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "|"
font: "text_bold"
id: "rich_input/cursor_text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "rich_input/cursor_node"
layer: ""
inherit_alpha: false
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: -150.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "rich_input_2"
parent: "root"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/templates/rich_input.gui"
template_node_child: false
custom_type: 0
enabled: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 500.0
y: 80.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "rich_input_2/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "rich_input_2"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 500.0
y: 80.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/rect_round2_width1"
id: "rich_input_2/button"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "rich_input_2/root"
layer: ""
inherit_alpha: true
slice9 {
x: 4.0
y: 4.0
z: 4.0
w: 4.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 480.0
y: 60.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Placeholder"
font: "text_bold"
id: "rich_input_2/placeholder_text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.4
y: 0.4
z: 0.4
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "rich_input_2/button"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 480.0
y: 60.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "User input"
font: "text_bold"
id: "rich_input_2/input_text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "rich_input_2/button"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 16.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.631
y: 0.843
z: 0.961
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_16"
id: "rich_input_2/cursor_node"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "rich_input_2/button"
layer: ""
inherit_alpha: true
slice9 {
x: 8.0
y: 8.0
z: 8.0
w: 8.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 0.5
overridden_fields: 1
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 4.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.2
y: 1.2
z: 1.0
w: 1.0
}
size {
x: 20.0
y: 40.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "|"
font: "text_bold"
id: "rich_input_2/cursor_text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "rich_input_2/cursor_node"
layer: ""
inherit_alpha: false
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,22 @@
local component = require("druid.component")
local rich_input = require("druid.custom.rich_input.rich_input")
---@class rich_input: druid.base_component
---@field druid druid_instance
---@field rich_input druid.rich_input
local M = component.create("rich_input")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.rich_input = self.druid:new(rich_input, "rich_input") --[[@as druid.rich_input]]
self.rich_input:set_placeholder("Enter text")
self.rich_input_2 = self.druid:new(rich_input, "rich_input_2") --[[@as druid.rich_input]]
self.rich_input_2:set_placeholder("Enter text")
end
return M

View File

@@ -0,0 +1,89 @@
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
nodes {
size {
x: 1000.0
y: 1000.0
}
type: TYPE_BOX
id: "root"
inherit_alpha: true
visible: false
}
nodes {
position {
x: -150.0
}
size {
x: 300.0
y: 32.0
}
color {
x: 0.463
y: 0.475
z: 0.49
}
type: TYPE_BOX
texture: "druid/pixel"
id: "progress_bar_back"
pivot: PIVOT_W
parent: "root"
inherit_alpha: true
}
nodes {
size {
x: 300.0
y: 32.0
}
color {
x: 0.631
y: 0.843
z: 0.961
}
type: TYPE_BOX
texture: "druid/pixel"
id: "progress_bar_fill"
pivot: PIVOT_W
parent: "progress_bar_back"
inherit_alpha: true
}
nodes {
position {
y: 50.0
}
size {
x: 150.0
y: 50.0
}
color {
x: 0.722
y: 0.741
z: 0.761
}
type: TYPE_TEXT
text: "0 %"
font: "text_bold"
id: "progress_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

View File

@@ -0,0 +1,28 @@
local component = require("druid.component")
local progress = require("druid.extended.progress")
---@class basic_progress_bar: druid.base_component
---@field druid druid_instance
---@field progress druid.progress
local M = component.create("basic_progress_bar")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.progress = self.druid:new(progress, "progress_bar_fill", "x")
self.text_value = self:get_node("progress_value")
self:set_value(self.progress:get())
end
function M:set_value(value)
gui.set_text(self.text_value, math.ceil(value * 100) .. "%")
self.progress:set_to(value)
end
return M

View File

@@ -0,0 +1,101 @@
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
nodes {
size {
x: 1000.0
y: 1000.0
}
type: TYPE_BOX
id: "root"
inherit_alpha: true
visible: false
}
nodes {
position {
x: -150.0
}
size {
x: 300.0
y: 32.0
}
color {
x: 0.463
y: 0.475
z: 0.49
}
type: TYPE_BOX
texture: "druid/ui_circle_16"
id: "progress_bar_back"
pivot: PIVOT_W
parent: "root"
inherit_alpha: true
slice9 {
x: 8.0
y: 8.0
z: 8.0
w: 8.0
}
}
nodes {
size {
x: 300.0
y: 32.0
}
color {
x: 0.631
y: 0.843
z: 0.961
}
type: TYPE_BOX
texture: "druid/ui_circle_16"
id: "progress_bar_fill"
pivot: PIVOT_W
parent: "progress_bar_back"
inherit_alpha: true
slice9 {
x: 8.0
y: 8.0
z: 8.0
w: 8.0
}
}
nodes {
position {
y: 50.0
}
size {
x: 150.0
y: 50.0
}
color {
x: 0.722
y: 0.741
z: 0.761
}
type: TYPE_TEXT
text: "0 %"
font: "text_bold"
id: "progress_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

View File

@@ -0,0 +1,28 @@
local component = require("druid.component")
local progress = require("druid.extended.progress")
---@class basic_progress_bar_slice9: druid.base_component
---@field druid druid_instance
---@field progress druid.progress
local M = component.create("basic_progress_bar_slice9")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.progress = self.druid:new(progress, "progress_bar_fill", "x")
self.text_value = self:get_node("progress_value")
self:set_value(self.progress:get())
end
function M:set_value(value)
gui.set_text(self.text_value, math.ceil(value * 100) .. "%")
self.progress:set_to(value)
end
return M

View File

@@ -0,0 +1,46 @@
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
fonts {
name: "text_regular"
font: "/example/assets/fonts/text_regular.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
nodes {
size {
x: 1000.0
y: 1000.0
}
type: TYPE_BOX
id: "root"
inherit_alpha: true
visible: false
}
nodes {
position {
x: -200.0
}
size {
x: 400.0
y: 100.0
}
color {
x: 0.941
y: 0.984
}
type: TYPE_TEXT
text: "Hello I\'m a Rich Text!"
font: "text_regular"
id: "text"
pivot: PIVOT_W
parent: "root"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT

View File

@@ -0,0 +1,18 @@
local component = require("druid.component")
local rich_text = require("druid.custom.rich_text.rich_text")
---@class basic_rich_text: druid.base_component
---@field druid druid_instance
---@field rich_text druid.rich_text
local M = component.create("basic_rich_text")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.druid:new(rich_text, "text", "Hello, I'm a <font=text_bold><color=E48155>Rich Text</font></color>!")
end
return M

View File

@@ -0,0 +1,167 @@
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
fonts {
name: "text_regular"
font: "/example/assets/fonts/text_regular.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
textures {
name: "druid_logo"
texture: "/example/assets/druid_logo.atlas"
}
nodes {
size {
x: 1000.0
y: 1000.0
}
type: TYPE_BOX
id: "root"
inherit_alpha: true
visible: false
}
nodes {
size {
x: 400.0
y: 1000.0
}
color {
x: 0.173
y: 0.184
z: 0.204
}
type: TYPE_BOX
texture: "druid/ui_circle_64"
id: "background"
parent: "root"
inherit_alpha: true
slice9 {
x: 32.0
y: 32.0
z: 32.0
w: 32.0
}
}
nodes {
position {
x: -200.0
y: 400.0
}
size {
x: 400.0
y: 100.0
}
color {
x: 0.941
y: 0.984
}
type: TYPE_TEXT
text: "Rich text"
font: "text_regular"
id: "rich_text_color"
pivot: PIVOT_W
parent: "root"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
nodes {
position {
x: -200.0
y: 200.0
}
size {
x: 400.0
y: 100.0
}
color {
x: 0.941
y: 0.984
}
type: TYPE_TEXT
text: "Rich text"
font: "text_regular"
id: "rich_text_breaks"
pivot: PIVOT_W
line_break: true
parent: "root"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
nodes {
position {
x: 200.0
}
size {
x: 400.0
y: 100.0
}
color {
x: 0.941
y: 0.984
}
type: TYPE_TEXT
text: "Rich text"
font: "text_regular"
id: "rich_text_size"
pivot: PIVOT_SE
line_break: true
parent: "root"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
nodes {
position {
x: -200.0
y: -200.0
}
size {
x: 400.0
y: 100.0
}
color {
x: 0.941
y: 0.984
}
type: TYPE_TEXT
text: "Rich text"
font: "text_regular"
id: "rich_text_font"
pivot: PIVOT_W
line_break: true
parent: "root"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
nodes {
position {
x: -200.0
y: -400.0
}
size {
x: 400.0
y: 100.0
}
color {
x: 0.941
y: 0.984
}
type: TYPE_TEXT
text: "Rich text"
font: "text_regular"
id: "rich_text_image"
pivot: PIVOT_W
parent: "root"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT

View File

@@ -0,0 +1,76 @@
local component = require("druid.component")
local rich_text = require("druid.custom.rich_text.rich_text")
local helper = require("druid.helper")
---@class rich_text_tags: druid.base_component
---@field druid druid_instance
---@field rich_text druid.rich_text
local M = component.create("rich_text_tags")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.rich_text_color = self.druid:new(rich_text, "rich_text_color") --[[@as druid.rich_text]]
self.rich_text_color:set_text("Hello, I'm a <color=E48155>Rich Text</color> and it's <color=8ED59E>nested <color=A1D7F5>color</color> tag</color>")
self.rich_text_font = self.druid:new(rich_text, "rich_text_font") --[[@as druid.rich_text]]
self.rich_text_font:set_text("Hello, I'm a <font=text_bold>Rich Text</font> and this is <font=text_bold><color=8ED59E>bold text</color></font>")
self.rich_text_size = self.druid:new(rich_text, "rich_text_size") --[[@as druid.rich_text]]
self.rich_text_size:set_text("Hello, I'm have <size=1.15><font=text_bold>East Pivot</font></size> and <size=0.85><font=text_bold>different text scale</font></size>")
self.rich_text_breaks = self.druid:new(rich_text, "rich_text_breaks") --[[@as druid.rich_text]]
self.rich_text_breaks:set_text("Hello, I'm Rich Text<br/>With \"<color=E6DF9F>Line Breaks</color>\"\nEnabled in GUI")
self.rich_text_image = self.druid:new(rich_text, "rich_text_image") --[[@as druid.rich_text]]
self.rich_text_image:set_text("Hello, I'm<img=druid:icon_cross,32/>Rich Text <img=druid_logo:icon_druid,48/> <color=8ED59E><img=druid_logo:icon_druid,48/></color> <color=F49B9B><img=druid_logo:icon_druid,48/></color>")
self.position = {
[self.rich_text_color] = gui.get_position(self.rich_text_color.root),
[self.rich_text_font] = gui.get_position(self.rich_text_font.root),
[self.rich_text_size] = gui.get_position(self.rich_text_size.root),
[self.rich_text_breaks] = gui.get_position(self.rich_text_breaks.root),
[self.rich_text_image] = gui.get_position(self.rich_text_image.root),
}
-- Adjust positions with pivots
for rich_text, pos in pairs(self.position) do
local size_x = gui.get(rich_text.root, "size.x")
local size_y = gui.get(rich_text.root, "size.y")
local parent_pivot = gui.get_pivot(rich_text.root)
local pivot_offset = helper.get_pivot_offset(parent_pivot)
local offset_x = size_x * pivot_offset.x
local offset_y = size_y * pivot_offset.y
pos.x = pos.x - offset_x
pos.y = pos.y - offset_y
end
end
function M:set_pivot(pivot)
local rich_texts = {
self.rich_text_color,
self.rich_text_font,
self.rich_text_size,
self.rich_text_breaks,
self.rich_text_image,
}
for _, rich_text in ipairs(rich_texts) do
gui.set_pivot(rich_text.root, pivot)
local pos = self.position[rich_text]
local size_x = gui.get(rich_text.root, "size.x")
local size_y = gui.get(rich_text.root, "size.y")
local parent_pivot = gui.get_pivot(rich_text.root)
local pivot_offset = helper.get_pivot_offset(parent_pivot)
local offset_x = size_x * pivot_offset.x
local offset_y = size_y * pivot_offset.y
gui.set_position(rich_text.root, vmath.vector3(pos.x + offset_x, pos.y + offset_y, pos.z))
rich_text:set_text(rich_text:get_text())
end
end
return M

View File

@@ -0,0 +1,92 @@
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
fonts {
name: "text_regular"
font: "/example/assets/fonts/text_regular.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
nodes {
size {
x: 1000.0
y: 1000.0
}
type: TYPE_BOX
id: "root"
inherit_alpha: true
visible: false
}
nodes {
position {
y: 200.0
}
size {
x: 400.0
y: 100.0
}
color {
x: 0.941
y: 0.984
}
type: TYPE_TEXT
text: "Rich text"
font: "text_regular"
id: "rich_text_link"
parent: "root"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
nodes {
position {
x: -200.0
}
size {
x: 400.0
y: 100.0
}
color {
x: 0.941
y: 0.984
}
type: TYPE_TEXT
text: "Rich text"
font: "text_regular"
id: "rich_text_characters"
pivot: PIVOT_W
line_break: true
parent: "root"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
nodes {
position {
x: -200.0
y: -200.0
}
size {
x: 400.0
y: 100.0
}
color {
x: 0.941
y: 0.984
}
type: TYPE_TEXT
text: "Rich text"
font: "text_regular"
id: "rich_text_custom"
pivot: PIVOT_W
line_break: true
parent: "root"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT

View File

@@ -0,0 +1,67 @@
local component = require("druid.component")
local rich_text = require("druid.custom.rich_text.rich_text")
local helper = require("druid.helper")
local event = require("druid.event")
---@class rich_text_tags_custom: druid.base_component
---@field druid druid_instance
---@field rich_text druid.rich_text
local M = component.create("rich_text_tags_custom")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
do -- Init rich text with links example
self.rich_text_link = self.druid:new(rich_text, "rich_text_link") --[[@as druid.rich_text]]
self.rich_text_link:set_text("Hello, I'm a <custom_link><color=A1D7F5>Custom Link</color></custom_link>")
local tagged = self.rich_text_link:tagged("custom_link")
for index = 1, #tagged do
local word = tagged[index]
self.druid:new_button(word.node, function()
self.on_link_click:trigger(word.text)
end)
end
end
self.rich_text_characters = self.druid:new(rich_text, "rich_text_characters") --[[@as druid.rich_text]]
self.rich_text_characters:set_text("Hello, I'm a have a splitted characters")
self.rich_text_custom = self.druid:new(rich_text, "rich_text_custom") --[[@as druid.rich_text]]
self.rich_text_custom:set_text("Hello, I'm have <size=1.25><font=text_bold>South Text Pivot</font></size> to adjust <size=0.75><font=text_bold>different text scale</font></size>")
self.position = {
[self.rich_text_link] = gui.get_position(self.rich_text_link.root),
[self.rich_text_characters] = gui.get_position(self.rich_text_characters.root),
[self.rich_text_custom] = gui.get_position(self.rich_text_custom.root),
}
self.on_link_click = event.create()
end
function M:set_pivot(pivot)
local pivot_offset = helper.get_pivot_offset(pivot)
local rich_texts = {
self.rich_text_link,
self.rich_text_characters,
self.rich_text_custom,
}
for _, rich_text in ipairs(rich_texts) do
gui.set_pivot(rich_text.root, pivot)
local pos = self.position[rich_text]
local size_x = gui.get(rich_text.root, "size.x")
local size_y = gui.get(rich_text.root, "size.y")
local offset_x = size_x * pivot_offset.x
local offset_y = size_y * pivot_offset.y
gui.set_position(rich_text.root, vmath.vector3(pos.x + offset_x, pos.y + offset_y, pos.z))
rich_text:set_text(rich_text:get_text())
end
end
return M

View File

@@ -0,0 +1,876 @@
script: ""
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 1000.0
z: 0.0
w: 1.0
}
color {
x: 0.173
y: 0.184
z: 0.204
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_32"
id: "scroll_view"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_STENCIL
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 500.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 1700.0
z: 0.0
w: 1.0
}
color {
x: 0.173
y: 0.184
z: 0.204
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "scroll_content"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_N
adjust_mode: ADJUST_MODE_FIT
parent: "scroll_view"
layer: ""
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: -946.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "button_tutorial"
parent: "scroll_content"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/templates/button_text_green.gui"
template_node_child: false
custom_type: 0
enabled: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 280.0
y: 90.0
z: 0.0
w: 1.0
}
color {
x: 0.557
y: 0.835
z: 0.62
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_32"
id: "button_tutorial/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "button_tutorial"
layer: "druid"
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 245.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "I do nothing!"
font: "text_bold"
id: "button_tutorial/text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "button_tutorial/root"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
overridden_fields: 8
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -185.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 500.0
y: 900.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "To setup scroll in your scene\n"
"\n"
"- Place \"View\" box node\n"
"\n"
"- Put \"Content\" node inside \"Scroll View\"\n"
"\n"
"- Init scroll with `druid:new_scroll(\"view\", \"content\")"
font: "text_bold"
id: "ui_scroll_text_1"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: true
parent: "scroll_content"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -185.0
y: -482.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 500.0
y: 400.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Now your content node can be scrollable in View node borders. In this example the content node contains this tutorial text"
font: "text_bold"
id: "ui_scroll_text_2"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: true
parent: "scroll_content"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -185.0
y: -713.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 500.0
y: 400.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "All other components are placed as usual.\n"
"\n"
"For example, button:"
font: "text_bold"
id: "ui_scroll_text_3"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: true
parent: "scroll_content"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -185.0
y: -1042.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 500.0
y: 400.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "You probably wish to add \"stencil\" to your view node to clip all content what outside scroll"
font: "text_bold"
id: "ui_scroll_text_4"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: true
parent: "scroll_content"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: -185.0
y: -1257.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 0.75
y: 0.75
z: 1.0
w: 1.0
}
size {
x: 500.0
y: 400.0
z: 0.0
w: 1.0
}
color {
x: 0.722
y: 0.741
z: 0.761
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Druid automatically checks the stencil nodes to add a \"click zone\" for input elements like buttons to prevent the input if they are outside of stencil nodes"
font: "text_bold"
id: "ui_scroll_text_5"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_NW
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: true
parent: "scroll_content"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: -1605.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_TEMPLATE
id: "button_stencil"
parent: "scroll_content"
layer: ""
inherit_alpha: true
alpha: 1.0
template: "/example/templates/button_text_green.gui"
template_node_child: false
custom_type: 0
enabled: true
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 280.0
y: 90.0
z: 0.0
w: 1.0
}
color {
x: 0.557
y: 0.835
z: 0.62
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_32"
id: "button_stencil/root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "button_stencil"
layer: "druid"
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: true
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 245.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Try click me outside"
font: "text_bold"
id: "button_stencil/text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: true
parent: "button_stencil/root"
layer: "text_bold"
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
overridden_fields: 8
overridden_fields: 18
template_node_child: true
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,21 @@
local component = require("druid.component")
---@class scroll: druid.base_component
---@field root node
---@field scroll druid.scroll
---@field druid druid_instance
local M = component.create("scroll")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.scroll = self.druid:new_scroll("scroll_view", "scroll_content")
self.button_tutorial = self.druid:new_button("button_tutorial/root")
self.button_stencil = self.druid:new_button("button_stencil/root")
end
return M

View File

@@ -0,0 +1,379 @@
script: ""
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1000.0
y: 1000.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 400.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 800.0
z: 0.0
w: 1.0
}
color {
x: 0.173
y: 0.184
z: 0.204
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_32"
id: "view"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_N
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_STENCIL
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 400.0
y: 800.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "content"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_N
adjust_mode: ADJUST_MODE_FIT
parent: "view"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: -400.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 300.0
y: 100.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "prefab"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "content"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 300.0
y: 90.0
z: 0.0
w: 1.0
}
color {
x: 0.631
y: 0.843
z: 0.961
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_32"
id: "panel"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "prefab"
layer: ""
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 240.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Grid Item 1"
font: "text_bold"
id: "text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: false
parent: "prefab"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,69 @@
local component = require("druid.component")
---@class scroll_bind_grid: druid.base_component
---@field scroll druid.scroll
---@field grid druid.static_grid
---@field text druid.text
---@field druid druid_instance
local M = component.create("scroll_bind_grid")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.created_nodes = {}
self.prefab = self:get_node("prefab")
gui.set_enabled(self.prefab, false)
self.scroll = self.druid:new_scroll("view", "content")
self.grid = self.druid:new_static_grid("content", "prefab", 1)
self.scroll:bind_grid(self.grid)
for index = 1, 20 do
self:add_element()
end
end
function M:on_remove()
self:clear()
end
function M:add_element()
local prefab_nodes = gui.clone_tree(self.prefab)
local root = prefab_nodes[self:get_template() .. "/prefab"]
local text = prefab_nodes[self:get_template() .. "/text"]
table.insert(self.created_nodes, root)
gui.set_text(text, "Grid Item " .. #self.created_nodes)
gui.set_enabled(root, true)
self.grid:add(root)
end
function M:remove_element()
local last_node = table.remove(self.created_nodes)
if last_node == nil then
return
end
gui.delete_node(last_node)
local grid_index = self.grid:get_index_by_node(last_node)
self.grid:remove(grid_index)
end
function M:clear()
for _, node in ipairs(self.created_nodes) do
gui.delete_node(node)
end
self.created_nodes = {}
self.grid:clear()
end
return M

View File

@@ -0,0 +1,379 @@
script: ""
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1000.0
y: 1000.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "root"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: -450.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 900.0
y: 360.0
z: 0.0
w: 1.0
}
color {
x: 0.173
y: 0.184
z: 0.204
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_32"
id: "view"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
adjust_mode: ADJUST_MODE_FIT
parent: "root"
layer: ""
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_STENCIL
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 900.0
y: 360.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/empty"
id: "content"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_W
adjust_mode: ADJUST_MODE_FIT
parent: "view"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 450.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 200.0
y: 270.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "prefab"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "content"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: false
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 190.0
y: 250.0
z: 0.0
w: 1.0
}
color {
x: 0.631
y: 0.843
z: 0.961
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "druid/ui_circle_32"
id: "panel"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
adjust_mode: ADJUST_MODE_FIT
parent: "prefab"
layer: ""
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
rotation {
x: 0.0
y: 0.0
z: 0.0
w: 1.0
}
scale {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 150.0
y: 50.0
z: 0.0
w: 1.0
}
color {
x: 0.31
y: 0.318
z: 0.322
w: 1.0
}
type: TYPE_TEXT
blend_mode: BLEND_MODE_ALPHA
text: "Grid Item 1"
font: "text_bold"
id: "text"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
outline {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
adjust_mode: ADJUST_MODE_FIT
line_break: true
parent: "prefab"
layer: ""
inherit_alpha: true
alpha: 1.0
outline_alpha: 0.0
shadow_alpha: 0.0
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

View File

@@ -0,0 +1,69 @@
local component = require("druid.component")
---@class scroll_bind_grid_horizontal: druid.base_component
---@field scroll druid.scroll
---@field grid druid.static_grid
---@field text druid.text
---@field druid druid_instance
local M = component.create("scroll_bind_grid_horizontal")
---@param template string
---@param nodes table<hash, node>
function M:init(template, nodes)
self.druid = self:get_druid(template, nodes)
self.created_nodes = {}
self.prefab = self:get_node("prefab")
gui.set_enabled(self.prefab, false)
self.scroll = self.druid:new_scroll("view", "content")
self.grid = self.druid:new_static_grid("content", "prefab", 99999)
self.scroll:bind_grid(self.grid)
for index = 1, 30 do
self:add_element()
end
end
function M:on_remove()
self:clear()
end
function M:add_element()
local prefab_nodes = gui.clone_tree(self.prefab)
local root = prefab_nodes[self:get_template() .. "/prefab"]
local text = prefab_nodes[self:get_template() .. "/text"]
table.insert(self.created_nodes, root)
gui.set_text(text, "Grid Item " .. #self.created_nodes)
gui.set_enabled(root, true)
self.grid:add(root)
end
function M:remove_element()
local last_node = table.remove(self.created_nodes)
if last_node == nil then
return
end
gui.delete_node(last_node)
local grid_index = self.grid:get_index_by_node(last_node)
self.grid:remove(grid_index)
end
function M:clear()
for _, node in ipairs(self.created_nodes) do
gui.delete_node(node)
end
self.created_nodes = {}
self.grid:clear()
end
return M

View File

@@ -0,0 +1,126 @@
fonts {
name: "text_bold"
font: "/example/assets/fonts/text_bold.font"
}
textures {
name: "druid"
texture: "/example/assets/druid.atlas"
}
nodes {
size {
x: 1000.0
y: 1000.0
}
type: TYPE_BOX
texture: "druid/empty"
id: "root"
inherit_alpha: true
visible: false
}
nodes {
position {
y: 400.0
}
size {
x: 400.0
y: 800.0
}
color {
x: 0.173
y: 0.184
z: 0.204
}
type: TYPE_BOX
texture: "druid/ui_circle_32"
id: "view"
pivot: PIVOT_N
parent: "root"
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
clipping_mode: CLIPPING_MODE_STENCIL
}
nodes {
size {
x: 400.0
y: 800.0
}
type: TYPE_BOX
texture: "druid/empty"
id: "content"
pivot: PIVOT_N
parent: "view"
inherit_alpha: true
visible: false
}
nodes {
position {
y: -400.0
}
size {
x: 300.0
y: 400.0
}
type: TYPE_BOX
id: "prefab"
parent: "content"
inherit_alpha: true
visible: false
}
nodes {
size {
x: 300.0
y: 90.0
}
color {
x: 0.631
y: 0.843
z: 0.961
}
type: TYPE_BOX
texture: "druid/ui_circle_32"
id: "panel"
parent: "prefab"
inherit_alpha: true
slice9 {
x: 16.0
y: 16.0
z: 16.0
w: 16.0
}
}
nodes {
size {
x: 240.0
y: 50.0
}
color {
x: 0.31
y: 0.318
z: 0.322
}
type: TYPE_TEXT
text: "Grid Item 1"
font: "text_bold"
id: "text"
outline {
x: 1.0
y: 1.0
z: 1.0
}
shadow {
x: 1.0
y: 1.0
z: 1.0
}
parent: "prefab"
inherit_alpha: true
outline_alpha: 0.0
shadow_alpha: 0.0
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT

Some files were not shown because too many files have changed in this diff Show More