Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

selection and cursor pos #258

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions druid/const.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ M.ACTION_BACK = hash(sys.get_config("druid.input_key_back", "key_back"))
M.ACTION_ENTER = hash(sys.get_config("druid.input_key_enter", "key_enter"))
M.ACTION_MULTITOUCH = hash(sys.get_config("druid.input_multitouch", "touch_multi"))
M.ACTION_BACKSPACE = hash(sys.get_config("druid.input_key_backspace", "key_backspace"))
M.ACTION_DEL = hash(sys.get_config("druid.input_key_del", "key_del"))
M.ACTION_SCROLL_UP = hash(sys.get_config("druid.input_scroll_up", "mouse_wheel_up"))
M.ACTION_SCROLL_DOWN = hash(sys.get_config("druid.input_scroll_down", "mouse_wheel_down"))
M.ACTION_LEFT = hash(sys.get_config("druid.input_key_left", "key_left"))
M.ACTION_RIGHT = hash(sys.get_config("druid.input_key_right", "key_right"))


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

Expand Down
95 changes: 89 additions & 6 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: 100.0
z: 0.0
w: 1.0
}
Expand Down Expand Up @@ -66,6 +66,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 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 @@ -268,8 +284,8 @@ nodes {
w: 1.0
}
size {
x: 1.0
y: 1.0
x: 200.0
y: 100.0
z: 0.0
w: 1.0
}
Expand Down Expand Up @@ -302,6 +318,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 @@ -365,6 +385,69 @@ nodes {
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: 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: 30.0
z: 0.0
w: 1.0
}
color {
x: 0.302
y: 0.4
z: 0.8
w: 1.0
}
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: ""
id: "highlight_node"
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: 0.35
template_node_child: false
size_mode: SIZE_MODE_MANUAL
custom_type: 0
enabled: false
visible: true
material: ""
}
material: "/builtins/materials/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
Expand Down
142 changes: 135 additions & 7 deletions druid/custom/rich_input/rich_input.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
-- @tfield druid.text placeholder @{Text}

---

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

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

Expand All @@ -30,37 +31,103 @@ local SCHEME = {
PLACEHOLDER = "placeholder_text",
INPUT = "input_text",
CURSOR = "cursor_node",
HIGHLIGHT = "highlight_node",
}


local function set_cursor(self)
if self.touch_pos_x then
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the touch_pos_x should be as arg of function, wdyt?

local text = self.input:get_text()
local node_pos = gui.get_screen_position(self.highlight)
local touch_delta_x = self.touch_pos_x - node_pos.x
local letters_count = utf8.len(self.input:get_text())
local cursor_delta = 0
local gap = self.input.total_width/2 * -1

for i = 1, letters_count do
cursor_delta = gap + self.text:get_text_size(utf8.sub(text, 1, i)) - self.half_cursor_width
if cursor_delta <= touch_delta_x then
gui.set_position(self.cursor, vmath.vector3(cursor_delta + self.half_cursor_width/2, 0, 0))
self.input.cursor_letter_index = i
end
end

self.touch_pos_x = nil
else
local text = self.input:get_text()
local gap = self.input.total_width/2 * -1
local cursor_delta = gap + self.text:get_text_size(utf8.sub(text, 1, self.input.cursor_letter_index)) - self.half_cursor_width
gui.set_position(self.cursor, vmath.vector3(cursor_delta + self.half_cursor_width/2, 0, 0))
end
end


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)
end


local function update_text(self, text)
local function update_text(self)
local text_width = self.input.total_width
animate_cursor(self)
gui.set_position(self.cursor, vmath.vector3(text_width/2, 0, 0))
local text_height = self.input.text_height
gui.set_scale(self.cursor, self.input.text.scale)
gui.set_size(self.highlight, vmath.vector3(text_width, text_height, 0))
set_cursor(self)
end


local function clear_text(self, replace_with_symbol)
local spacer = replace_with_symbol or ""
self.input:set_text(spacer)
update_text(self)

if replace_with_symbol then
gui.set_position(self.cursor, vmath.vector3(self.input.total_width/2, 0, 0))
self.input.cursor_letter_index = 1
else
gui.set_position(self.cursor, vmath.vector3(0, 0, 0))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can create a local TEMP_VECTOR = vector3(0) in module scope, change their fields instead creating vector each time. It allows to save a bit of memory

