mirror of
https://github.com/Insality/druid
synced 2025-09-28 02:22:19 +02:00
Update example with new brand one
This commit is contained in:
227
example/examples/gamepad/on_screen_control/on_screen_control.gui
Normal file
227
example/examples/gamepad/on_screen_control/on_screen_control.gui
Normal file
@@ -0,0 +1,227 @@
|
||||
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: 128.0
|
||||
y: 128.0
|
||||
}
|
||||
color {
|
||||
x: 0.902
|
||||
y: 0.875
|
||||
z: 0.624
|
||||
}
|
||||
type: TYPE_BOX
|
||||
texture: "druid/ui_circle_64"
|
||||
id: "character"
|
||||
parent: "root"
|
||||
inherit_alpha: true
|
||||
slice9 {
|
||||
x: 32.0
|
||||
y: 32.0
|
||||
z: 32.0
|
||||
w: 32.0
|
||||
}
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
x: -25.0
|
||||
y: 21.0
|
||||
}
|
||||
color {
|
||||
x: 0.129
|
||||
y: 0.141
|
||||
z: 0.157
|
||||
}
|
||||
type: TYPE_BOX
|
||||
texture: "druid/ui_circle_32"
|
||||
id: "eye_left"
|
||||
parent: "character"
|
||||
inherit_alpha: true
|
||||
size_mode: SIZE_MODE_AUTO
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
x: -8.0
|
||||
y: 8.0
|
||||
}
|
||||
color {
|
||||
x: 0.941
|
||||
y: 0.984
|
||||
}
|
||||
type: TYPE_BOX
|
||||
texture: "druid/ui_circle_8"
|
||||
id: "eye_left_blick"
|
||||
parent: "eye_left"
|
||||
inherit_alpha: true
|
||||
size_mode: SIZE_MODE_AUTO
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
x: 25.0
|
||||
y: 21.0
|
||||
}
|
||||
color {
|
||||
x: 0.129
|
||||
y: 0.141
|
||||
z: 0.157
|
||||
}
|
||||
type: TYPE_BOX
|
||||
texture: "druid/ui_circle_32"
|
||||
id: "eye_right"
|
||||
parent: "character"
|
||||
inherit_alpha: true
|
||||
size_mode: SIZE_MODE_AUTO
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
x: -8.0
|
||||
y: 8.0
|
||||
}
|
||||
color {
|
||||
x: 0.941
|
||||
y: 0.984
|
||||
}
|
||||
type: TYPE_BOX
|
||||
texture: "druid/ui_circle_8"
|
||||
id: "eye_right_blick"
|
||||
parent: "eye_right"
|
||||
inherit_alpha: true
|
||||
size_mode: SIZE_MODE_AUTO
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
y: -300.0
|
||||
}
|
||||
type: TYPE_TEMPLATE
|
||||
id: "on_screen_input"
|
||||
parent: "root"
|
||||
inherit_alpha: true
|
||||
template: "/example/examples/gamepad/on_screen_control/on_screen_input.gui"
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_input/root"
|
||||
parent: "on_screen_input"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_TEMPLATE
|
||||
id: "on_screen_input/on_screen_stick"
|
||||
parent: "on_screen_input/root"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_input/on_screen_stick/root"
|
||||
parent: "on_screen_input/on_screen_stick"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_PIE
|
||||
id: "on_screen_input/on_screen_stick/background_mask"
|
||||
parent: "on_screen_input/on_screen_stick/root"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_input/on_screen_stick/background"
|
||||
parent: "on_screen_input/on_screen_stick/background_mask"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_input/on_screen_stick/stick_root"
|
||||
parent: "on_screen_input/on_screen_stick/root"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_input/on_screen_stick/stick_shadow"
|
||||
parent: "on_screen_input/on_screen_stick/stick_root"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_input/on_screen_stick/stick"
|
||||
parent: "on_screen_input/on_screen_stick/stick_root"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_input/on_screen_stick/dot_1"
|
||||
parent: "on_screen_input/on_screen_stick/stick"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_input/on_screen_stick/dot_2"
|
||||
parent: "on_screen_input/on_screen_stick/stick"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_input/on_screen_stick/dot_3"
|
||||
parent: "on_screen_input/on_screen_stick/stick"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_input/on_screen_stick/dot_4"
|
||||
parent: "on_screen_input/on_screen_stick/stick"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_input/on_screen_button"
|
||||
parent: "on_screen_input/root"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_TEMPLATE
|
||||
id: "on_screen_input/button_action"
|
||||
parent: "on_screen_input/on_screen_button"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_input/button_action/button"
|
||||
parent: "on_screen_input/button_action"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_TEXT
|
||||
id: "on_screen_input/button_action/text"
|
||||
parent: "on_screen_input/button_action/button"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_input/button_action/icon"
|
||||
parent: "on_screen_input/button_action/button"
|
||||
template_node_child: true
|
||||
}
|
||||
material: "/builtins/materials/gui.material"
|
||||
adjust_reference: ADJUST_REFERENCE_PARENT
|
@@ -0,0 +1,59 @@
|
||||
local component = require("druid.component")
|
||||
local on_screen_input = require("example.examples.gamepad.on_screen_control.on_screen_input")
|
||||
|
||||
---@class on_screen_control: druid.base_component
|
||||
---@field druid druid_instance
|
||||
---@field on_screen_input on_screen_input
|
||||
local M = component.create("on_screen_control")
|
||||
|
||||
local CHARACTER_SPEED = 700
|
||||
|
||||
---@param template string
|
||||
---@param nodes table<hash, node>
|
||||
function M:init(template, nodes)
|
||||
self.druid = self:get_druid(template, nodes)
|
||||
|
||||
self.character = self:get_node("character")
|
||||
self.character_position = gui.get_position(self.character)
|
||||
|
||||
self.character_eye_left = self:get_node("eye_left")
|
||||
self.character_eye_right = self:get_node("eye_right")
|
||||
|
||||
self.on_screen_input = self.druid:new(on_screen_input, "on_screen_input") --[[@as on_screen_input]]
|
||||
|
||||
self.on_screen_input.on_action:subscribe(self.on_action_button, self)
|
||||
self.on_screen_input.on_movement:subscribe(self.on_movement, self)
|
||||
self.on_screen_input.on_movement_stop:subscribe(self.on_movement_stop, self)
|
||||
end
|
||||
|
||||
|
||||
function M:on_action_button()
|
||||
gui.set_scale(self.character, vmath.vector3(1.5))
|
||||
gui.animate(self.character, gui.PROP_SCALE, vmath.vector3(1), gui.EASING_INSINE, 0.2)
|
||||
end
|
||||
|
||||
|
||||
function M:on_movement(x, y, dt)
|
||||
self.character_position.x = self.character_position.x + x * CHARACTER_SPEED * dt
|
||||
self.character_position.y = self.character_position.y + y * CHARACTER_SPEED * dt
|
||||
|
||||
-- Clamp to -436, 436, area of the screen
|
||||
self.character_position.x = math.min(436, math.max(-436, self.character_position.x))
|
||||
self.character_position.y = math.min(436, math.max(-436, self.character_position.y))
|
||||
|
||||
gui.set_position(self.character, self.character_position)
|
||||
|
||||
-- Adjust angle of the eyes
|
||||
local angle = math.deg(math.atan2(y, x)) - 135
|
||||
gui.set(self.character_eye_left, "euler.z", angle)
|
||||
gui.set(self.character_eye_right, "euler.z", angle)
|
||||
end
|
||||
|
||||
|
||||
function M:on_movement_stop()
|
||||
gui.set(self.character_eye_left, "euler.z", 0)
|
||||
gui.set(self.character_eye_right, "euler.z", 0)
|
||||
end
|
||||
|
||||
|
||||
return M
|
132
example/examples/gamepad/on_screen_control/on_screen_input.gui
Normal file
132
example/examples/gamepad/on_screen_control/on_screen_input.gui
Normal file
@@ -0,0 +1,132 @@
|
||||
textures {
|
||||
name: "druid"
|
||||
texture: "/example/assets/druid.atlas"
|
||||
}
|
||||
nodes {
|
||||
size {
|
||||
x: 1000.0
|
||||
y: 400.0
|
||||
}
|
||||
type: TYPE_BOX
|
||||
id: "root"
|
||||
inherit_alpha: true
|
||||
visible: false
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
x: -300.0
|
||||
}
|
||||
type: TYPE_TEMPLATE
|
||||
id: "on_screen_stick"
|
||||
parent: "root"
|
||||
inherit_alpha: true
|
||||
template: "/example/examples/gamepad/gamepad_tester/templates/gamepad_stick.gui"
|
||||
}
|
||||
nodes {
|
||||
size {
|
||||
x: 400.0
|
||||
y: 400.0
|
||||
}
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_stick/root"
|
||||
parent: "on_screen_stick"
|
||||
overridden_fields: 4
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_PIE
|
||||
id: "on_screen_stick/background_mask"
|
||||
parent: "on_screen_stick/root"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_stick/background"
|
||||
parent: "on_screen_stick/background_mask"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_stick/stick_root"
|
||||
parent: "on_screen_stick/root"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_stick/stick_shadow"
|
||||
parent: "on_screen_stick/stick_root"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_stick/stick"
|
||||
parent: "on_screen_stick/stick_root"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_stick/dot_1"
|
||||
parent: "on_screen_stick/stick"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_stick/dot_2"
|
||||
parent: "on_screen_stick/stick"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_stick/dot_3"
|
||||
parent: "on_screen_stick/stick"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_stick/dot_4"
|
||||
parent: "on_screen_stick/stick"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
position {
|
||||
x: 300.0
|
||||
}
|
||||
size {
|
||||
x: 400.0
|
||||
y: 400.0
|
||||
}
|
||||
type: TYPE_BOX
|
||||
id: "on_screen_button"
|
||||
parent: "root"
|
||||
inherit_alpha: true
|
||||
visible: false
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_TEMPLATE
|
||||
id: "button_action"
|
||||
parent: "on_screen_button"
|
||||
inherit_alpha: true
|
||||
template: "/example/examples/gamepad/gamepad_tester/templates/gamepad_button.gui"
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "button_action/button"
|
||||
parent: "button_action"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_TEXT
|
||||
id: "button_action/text"
|
||||
parent: "button_action/button"
|
||||
template_node_child: true
|
||||
}
|
||||
nodes {
|
||||
type: TYPE_BOX
|
||||
id: "button_action/icon"
|
||||
parent: "button_action/button"
|
||||
overridden_fields: 45
|
||||
template_node_child: true
|
||||
enabled: false
|
||||
}
|
||||
material: "/builtins/materials/gui.material"
|
||||
adjust_reference: ADJUST_REFERENCE_PARENT
|
107
example/examples/gamepad/on_screen_control/on_screen_input.lua
Normal file
107
example/examples/gamepad/on_screen_control/on_screen_input.lua
Normal file
@@ -0,0 +1,107 @@
|
||||
local const = require("druid.const")
|
||||
local event = require("druid.event")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
---@class on_screen_input: druid.base_component
|
||||
---@field druid druid_instance
|
||||
---@field on_action druid.event @()
|
||||
---@field on_movement druid.event @(x: number, y: number, dt: number) X/Y values are in range -1..1
|
||||
---@field on_movement_stop druid.event @()
|
||||
local M = component.create("on_screen_input")
|
||||
|
||||
local STICK_DISTANCE = 80
|
||||
|
||||
---@param template string
|
||||
---@param nodes table<hash, node>
|
||||
function M:init(template, nodes)
|
||||
self.druid = self:get_druid(template, nodes)
|
||||
|
||||
self.button_action = self:get_node("on_screen_button")
|
||||
self.on_screen_control = self:get_node("on_screen_stick/root")
|
||||
|
||||
self.stick_root = self:get_node("on_screen_stick/stick_root")
|
||||
self.stick_position = gui.get_position(self.stick_root)
|
||||
|
||||
self.on_action = event()
|
||||
self.on_movement = event()
|
||||
self.on_movement_stop = event()
|
||||
|
||||
self.is_multitouch = helper.is_multitouch_supported()
|
||||
end
|
||||
|
||||
|
||||
---@param action_id hash
|
||||
---@param action action
|
||||
function M:on_input(action_id, action)
|
||||
if self.is_multitouch then
|
||||
if action_id == const.ACTION_MULTITOUCH then
|
||||
for _, touch in ipairs(action.touch) do
|
||||
self:process_touch(touch)
|
||||
end
|
||||
end
|
||||
else
|
||||
if action_id == const.ACTION_TOUCH then
|
||||
self:process_touch(action)
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
---@param action action|touch
|
||||
function M:process_touch(action)
|
||||
if action.pressed and gui.pick_node(self.button_action, action.x, action.y) then
|
||||
self.on_action:trigger()
|
||||
|
||||
gui.animate(self.button_action, gui.PROP_SCALE, vmath.vector3(1.2), gui.EASING_OUTSINE, 0.1, 0, function()
|
||||
gui.animate(self.button_action, gui.PROP_SCALE, vmath.vector3(1), gui.EASING_INSINE, 0.2, 0.05)
|
||||
end)
|
||||
end
|
||||
|
||||
if gui.pick_node(self.on_screen_control, action.x, action.y) then
|
||||
self._is_stick_drag = action.id or true
|
||||
end
|
||||
|
||||
local is_the_same_touch_id = not action.id or action.id == self._is_stick_drag
|
||||
if self._is_stick_drag and is_the_same_touch_id then
|
||||
-- action.dx and action.dy are broken inside touches for some reason, manual calculations seems fine
|
||||
local dx = action.x - (self._prev_x or action.x)
|
||||
local dy = action.y - (self._prev_y or action.y)
|
||||
self._prev_x = action.x
|
||||
self._prev_y = action.y
|
||||
|
||||
self.stick_position.x = self.stick_position.x + dx
|
||||
self.stick_position.y = self.stick_position.y + dy
|
||||
|
||||
-- Limit to STICK_DISTANCE
|
||||
local length = vmath.length(self.stick_position)
|
||||
if length > STICK_DISTANCE then
|
||||
self.stick_position.x = self.stick_position.x / length * STICK_DISTANCE
|
||||
self.stick_position.y = self.stick_position.y / length * STICK_DISTANCE
|
||||
end
|
||||
|
||||
gui.set_position(self.stick_root, self.stick_position)
|
||||
end
|
||||
|
||||
if action.released and is_the_same_touch_id then
|
||||
self._is_stick_drag = false
|
||||
self.stick_position.x = 0
|
||||
self.stick_position.y = 0
|
||||
self._prev_x = nil
|
||||
self._prev_y = nil
|
||||
gui.animate(self.stick_root, gui.PROP_POSITION, self.stick_position, gui.EASING_OUTBACK, 0.3)
|
||||
self.on_movement_stop:trigger()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function M:update(dt)
|
||||
if self.stick_position.x ~= 0 or self.stick_position.y ~= 0 then
|
||||
self.on_movement:trigger(self.stick_position.x / STICK_DISTANCE, self.stick_position.y / STICK_DISTANCE, dt)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return M
|
Reference in New Issue
Block a user