Skip to content

Commit

Permalink
Add cursor to rich input component, add additional controls to it
Browse files Browse the repository at this point in the history
  • Loading branch information
Insality committed Apr 9, 2024
1 parent 84c917f commit 118d0bd
Show file tree
Hide file tree
Showing 12 changed files with 346 additions and 61 deletions.
6 changes: 6 additions & 0 deletions docs_md/advanced-setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ By default, **Druid** utilizes the `/builtins/input/all.input_binding` for input
- Key trigger: `Back` -> `key_back` (for BackHandler component, Android back button, input component)
- Key trigger: `Enter` -> `key_enter` (for Input component, optional)
- Key trigger: `Esc` -> `key_esc` (for Input component, optional)
- Key trigger: `Left` -> `key_left` (for Input component, optional)
- Key trigger: `Right` -> `key_right` (for Input component, optional)
- Key trigger: `Shift` -> `key_lshift` (for Input component, optional)
- Touch triggers: `Touch multi` -> `touch_multi` (for Scroll component)

![](../media/input_binding_2.png)
Expand All @@ -37,6 +40,9 @@ input_key_backspace = key_backspace
input_multitouch = touch_multi
input_scroll_up = mouse_wheel_up
input_scroll_down = mouse_wheel_down
input_key_left = key_left
input_key_right = key_right
input_key_lshift = key_lshift
```


Expand Down
1 change: 1 addition & 0 deletions druid/annotations.lua
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,7 @@ function druid__hover.set_mouse_hover(self, state) end
---@field on_input_text druid.event On input field text change callback(self, input_text)
---@field on_input_unselect druid.event On input field unselect callback(self, input_text)
---@field on_input_wrong druid.event On trying user input with not allowed character callback(self, params, button_instance)
---@field on_select_cursor_change druid.event On input field cursor change callback(self, start_index, end_index)
---@field style druid.input.style Component style params.
---@field text druid.text Text component
local druid__input = {}
Expand Down
4 changes: 4 additions & 0 deletions druid/const.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ M.ACTION_MULTITOUCH = hash(sys.get_config_string("druid.input_multitouch", "touc
M.ACTION_BACKSPACE = hash(sys.get_config_string("druid.input_key_backspace", "key_backspace"))
M.ACTION_SCROLL_UP = hash(sys.get_config_string("druid.input_scroll_up", "mouse_wheel_up"))
M.ACTION_SCROLL_DOWN = hash(sys.get_config_string("druid.input_scroll_down", "mouse_wheel_down"))
M.ACTION_LEFT = hash(sys.get_config_string("druid.input_key_left", "key_left"))
M.ACTION_RIGHT = hash(sys.get_config_string("druid.input_key_right", "key_right"))
M.ACTION_LSHIFT = hash(sys.get_config_string("druid.input_key_lshift", "key_lshift"))


M.IS_STENCIL_CHECK = not (sys.get_config_string("druid.no_stencil_check") == "1")

Expand Down
64 changes: 44 additions & 20 deletions druid/custom/rich_input/rich_input.gui
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ nodes {
w: 1.0
}
size {
x: 1.0
y: 1.0
x: 200.0
y: 50.0
z: 0.0
w: 1.0
}
Expand Down Expand Up @@ -65,7 +65,11 @@ nodes {
clipping_inverted: false
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
Expand All @@ -87,8 +91,8 @@ nodes {
w: 1.0
}
size {
x: 190.0
y: 45.0
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
Expand Down Expand Up @@ -121,6 +125,10 @@ nodes {
alpha: 1.0
template_node_child: false
size_mode: SIZE_MODE_AUTO
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
Expand Down Expand Up @@ -184,6 +192,10 @@ nodes {
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
Expand Down Expand Up @@ -247,6 +259,10 @@ nodes {
template_node_child: false
text_leading: 1.0
text_tracking: 0.0
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
Expand All @@ -262,46 +278,50 @@ nodes {
w: 1.0
}
scale {
x: 0.6
y: 0.6
x: 1.0
y: 1.0
z: 1.0
w: 1.0
}
size {
x: 1.0
y: 1.0
x: 32.0
y: 44.0
z: 0.0
w: 1.0
}
color {
x: 1.0
y: 1.0
x: 0.702
y: 0.8
z: 1.0
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "kenney/empty"
texture: "kenney/ui_rect_round_8"
id: "cursor_node"
xanchor: XANCHOR_NONE
yanchor: YANCHOR_NONE
pivot: PIVOT_CENTER
pivot: PIVOT_W
adjust_mode: ADJUST_MODE_FIT
parent: "button"
layer: ""
inherit_alpha: true
slice9 {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
x: 8.0
y: 8.0
z: 8.0
w: 8.0
}
clipping_mode: CLIPPING_MODE_NONE
clipping_visible: true
clipping_inverted: false
alpha: 1.0
alpha: 0.6
template_node_child: false
size_mode: SIZE_MODE_AUTO
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: true
visible: true
material: ""
}
nodes {
position {
Expand Down Expand Up @@ -358,13 +378,17 @@ nodes {
line_break: false
parent: "cursor_node"
layer: ""
inherit_alpha: true
inherit_alpha: false
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
Expand Down
106 changes: 95 additions & 11 deletions druid/custom/rich_input/rich_input.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
---

local component = require("druid.component")
local helper = require("druid.helper")
local const = require("druid.const")
local utf8_lua = require("druid.system.utf8")
local utf8 = utf8 or utf8_lua

local RichInput = component.create("druid.rich_input")

Expand All @@ -33,21 +37,43 @@ local SCHEME = {
PLACEHOLDER = "placeholder_text",
INPUT = "input_text",
CURSOR = "cursor_node",
CURSOR_TEXT = "cursor_text",
}


local function animate_cursor(self)
gui.cancel_animation(self.cursor, gui.PROP_COLOR)
gui.set_color(self.cursor, vmath.vector4(1))
gui.animate(self.cursor, gui.PROP_COLOR, vmath.vector4(1,1,1,0), gui.EASING_INSINE, 0.8, 0, nil, gui.PLAYBACK_LOOP_PINGPONG)
gui.cancel_animation(self.cursor_text, "color.w")
gui.set_alpha(self.cursor_text, 1)
gui.animate(self.cursor_text, "color.w", 0, gui.EASING_INSINE, 0.8, 0, nil, gui.PLAYBACK_LOOP_PINGPONG)
end


local function set_selection_width(self, selection_width)
gui.set_visible(self.cursor, selection_width > 0)

local width = selection_width / self.input.text.scale.x
local height = gui.get_size(self.cursor).y
gui.set_size(self.cursor, vmath.vector3(width, height, 0))
end


local function update_text(self, text)
local function update_text(self)
local left_text_part = utf8.sub(self.input:get_text(), 0, self.input.start_index)
local selected_text_part = utf8.sub(self.input:get_text(), self.input.start_index + 1, self.input.end_index)

local left_part_width = self.input.text:get_text_size(left_text_part)
local selected_part_width = self.input.text:get_text_size(selected_text_part)

local text_width = self.input.total_width
animate_cursor(self)
gui.set_position(self.cursor, vmath.vector3(text_width/2, 0, 0))

local pivot_text = gui.get_pivot(self.input.text.node)
local pivot_offset = helper.get_pivot_offset(pivot_text)

self.cursor_position.x = self.text_position.x - text_width * (0.5 - pivot_offset.x) + left_part_width
gui.set_position(self.cursor, self.cursor_position)
gui.set_scale(self.cursor, self.input.text.scale)

set_selection_width(self, selected_part_width)
end


Expand All @@ -59,11 +85,26 @@ end


local function on_unselect(self)
gui.cancel_animation(self.cursor, gui.PROP_COLOR)
gui.set_enabled(self.cursor, false)
gui.set_enabled(self.placeholder.node, true and #self.input:get_text() == 0)
end


--- Update selection
local function update_selection(self, start_index, end_index)
update_text(self)
end


local function on_touch_start_callback(self, touch)
end


local function on_drag_callback(self)
end


--- The @{RichInput} constructor
-- @tparam RichInput self @{RichInput}
-- @tparam string template The template string name
Expand All @@ -74,33 +115,76 @@ function RichInput.init(self, template, nodes)
self.druid = self:get_druid()
self.root = self:get_node(SCHEME.ROOT)

---@type druid.input
self.input = self.druid:new_input(self:get_node(SCHEME.BUTTON), self:get_node(SCHEME.INPUT))
self.cursor = self:get_node(SCHEME.CURSOR)
self.cursor_position = gui.get_position(self.cursor)
self.cursor_text = self:get_node(SCHEME.CURSOR_TEXT)
self.drag = self.druid:new_drag(self.root, on_drag_callback)
self.drag.on_touch_start:subscribe(on_touch_start_callback)
self.drag:set_input_priority(const.PRIORITY_INPUT_MAX + 1)

self.input:set_text("")
self.placeholder = self.druid:new_text(self:get_node(SCHEME.PLACEHOLDER))
self.text_position = gui.get_position(self.input.text.node)

self.input.on_input_text:subscribe(update_text)
self.input.on_input_select:subscribe(on_select)
self.input.on_input_unselect:subscribe(on_unselect)
self.input.on_select_cursor_change:subscribe(update_selection)

on_unselect(self)
update_text(self, "")
end


--- Component style params.
-- You can override this component styles params in druid styles table
-- or create your own style
-- @table style
function RichInput.on_style_change(self, style)
self.style = {}
end



--- Set placeholder text
-- @tparam RichInput self @{RichInput}
-- @tparam string|nil placeholder_text The placeholder text
-- @treturn RichInput Current instance
-- @tparam string placeholder_text The placeholder text
function RichInput.set_placeholder(self, placeholder_text)
self.placeholder:set_to(placeholder_text)
return self
end


---GSet input field text
--- Select input field
-- @tparam RichInput self @{RichInput}
function RichInput.select(self)
self.input:select()
end


--- Set input field text
-- @tparam RichInput self @{RichInput}
-- @tparam string text The input text
function RichInput.set_text(self, text)
self.input:set_text(text)
gui.set_enabled(self.placeholder.node, true and #self.input:get_text() == 0)

return self
end


function RichInput.set_font(self, font)
gui.set_font(self.input.text.node, font)
gui.set_font(self.placeholder.node, font)

return self
end


--- Set input field text
-- @tparam RichInput self @{RichInput}
-- @treturn string Current input text
function RichInput.get_text(self)
return self.input:get_text()
end
Expand All @@ -111,7 +195,7 @@ end
-- ex: [%a%d] for alpha and numeric
-- @tparam RichInput self @{RichInput}
-- @tparam string characters Regulax exp. for validate user input
-- @treturn RichInput Current instance
-- @treturn druid.input Current input instance
function RichInput.set_allowed_characters(self, characters)
self.input:set_allowed_characters(characters)

Expand Down
Loading

0 comments on commit 118d0bd

Please sign in to comment.