self.input.cursor_letter_index = 1
end

gui.set_enabled(self.highlight, false)
gui.set_enabled(self.cursor, true)
end


local function on_select(self)
self.input.cursor_letter_index = utf8.len(self.input:get_text()) or 0
gui.set_enabled(self.cursor, true)
gui.set_enabled(self.highlight, false)
gui.set_enabled(self.placeholder.node, false)
animate_cursor(self)
end


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


local function on_button_click(self)
self.touch_pos_x = self.action_pos_x
gui.set_enabled(self.highlight, false)
gui.set_enabled(self.cursor, true)
self.text:set_to(self.input:get_text())
set_cursor(self)
end


local function on_button_double_click(self)
if #self.input:get_text() > 0 then
gui.set_enabled(self.highlight, true)
gui.set_enabled(self.cursor, false)
end
end

--- Component init function
-- @tparam RichInput self @{RichInput}
-- @tparam string template The template string name
Expand All @@ -71,15 +138,27 @@ function RichInput.init(self, template, nodes)
self.druid = self:get_druid()
self.input = self.druid:new_input(self:get_node(SCHEME.BUTTON), self:get_node(SCHEME.INPUT))
self.cursor = self:get_node(SCHEME.CURSOR)

self.input:set_text("")
self.highlight = self:get_node(SCHEME.HIGHLIGHT)

self.placeholder = self.druid:new_text(self:get_node(SCHEME.PLACEHOLDER))
self.text = self.druid:new_text(self:get_node(SCHEME.INPUT))

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.button.on_click:subscribe(on_button_click, self)
self.input.button.on_double_click:subscribe(on_button_double_click, self)
self.input.style.NO_CONSUME_INPUT_WHILE_SELECTED = true
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the rich input should not change these style settings (and for skip input keys same)

self.input.style.SKIP_INPUT_KEYS = true
self.input.style.IS_LONGTAP_ERASE = false

self.input.cursor_letter_index = 0
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already inited in input component

self.action_pos_x = nil
self.half_cursor_width = self.text:get_text_size("|")/2

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


Expand All @@ -92,4 +171,53 @@ function RichInput.set_placeholder(self, placeholder_text)
end


function RichInput.on_input(self, action_id, action)
self.action_pos_x = action.screen_x
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The values action_pos_x and touch_pos_x should not be stored in rich input component. You can use it as a local variables inside only on_input functions


if gui.is_enabled(self.highlight) then
if action_id == const.ACTION_BACKSPACE or action_id == const.ACTION_DEL then
clear_text(self)
on_select(self)
elseif action_id == const.ACTION_TEXT then
clear_text(self, action.text)
end
else
if action_id == const.ACTION_DEL and action.pressed then
local text = self.input:get_text()
local new_text = utf8.sub(text, 1, self.input.cursor_letter_index) .. utf8.sub(text, self.input.cursor_letter_index +2 )
self.input:set_text(new_text)
end

if action_id == const.ACTION_BACKSPACE then
if self.input.cursor_letter_index > 0 and gui.is_enabled(self.cursor) and action.pressed then
local text = self.input:get_text()
local new_text = utf8.sub(text, 1, self.input.cursor_letter_index-1) .. utf8.sub(text, self.input.cursor_letter_index +1 )
self.input.cursor_letter_index = self.input.cursor_letter_index -1
self.input:set_text(new_text)
end
return true
end

if action_id == const.ACTION_LEFT and action.pressed then
--print("left")
if self.input.cursor_letter_index > 1 then
self.input.cursor_letter_index = self.input.cursor_letter_index -1
end
elseif action_id == const.ACTION_RIGHT and action.pressed then
--print("right")
if self.input.cursor_letter_index < utf8.len(self.input:get_text()) then
self.input.cursor_letter_index = self.input.cursor_letter_index + 1
end
end

update_text(self)
self.touch_pos_x = nil

if utf8.len(self.input:get_text()) <=0 then
self.input.cursor_letter_index = 0
end
end
return false
end

return RichInput
Loading